Allow out-of-process iframes to render to compositing surfaces.
When compositing surfaces are enabled, the browser process upon
receiving a frame from an OOPIF will pass a surface identifier to the
embedding renderer process rather than the frame itself. This prevents
frames from having to be composited at an arbitrary number of levels
when OOPIFs are chained.
BUG=478802
TEST=RenderWidgetHostViewChildFrameTest.SwapCompositorFrame
Review URL: https://codereview.chromium.org/1094113003
Cr-Commit-Position: refs/heads/master@{#332060}
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc
index 550152b..de018b0 100644
--- a/content/renderer/child_frame_compositing_helper.cc
+++ b/content/renderer/child_frame_compositing_helper.cc
@@ -9,6 +9,7 @@
#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/layers/delegated_renderer_layer.h"
#include "cc/layers/solid_color_layer.h"
+#include "cc/layers/surface_layer.h"
#include "cc/output/context_provider.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
@@ -34,7 +35,8 @@
ChildFrameCompositingHelper::CreateForBrowserPlugin(
const base::WeakPtr<BrowserPlugin>& browser_plugin) {
return new ChildFrameCompositingHelper(
- browser_plugin, NULL, NULL, browser_plugin->render_frame_routing_id());
+ browser_plugin, nullptr, nullptr,
+ browser_plugin->render_frame_routing_id());
}
ChildFrameCompositingHelper*
@@ -59,23 +61,25 @@
opaque_(true),
browser_plugin_(browser_plugin),
render_frame_proxy_(render_frame_proxy),
- frame_(frame) {}
+ frame_(frame),
+ weak_factory_(this) {
+}
ChildFrameCompositingHelper::~ChildFrameCompositingHelper() {
if (resource_collection_.get())
- resource_collection_->SetClient(NULL);
+ resource_collection_->SetClient(nullptr);
}
BrowserPluginManager* ChildFrameCompositingHelper::GetBrowserPluginManager() {
if (!browser_plugin_)
- return NULL;
+ return nullptr;
return BrowserPluginManager::Get();
}
blink::WebPluginContainer* ChildFrameCompositingHelper::GetContainer() {
if (!browser_plugin_)
- return NULL;
+ return nullptr;
return browser_plugin_->container();
}
@@ -142,9 +146,9 @@
}
if (GetContainer()) {
- GetContainer()->setWebLayer(enable ? web_layer_.get() : NULL);
+ GetContainer()->setWebLayer(enable ? web_layer_.get() : nullptr);
} else if (frame_) {
- frame_->setRemoteWebLayer(enable ? web_layer_.get() : NULL);
+ frame_->setRemoteWebLayer(enable ? web_layer_.get() : nullptr);
}
}
@@ -173,16 +177,17 @@
DidCommitCompositorFrame();
if (GetContainer())
- GetContainer()->setWebLayer(NULL);
+ GetContainer()->setWebLayer(nullptr);
if (resource_collection_.get())
- resource_collection_->SetClient(NULL);
+ resource_collection_->SetClient(nullptr);
ack_pending_ = false;
- resource_collection_ = NULL;
- frame_provider_ = NULL;
- delegated_layer_ = NULL;
- background_layer_ = NULL;
+ resource_collection_ = nullptr;
+ frame_provider_ = nullptr;
+ delegated_layer_ = nullptr;
+ background_layer_ = nullptr;
+ surface_layer_ = nullptr;
web_layer_.reset();
}
@@ -200,6 +205,11 @@
int host_id,
base::SharedMemoryHandle handle) {
cc::DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
+
+ // Surface IDs and compositor frames should never be received
+ // interchangeably.
+ DCHECK(!surface_layer_.get());
+
// Do nothing if we are getting destroyed or have no frame data.
if (!frame_data || !background_layer_.get())
return;
@@ -217,16 +227,16 @@
// case we should recreate the DelegatedRendererLayer, to avoid matching
// resources from the old one with resources from the new one which would
// have the same id.
- frame_provider_ = NULL;
+ frame_provider_ = nullptr;
// Drop the cc::DelegatedFrameResourceCollection so that we will not return
// any resources from the old output surface with the new output surface id.
if (resource_collection_.get()) {
- resource_collection_->SetClient(NULL);
+ resource_collection_->SetClient(nullptr);
if (resource_collection_->LoseAllResources())
SendReturnedDelegatedResources();
- resource_collection_ = NULL;
+ resource_collection_ = nullptr;
}
last_output_surface_id_ = output_surface_id;
last_route_id_ = route_id;
@@ -259,9 +269,68 @@
ack_pending_ = true;
}
+// static
+void ChildFrameCompositingHelper::SatisfyCallback(
+ base::WeakPtr<ChildFrameCompositingHelper> helper,
+ cc::SurfaceSequence sequence) {
+ if (helper && helper->render_frame_proxy_) {
+ helper->render_frame_proxy_->Send(
+ new FrameHostMsg_SatisfySequence(helper->host_routing_id_, sequence));
+ }
+}
+
+// static
+void ChildFrameCompositingHelper::RequireCallback(
+ base::WeakPtr<ChildFrameCompositingHelper> helper,
+ cc::SurfaceId id,
+ cc::SurfaceSequence sequence) {
+ if (helper && helper->render_frame_proxy_) {
+ helper->render_frame_proxy_->Send(new FrameHostMsg_RequireSequence(
+ helper->host_routing_id_, id, sequence));
+ }
+}
+
+void ChildFrameCompositingHelper::OnSetSurface(
+ const cc::SurfaceId& surface_id,
+ const gfx::Size& frame_size,
+ float scale_factor,
+ const cc::SurfaceSequence& sequence) {
+ // Surface IDs and compositor frames should never be received
+ // interchangably.
+ DCHECK(!delegated_layer_.get());
+
+ // Do nothing if we are getting destroyed.
+ if (!background_layer_.get())
+ return;
+
+ if (!surface_layer_.get()) {
+ cc::SurfaceLayer::SatisfyCallback satisfy_callback =
+ base::Bind(&ChildFrameCompositingHelper::SatisfyCallback, GetWeakPtr());
+ cc::SurfaceLayer::RequireCallback require_callback =
+ base::Bind(&ChildFrameCompositingHelper::RequireCallback, GetWeakPtr());
+ surface_layer_ =
+ cc::SurfaceLayer::Create(cc_blink::WebLayerImpl::LayerSettings(),
+ satisfy_callback, require_callback);
+ }
+ surface_layer_->SetSurfaceId(surface_id, scale_factor, frame_size);
+ UpdateVisibility(true);
+ SetContentsOpaque(opaque_);
+ background_layer_->AddChild(surface_layer_);
+
+ // The RWHV creates a destruction dependency on the surface that needs to be
+ // satisfied.
+ render_frame_proxy_->Send(
+ new FrameHostMsg_SatisfySequence(host_routing_id_, sequence));
+
+ CheckSizeAndAdjustLayerProperties(frame_size, scale_factor,
+ surface_layer_.get());
+}
+
void ChildFrameCompositingHelper::UpdateVisibility(bool visible) {
if (delegated_layer_.get())
delegated_layer_->SetIsDrawable(visible);
+ if (surface_layer_.get())
+ surface_layer_->SetIsDrawable(visible);
}
void ChildFrameCompositingHelper::UnusedResourcesAreAvailable() {
@@ -288,6 +357,8 @@
opaque_ = opaque;
if (delegated_layer_.get())
delegated_layer_->SetContentsOpaque(opaque_);
+ if (surface_layer_.get())
+ surface_layer_->SetContentsOpaque(opaque_);
}
} // namespace content
diff --git a/content/renderer/child_frame_compositing_helper.h b/content/renderer/child_frame_compositing_helper.h
index 0700d9cc..dd822c0 100644
--- a/content/renderer/child_frame_compositing_helper.h
+++ b/content/renderer/child_frame_compositing_helper.h
@@ -20,9 +20,13 @@
}
namespace cc {
+struct SurfaceId;
+struct SurfaceSequence;
+
class CompositorFrame;
class Layer;
class SolidColorLayer;
+class SurfaceLayer;
class DelegatedFrameProvider;
class DelegatedFrameResourceCollection;
class DelegatedRendererLayer;
@@ -66,6 +70,10 @@
uint32 output_surface_id,
int host_id,
base::SharedMemoryHandle handle);
+ void OnSetSurface(const cc::SurfaceId& surface_id,
+ const gfx::Size& frame_size,
+ float scale_factor,
+ const cc::SurfaceSequence& sequence);
void UpdateVisibility(bool);
void ChildFrameGone();
@@ -98,6 +106,15 @@
float device_scale_factor,
cc::Layer* layer);
void SendReturnedDelegatedResources();
+ static void SatisfyCallback(base::WeakPtr<ChildFrameCompositingHelper> helper,
+ cc::SurfaceSequence sequence);
+ static void RequireCallback(base::WeakPtr<ChildFrameCompositingHelper> helper,
+ cc::SurfaceId id,
+ cc::SurfaceSequence sequence);
+
+ base::WeakPtr<ChildFrameCompositingHelper> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
int host_routing_id_;
int last_route_id_;
@@ -117,11 +134,16 @@
scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_;
scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
+ // For cc::Surface support.
+ scoped_refptr<cc::SurfaceLayer> surface_layer_;
+
scoped_refptr<cc::SolidColorLayer> background_layer_;
scoped_refptr<cc::DelegatedRendererLayer> delegated_layer_;
scoped_ptr<blink::WebLayer> web_layer_;
blink::WebFrame* frame_;
+ base::WeakPtrFactory<ChildFrameCompositingHelper> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ChildFrameCompositingHelper);
};
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index 68c405b..fe8d066 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -205,6 +205,7 @@
IPC_MESSAGE_HANDLER(FrameMsg_ChildFrameProcessGone, OnChildFrameProcessGone)
IPC_MESSAGE_HANDLER_GENERIC(FrameMsg_CompositorFrameSwapped,
OnCompositorFrameSwapped(msg))
+ IPC_MESSAGE_HANDLER(FrameMsg_SetChildFrameSurface, OnSetChildFrameSurface)
IPC_MESSAGE_HANDLER(FrameMsg_DisownOpener, OnDisownOpener)
IPC_MESSAGE_HANDLER(FrameMsg_DidStartLoading, OnDidStartLoading)
IPC_MESSAGE_HANDLER(FrameMsg_DidStopLoading, OnDidStopLoading)
@@ -261,6 +262,27 @@
base::get<0>(param).shared_memory_handle);
}
+void RenderFrameProxy::OnSetChildFrameSurface(
+ const cc::SurfaceId& surface_id,
+ const gfx::Size& frame_size,
+ float scale_factor,
+ const cc::SurfaceSequence& sequence) {
+ // If this WebFrame has already been detached, its parent will be null. This
+ // can happen when swapping a WebRemoteFrame with a WebLocalFrame, where this
+ // message may arrive after the frame was removed from the frame tree, but
+ // before the frame has been destroyed. http://crbug.com/446575.
+ if (!web_frame()->parent())
+ return;
+
+ if (!compositing_helper_.get()) {
+ compositing_helper_ =
+ ChildFrameCompositingHelper::CreateForRenderFrameProxy(this);
+ compositing_helper_->EnableCompositing(true);
+ }
+ compositing_helper_->OnSetSurface(surface_id, frame_size, scale_factor,
+ sequence);
+}
+
void RenderFrameProxy::OnDisownOpener() {
// TODO(creis): We should only see this for main frames for now. To support
// disowning the opener on subframes, we will need to move WebContentsImpl's
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h
index 65ad70fa..b2ac60f 100644
--- a/content/renderer/render_frame_proxy.h
+++ b/content/renderer/render_frame_proxy.h
@@ -21,6 +21,11 @@
class WebInputEvent;
}
+namespace cc {
+struct SurfaceId;
+struct SurfaceSequence;
+}
+
namespace content {
class ChildFrameCompositingHelper;
@@ -140,6 +145,10 @@
void OnDeleteProxy();
void OnChildFrameProcessGone();
void OnCompositorFrameSwapped(const IPC::Message& message);
+ void OnSetChildFrameSurface(const cc::SurfaceId& surface_id,
+ const gfx::Size& frame_size,
+ float scale_factor,
+ const cc::SurfaceSequence& sequence);
void OnDisownOpener();
void OnDidStopLoading();
void OnDidUpdateSandboxFlags(blink::WebSandboxFlags flags);