Bug 1429373 - During hit-testing, ignore clips on layers whose parent has a perspective transform. r=kats draft
authorBotond Ballo <botond@mozilla.com>
Wed, 17 Jan 2018 18:45:25 -0500
changeset 724281 441d173e486b9be6557916219a849b2f9425d55b
parent 721855 916c52d44857d93e6046d81c96a9716d32136fb6
child 724282 991f134b7f46af30b084f807f22e6460430a3e62
child 724283 3b5b3e4c0a955ee515a5b16717c25db1d0113d57
push id96721
push userbballo@mozilla.com
push dateWed, 24 Jan 2018 21:20:57 +0000
reviewerskats
bugs1429373, 1168263
milestone59.0a1
Bug 1429373 - During hit-testing, ignore clips on layers whose parent has a perspective transform. r=kats This corresponds to the treatment of such layers in AsyncCompositionManager added in bug 1168263. MozReview-Commit-ID: 34IKk5TH9vV
gfx/layers/apz/src/APZCTreeManager.cpp
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -96,16 +96,20 @@ struct APZCTreeManager::TreeBuildingStat
   // is needed in addition to mNodesToDestroy because a hit testing node for a
   // layer tree can be removed without the whole layer tree being removed.
   std::unordered_set<uint64_t> mLayersIdsToDestroy;
 
   // This map is populated as we place APZCs into the new tree. Its purpose is
   // to facilitate re-using the same APZC for different layers that scroll
   // together (and thus have the same ScrollableLayerGuid).
   std::unordered_map<ScrollableLayerGuid, AsyncPanZoomController*, ScrollableLayerGuidHash> mApzcMap;
+
+  // As the tree is traversed, the top element of this stack tracks whether
+  // the parent scroll node has a perspective transform.
+  std::stack<bool> mParentHasPerspective;
 };
 
 class APZCTreeManager::CheckerboardFlushObserver : public nsIObserver {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   explicit CheckerboardFlushObserver(APZCTreeManager* aTreeManager)
@@ -322,16 +326,17 @@ APZCTreeManager::UpdateHitTestingTreeImp
 
   if (aRoot) {
     std::stack<gfx::TreeAutoIndent> indents;
     std::stack<AncestorTransform> ancestorTransforms;
     HitTestingTreeNode* parent = nullptr;
     HitTestingTreeNode* next = nullptr;
     uint64_t layersId = aRootLayerTreeId;
     ancestorTransforms.push(AncestorTransform());
+    state.mParentHasPerspective.push(false);
 
     state.mLayersIdsToDestroy.erase(aRootLayerTreeId);
 
     mApzcTreeLog << "[start]\n";
     mTreeLock.AssertCurrentThreadOwns();
 
     ForEachNode<ReverseIterator>(aRoot,
         [&](ScrollNode aLayerMetrics)
@@ -371,24 +376,26 @@ APZCTreeManager::UpdateHitTestingTreeImp
           if (Maybe<uint64_t> newLayersId = aLayerMetrics.GetReferentId()) {
             layersId = *newLayersId;
 
             // Mark that this layer tree is being used
             state.mLayersIdsToDestroy.erase(layersId);
           }
 
           indents.push(gfx::TreeAutoIndent(mApzcTreeLog));
+          state.mParentHasPerspective.push(aLayerMetrics.TransformIsPerspective());
         },
         [&](ScrollNode aLayerMetrics)
         {
           next = parent;
           parent = parent->GetParent();
           layersId = next->GetLayersId();
           ancestorTransforms.pop();
           indents.pop();
+          state.mParentHasPerspective.pop();
         });
 
     mApzcTreeLog << "[end]\n";
   }
 
   // We do not support tree structures where the root node has siblings.
   MOZ_ASSERT(!(mRootNode && mRootNode->GetPrevSibling()));
 
@@ -739,28 +746,32 @@ APZCTreeManager::PrepareNodeForLayer(con
     needsApzc = false;
   }
 
   const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
   if (!(state && state->mController.get())) {
     needsApzc = false;
   }
 
+  bool parentHasPerspective = aState.mParentHasPerspective.top();
+
   RefPtr<HitTestingTreeNode> node = nullptr;
   if (!needsApzc) {
     // Note: if layer properties must be propagated to nodes, RecvUpdate in
     // LayerTransactionParent.cpp must ensure that APZ will be notified
     // when those properties change.
     node = RecycleOrCreateNode(aState, nullptr, aLayersId);
     AttachNodeToTree(node, aParent, aNextSibling);
     node->SetHitTestData(
         GetEventRegions(aLayer),
         aLayer.GetVisibleRegion(),
         aLayer.GetTransformTyped(),
-        aLayer.GetClipRect() ? Some(ParentLayerIntRegion(*aLayer.GetClipRect())) : Nothing(),
+        (!parentHasPerspective && aLayer.GetClipRect())
+          ? Some(ParentLayerIntRegion(*aLayer.GetClipRect()))
+          : Nothing(),
         GetEventRegionsOverride(aParent, aLayer));
     node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
                            aLayer.GetScrollbarAnimationId(),
                            aLayer.GetScrollThumbData(),
                            aLayer.GetScrollbarContainerDirection());
     node->SetFixedPosData(aLayer.GetFixedPositionScrollContainerId());
     return node;
   }
@@ -857,22 +868,24 @@ APZCTreeManager::PrepareNodeForLayer(con
     apzc->NotifyLayersUpdated(aLayer.Metadata(), aState.mIsFirstPaint,
         aLayersId == aState.mOriginatingLayersId);
 
     // 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));
 
-    ParentLayerIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer);
+    Maybe<ParentLayerIntRegion> clipRegion = parentHasPerspective
+      ? Nothing()
+      : Some(ComputeClipRegion(state->mController, aLayer));
     node->SetHitTestData(
         GetEventRegions(aLayer),
         aLayer.GetVisibleRegion(),
         aLayer.GetTransformTyped(),
-        Some(clipRegion),
+        clipRegion,
         GetEventRegionsOverride(aParent, aLayer));
     apzc->SetAncestorTransform(aAncestorTransform);
 
     PrintAPZCInfo(aLayer, apzc);
 
     // Bind the APZC instance into the tree of APZCs
     AttachNodeToTree(node, aParent, aNextSibling);
 
@@ -947,22 +960,24 @@ APZCTreeManager::PrepareNodeForLayer(con
       if (!aAncestorTransform.mContainsPerspectiveTransform &&
           !apzc->AncestorTransformContainsPerspective()) {
         MOZ_ASSERT(false, "Two layers that scroll together have different ancestor transforms");
       } else if (!aAncestorTransform.mContainsPerspectiveTransform) {
         apzc->SetAncestorTransform(aAncestorTransform);
       }
     }
 
-    ParentLayerIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer);
+    Maybe<ParentLayerIntRegion> clipRegion = parentHasPerspective
+      ? Nothing()
+      : Some(ComputeClipRegion(state->mController, aLayer));
     node->SetHitTestData(
         GetEventRegions(aLayer),
         aLayer.GetVisibleRegion(),
         aLayer.GetTransformTyped(),
-        Some(clipRegion),
+        clipRegion,
         GetEventRegionsOverride(aParent, aLayer));
   }
 
   // Note: if layer properties must be propagated to nodes, RecvUpdate in
   // LayerTransactionParent.cpp must ensure that APZ will be notified
   // when those properties change.
   node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
                          aLayer.GetScrollbarAnimationId(),