Bug 1274284 - Make snapshotting using widget layers work in the child process. r?nical,mattwoodrow draft
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 19 May 2016 11:35:09 -0400
changeset 368743 ce630b52c438c7a775da97d4b268278ee6cec1c1
parent 368742 af7d3ba0f08147c86c4469b8d32cc8d2f9f6ce79
child 368744 733746a64122ceb1e92aa25d52838262b3d0794a
push id18650
push userkgupta@mozilla.com
push dateThu, 19 May 2016 15:35:43 +0000
reviewersnical, mattwoodrow
bugs1274284
milestone49.0a1
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
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/ipc/CompositorBridgeChild.cpp
gfx/layers/ipc/CompositorBridgeChild.h
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CompositorBridgeParent.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/PCompositorBridge.ipdl
gfx/layers/ipc/PLayerTransaction.ipdl
layout/base/nsPresShell.cpp
--- 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;
   }