Bug 1357754 - Extract a template function from UpdateHitTestingTree. r=botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 20 Apr 2017 10:04:48 -0400
changeset 565807 b81f935cc45ff6baaf6b7fb05832e49dd37afe10
parent 565806 af09585c0d36971972dcf2923cdc0f159ae3e574
child 565808 7b889e9b77589caab41f7c35f83a8f257eaacdd6
push id55024
push userkgupta@mozilla.com
push dateThu, 20 Apr 2017 14:05:27 +0000
reviewersbotond
bugs1357754
milestone55.0a1
Bug 1357754 - Extract a template function from UpdateHitTestingTree. r=botond Currently the public UpdateHitTestingTree function takes a Layer* which assumes there is a layer tree to traverse. However, with WebRender, that is not the case. This patch has two conceptual changes. The first change is to extract the innards of UpdateHitTestingTree to take a LayerMetricsWrapper instead of a Layer* and traverse the layer tree using that. This was already mostly happening but this makes the Layer*/LayerMetricsWrapper boundary a little more explicit. The second change is to make the extracted helper function templated, so it accepts anything that is template-compatible with LayerMetricsWrapper. I chose to use a template rather inheritance to avoid the performance hit of virtual functions, since this code runs relatively often. This paves the way for adding a different kind of tree-traversal object instead of the LayerMetricsWrapper while reusing the same logic to build the hit-testing tree and APZC nodes. MozReview-Commit-ID: 6SmnX6Bn2QV
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -208,22 +208,22 @@ APZCTreeManager::GetFrameTime()
 
 void
 APZCTreeManager::SetAllowedTouchBehavior(uint64_t aInputBlockId,
                                          const nsTArray<TouchBehaviorFlags> &aValues)
 {
   mInputQueue->SetAllowedTouchBehavior(aInputBlockId, aValues);
 }
 
