Track whether or not remote layers have acknowledged compositor changes. (bug 1256517 part 1, r=mattwoodrow)
authorDavid Anderson <danderson@mozilla.com>
Fri, 25 Mar 2016 01:35:07 -0700
changeset 290503 3b995a72599cd8c3967043f5eea5d428e251eb4e
parent 290502 45c67a5e2d5dc0bfe43c16c7a88ec6c120c71c85
child 290504 eb55f7b93b3dde3529bba512e9e146a0ce08563c
push id74277
push userdanderson@mozilla.com
push dateSun, 27 Mar 2016 05:22:47 +0000
treeherdermozilla-inbound@e63011d83825 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1256517
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Track whether or not remote layers have acknowledged compositor changes. (bug 1256517 part 1, r=mattwoodrow)
gfx/layers/ipc/CompositorBridgeChild.cpp
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
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -207,25 +207,26 @@ CompositorBridgeChild::RecvInvalidateLay
       child->InvalidateLayers();
     }
   }
   return true;
 }
 
 bool
 CompositorBridgeChild::RecvCompositorUpdated(const uint64_t& aLayersId,
-                                      const TextureFactoryIdentifier& aNewIdentifier)
+                                             const TextureFactoryIdentifier& aNewIdentifier)
 {
   if (mLayerManager) {
     // This case is handled directly by nsBaseWidget.
     MOZ_ASSERT(aLayersId == 0);
   } else if (aLayersId != 0) {
     if (dom::TabChild* child = dom::TabChild::GetFrom(aLayersId)) {
       child->CompositorUpdated(aNewIdentifier);
     }
+    SendAcknowledgeCompositorUpdate(aLayersId);
   }
   return true;
 }
 
 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
 static void CalculatePluginClip(const LayoutDeviceIntRect& aBounds,
                                 const nsTArray<LayoutDeviceIntRect>& aPluginClipRects,
                                 const LayoutDeviceIntPoint& aContentOffset,
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -104,16 +104,17 @@ using base::ProcessId;
 using base::Thread;
 
 CompositorBridgeParent::LayerTreeState::LayerTreeState()
   : mParent(nullptr)
   , mLayerManager(nullptr)
   , mCrossProcessParent(nullptr)
   , mLayerTree(nullptr)
   , mUpdatedPluginDataAvailable(false)
+  , mPendingCompositorUpdates(0)
 {
 }
 
 CompositorBridgeParent::LayerTreeState::~LayerTreeState()
 {
   if (mController) {
     mController->Destroy();
   }
@@ -2049,16 +2050,17 @@ public:
   virtual void GetAPZTestData(const LayerTransactionParent* aLayerTree,
                               APZTestData* aOutData) override;
   virtual void SetConfirmedTargetAPZC(const LayerTransactionParent* aLayerTree,
                                       const uint64_t& aInputBlockId,
                                       const nsTArray<ScrollableLayerGuid>& aTargets) override;
 
   virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) override;
   virtual bool RecvRemotePluginsReady()  override { return false; }
+  virtual bool RecvAcknowledgeCompositorUpdate(const uint64_t& aLayersId) override;
 
   void DidComposite(uint64_t aId,
                     TimeStamp& aCompositeStart,
                     TimeStamp& aCompositeEnd);
 
 protected:
   void OnChannelConnected(int32_t pid) override { mCompositorThreadHolder = sCompositorThreadHolder; }
 private:
@@ -2176,16 +2178,21 @@ CompositorBridgeParent::ResetCompositorT
     // No compositor change; nothing to do.
     return;
   }
 
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   ForEachIndirectLayerTree([&] (LayerTreeState* lts, uint64_t layersId) -> void {
     if (CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent) {
       Unused << cpcp->SendCompositorUpdated(layersId, newIdentifier.value());
+
+      if (LayerTransactionParent* ltp = lts->mLayerTree) {
+        ltp->AddPendingCompositorUpdate();
+      }
+      lts->mPendingCompositorUpdates++;
     }
   });
 }
 
 Maybe<TextureFactoryIdentifier>
 CompositorBridgeParent::ResetCompositorImpl(const nsTArray<LayersBackend>& aBackendHints)
 {
   if (!mLayerManager) {
@@ -2311,16 +2318,17 @@ CrossProcessCompositorBridgeParent::Allo
   if (state && state->mLayerManager) {
     state->mCrossProcessParent = this;
     LayerManagerComposite* lm = state->mLayerManager;
     *aTextureFactoryIdentifier = lm->GetCompositor()->GetTextureFactoryIdentifier();
     *aSuccess = true;
     LayerTransactionParent* p = new LayerTransactionParent(lm, this, aId);
     p->AddIPDLReference();
     sIndirectLayerTrees[aId].mLayerTree = p;
+    p->SetPendingCompositorUpdates(state->mPendingCompositorUpdates);
     return p;
   }
 
   NS_WARNING("Created child without a matching parent?");
   // XXX: should be false, but that causes us to fail some tests on Mac w/ OMTC.
   // Bug 900745. change *aSuccess to false to see test failures.
   *aSuccess = true;
   LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, aId);
@@ -2715,16 +2723,30 @@ CrossProcessCompositorBridgeParent::GetC
   if (!state) {
     return nullptr;
   }
 
   MOZ_ASSERT(state->mParent);
   return state->mParent->GetCompositionManager(aLayerTree);
 }
 
