Bug 1417519 - Hook up APZ to use the hit-testing API. r?botond,mstange draft
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 17 Nov 2017 20:28:44 -0500
changeset 700073 eb9ba0619a188a5044a581e956f6c67c5a27f238
parent 699748 7662e8299c48183cc5b273bea32d040a6266636b
child 740777 0b7ce893f911a3c4c68e0af138bb3daff60526c0
push id89731
push userkgupta@mozilla.com
push dateSat, 18 Nov 2017 01:29:23 +0000
reviewersbotond, mstange
bugs1417519
milestone59.0a1
Bug 1417519 - Hook up APZ to use the hit-testing API. r?botond,mstange This adds the code that APZ needs to use the WR hit-testing API. For now (if the pref is enabled) it just does the hit-test and compares the result to the regular hit-test, printing out discrepancies. It also doesn't yet get the scrollbar result. MozReview-Commit-ID: 3pjYSWDGeDr
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
gfx/webrender_bindings/WebRenderTypes.h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -2182,33 +2182,109 @@ APZCTreeManager::GetTargetNode(const Scr
   return target.forget();
 }
 
 already_AddRefed<AsyncPanZoomController>
 APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint,
                                HitTestResult* aOutHitResult,
                                RefPtr<HitTestingTreeNode>* aOutScrollbarNode)
 {
-  MutexAutoLock lock(mTreeLock);
   HitTestResult hitResult = HitNothing;
   HitTestingTreeNode* scrollbarNode = nullptr;
-  ParentLayerPoint point = ViewAs<ParentLayerPixel>(aPoint,
-    PixelCastJustification::ScreenIsParentLayerForRoot);
-  RefPtr<AsyncPanZoomController> target = GetAPZCAtPoint(mRootNode, point,
-      &hitResult, &scrollbarNode);
+  RefPtr<AsyncPanZoomController> target;
+
+  { // scope mTreeLock
+    MutexAutoLock lock(mTreeLock);
+    target = GetAPZCAtPoint(mRootNode, aPoint, &hitResult, &scrollbarNode);
+  }
+
+  if (gfxPrefs::WebRenderHitTest()) {
+    HitTestResult wrHitResult = HitNothing;
+    RefPtr<AsyncPanZoomController> wrTarget = GetAPZCAtPointWR(aPoint, &wrHitResult);
+    // For now just compare the WR and non-WR results.
+    if (wrHitResult != hitResult) {
+      printf_stderr("WR hit result mismatch at %s: got %d, expected %d\n",
+          Stringify(aPoint).c_str(), (int)wrHitResult, (int)hitResult);
+      // MOZ_RELEASE_ASSERT(false);
+    }
+    if (wrTarget.get() != target.get()) {
+      printf_stderr("WR hit target mismatch at %s: got %s, expected %s\n",
+          Stringify(aPoint).c_str(),
+          wrTarget ? Stringify(wrTarget->GetGuid()).c_str() : "null",
+          target ? Stringify(target->GetGuid()).c_str() : "null");
+      // MOZ_RELEASE_ASSERT(false);
+    }
+  }
 
   if (aOutHitResult) {
     *aOutHitResult = hitResult;
   }
   if (aOutScrollbarNode) {
     *aOutScrollbarNode = scrollbarNode;
   }
   return target.forget();
 }
 
+already_AddRefed<AsyncPanZoomController>
+APZCTreeManager::GetAPZCAtPointWR(const ScreenPoint& aHitTestPoint,
+                                  HitTestResult* aOutHitResult)
+{
+  MOZ_ASSERT(aOutHitResult);
+
+  RefPtr<AsyncPanZoomController> result;
+  RefPtr<wr::WebRenderAPI> wr = GetWebRenderAPI();
+  if (!wr) {
+    return result.forget();
+  }
+
+  wr::WrPipelineId pipelineId;
+  FrameMetrics::ViewID scrollId;
+  gfx::CompositorHitTestInfo hitInfo;
+  bool hitSomething = wr->HitTest(wr::ToWorldPoint(aHitTestPoint),
+      pipelineId, scrollId, hitInfo);
+  if (!hitSomething) {
+    return result.forget();
+  }
+
+  uint64_t layersId = wr::AsUint64(pipelineId);
+  result = GetTargetAPZC(layersId, scrollId);
+  if (!result) {
+    // It falls back to the root
+    MOZ_ASSERT(scrollId == FrameMetrics::NULL_SCROLL_ID);
+    result = FindRootApzcForLayersId(layersId);
+    MOZ_ASSERT(result);
+  }
+
+  *aOutHitResult = HitLayer;
+  if (hitInfo & gfx::CompositorHitTestInfo::eDispatchToContent) {
+    *aOutHitResult = HitDispatchToContentRegion;
+    return result.forget();
+  }
+
+  auto touchFlags = hitInfo & gfx::CompositorHitTestInfo::eTouchActionMask;
+  if (!touchFlags) {
+    return result.forget();
+  }
+  if (touchFlags == gfx::CompositorHitTestInfo::eTouchActionMask) {
+    *aOutHitResult = HitLayerTouchActionNone;
+    return result.forget();
+  }
+
+  bool panX = !(hitInfo & gfx::CompositorHitTestInfo::eTouchActionPanXDisabled);
+  bool panY = !(hitInfo & gfx::CompositorHitTestInfo::eTouchActionPanYDisabled);
+  if (panX && panY) {
+    *aOutHitResult = HitLayerTouchActionPanXY;
+  } else if (panY) {
+    *aOutHitResult = HitLayerTouchActionPanY;
+  } else if (panX) {
+    *aOutHitResult = HitLayerTouchActionPanX;
+  }
+  return result.forget();
+}
+
 RefPtr<const OverscrollHandoffChain>
 APZCTreeManager::BuildOverscrollHandoffChain(const RefPtr<AsyncPanZoomController>& aInitialTarget)
 {
   // Scroll grabbing is a mechanism that allows content to specify that
   // the initial target of a pan should be not the innermost scrollable
   // frame at the touch point (which is what GetTargetAPZC finds), but
   // something higher up in the tree.
   // It's not sufficient to just find the initial target, however, as
@@ -2316,28 +2392,30 @@ APZCTreeManager::GetTargetApzcForNode(Hi
       return fpNode ? fpNode->GetApzc() : nullptr;
     }
   }
   return nullptr;
 }
 
 AsyncPanZoomController*
 APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
