Index: content/browser/renderer_host/software_framebuffer.cc |
diff --git a/content/browser/renderer_host/software_framebuffer.cc b/content/browser/renderer_host/software_framebuffer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3101da74b49ef79880bac16d4801cfbff331a0a2 |
--- /dev/null |
+++ b/content/browser/renderer_host/software_framebuffer.cc |
@@ -0,0 +1,188 @@ |
+// Copyright (c) 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 "software_framebuffer.h" |
+ |
+#include "cc/output/compositor_frame_ack.h" |
+#include "content/browser/renderer_host/dip_util.h" |
+#include "content/browser/renderer_host/frame_memory_manager.h" |
+#include "content/public/browser/render_process_host.h" |
+ |
+namespace content { |
+ |
+class MemoryHolder : public base::RefCounted<MemoryHolder> { |
+ public: |
+ MemoryHolder(scoped_ptr<base::SharedMemory> shared_memory, |
+ gfx::Size frame_size, |
+ float frame_scale_factor, |
+ base::Callback<void()> callback) |
+ : shared_memory_(shared_memory.Pass()), |
+ frame_size_(frame_size), |
+ frame_scale_factor_(frame_scale_factor), |
+ callback_(callback) {} |
+ |
+ void GetMailbox(cc::TextureMailbox* mailbox, |
+ scoped_ptr<cc::SingleReleaseCallback>* release_callback) { |
+ *mailbox = cc::TextureMailbox(shared_memory_.get(), frame_size_); |
+ *release_callback = cc::SingleReleaseCallback::Create( |
+ base::Bind(ReleaseMailbox, make_scoped_refptr(this))); |
+ } |
+ const gfx::Size& GetSizeInPixels() const { return frame_size_; } |
+ float GetScaleFactor() const { return frame_scale_factor_; } |
+ const void* GetPixels() const { return shared_memory_->memory(); } |
+ |
+ private: |
+ friend class base::RefCounted<MemoryHolder>; |
+ ~MemoryHolder() { callback_.Run(); } |
+ |
+ static void ReleaseMailbox(scoped_refptr<MemoryHolder> holder, |
+ unsigned sync_point, |
+ bool lost_resource) {} |
+ |
+ scoped_ptr<base::SharedMemory> shared_memory_; |
+ gfx::Size frame_size_; |
+ float frame_scale_factor_; |
+ base::Callback<void()> callback_; |
+}; |
+ |
+SoftwareFramebuffer::SoftwareFramebuffer( |
+ SoftwareFramebufferClient* client, |
+ RenderWidgetHostImpl* render_widget_host_impl) |
+ : client_(client), render_widget_host_impl_(render_widget_host_impl) {} |
+ |
+SoftwareFramebuffer::~SoftwareFramebuffer() { |
+ client_ = NULL; |
+ render_widget_host_impl_ = NULL; |
+ DiscardCurrentFrame(); |
+} |
+ |
+void SoftwareFramebuffer::WasShown() { |
+ if (framebuffer_holder_) |
+ FrameMemoryManager::GetInstance()->SetFrameVisibility(this, true); |
+} |
+ |
+void SoftwareFramebuffer::WasHidden() { |
+ if (framebuffer_holder_) |
+ FrameMemoryManager::GetInstance()->SetFrameVisibility(this, false); |
+} |
+ |
+void SoftwareFramebuffer::DiscardCurrentFrame() { |
+ FrameMemoryManager::GetInstance()->RemoveFrame(this); |
+ framebuffer_holder_ = NULL; |
+} |
+ |
+void SoftwareFramebuffer::GetCurrentFrameMailbox( |
+ cc::TextureMailbox* mailbox, |
+ scoped_ptr<cc::SingleReleaseCallback>* release_callback) const { |
+ DCHECK(framebuffer_holder_); |
+ return framebuffer_holder_->GetMailbox(mailbox, |
+ release_callback); |
+} |
+ |
+gfx::Size SoftwareFramebuffer::GetCurrentFrameSizeInPixels() const { |
+ DCHECK(framebuffer_holder_); |
+ return framebuffer_holder_->GetSizeInPixels(); |
+} |
+ |
+gfx::Size SoftwareFramebuffer::GetCurrentFrameSizeInDIP() const { |
+ DCHECK(framebuffer_holder_); |
+ return ConvertSizeToDIP(framebuffer_holder_->GetScaleFactor(), |
+ framebuffer_holder_->GetSizeInPixels()); |
+} |
+ |
+const void* SoftwareFramebuffer::GetCurrentFramePixels() const { |
+ DCHECK(framebuffer_holder_); |
+ return framebuffer_holder_->GetPixels(); |
+} |
+ |
+void SoftwareFramebuffer::SwapToNewFrame( |
+ uint32 output_surface_id, |
+ const cc::SoftwareFrameData* frame_data, |
+ float frame_scale_factor) { |
+ const gfx::Size& frame_size = frame_data->size; |
+ const size_t size_in_bytes = 4 * frame_size.GetArea(); |
+ |
+#ifdef OS_WIN |
+ scoped_ptr<base::SharedMemory> shared_memory( |
+ new base::SharedMemory(frame_data->handle, true, |
+ render_widget_host_impl_->GetProcess()->GetHandle())); |
+#else |
+ scoped_ptr<base::SharedMemory> shared_memory( |
+ new base::SharedMemory(frame_data->handle, true)); |
+#endif |
+ |
+ if (!shared_memory->Map(size_in_bytes)) { |
+ render_widget_host_impl_->GetProcess()->ReceivedBadMessage(); |
+ framebuffer_holder_ = NULL; |
+ return; |
+ } |
+ |
+ scoped_refptr<MemoryHolder> holder(new MemoryHolder( |
+ shared_memory.Pass(), |
+ frame_size, |
+ frame_scale_factor, |
+ base::Bind(&SoftwareFramebuffer::ReleaseSoftwareFrame, |
+ AsWeakPtr(), |
+ output_surface_id, |
+ frame_data->id))); |
+ framebuffer_holder_.swap(holder); |
+ |
+ FrameMemoryManager::GetInstance()->AddFrame( |
+ this, !render_widget_host_impl_->is_hidden()); |
+} |
+ |
+void SoftwareFramebuffer::SendSoftwareFrameAck(uint32 output_surface_id) { |
+ unsigned software_frame_id = 0; |
+ if (!released_software_frames_.empty()) { |
+ unsigned released_output_surface_id = |
+ released_software_frames_.back().output_surface_id; |
+ if (released_output_surface_id == output_surface_id) { |
+ software_frame_id = released_software_frames_.back().frame_id; |
+ released_software_frames_.pop_back(); |
+ } |
+ } |
+ |
+ cc::CompositorFrameAck ack; |
+ ack.last_software_frame_id = software_frame_id; |
+ if (render_widget_host_impl_) { |
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck( |
piman
2013/10/08 02:58:38
I would really prefer if the message sending logic
ccameron
2013/10/22 07:15:55
I did essentially this in the new version. The cal
|
+ render_widget_host_impl_->GetRoutingID(), output_surface_id, |
+ render_widget_host_impl_->GetProcess()->GetID(), ack); |
+ } |
+ SendReclaimSoftwareFrames(); |
+} |
+ |
+void SoftwareFramebuffer::SendReclaimSoftwareFrames() { |
+ while (!released_software_frames_.empty()) { |
+ cc::CompositorFrameAck ack; |
+ ack.last_software_frame_id = released_software_frames_.back().frame_id; |
+ if (render_widget_host_impl_) { |
+ RenderWidgetHostImpl::SendReclaimCompositorResources( |
+ render_widget_host_impl_->GetRoutingID(), |
+ released_software_frames_.back().output_surface_id, |
+ render_widget_host_impl_->GetProcess()->GetID(), |
+ ack); |
+ } |
+ released_software_frames_.pop_back(); |
+ } |
+} |
+ |
+void SoftwareFramebuffer::ReleaseSoftwareFrame( |
+ uint32 output_surface_id, |
+ unsigned software_frame_id) { |
+ SendReclaimSoftwareFrames(); |
+ released_software_frames_.push_back( |
+ ReleasedFrameInfo(output_surface_id, software_frame_id)); |
+} |
+ |
+void SoftwareFramebuffer::ReleaseCurrentFrame() { |
+ DCHECK(framebuffer_holder_); |
+ |
+ DiscardCurrentFrame(); |
+ |
+ if (client_) |
+ client_->CurrentSoftwareFrameWasDiscarded(); |
+} |
+ |
+} // namespace content |