Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(248)

Unified Diff: content/browser/frame_host/render_widget_host_view_child_frame.cc

Issue 1094113003: Allow out-of-process iframes to render to compositing surfaces. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Destroy Surface when resetting id Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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) {

Powered by Google App Engine
This is Rietveld 408576698