-void
-APZCTreeManager::UpdateHitTestingTree(uint64_t aRootLayerTreeId,
-                                      Layer* aRoot,
-                                      bool aIsFirstPaint,
-                                      uint64_t aOriginatingLayersId,
-                                      uint32_t aPaintSequenceNumber)
+template<class ScrollNode> void // ScrollNode is a LayerMetricsWrapper
+APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
+                                          const ScrollNode& aRoot,
+                                          bool aIsFirstPaint,
+                                          uint64_t aOriginatingLayersId,
+                                          uint32_t aPaintSequenceNumber)
 {
   APZThreadUtils::AssertOnCompositorThread();
 
   MutexAutoLock lock(mTreeLock);
 
   // For testing purposes, we log some data to the APZTestData associated with
   // the layers id that originated this update.
   APZTestData* testData = nullptr;
@@ -263,21 +263,20 @@ APZCTreeManager::UpdateHitTestingTree(ui
     std::stack<gfx::TreeAutoIndent> indents;
     std::stack<gfx::Matrix4x4> ancestorTransforms;
     HitTestingTreeNode* parent = nullptr;
     HitTestingTreeNode* next = nullptr;
     uint64_t layersId = aRootLayerTreeId;
     ancestorTransforms.push(Matrix4x4());
 
     mApzcTreeLog << "[start]\n";
-    LayerMetricsWrapper root(aRoot);
     mTreeLock.AssertCurrentThreadOwns();
 
-    ForEachNode<ReverseIterator>(root,
-        [&](LayerMetricsWrapper aLayerMetrics)
+    ForEachNode<ReverseIterator>(aRoot,
+        [&](ScrollNode aLayerMetrics)
         {
           mApzcTreeLog << aLayerMetrics.Name() << '\t';
 
           HitTestingTreeNode* node = PrepareNodeForLayer(aLayerMetrics,
                 aLayerMetrics.Metrics(), layersId, ancestorTransforms.top(),
                 parent, next, state);
           MOZ_ASSERT(node);
           AsyncPanZoomController* apzc = node->GetApzc();
@@ -303,17 +302,17 @@ APZCTreeManager::UpdateHitTestingTree(ui
           // Note that |node| at this point will not have any children, otherwise we
           // we would have to set next to node->GetFirstChild().
           MOZ_ASSERT(!node->GetFirstChild());
           parent = node;
           next = nullptr;
           layersId = (aLayerMetrics.AsRefLayer() ? aLayerMetrics.AsRefLayer()->GetReferentId() : layersId);
           indents.push(gfx::TreeAutoIndent(mApzcTreeLog));
         },
-        [&](LayerMetricsWrapper aLayerMetrics)
+        [&](ScrollNode aLayerMetrics)
         {
           next = parent;
           parent = parent->GetParent();
           layersId = next->GetLayersId();
           ancestorTransforms.pop();
           indents.pop();
         });
 
@@ -332,38 +331,50 @@ APZCTreeManager::UpdateHitTestingTree(ui
 
 #if ENABLE_APZCTM_LOGGING
   // Make the hit-test tree line up with the layer dump
   printf_stderr("APZCTreeManager (%p)\n", this);
   mRootNode->Dump("  ");
 #endif
 }
 
+void
+APZCTreeManager::UpdateHitTestingTree(uint64_t aRootLayerTreeId,
+                                      Layer* aRoot,
+                                      bool aIsFirstPaint,
+                                      uint64_t aOriginatingLayersId,
+                                      uint32_t aPaintSequenceNumber)
+{
+  LayerMetricsWrapper root(aRoot);
+  UpdateHitTestingTreeImpl(aRootLayerTreeId, root, aIsFirstPaint,
+                           aOriginatingLayersId, aPaintSequenceNumber);
+}
+
 // 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.
-static ParentLayerIntRegion
+template<class ScrollNode> static ParentLayerIntRegion
 ComputeClipRegion(GeckoContentController* aController,
-                  const LayerMetricsWrapper& aLayer)
+                  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
     // bounds which should be equivalent.
     clipRegion = RoundedToInt(aLayer.Metrics().GetCompositionBounds());
   }
 
   return clipRegion;
 }
 
-void
-APZCTreeManager::PrintAPZCInfo(const LayerMetricsWrapper& aLayer,
+template<class ScrollNode> void
+APZCTreeManager::PrintAPZCInfo(const ScrollNode& aLayer,
                                const AsyncPanZoomController* apzc)
 {
   const FrameMetrics& metrics = aLayer.Metrics();
   mApzcTreeLog << "APZC " << apzc->GetGuid()
                << "\tcb=" << metrics.GetCompositionBounds()
                << "\tsr=" << metrics.GetScrollableRect()
                << (aLayer.IsScrollInfoLayer() ? "\tscrollinfo" : "")
                << (apzc->HasScrollgrab() ? "\tscrollgrab" : "") << "\t"
@@ -381,18 +392,18 @@ APZCTreeManager::AttachNodeToTree(HitTes
     aParent->SetLastChild(aNode);
   } else {
     MOZ_ASSERT(!mRootNode);
     mRootNode = aNode;
     aNode->MakeRoot();
   }
 }
 
-static EventRegions
-GetEventRegions(const LayerMetricsWrapper& aLayer)
+template<class ScrollNode> static EventRegions
+GetEventRegions(const ScrollNode& aLayer)
 {
   if (aLayer.IsScrollInfoLayer()) {
     ParentLayerIntRect compositionBounds(RoundedToInt(aLayer.Metrics().GetCompositionBounds()));
     nsIntRegion hitRegion(compositionBounds.ToUnknownRect());
     EventRegions eventRegions(hitRegion);
     eventRegions.mDispatchToContentHitRegion = eventRegions.mHitRegion;
     return eventRegions;
   }
@@ -414,19 +425,19 @@ APZCTreeManager::RecycleOrCreateNode(Tre
       node->RecycleWith(aApzc, aLayersId);
       return node.forget();
     }
   }
   RefPtr<HitTestingTreeNode> node = new HitTestingTreeNode(aApzc, false, aLayersId);
   return node.forget();
 }
 
-static EventRegionsOverride
+template<class ScrollNode> static EventRegionsOverride
 GetEventRegionsOverride(HitTestingTreeNode* aParent,
-                       const LayerMetricsWrapper& aLayer)
+                       const ScrollNode& aLayer)
 {
   // Make it so that if the flag is set on the layer tree, it automatically
   // propagates to all the nodes in the corresponding subtree rooted at that
   // layer in the hit-test tree. This saves having to walk up the tree every
   // we want to see if a hit-test node is affected by this flag.
   EventRegionsOverride result = aLayer.GetEventRegionsOverride();
   if (aParent) {
     result |= aParent->GetEventRegionsOverride();
@@ -452,18 +463,18 @@ APZCTreeManager::StartScrollbarDrag(cons
 void
 APZCTreeManager::NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const
 {
   const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aGuid.mLayersId);
   MOZ_ASSERT(state && state->mController);
   state->mController->NotifyAsyncScrollbarDragRejected(aGuid.mScrollId);
 }
 
-HitTestingTreeNode*
-APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
+template<class ScrollNode> HitTestingTreeNode*
+APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer,
                                      const FrameMetrics& aMetrics,
                                      uint64_t aLayersId,
                                      const gfx::Matrix4x4& aAncestorTransform,
                                      HitTestingTreeNode* aParent,
                                      HitTestingTreeNode* aNextSibling,
                                      TreeBuildingState& aState)
 {
   mTreeLock.AssertCurrentThreadOwns();
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -431,16 +431,23 @@ public:
    * is occurring such as when the toolbar is being hidden/shown in Fennec.
    * This function can be called to have the y axis' velocity queue updated.
    */
   void ProcessTouchVelocity(uint32_t aTimestampMs, float aSpeedY) override;
 private:
   typedef bool (*GuidComparator)(const ScrollableLayerGuid&, const ScrollableLayerGuid&);
 
   /* Helpers */
+  template<class ScrollNode>
+  void UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
+                                const ScrollNode& aRoot,
+                                bool aIsFirstPaint,
+                                uint64_t aOriginatingLayersId,
+                                uint32_t aPaintSequenceNumber);
+
   void AttachNodeToTree(HitTestingTreeNode* aNode,
                         HitTestingTreeNode* aParent,
                         HitTestingTreeNode* aNextSibling);
   already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScrollableLayerGuid& aGuid);
   already_AddRefed<HitTestingTreeNode> GetTargetNode(const ScrollableLayerGuid& aGuid,
                                                      GuidComparator aComparator);
   HitTestingTreeNode* FindTargetNode(HitTestingTreeNode* aNode,
                                      const ScrollableLayerGuid& aGuid,
@@ -461,25 +468,27 @@ private:
   nsEventStatus ProcessTouchInput(MultiTouchInput& aInput,
                                   ScrollableLayerGuid* aOutTargetGuid,
                                   uint64_t* aOutInputBlockId);
   void FlushRepaintsToClearScreenToGeckoTransform();
 
   already_AddRefed<HitTestingTreeNode> RecycleOrCreateNode(TreeBuildingState& aState,
                                                            AsyncPanZoomController* aApzc,
                                                            uint64_t aLayersId);
-  HitTestingTreeNode* PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
+  template<class ScrollNode>
+  HitTestingTreeNode* PrepareNodeForLayer(const ScrollNode& aLayer,
                                           const FrameMetrics& aMetrics,
                                           uint64_t aLayersId,
                                           const gfx::Matrix4x4& aAncestorTransform,
                                           HitTestingTreeNode* aParent,
                                           HitTestingTreeNode* aNextSibling,
                                           TreeBuildingState& aState);
 
-  void PrintAPZCInfo(const LayerMetricsWrapper& aLayer,
+  template<class ScrollNode>
+  void PrintAPZCInfo(const ScrollNode& aLayer,
                      const AsyncPanZoomController* apzc);
 
   void NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const;
 
 protected:
   /* The input queue where input events are held until we know enough to
    * figure out where they're going. Protected so gtests can access it.
    */