OLD | NEW |
(Empty) | |
| 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/sys_info.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 gfx::Size frame_size_dip, |
| 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 const gfx::Size frame_size_dip_; |
| 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 gfx::Size frame_size_dip, |
| 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_size_dip_(frame_size_dip), |
| 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(UserMetricsAction( |
| 104 "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(UserMetricsAction( |
| 111 "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(UserMetricsAction( |
| 118 "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 ConvertSizeToDIP(frame_device_scale_factor, frame_data->size), |
| 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 SoftwareFrameMemoryManager::GetInstance()->RemoveFrame(this); |
| 144 } |
| 145 |
| 146 void SoftwareFrameManager::SwapToNewFrameComplete(bool visible) { |
| 147 DCHECK(HasCurrentFrame()); |
| 148 SoftwareFrameMemoryManager::GetInstance()->AddFrame(this, visible); |
| 149 } |
| 150 |
| 151 void SoftwareFrameManager::SetVisibility(bool visible) { |
| 152 if (HasCurrentFrame()) { |
| 153 SoftwareFrameMemoryManager::GetInstance()->SetFrameVisibility(this, |
| 154 visible); |
| 155 } |
| 156 } |
| 157 |
| 158 void SoftwareFrameManager::GetCurrentFrameMailbox( |
| 159 cc::TextureMailbox* mailbox, |
| 160 scoped_ptr<cc::SingleReleaseCallback>* callback) { |
| 161 DCHECK(HasCurrentFrame()); |
| 162 *mailbox = cc::TextureMailbox( |
| 163 current_frame_->shared_memory_.get(), current_frame_->frame_size_pixels_); |
| 164 *callback = cc::SingleReleaseCallback::Create( |
| 165 base::Bind(ReleaseMailbox, current_frame_)); |
| 166 } |
| 167 |
| 168 const void* SoftwareFrameManager::GetCurrentFramePixels() const { |
| 169 DCHECK(HasCurrentFrame()); |
| 170 DCHECK(base::SharedMemory::IsHandleValid( |
| 171 current_frame_->shared_memory_->handle())); |
| 172 return current_frame_->shared_memory_->memory(); |
| 173 } |
| 174 |
| 175 gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInPixels() const { |
| 176 DCHECK(HasCurrentFrame()); |
| 177 return current_frame_->frame_size_pixels_; |
| 178 } |
| 179 |
| 180 gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInDIP() const { |
| 181 DCHECK(HasCurrentFrame()); |
| 182 return current_frame_->frame_size_dip_; |
| 183 } |
| 184 |
| 185 void SoftwareFrameManager::EvictCurrentFrame() { |
| 186 DCHECK(HasCurrentFrame()); |
| 187 DiscardCurrentFrame(); |
| 188 if (client_) |
| 189 client_->ReleaseReferencesToSoftwareFrame(); |
| 190 } |
| 191 |
| 192 //////////////////////////////////////////////////////////////////////////////// |
| 193 // SoftwareFrameMemoryManager |
| 194 |
| 195 SoftwareFrameMemoryManager* SoftwareFrameMemoryManager::GetInstance() { |
| 196 return Singleton<SoftwareFrameMemoryManager>::get(); |
| 197 } |
| 198 |
| 199 void SoftwareFrameMemoryManager::AddFrame(SoftwareFrameManager* frame, |
| 200 bool visible) { |
| 201 RemoveFrame(frame); |
| 202 if (visible) |
| 203 visible_frames_.insert(frame); |
| 204 else |
| 205 hidden_frames_.push_front(frame); |
| 206 CullHiddenFrames(); |
| 207 } |
| 208 |
| 209 void SoftwareFrameMemoryManager::RemoveFrame(SoftwareFrameManager* frame) { |
| 210 visible_frames_.erase(frame); |
| 211 hidden_frames_.remove(frame); |
| 212 } |
| 213 |
| 214 void SoftwareFrameMemoryManager::SetFrameVisibility(SoftwareFrameManager* frame, |
| 215 bool visible) { |
| 216 if (visible) { |
| 217 hidden_frames_.remove(frame); |
| 218 visible_frames_.insert(frame); |
| 219 } else { |
| 220 visible_frames_.erase(frame); |
| 221 hidden_frames_.push_front(frame); |
| 222 CullHiddenFrames(); |
| 223 } |
| 224 } |
| 225 |
| 226 SoftwareFrameMemoryManager::SoftwareFrameMemoryManager() |
| 227 : max_number_of_saved_frames_( |
| 228 std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256))) {} |
| 229 |
| 230 SoftwareFrameMemoryManager::~SoftwareFrameMemoryManager() {} |
| 231 |
| 232 void SoftwareFrameMemoryManager::CullHiddenFrames() { |
| 233 while (!hidden_frames_.empty() && |
| 234 hidden_frames_.size() + visible_frames_.size() > |
| 235 max_number_of_saved_frames()) { |
| 236 size_t old_size = hidden_frames_.size(); |
| 237 // Should remove self from list. |
| 238 hidden_frames_.back()->EvictCurrentFrame(); |
| 239 DCHECK_EQ(hidden_frames_.size() + 1, old_size); |
| 240 } |
| 241 } |
| 242 |
| 243 } // namespace content |
OLD | NEW |