Bug 1441916 - Remove calls to GetIndirectShadowTree inside APZCTreeManager. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 01 Mar 2018 23:00:41 -0500
changeset 762499 a99abc3cff3bf8a8a27910260f53b692967f5718
parent 762498 81abbeee00b0210811844d6d20b297b2946ca673
child 762500 aabf999f6a980981ff5c7d4ef16c02368363ab26
push id101178
push userkgupta@mozilla.com
push dateFri, 02 Mar 2018 13:48:39 +0000
reviewersbotond
bugs1441916
milestone60.0a1
Bug 1441916 - Remove calls to GetIndirectShadowTree inside APZCTreeManager. r?botond Calling GetIndirectShadowTree and holding on to the result - or holding on to pointers from the LayerTreeState - is fine on the compositor thread, but if we want to allow APZ to accept layer updates and scroll offset sampling on some other thread, then we should avoid doing this. This patch replaces calls to GetIndirectShadowTree with the CallWithIndirectShadowTree function and ensures anything that outlives the function is held on to with a RefPtr. Of course, this only takes care of the more superficial concerns - we will also need to robustify those classes' implementations to handle being called from multiple threads; that will be tackled later. MozReview-Commit-ID: E40JGFjooPo
gfx/layers/apz/src/APZCTreeManager.cpp
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -64,30 +64,35 @@ typedef mozilla::gfx::Point Point;
 typedef mozilla::gfx::Point4D Point4D;
 typedef mozilla::gfx::Matrix4x4 Matrix4x4;
 
 typedef CompositorBridgeParent::LayerTreeState LayerTreeState;
 
 float APZCTreeManager::sDPI = 160.0;
 
 struct APZCTreeManager::TreeBuildingState {
-  TreeBuildingState(const LayerTreeState* const aLayerTreeState,
+  TreeBuildingState(uint64_t aRootLayersId,
                     bool aIsFirstPaint, uint64_t aOriginatingLayersId,
                     APZTestData* aTestData, uint32_t aPaintSequence)
-    : mLayerTreeState(aLayerTreeState)
-    , mIsFirstPaint(aIsFirstPaint)
+    : mIsFirstPaint(aIsFirstPaint)
     , mOriginatingLayersId(aOriginatingLayersId)
     , mPaintLogger(aTestData, aPaintSequence)
   {
+    CompositorBridgeParent::CallWithIndirectShadowTree(aRootLayersId,
+        [this](LayerTreeState& aState) -> void {
+          mCompositorController = aState.GetCompositorController();
+          mInProcessSharingController = aState.InProcessSharingController();
+        });
   }
 
   typedef std::unordered_map<AsyncPanZoomController*, gfx::Matrix4x4> DeferredTransformMap;
 
   // State that doesn't change as we recurse in the tree building
-  const LayerTreeState* const mLayerTreeState;
+  RefPtr<CompositorController> mCompositorController;
+  RefPtr<MetricsSharingController> mInProcessSharingController;
   const bool mIsFirstPaint;
   const uint64_t mOriginatingLayersId;
   const APZPaintLogHelper mPaintLogger;
 
   // State that is updated as we perform the tree build
 
   // A list of nodes that need to be destroyed at the end of the tree building.
   // This is initialized with all nodes in the old tree, and nodes are removed
@@ -338,20 +343,17 @@ APZCTreeManager::UpdateHitTestingTreeImp
   if (gfxPrefs::APZTestLoggingEnabled()) {
     MutexAutoLock lock(mTestDataLock);
     UniquePtr<APZTestData> ptr = MakeUnique<APZTestData>();
     auto result = mTestData.insert(std::make_pair(aOriginatingLayersId, Move(ptr)));
     testData = result.first->second.get();
     testData->StartNewPaint(aPaintSequenceNumber);
   }
 
-  const LayerTreeState* treeState =
-    CompositorBridgeParent::GetIndirectShadowTree(aRootLayerTreeId);
-  MOZ_ASSERT(treeState);
-  TreeBuildingState state(treeState, aIsFirstPaint, aOriginatingLayersId,
+  TreeBuildingState state(aRootLayerTreeId, aIsFirstPaint, aOriginatingLayersId,
                           testData, aPaintSequenceNumber);
 
   // We do this business with collecting the entire tree into an array because otherwise
   // it's very hard to determine which APZC instances need to be destroyed. In the worst
   // case, there are two scenarios: (a) a layer with an APZC is removed from the layer
   // tree and (b) a layer with an APZC is moved in the layer tree from one place to a
   // completely different place. In scenario (a) we would want to destroy the APZC while
   // walking the layer tree and noticing that the layer/APZC is no longer there. But if
@@ -554,24 +556,28 @@ APZCTreeManager::PushStateToWR(wr::Trans
           return;
         }
         AsyncPanZoomController* apzc = aNode->GetApzc();
         MOZ_ASSERT(apzc);
 
         if (aNode->GetLayersId() != lastLayersId) {
           // If we walked into or out of a subtree, we need to get the new
           // pipeline id.
-          const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aNode->GetLayersId());
-          if (!(state && state->mWrBridge)) {
+          RefPtr<WebRenderBridgeParent> wrBridge;
+          CompositorBridgeParent::CallWithIndirectShadowTree(aNode->GetLayersId(),
+              [&wrBridge](LayerTreeState& aState) -> void {
+                wrBridge = aState.mWrBridge;
+              });
+          if (!wrBridge) {
             // During shutdown we might have layer tree information for stuff
             // that has already been torn down. In that case just skip over
             // those layers.
             return;
           }
-          lastPipelineId = state->mWrBridge->PipelineId();
+          lastPipelineId = wrBridge->PipelineId();
           lastLayersId = aNode->GetLayersId();
         }
 
         // Use a 0 presShellId because when we do a lookup in this map for the
         // scrollbar below we don't have (or care about) the presShellId.
         ScrollableLayerGuid guid(lastLayersId, 0, apzc->GetGuid().mScrollId);
         httnMap.emplace(guid, aNode);
 
@@ -630,18 +636,17 @@ APZCTreeManager::PushStateToWR(wr::Trans
       });
 
   return activeAnimations;
 }
 
 // Compute the clip region to be used for a layer with an APZC. This function
 // is only called for layers which actually have scrollable metrics and an APZC.
 template<class ScrollNode> static ParentLayerIntRegion
-ComputeClipRegion(GeckoContentController* aController,
-                  const ScrollNode& aLayer)
+ComputeClipRegion(const ScrollNode& aLayer)
 {
   ParentLayerIntRegion clipRegion;
   if (aLayer.GetClipRect()) {
     clipRegion = *aLayer.GetClipRect();
   } else {
     // if there is no clip on this layer (which should only happen for the
     // root scrollable layer in a process, or for some of the LayerMetrics
     // expansions of a multi-metrics layer), fall back to using the comp
@@ -806,18 +811,28 @@ APZCTreeManager::PrepareNodeForLayer(con
 {
   mTreeLock.AssertCurrentThreadIn();
 
   bool needsApzc = true;
   if (!aMetrics.IsScrollable()) {
     needsApzc = false;
   }
 
-  const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
-  if (!(state && state->mController.get())) {
+  // XXX: As a future optimization we can probably stick these things on the
+  // TreeBuildingState, and update them as we change layers id during the
+  // traversal
+  RefPtr<GeckoContentController> geckoContentController;
+  RefPtr<MetricsSharingController> crossProcessSharingController;
+  CompositorBridgeParent::CallWithIndirectShadowTree(aLayersId,
+      [&](LayerTreeState& lts) -> void {
+        geckoContentController = lts.mController;
+        crossProcessSharingController = lts.CrossProcessSharingController();
+      });
+
+  if (!geckoContentController) {
     needsApzc = false;
   }
 
   bool parentHasPerspective = aState.mParentHasPerspective.top();
 
   RefPtr<HitTestingTreeNode> node = nullptr;
   if (!needsApzc) {
     // Note: if layer properties must be propagated to nodes, RecvUpdate in
@@ -902,23 +917,22 @@ APZCTreeManager::PrepareNodeForLayer(con
     }
 
     // The APZC we get off the layer may have been destroyed previously if the
     // layer was inactive or omitted from the layer tree for whatever reason
     // from a layers update. If it later comes back it will have a reference to
     // a destroyed APZC and so we need to throw that out and make a new one.
     bool newApzc = (apzc == nullptr || apzc->IsDestroyed());
     if (newApzc) {
-      MOZ_ASSERT(aState.mLayerTreeState);
-      apzc = NewAPZCInstance(aLayersId, state->mController);
-      apzc->SetCompositorController(aState.mLayerTreeState->GetCompositorController());
-      if (state->mCrossProcessParent) {
-        apzc->SetMetricsSharingController(state->CrossProcessSharingController());
+      apzc = NewAPZCInstance(aLayersId, geckoContentController);
+      apzc->SetCompositorController(aState.mCompositorController.get());
+      if (crossProcessSharingController) {
+        apzc->SetMetricsSharingController(crossProcessSharingController);
       } else {
-        apzc->SetMetricsSharingController(aState.mLayerTreeState->InProcessSharingController());
+        apzc->SetMetricsSharingController(aState.mInProcessSharingController.get());
       }
       MOZ_ASSERT(node == nullptr);
       node = new HitTestingTreeNode(apzc, true, aLayersId);
     } else {
       // If we are re-using a node for this layer clear the tree pointers
       // so that it doesn't continue pointing to nodes that might no longer
       // be in the tree. These pointers will get reset properly as we continue
       // building the tree. Also remove it from the set of nodes that are going
@@ -935,17 +949,17 @@ APZCTreeManager::PrepareNodeForLayer(con
 
     // Since this is the first time we are encountering an APZC with this guid,
     // the node holding it must be the primary holder. It may be newly-created
     // or not, depending on whether it went through the newApzc branch above.
     MOZ_ASSERT(node->IsPrimaryHolder() && node->GetApzc() && node->GetApzc()->Matches(guid));
 
     Maybe<ParentLayerIntRegion> clipRegion = parentHasPerspective
       ? Nothing()
-      : Some(ComputeClipRegion(state->mController, aLayer));
+      : Some(ComputeClipRegion(aLayer));
     node->SetHitTestData(
         GetEventRegions(aLayer),
         aLayer.GetVisibleRegion(),
         aLayer.GetTransformTyped(),
         clipRegion,
         GetEventRegionsOverride(aParent, aLayer));
     apzc->SetAncestorTransform(aAncestorTransform);
 
@@ -1034,17 +1048,17 @@ APZCTreeManager::PrepareNodeForLayer(con
       } else {
         aState.mPerspectiveTransformsDeferredToChildren.insert(
             PairType{apzc, aAncestorTransform.GetPerspectiveTransform()});
       }
     }
 
     Maybe<ParentLayerIntRegion> clipRegion = parentHasPerspective
       ? Nothing()
-      : Some(ComputeClipRegion(state->mController, aLayer));
+      : Some(ComputeClipRegion(aLayer));
     node->SetHitTestData(
         GetEventRegions(aLayer),
         aLayer.GetVisibleRegion(),
         aLayer.GetTransformTyped(),
         clipRegion,
         GetEventRegionsOverride(aParent, aLayer));
   }