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