Bug 1274284 - Make snapshotting using widget layers work in the child process. r?nical,mattwoodrow
This patch moves the snapshot ipc code from PCompositorBridge to PLayerTransaction,
so that the parent side receiving the request can grab the correct
PCompositorBridgeParent instance. Otherwise in the case of cross-process
communication the request arrives in the CrossProcessCompositorBridgeParent,
from which is it is not easy to get a hold of the corresponding CompositorBridgeParent.
That, combined with removing various XRE_IsParentProcess checks, seems to be
sufficient to make snapshotting using widget layers work in e10s child processes.
MozReview-Commit-ID: 6uLNV1dn16j
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -237,21 +237,18 @@ ClientLayerManager::BeginTransactionWith
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_UIKIT)
if (mWidget && mWidget->GetOwningTabChild()) {
mCompositorMightResample = AsyncPanZoomEnabled();
}
#endif
// If we have a non-default target, we need to let our shadow manager draw
// to it. This will happen at the end of the transaction.
- if (aTarget && XRE_IsParentProcess()) {
+ if (aTarget) {
mShadowTarget = aTarget;
- } else {
- NS_ASSERTION(!aTarget,
- "Content-process ClientLayerManager::BeginTransactionWithTarget not supported");
}
// If this is a new paint, increment the paint sequence number.
if (!mIsRepeatTransaction) {
// Increment the paint sequence number even if test logging isn't
// enabled in this process; it may be enabled in the parent process,
// and the parent process expects unique sequence numbers.
++mPaintSequenceNumber;
@@ -511,17 +508,17 @@ ClientLayerManager::RunOverfillCallback(
void
ClientLayerManager::MakeSnapshotIfRequired()
{
if (!mShadowTarget) {
return;
}
if (mWidget) {
- if (CompositorBridgeChild* remoteRenderer = GetRemoteRenderer()) {
+ if (mForwarder->HasShadowManager()) {
// The compositor doesn't draw to a different sized surface
// when there's a rotation. Instead we rotate the result
// when drawing into dt
LayoutDeviceIntRect outerBounds;
mWidget->GetBounds(outerBounds);
IntRect bounds = ToOutsideIntRect(mShadowTarget->GetClipExtents());
if (mTargetRotation) {
@@ -534,17 +531,17 @@ ClientLayerManager::MakeSnapshotIfRequir
mForwarder->AllocSurfaceDescriptor(bounds.Size(),
gfxContentType::COLOR_ALPHA,
&inSnapshot)) {
// Make a copy of |inSnapshot| because the call to send it over IPC
// will call forget() on the Shmem inside, and zero it out.
SurfaceDescriptor outSnapshot = inSnapshot;
- if (remoteRenderer->SendMakeSnapshot(inSnapshot, bounds)) {
+ if (mForwarder->GetShadowManager()->SendMakeSnapshot(inSnapshot, bounds)) {
RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(outSnapshot);
DrawTarget* dt = mShadowTarget->GetDrawTarget();
Rect dstRect(bounds.x, bounds.y, bounds.width, bounds.height);
Rect srcRect(0, 0, bounds.width, bounds.height);
gfx::Matrix rotate =
ComputeTransformForUnRotation(outerBounds.ToUnknownRect(),
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -664,26 +664,16 @@ CompositorBridgeChild::SendAdoptChild(co
MOZ_ASSERT(mCanSend);
if (!mCanSend) {
return true;
}
return PCompositorBridgeChild::SendAdoptChild(id);
}
bool
-CompositorBridgeChild::SendMakeSnapshot(const SurfaceDescriptor& inSnapshot, const gfx::IntRect& dirtyRect)
-{
- MOZ_ASSERT(mCanSend);
- if (!mCanSend) {
- return true;
- }
- return PCompositorBridgeChild::SendMakeSnapshot(inSnapshot, dirtyRect);
-}
-
-bool
CompositorBridgeChild::SendFlushRendering()
{
MOZ_ASSERT(mCanSend);
if (!mCanSend) {
return true;
}
return PCompositorBridgeChild::SendFlushRendering();
}
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -121,17 +121,16 @@ public:
// you won't get the extra safety provided here.
bool SendWillClose();
bool SendPause();
bool SendResume();
bool SendNotifyHidden(const uint64_t& id);
bool SendNotifyVisible(const uint64_t& id);
bool SendNotifyChildCreated(const uint64_t& id);
bool SendAdoptChild(const uint64_t& id);
- bool SendMakeSnapshot(const SurfaceDescriptor& inSnapshot, const gfx::IntRect& dirtyRect);
bool SendFlushRendering();
bool SendGetTileSize(int32_t* tileWidth, int32_t* tileHeight);
bool SendStartFrameTimeRecording(const int32_t& bufferSize, uint32_t* startIndex);
bool SendStopFrameTimeRecording(const uint32_t& startIndex, nsTArray<float>* intervals);
bool SendNotifyRegionInvalidated(const nsIntRegion& region);
bool SendRequestNotifyAfterRemotePaint();
bool SendClearVisibleRegions(uint64_t aLayersId, uint32_t aPresShellId);
bool SendUpdateVisibleRegion(VisibilityCounter aCounter,
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -716,18 +716,18 @@ CompositorBridgeParent::RecvPause()
bool
CompositorBridgeParent::RecvResume()
{
ResumeComposition();
return true;
}
bool
-CompositorBridgeParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
- const gfx::IntRect& aRect)
+CompositorBridgeParent::MakeSnapshot(const SurfaceDescriptor& aInSnapshot,
+ const gfx::IntRect& aRect)
{
RefPtr<DrawTarget> target = GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
MOZ_ASSERT(target);
if (!target) {
// We kill the content process rather than have it continue with an invalid
// snapshot, that may be too harsh and we could decide to return some sort
// of error to the child process and let it deal with it...
return false;
@@ -1835,19 +1835,16 @@ public:
virtual bool RecvRequestOverfill() override { return true; }
virtual bool RecvWillClose() override { return true; }
virtual bool RecvPause() override { return true; }
virtual bool RecvResume() override { return true; }
virtual bool RecvNotifyHidden(const uint64_t& id) override;
virtual bool RecvNotifyVisible(const uint64_t& id) override;
virtual bool RecvNotifyChildCreated(const uint64_t& child) override;
virtual bool RecvAdoptChild(const uint64_t& child) override { return false; }
- virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
- const gfx::IntRect& aRect) override
- { return true; }
virtual bool RecvFlushRendering() override { return true; }
virtual bool RecvForcePresent() override { return true; }
virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override { return true; }
virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override { return true; }
virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) override { return true; }
virtual bool RecvClearVisibleRegions(const uint64_t& aLayersId,
const uint32_t& aPresShellId) override
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -220,18 +220,20 @@ public:
virtual bool RecvRequestOverfill() override;
virtual bool RecvWillClose() override;
virtual bool RecvPause() override;
virtual bool RecvResume() override;
virtual bool RecvNotifyHidden(const uint64_t& id) override { return true; }
virtual bool RecvNotifyVisible(const uint64_t& id) override { return true; }
virtual bool RecvNotifyChildCreated(const uint64_t& child) override;
virtual bool RecvAdoptChild(const uint64_t& child) override;
- virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
- const gfx::IntRect& aRect) override;
+
+ bool MakeSnapshot(const SurfaceDescriptor& aInSnapshot,
+ const gfx::IntRect& aRect);
+
virtual bool RecvFlushRendering() override;
virtual bool RecvForcePresent() override;
virtual bool RecvAcknowledgeCompositorUpdate(const uint64_t& aLayersId) override {
MOZ_ASSERT_UNREACHABLE("This message is only sent cross-process");
return true;
}
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -998,16 +998,24 @@ LayerTransactionParent::RecvChildAsyncMe
default:
NS_ERROR("unknown AsyncChildMessageData type");
return false;
}
}
return true;
}
+bool
+LayerTransactionParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
+ const gfx::IntRect& aRect)
+{
+ CompositorBridgeParent* compositor = CompositorBridgeParent::GetCompositor(GetId());
+ return compositor ? compositor->MakeSnapshot(aInSnapshot, aRect) : false;
+}
+
void
LayerTransactionParent::ActorDestroy(ActorDestroyReason why)
{
}
bool
LayerTransactionParent::AllocShmem(size_t aSize,
ipc::SharedMemory::SharedMemoryType aType,
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -157,16 +157,19 @@ protected:
virtual bool DeallocPLayerParent(PLayerParent* actor) override;
virtual PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo) override;
virtual bool DeallocPCompositableParent(PCompositableParent* actor) override;
virtual bool
RecvChildAsyncMessages(InfallibleTArray<AsyncChildMessageData>&& aMessages) override;
+ virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
+ const gfx::IntRect& aRect) override;
+
virtual void ActorDestroy(ActorDestroyReason why) override;
bool Attach(ShadowLayerParent* aLayerParent,
CompositableHost* aCompositable,
bool aIsAsyncVideo);
void AddIPDLReference() {
MOZ_ASSERT(mIPCOpen == false);
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -130,25 +130,16 @@ parent:
// The child layer tree is visible. id is the layers id of the child
// layer tree.
async NotifyVisible(uint64_t id);
async NotifyChildCreated(uint64_t id);
async AdoptChild(uint64_t id);
- // Make a snapshot of the content that would have been drawn to our
- // render target at the time this message is received. If the size
- // or format of |inSnapshot| doesn't match our render target,
- // results are undefined.
- //
- // NB: this message will result in animations, transforms, effects,
- // and so forth being interpolated. That's what we want to happen.
- sync MakeSnapshot(SurfaceDescriptor inSnapshot, IntRect dirtyRect);
-
// Make sure any pending composites are started immediately and
// block until they are completed.
sync FlushRendering();
// Force an additional frame presentation to be executed. This is used to
// work around a windows presentation bug (See Bug 1232042)
async ForcePresent();
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -117,14 +117,23 @@ parent:
// input event.
async SetConfirmedTargetAPZC(uint64_t aInputBlockId, ScrollableLayerGuid[] aTargets);
async ChildAsyncMessages(AsyncChildMessageData[] aMessages);
async Shutdown();
sync SyncWithCompositor();
+
+ // Make a snapshot of the content that would have been drawn to our
+ // render target at the time this message is received. If the size
+ // or format of |inSnapshot| doesn't match our render target,
+ // results are undefined.
+ //
+ // NB: this message will result in animations, transforms, effects,
+ // and so forth being interpolated. That's what we want to happen.
+ sync MakeSnapshot(SurfaceDescriptor inSnapshot, IntRect dirtyRect);
child:
async __delete__();
};
} // namespace layers
} // namespace mozilla
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -4816,21 +4816,17 @@ PresShell::RenderDocument(const nsRect&
flags |= PaintFrameFlags::PAINT_SYNC_DECODE_IMAGES;
}
if (aFlags & RENDER_USE_WIDGET_LAYERS) {
// We only support using widget layers on display root's with widgets.
nsView* view = rootFrame->GetView();
if (view && view->GetWidget() &&
nsLayoutUtils::GetDisplayRootFrame(rootFrame) == rootFrame) {
LayerManager* layerManager = view->GetWidget()->GetLayerManager();
- // ClientLayerManagers in content processes don't support
- // taking snapshots.
- if (layerManager &&
- (!layerManager->AsClientLayerManager() ||
- XRE_IsParentProcess())) {
+ if (layerManager) {
flags |= PaintFrameFlags::PAINT_WIDGET_LAYERS;
}
}
}
if (!(aFlags & RENDER_CARET)) {
wouldFlushRetainedLayers = true;
flags |= PaintFrameFlags::PAINT_HIDE_CARET;
}