Track whether or not remote layers have acknowledged compositor changes. (bug 1256517 part 1, r=mattwoodrow, a=rkothari)
authorDavid Anderson <danderson@mozilla.com>
Fri, 25 Mar 2016 01:35:07 -0700
changeset 310750 b577f69f24286bbadb9be2ba1345b2ff18f58338
parent 310749 c0be14550a2b77f8f8b4aab158fc3525ffc82828
child 310751 6a570bddbec9d6f941cca89c242c938508dfb0da
push id9467
push userdanderson@mozilla.com
push dateFri, 22 Apr 2016 21:26:27 +0000
treeherdermozilla-aurora@922334c70324 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, rkothari
bugs1256517
milestone47.0a2
Track whether or not remote layers have acknowledged compositor changes. (bug 1256517 part 1, r=mattwoodrow, a=rkothari)
gfx/layers/ipc/CompositorChild.cpp
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/PCompositor.ipdl
--- a/gfx/layers/ipc/CompositorChild.cpp
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -207,25 +207,26 @@ CompositorChild::RecvInvalidateLayers(co
       child->InvalidateLayers();
     }
   }
   return true;
 }
 
 bool
 CompositorChild::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/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -104,16 +104,17 @@ using base::ProcessId;
 using base::Thread;
 
 CompositorParent::LayerTreeState::LayerTreeState()
   : mParent(nullptr)
   , mLayerManager(nullptr)
   , mCrossProcessParent(nullptr)
   , mLayerTree(nullptr)
   , mUpdatedPluginDataAvailable(false)
+  , mPendingCompositorUpdates(0)
 {
 }
 
 CompositorParent::LayerTreeState::~LayerTreeState()
 {
   if (mController) {
     mController->Destroy();
   }
@@ -1956,16 +1957,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:
@@ -2083,16 +2085,21 @@ CompositorParent::ResetCompositorTask(co
     // No compositor change; nothing to do.
     return;
   }
 
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   ForEachIndirectLayerTree([&] (LayerTreeState* lts, uint64_t layersId) -> void {
     if (CrossProcessCompositorParent* cpcp = lts->mCrossProcessParent) {
       Unused << cpcp->SendCompositorUpdated(layersId, newIdentifier.value());
+
+      if (LayerTransactionParent* ltp = lts->mLayerTree) {
+        ltp->AddPendingCompositorUpdate();
+      }
+      lts->mPendingCompositorUpdates++;
     }
   });
 }
 
 Maybe<TextureFactoryIdentifier>
 CompositorParent::ResetCompositorImpl(const nsTArray<LayersBackend>& aBackendHints)
 {
   if (!mLayerManager) {
@@ -2217,16 +2224,17 @@ CrossProcessCompositorParent::AllocPLaye
   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);
@@ -2607,16 +2615,30 @@ CrossProcessCompositorParent::GetComposi
   if (!state) {
     return nullptr;
   }
 
   MOZ_ASSERT(state->mParent);
   return state->mParent->GetCompositionManager(aLayerTree);
 }
 
+bool
+CrossProcessCompositorParent::RecvAcknowledgeCompositorUpdate(const uint64_t& aLayersId)
+{
+  MonitorAutoLock lock(*sIndirectLayerTreesLock);
+  CompositorParent::LayerTreeState& state = sIndirectLayerTrees[aLayersId];
+
+  if (LayerTransactionParent* ltp = state.mLayerTree) {
+    ltp->AcknowledgeCompositorUpdate();
+  }
+  MOZ_ASSERT(state.mPendingCompositorUpdates > 0);
+  state.mPendingCompositorUpdates--;
+  return true;
+}
+
 void
 CrossProcessCompositorParent::DeferredDestroy()
 {
   MOZ_ASSERT(mCompositorThreadHolder);
   mCompositorThreadHolder = nullptr;
   mSelfRef = nullptr;
 }
 
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.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 CrossProcessCompositorParent::RecvRequestNotifyAfterRemotePaint
@@ -419,16 +424,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;
+
     PCompositorParent* CrossProcessPCompositor() 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
@@ -85,16 +85,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,
@@ -181,16 +194,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/PCompositor.ipdl
+++ b/gfx/layers/ipc/PCompositor.ipdl
@@ -93,16 +93,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();