-                                const ParentLayerPoint& aHitTestPoint,
+                                const ScreenPoint& aHitTestPoint,
                                 HitTestResult* aOutHitResult,
                                 HitTestingTreeNode** aOutScrollbarNode)
 {
   mTreeLock.AssertCurrentThreadOwns();
 
   // This walks the tree in depth-first, reverse order, so that it encounters
   // APZCs front-to-back on the screen.
   HitTestingTreeNode* resultNode;
   HitTestingTreeNode* root = aNode;
   std::stack<LayerPoint> hitTestPoints;
-  hitTestPoints.push(ViewAs<LayerPixel>(aHitTestPoint,
+  ParentLayerPoint point = ViewAs<ParentLayerPixel>(aHitTestPoint,
+      PixelCastJustification::ScreenIsParentLayerForRoot);
+  hitTestPoints.push(ViewAs<LayerPixel>(point,
       PixelCastJustification::MovingDownToChildren));
 
   ForEachNode<ReverseIterator>(root,
       [&hitTestPoints, this](HitTestingTreeNode* aNode) {
         ParentLayerPoint hitTestPointForParent = ViewAs<ParentLayerPixel>(hitTestPoints.top(),
             PixelCastJustification::MovingDownToChildren);
         if (aNode->IsOutsideClip(hitTestPointForParent)) {
           // If the point being tested is outside the clip region for this node
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -515,19 +515,21 @@ private:
   already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScrollableLayerGuid& aGuid);
   already_AddRefed<HitTestingTreeNode> GetTargetNode(const ScrollableLayerGuid& aGuid,
                                                      GuidComparator aComparator) const;
   HitTestingTreeNode* FindTargetNode(HitTestingTreeNode* aNode,
                                      const ScrollableLayerGuid& aGuid,
                                      GuidComparator aComparator);
   AsyncPanZoomController* GetTargetApzcForNode(HitTestingTreeNode* aNode);
   AsyncPanZoomController* GetAPZCAtPoint(HitTestingTreeNode* aNode,
-                                         const ParentLayerPoint& aHitTestPoint,
+                                         const ScreenPoint& aHitTestPoint,
                                          HitTestResult* aOutHitResult,
                                          HitTestingTreeNode** aOutScrollbarNode);
+  already_AddRefed<AsyncPanZoomController> GetAPZCAtPointWR(const ScreenPoint& aHitTestPoint,
+                                                            HitTestResult* aOutHitResult);
   AsyncPanZoomController* FindRootApzcForLayersId(uint64_t aLayersId) const;
   AsyncPanZoomController* FindRootContentApzcForLayersId(uint64_t aLayersId) const;
   AsyncPanZoomController* FindRootContentOrRootApzc() const;
   already_AddRefed<AsyncPanZoomController> GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const;
   already_AddRefed<AsyncPanZoomController> CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const;
   /**
    * Perform hit testing for a touch-start event.
    *
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -278,16 +278,24 @@ static inline wr::LayoutPoint ToLayoutPo
   return p;
 }
 
 static inline wr::LayoutPoint ToLayoutPoint(const mozilla::LayoutDeviceIntPoint& point)
 {
   return ToLayoutPoint(LayoutDevicePoint(point));
 }
 
+static inline wr::WorldPoint ToWorldPoint(const mozilla::ScreenPoint& point)
+{
+  wr::WorldPoint p;
+  p.x = point.x;
+  p.y = point.y;
+  return p;
+}
+
 static inline wr::LayoutVector2D ToLayoutVector2D(const mozilla::LayoutDevicePoint& point)
 {
   wr::LayoutVector2D p;
   p.x = point.x;
   p.y = point.y;
   return p;
 }