+bool
+CrossProcessCompositorBridgeParent::RecvAcknowledgeCompositorUpdate(const uint64_t& aLayersId)
+{
+  MonitorAutoLock lock(*sIndirectLayerTreesLock);
+  CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[aLayersId];
+
+  if (LayerTransactionParent* ltp = state.mLayerTree) {
+    ltp->AcknowledgeCompositorUpdate();
+  }
+  MOZ_ASSERT(state.mPendingCompositorUpdates > 0);
+  state.mPendingCompositorUpdates--;
+  return true;
+}
+
 void
 CrossProcessCompositorBridgeParent::DeferredDestroy()
 {
   MOZ_ASSERT(mCompositorThreadHolder);
   mCompositorThreadHolder = nullptr;
   mSelfRef = nullptr;
 }
 
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -236,16 +236,21 @@ public:
   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;
   virtual bool RecvMakeWidgetSnapshot(const SurfaceDescriptor& aInSnapshot) override;
   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;
+  }
+
   virtual bool RecvGetTileSize(int32_t* aWidth, int32_t* aHeight) override;
 
   virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override;
   virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override;
   virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) override;
 
   // Unused for chrome <-> compositor communication (which this class does).
   // @see CrossProcessCompositorBridgeParent::RecvRequestNotifyAfterRemotePaint
@@ -426,16 +431,20 @@ public:
     TargetConfig mTargetConfig;
     APZTestData mApzTestData;
     LayerTransactionParent* mLayerTree;
     nsTArray<PluginWindowData> mPluginData;
     bool mUpdatedPluginDataAvailable;
     RefPtr<CompositorUpdateObserver> mLayerTreeReadyObserver;
     RefPtr<CompositorUpdateObserver> mLayerTreeClearedObserver;
 
+    // Number of times the compositor has been reset without having been
+    // acknowledged by the child.
+    uint32_t mPendingCompositorUpdates;
+
     PCompositorBridgeParent* CrossProcessPCompositorBridge() const;
   };
 
   /**
    * Lookup the indirect shadow tree for |aId| and return it if it
    * exists.  Otherwise null is returned.  This must only be called on
    * the compositor thread.
    */
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -144,16 +144,17 @@ ShadowChild(const OpRaiseToTopChild& op)
 // LayerTransactionParent
 LayerTransactionParent::LayerTransactionParent(LayerManagerComposite* aManager,
                                                ShadowLayersManager* aLayersManager,
                                                uint64_t aId)
   : mLayerManager(aManager)
   , mShadowLayersManager(aLayersManager)
   , mId(aId)
   , mPendingTransaction(0)
+  , mPendingCompositorUpdates(0)
   , mDestroyed(false)
   , mIPCOpen(false)
 {
   MOZ_COUNT_CTOR(LayerTransactionParent);
 }
 
 LayerTransactionParent::~LayerTransactionParent()
 {
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -86,16 +86,29 @@ public:
 
   virtual base::ProcessId GetChildProcessId() override
   {
     return OtherPid();
   }
 
   virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) override;
 
+  void AddPendingCompositorUpdate() {
+    mPendingCompositorUpdates++;
+  }
+  void SetPendingCompositorUpdates(uint32_t aCount) {
+    // Only called after construction.
+    MOZ_ASSERT(mPendingCompositorUpdates == 0);
+    mPendingCompositorUpdates = aCount;
+  }
+  void AcknowledgeCompositorUpdate() {
+    MOZ_ASSERT(mPendingCompositorUpdates > 0);
+    mPendingCompositorUpdates--;
+  }
+
 protected:
   virtual bool RecvSyncWithCompositor() override { return true; }
 
   virtual bool RecvShutdown() override;
 
   virtual bool RecvUpdate(EditArray&& cset,
                           OpDestroyArray&& aToDestroy,
                           const uint64_t& aTransactionId,
@@ -185,16 +198,21 @@ private:
   RefPtr<Layer> mRoot;
   // When this is nonzero, it refers to a layer tree owned by the
   // compositor thread.  It is always true that
   //   mId != 0 => mRoot == null
   // because the "real tree" is owned by the compositor.
   uint64_t mId;
 
   uint64_t mPendingTransaction;
+
+  // Number of compositor updates we're waiting for the child to
+  // acknowledge.
+  uint32_t mPendingCompositorUpdates;
+
   // When the widget/frame/browser stuff in this process begins its
   // destruction process, we need to Disconnect() all the currently
   // live shadow layers, because some of them might be orphaned from
   // the layer tree.  This happens in Destroy() above.  After we
   // Destroy() ourself, there's a window in which that information
   // hasn't yet propagated back to the child side and it might still
   // send us layer transactions.  We want to ignore those transactions
   // because they refer to "zombie layers" on this side.  So, we track
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -95,16 +95,20 @@ child:
   async ClearCachedResources(uint64_t id);
 
 parent:
   /**
    * Confirmation callback for UpdatePluginConfigurations and HideAllPlugins.
    */
   async RemotePluginsReady();
 
+  // Confirmation that the child has invalidated all its layers, and will not
+  // request layers against an old compositor.
+  async AcknowledgeCompositorUpdate(uint64_t id);
+
   // Child sends the parent a request for fill ratio numbers.
   async RequestOverfill();
 
   // Child requests frame uniformity measurements
   sync GetFrameUniformity() returns (FrameUniformityData data);
 
   // The child is about to be destroyed, so perform any necessary cleanup.
   sync WillStop();