Chromium Code Reviews| Index: content/browser/frame_host/render_widget_host_view_child_frame.cc |
| diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc |
| index b8fdb0193d5800ad2867f95a5c1dc74014bf1828..48423c32b2945c4df8ca83d7b281f68b6e0e6fc1 100644 |
| --- a/content/browser/frame_host/render_widget_host_view_child_frame.cc |
| +++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc |
| @@ -4,8 +4,13 @@ |
| #include "content/browser/frame_host/render_widget_host_view_child_frame.h" |
| +#include "cc/surfaces/surface.h" |
| +#include "cc/surfaces/surface_factory.h" |
| +#include "cc/surfaces/surface_manager.h" |
| +#include "cc/surfaces/surface_sequence.h" |
| #include "content/browser/accessibility/browser_accessibility_manager.h" |
| #include "content/browser/frame_host/cross_process_frame_connector.h" |
| +#include "content/browser/gpu/compositor_util.h" |
| #include "content/browser/renderer_host/render_widget_host_impl.h" |
| #include "content/common/gpu/gpu_messages.h" |
| #include "content/common/view_messages.h" |
| @@ -16,11 +21,25 @@ namespace content { |
| RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame( |
| RenderWidgetHost* widget_host) |
| : host_(RenderWidgetHostImpl::From(widget_host)), |
| + use_surfaces_(UseSurfacesEnabled()), |
| + next_surface_sequence_(1u), |
| + last_output_surface_id_(0), |
| + current_surface_scale_factor_(1.f), |
| + ack_pending_count_(0), |
| frame_connector_(NULL) { |
| +#if !defined(OS_ANDROID) |
| + if (use_surfaces_) { |
| + ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); |
| + id_allocator_ = factory->GetContextFactory()->CreateSurfaceIdAllocator(); |
| + } |
| +#endif // !defined(OS_ANDROID) |
| + |
| host_->SetView(this); |
| } |
| RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() { |
|
ncarter (slow)
2015/05/28 22:32:52
If there are still entries in surface_returned_res
kenrb
2015/05/29 19:29:36
John answered this separately, but yes: RWHVCF bei
|
| + if (!surface_id_.is_null()) |
| + surface_factory_->Destroy(surface_id_); |
| } |
| void RenderWidgetHostViewChildFrame::InitAsChild( |
| @@ -186,17 +205,89 @@ void RenderWidgetHostViewChildFrame::UnlockCompositingSurface() { |
| } |
| #endif |
| +void RenderWidgetHostViewChildFrame::SurfaceDrawn(uint32 output_surface_id, |
| + cc::SurfaceDrawStatus drawn) { |
| + cc::CompositorFrameAck ack; |
| + DCHECK(ack_pending_count_ > 0); |
| + if (!surface_returned_resources_.empty()) |
| + ack.resources.swap(surface_returned_resources_); |
| + if (host_) |
|
nasko
2015/05/28 20:42:36
nit: Two line body requires {}.
kenrb
2015/05/29 19:29:36
Done.
|
| + host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(), |
| + output_surface_id, ack)); |
| + ack_pending_count_--; |
| +} |
| + |
| void RenderWidgetHostViewChildFrame::OnSwapCompositorFrame( |
| uint32 output_surface_id, |
| scoped_ptr<cc::CompositorFrame> frame) { |
| last_scroll_offset_ = frame->metadata.root_scroll_offset; |
| - if (frame_connector_) { |
| + |
| + if (!frame_connector_) |
| + return; |
| + |
| + // When not using surfaces, the frame just gets proxied to |
| + // the embedder's renderer to be composited. |
| + if (!frame->delegated_frame_data || !use_surfaces_) { |
| frame_connector_->ChildFrameCompositorFrameSwapped( |
| output_surface_id, |
| host_->GetProcess()->GetID(), |
| host_->GetRoutingID(), |
| frame.Pass()); |
| + return; |
| + } |
| + |
| +#if !defined(OS_ANDROID) |
| + cc::RenderPass* root_pass = |
| + frame->delegated_frame_data->render_pass_list.back(); |
| + |
| + gfx::Size frame_size = root_pass->output_rect.size(); |
| + float scale_factor = frame->metadata.device_scale_factor; |
| + |
| + // Check whether we need to recreate the cc::Surface, which means the child |
| + // frame renderer has changed its output surface, or size, or scale factor. |
| + if (output_surface_id != last_output_surface_id_ && surface_factory_) { |
| + surface_factory_->Destroy(surface_id_); |
| + surface_factory_.reset(); |
|
ncarter (slow)
2015/05/28 22:32:52
Why do we need a new SurfaceFactory each time the
kenrb
2015/05/29 19:29:36
Answered.
|
| + } |
| + if (output_surface_id != last_output_surface_id_ || |
| + frame_size != current_surface_size_ || |
| + scale_factor != current_surface_scale_factor_) { |
| + if (surface_factory_ && !surface_id_.is_null()) |
| + surface_factory_->Destroy(surface_id_); |
| + surface_id_ = cc::SurfaceId(); |
| + last_output_surface_id_ = output_surface_id; |
| + current_surface_size_ = frame_size; |
| + current_surface_scale_factor_ = scale_factor; |
| } |
| + |
| + if (!surface_factory_) { |
| + ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); |
| + cc::SurfaceManager* manager = factory->GetSurfaceManager(); |
| + surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this)); |
| + } |
| + |
| + if (surface_id_.is_null()) { |
| + surface_id_ = id_allocator_->GenerateId(); |
| + surface_factory_->Create(surface_id_); |
| + |
| + ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); |
| + cc::SurfaceSequence sequence = cc::SurfaceSequence( |
| + id_allocator_->id_namespace(), next_surface_sequence_++); |
| + // The renderer will satisfy this dependency when it creates a |
|
nasko
2015/05/28 20:42:36
nit: s/renderer/renderer process/?
kenrb
2015/05/29 19:29:36
Done.
|
| + // SurfaceLayer. |
| + factory->GetSurfaceManager() |
| + ->GetSurfaceForId(surface_id_) |
| + ->AddDestructionDependency(sequence); |
| + frame_connector_->SetChildFrameSurface(surface_id_, frame_size, |
| + scale_factor, sequence); |
| + } |
| + |
| + cc::SurfaceFactory::DrawCallback ack_callback = |
| + base::Bind(&RenderWidgetHostViewChildFrame::SurfaceDrawn, AsWeakPtr(), |
| + output_surface_id); |
| + ack_pending_count_++; |
|
ncarter (slow)
2015/05/28 22:32:52
Could we dcheck some upper limit for ack_pending_c
kenrb
2015/05/29 19:29:36
That's a good idea. I don't really know what a saf
|
| + surface_factory_->SubmitFrame(surface_id_, frame.Pass(), ack_callback); |
| +#endif // !defined(OS_ANDROID) |
| } |
| void RenderWidgetHostViewChildFrame::GetScreenInfo( |
| @@ -223,9 +314,10 @@ void RenderWidgetHostViewChildFrame::UnlockMouse() { |
| } |
| uint32_t RenderWidgetHostViewChildFrame::GetSurfaceIdNamespace() { |
| - // TODO(kenrb): Create SurfaceFactory here when RWHVChildFrame |
| - // gets compositor surface support. |
| - return 0; |
| + if (!use_surfaces_) |
| + return 0; |
| + |
| + return id_allocator_->id_namespace(); |
| } |
| #if defined(OS_MACOSX) |
| @@ -301,6 +393,25 @@ gfx::NativeViewId RenderWidgetHostViewChildFrame::GetParentForWindowlessPlugin() |
| } |
| #endif // defined(OS_WIN) |
| +// cc::SurfaceFactoryClient implementation. |
| +void RenderWidgetHostViewChildFrame::ReturnResources( |
| + const cc::ReturnedResourceArray& resources) { |
| + if (resources.empty()) |
| + return; |
| + |
| + if (!ack_pending_count_ && host_) { |
| + cc::CompositorFrameAck ack; |
| + std::copy(resources.begin(), resources.end(), |
| + std::back_inserter(ack.resources)); |
| + host_->Send(new ViewMsg_ReclaimCompositorResources( |
| + host_->GetRoutingID(), last_output_surface_id_, ack)); |
| + return; |
| + } |
| + |
| + std::copy(resources.begin(), resources.end(), |
| + std::back_inserter(surface_returned_resources_)); |
| +} |
| + |
| BrowserAccessibilityManager* |
| RenderWidgetHostViewChildFrame::CreateBrowserAccessibilityManager( |
| BrowserAccessibilityDelegate* delegate) { |