Home | History | Annotate | Download | only in renderer_host
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/renderer_host/software_frame_manager.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback_helpers.h"
      9 #include "base/debug/alias.h"
     10 #include "content/browser/renderer_host/dip_util.h"
     11 #include "content/public/browser/user_metrics.h"
     12 
     13 namespace {
     14 
     15 void ReleaseMailbox(scoped_refptr<content::SoftwareFrame> frame,
     16                     unsigned sync_point,
     17                     bool lost_resource) {}
     18 
     19 }  // namespace
     20 
     21 namespace content {
     22 
     23 ////////////////////////////////////////////////////////////////////////////////
     24 // SoftwareFrame
     25 
     26 class CONTENT_EXPORT SoftwareFrame : public base::RefCounted<SoftwareFrame> {
     27  private:
     28   friend class base::RefCounted<SoftwareFrame>;
     29   friend class SoftwareFrameManager;
     30 
     31   SoftwareFrame(
     32     base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client,
     33     uint32 output_surface_id,
     34     unsigned frame_id,
     35     float frame_device_scale_factor,
     36     gfx::Size frame_size_pixels,
     37     scoped_ptr<base::SharedMemory> shared_memory);
     38   ~SoftwareFrame();
     39 
     40   base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client_;
     41   const uint32 output_surface_id_;
     42   const unsigned frame_id_;
     43   float frame_device_scale_factor_;
     44   const gfx::Size frame_size_pixels_;
     45   scoped_ptr<base::SharedMemory> shared_memory_;
     46 
     47   DISALLOW_COPY_AND_ASSIGN(SoftwareFrame);
     48 };
     49 
     50 SoftwareFrame::SoftwareFrame(
     51     base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client,
     52     uint32 output_surface_id,
     53     unsigned frame_id,
     54     float frame_device_scale_factor,
     55     gfx::Size frame_size_pixels,
     56     scoped_ptr<base::SharedMemory> shared_memory)
     57     : frame_manager_client_(frame_manager_client),
     58       output_surface_id_(output_surface_id),
     59       frame_id_(frame_id),
     60       frame_device_scale_factor_(frame_device_scale_factor),
     61       frame_size_pixels_(frame_size_pixels),
     62       shared_memory_(shared_memory.Pass()) {}
     63 
     64 SoftwareFrame::~SoftwareFrame() {
     65   if (frame_manager_client_) {
     66     frame_manager_client_->SoftwareFrameWasFreed(
     67         output_surface_id_, frame_id_);
     68   }
     69 }
     70 
     71 ////////////////////////////////////////////////////////////////////////////////
     72 // SoftwareFrameManager
     73 
     74 SoftwareFrameManager::SoftwareFrameManager(
     75     base::WeakPtr<SoftwareFrameManagerClient> client)
     76       : client_(client) {}
     77 
     78 SoftwareFrameManager::~SoftwareFrameManager() {
     79   DiscardCurrentFrame();
     80 }
     81 
     82 bool SoftwareFrameManager::SwapToNewFrame(
     83     uint32 output_surface_id,
     84     const cc::SoftwareFrameData* frame_data,
     85     float frame_device_scale_factor,
     86     base::ProcessHandle process_handle) {
     87 
     88 #ifdef OS_WIN
     89   scoped_ptr<base::SharedMemory> shared_memory(
     90       new base::SharedMemory(frame_data->handle, true,
     91                              process_handle));
     92 #else
     93   scoped_ptr<base::SharedMemory> shared_memory(
     94       new base::SharedMemory(frame_data->handle, true));
     95 #endif
     96 
     97   // The NULL handle is used in testing.
     98   if (base::SharedMemory::IsHandleValid(shared_memory->handle())) {
     99     const size_t size_in_bytes = 4 * frame_data->size.GetArea();
    100 #ifdef OS_WIN
    101     if (!shared_memory->Map(0)) {
    102       DLOG(ERROR) << "Unable to map renderer memory.";
    103       RecordAction(
    104           UserMetricsAction("BadMessageTerminate_SharedMemoryManager1"));
    105       return false;
    106     }
    107 
    108     if (shared_memory->mapped_size() < size_in_bytes) {
    109       DLOG(ERROR) << "Shared memory too small for given rectangle";
    110       RecordAction(
    111           UserMetricsAction("BadMessageTerminate_SharedMemoryManager2"));
    112       return false;
    113     }
    114 #else
    115     if (!shared_memory->Map(size_in_bytes)) {
    116       DLOG(ERROR) << "Unable to map renderer memory.";
    117       RecordAction(
    118           UserMetricsAction("BadMessageTerminate_SharedMemoryManager1"));
    119       return false;
    120     }
    121 #endif
    122   }
    123 
    124   scoped_refptr<SoftwareFrame> next_frame(new SoftwareFrame(
    125       client_,
    126       output_surface_id,
    127       frame_data->id,
    128       frame_device_scale_factor,
    129       frame_data->size,
    130       shared_memory.Pass()));
    131   current_frame_.swap(next_frame);
    132   return true;
    133 }
    134 
    135 bool SoftwareFrameManager::HasCurrentFrame() const {
    136   return current_frame_.get() ? true : false;
    137 }
    138 
    139 void SoftwareFrameManager::DiscardCurrentFrame() {
    140   if (!HasCurrentFrame())
    141     return;
    142   current_frame_ = NULL;
    143   RendererFrameManager::GetInstance()->RemoveFrame(this);
    144 }
    145 
    146 void SoftwareFrameManager::SwapToNewFrameComplete(bool visible) {
    147   DCHECK(HasCurrentFrame());
    148   RendererFrameManager::GetInstance()->AddFrame(this, visible);
    149 }
    150 
    151 void SoftwareFrameManager::SetVisibility(bool visible) {
    152   if (HasCurrentFrame()) {
    153     RendererFrameManager::GetInstance()->SetFrameVisibility(this, visible);
    154   }
    155 }
    156 
    157 uint32 SoftwareFrameManager::GetCurrentFrameOutputSurfaceId() const {
    158   DCHECK(HasCurrentFrame());
    159   return current_frame_->output_surface_id_;
    160 }
    161 
    162 void SoftwareFrameManager::GetCurrentFrameMailbox(
    163     cc::TextureMailbox* mailbox,
    164     scoped_ptr<cc::SingleReleaseCallback>* callback) {
    165   DCHECK(HasCurrentFrame());
    166   *mailbox = cc::TextureMailbox(
    167       current_frame_->shared_memory_.get(), current_frame_->frame_size_pixels_);
    168   *callback = cc::SingleReleaseCallback::Create(
    169       base::Bind(ReleaseMailbox, current_frame_));
    170 }
    171 
    172 void* SoftwareFrameManager::GetCurrentFramePixels() const {
    173   DCHECK(HasCurrentFrame());
    174   DCHECK(base::SharedMemory::IsHandleValid(
    175       current_frame_->shared_memory_->handle()));
    176   return current_frame_->shared_memory_->memory();
    177 }
    178 
    179 float SoftwareFrameManager::GetCurrentFrameDeviceScaleFactor() const {
    180   DCHECK(HasCurrentFrame());
    181   return current_frame_->frame_device_scale_factor_;
    182 }
    183 
    184 gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInPixels() const {
    185   DCHECK(HasCurrentFrame());
    186   return current_frame_->frame_size_pixels_;
    187 }
    188 
    189 gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInDIP() const {
    190   DCHECK(HasCurrentFrame());
    191   return ConvertSizeToDIP(current_frame_->frame_device_scale_factor_,
    192                           current_frame_->frame_size_pixels_);
    193 }
    194 
    195 void SoftwareFrameManager::EvictCurrentFrame() {
    196   DCHECK(HasCurrentFrame());
    197   DiscardCurrentFrame();
    198   if (client_)
    199     client_->ReleaseReferencesToSoftwareFrame();
    200 }
    201 
    202 }  // namespace content
    203