Chromium Code Reviews| Index: content/browser/renderer_host/software_frame_manager.cc |
| diff --git a/content/browser/renderer_host/software_frame_manager.cc b/content/browser/renderer_host/software_frame_manager.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..78596f17fa713eab7d2700fda0011b4839be3ea5 |
| --- /dev/null |
| +++ b/content/browser/renderer_host/software_frame_manager.cc |
| @@ -0,0 +1,235 @@ |
| +// Copyright 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/renderer_host/software_frame_manager.h" |
| + |
| +#include <list> |
| +#include <set> |
| + |
| +#include "base/bind.h" |
| +#include "base/callback_helpers.h" |
| +#include "base/memory/singleton.h" |
| +#include "base/sys_info.h" |
| +#include "content/browser/renderer_host/dip_util.h" |
| + |
| +namespace { |
| + |
| +size_t MaxNumberOfSavedFrames() { |
| + return std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256)); |
| +} |
| + |
| +void ReleaseMailbox(scoped_refptr<content::SoftwareFrame> frame, |
| + unsigned sync_point, |
| + bool lost_resource) {} |
| + |
| +} // namespace |
| + |
| +namespace content { |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// SoftwareFrameMemoryManager |
| + |
| +class SoftwareFrameMemoryManager { |
| + public: |
| + static SoftwareFrameMemoryManager* GetInstance(); |
| + |
| + void AddFrame(SoftwareFrameManager*, bool visible); |
| + void RemoveFrame(SoftwareFrameManager*); |
| + void SetFrameVisibility(SoftwareFrameManager*, bool visible); |
| + |
| + private: |
| + SoftwareFrameMemoryManager(); |
| + ~SoftwareFrameMemoryManager(); |
| + void CullHiddenFrames(); |
| + friend struct DefaultSingletonTraits<SoftwareFrameMemoryManager>; |
| + |
| + std::set<SoftwareFrameManager*> visible_frames_; |
| + std::list<SoftwareFrameManager*> hidden_frames_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SoftwareFrameMemoryManager); |
| +}; |
| + |
| +SoftwareFrameMemoryManager* SoftwareFrameMemoryManager::GetInstance() { |
| + return Singleton<SoftwareFrameMemoryManager>::get(); |
| +} |
| + |
| +void SoftwareFrameMemoryManager::AddFrame(SoftwareFrameManager* frame, |
| + bool visible) { |
| + RemoveFrame(frame); |
| + if (visible) |
| + visible_frames_.insert(frame); |
| + else |
| + hidden_frames_.push_front(frame); |
| + CullHiddenFrames(); |
| +} |
| + |
| +void SoftwareFrameMemoryManager::RemoveFrame(SoftwareFrameManager* frame) { |
| + visible_frames_.erase(frame); |
| + hidden_frames_.remove(frame); |
| +} |
| + |
| +void SoftwareFrameMemoryManager::SetFrameVisibility(SoftwareFrameManager* frame, |
| + bool visible) { |
| + if (visible) { |
| + hidden_frames_.remove(frame); |
| + visible_frames_.insert(frame); |
| + } else { |
| + visible_frames_.erase(frame); |
| + hidden_frames_.push_front(frame); |
| + CullHiddenFrames(); |
| + } |
| +} |
| + |
| +SoftwareFrameMemoryManager::SoftwareFrameMemoryManager() {} |
| + |
| +SoftwareFrameMemoryManager::~SoftwareFrameMemoryManager() {} |
| + |
| +void SoftwareFrameMemoryManager::CullHiddenFrames() { |
| + while (!hidden_frames_.empty() && |
| + hidden_frames_.size() + visible_frames_.size() > |
| + MaxNumberOfSavedFrames()) { |
|
piman
2013/10/22 22:32:48
nit: MaxNumberOfSavedFrames() is a constant, right
ccameron
2013/10/23 01:05:58
Done.
|
| + size_t old_size = hidden_frames_.size(); |
| + // Should remove self from list. |
| + hidden_frames_.back()->EvictCurrentFrame(); |
| + DCHECK_EQ(hidden_frames_.size() + 1, old_size); |
| + } |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// SoftwareFrame |
| + |
| +class SoftwareFrame : public base::RefCounted<SoftwareFrame> { |
| + public: |
| + SoftwareFrame( |
| + base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client, |
| + uint32 output_surface_id, |
| + unsigned frame_id, |
| + gfx::Size frame_size_dip, |
| + gfx::Size frame_size_pixels, |
| + scoped_ptr<base::SharedMemory> shared_memory) |
| + : frame_manager_client_(frame_manager_client), |
| + output_surface_id_(output_surface_id), |
| + frame_id_(frame_id), |
| + frame_size_dip_(frame_size_dip), |
| + frame_size_pixels_(frame_size_pixels), |
| + shared_memory_(shared_memory.Pass()) {} |
| + |
| + void GetMailbox(cc::TextureMailbox* mailbox, |
| + scoped_ptr<cc::SingleReleaseCallback>* callback) { |
| + *mailbox = cc::TextureMailbox(shared_memory_.get(), frame_size_pixels_); |
| + *callback = cc::SingleReleaseCallback::Create( |
| + base::Bind(ReleaseMailbox, make_scoped_refptr(this))); |
| + } |
| + const void* GetPixels() const { return shared_memory_->memory(); } |
| + gfx::Size GetSizeInDIP() const { return frame_size_dip_; } |
| + gfx::Size GetSizeInPixels() const { return frame_size_pixels_; } |
| + |
| + private: |
| + friend class base::RefCounted<SoftwareFrame>; |
| + |
| + ~SoftwareFrame() { |
| + if (frame_manager_client_) { |
| + frame_manager_client_->SoftwareFrameWasFreed( |
| + output_surface_id_, frame_id_); |
| + } |
| + } |
| + |
| + base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client_; |
| + const uint32 output_surface_id_; |
| + const unsigned frame_id_; |
| + const gfx::Size frame_size_dip_; |
| + const gfx::Size frame_size_pixels_; |
| + scoped_ptr<base::SharedMemory> shared_memory_; |
| +}; |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// SoftwareFrameManager |
| + |
| +SoftwareFrameManager::SoftwareFrameManager( |
| + base::WeakPtr<SoftwareFrameManagerClient> client) |
| + : client_(client) {} |
| + |
| +SoftwareFrameManager::~SoftwareFrameManager() {} |
| + |
| +bool SoftwareFrameManager::SwapToNewFrame( |
| + uint32 output_surface_id, |
| + const cc::SoftwareFrameData* frame_data, |
| + float frame_device_scale_factor, |
| + base::ProcessHandle process_handle) { |
| + const size_t size_in_bytes = 4 * frame_data->size.GetArea(); |
| +#ifdef OS_WIN |
| + scoped_ptr<base::SharedMemory> shared_memory( |
| + new base::SharedMemory(frame_data->handle, true, process_handle)); |
| +#else |
| + scoped_ptr<base::SharedMemory> shared_memory( |
| + new base::SharedMemory(frame_data->handle, true)); |
| +#endif |
| + if (!shared_memory->Map(size_in_bytes)) { |
| + return false; |
| + } |
| + |
| + scoped_refptr<SoftwareFrame> next_frame(new SoftwareFrame( |
| + client_, |
| + output_surface_id, |
| + frame_data->id, |
| + ConvertSizeToDIP(frame_device_scale_factor, frame_data->size), |
| + frame_data->size, |
| + shared_memory.Pass())); |
| + current_frame_.swap(next_frame); |
| + return true; |
| +} |
| + |
| +bool SoftwareFrameManager::HasCurrentFrame() const { |
| + return current_frame_; |
| +} |
| + |
| +void SoftwareFrameManager::DiscardCurrentFrame() { |
| + if (!HasCurrentFrame()) |
| + return; |
| + current_frame_ = NULL; |
| + SoftwareFrameMemoryManager::GetInstance()->RemoveFrame(this); |
| +} |
| + |
| +void SoftwareFrameManager::SwapToNewFrameComplete(bool visible) { |
| + DCHECK(HasCurrentFrame()); |
| + SoftwareFrameMemoryManager::GetInstance()->AddFrame(this, visible); |
| +} |
| + |
| +void SoftwareFrameManager::SetVisibility(bool visible) { |
| + if (HasCurrentFrame()) { |
| + SoftwareFrameMemoryManager::GetInstance()->SetFrameVisibility(this, |
| + visible); |
| + } |
| +} |
| + |
| +void SoftwareFrameManager::GetCurrentFrameMailbox( |
| + cc::TextureMailbox* mailbox, |
| + scoped_ptr<cc::SingleReleaseCallback>* callback) { |
| + DCHECK(HasCurrentFrame()); |
| + current_frame_->GetMailbox(mailbox, callback); |
| +} |
| + |
| +const void* SoftwareFrameManager::GetCurrentFramePixels() const { |
| + DCHECK(HasCurrentFrame()); |
| + return current_frame_->GetPixels(); |
| +} |
| + |
| +gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInPixels() const { |
| + DCHECK(HasCurrentFrame()); |
| + return current_frame_->GetSizeInPixels(); |
| +} |
| + |
| +gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInDIP() const { |
| + DCHECK(HasCurrentFrame()); |
| + return current_frame_->GetSizeInDIP(); |
| +} |
| + |
| +void SoftwareFrameManager::EvictCurrentFrame() { |
| + DCHECK(HasCurrentFrame()); |
| + DiscardCurrentFrame(); |
| + if (client_) |
| + client_->CurrentSoftwareFrameWasEvicted(); |
| +} |
| + |
| +} // namespace content |