Bug 1523500 - Don't use cross-doc checks for perspective scrolling. r=mattwoodrow
☠☠ backed out by e2cbda47cf40 ☠ ☠
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 29 Jan 2019 19:39:50 +0000
changeset 455978 1885a467de3c3aebd529355da08e20d376ada4c8
parent 455977 453fbc9760d4a46d3c7e33886160f71a790a4b25
child 455979 4fd4dab100c6ff2b945e1506206d6216c0f3249a
push id35465
push usershindli@mozilla.com
push dateWed, 30 Jan 2019 04:10:12 +0000
treeherdermozilla-central@9e919be867b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1523500
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1523500 - Don't use cross-doc checks for perspective scrolling. r=mattwoodrow Would be pretty surprising if a perspective transform scrolled stuff in an iframe for example. Differential Revision: https://phabricator.services.mozilla.com/D17905
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/painting/FrameLayerBuilder.cpp
layout/painting/nsDisplayList.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1484,25 +1484,33 @@ bool nsLayoutUtils::IsAncestorFrameCross
                                             const nsIFrame* aCommonAncestor) {
   for (const nsIFrame* f = aFrame; f != aCommonAncestor;
        f = GetCrossDocParentFrame(f)) {
     if (f == aAncestorFrame) return true;
   }
   return aCommonAncestor == aAncestorFrame;
 }
 
+bool nsLayoutUtils::IsAncestorFrame(const nsIFrame* aAncestorFrame,
+                                    const nsIFrame* aFrame,
+                                    const nsIFrame* aCommonAncestor) {
+  for (const nsIFrame* f = aFrame; f != aCommonAncestor; f = f->GetParent()) {
+    if (f == aAncestorFrame) {
+      return true;
+    }
+  }
+  return aCommonAncestor == aAncestorFrame;
+}
+
 // static
 bool nsLayoutUtils::IsProperAncestorFrame(const nsIFrame* aAncestorFrame,
                                           const nsIFrame* aFrame,
                                           const nsIFrame* aCommonAncestor) {
-  if (aFrame == aAncestorFrame) return false;
-  for (const nsIFrame* f = aFrame; f != aCommonAncestor; f = f->GetParent()) {
-    if (f == aAncestorFrame) return true;
-  }
-  return aCommonAncestor == aAncestorFrame;
+  return aFrame != aAncestorFrame &&
+    IsAncestorFrame(aAncestorFrame, aFrame, aCommonAncestor);
 }
 
 // static
 int32_t nsLayoutUtils::DoCompareTreePosition(
     nsIContent* aContent1, nsIContent* aContent2, int32_t aIf1Ancestor,
     int32_t aIf2Ancestor, const nsIContent* aCommonAncestor) {
   MOZ_ASSERT(aContent1, "aContent1 must not be null");
   MOZ_ASSERT(aContent2, "aContent2 must not be null");
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -528,16 +528,27 @@ class nsLayoutUtils {
    * aAncestorFrame. If non-null, this can bound the search and speed up
    * the function
    */
   static bool IsProperAncestorFrame(const nsIFrame* aAncestorFrame,
                                     const nsIFrame* aFrame,
                                     const nsIFrame* aCommonAncestor = nullptr);
 
   /**
+   * IsAncestorFrame checks whether aAncestorFrame is an ancestor
+   * of aFrame or equal to aFrame.
+   * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
+   * aAncestorFrame. If non-null, this can bound the search and speed up
+   * the function
+   */
+  static bool IsAncestorFrame(const nsIFrame* aAncestorFrame,
+                              const nsIFrame* aFrame,
+                              const nsIFrame* aCommonAncestor = nullptr);
+
+  /**
    * Like IsProperAncestorFrame, but looks across document boundaries.
    *
    * Just like IsAncestorFrameCrossDoc, except that it returns false when
    * aFrame == aAncestorFrame.
    */
   static bool IsProperAncestorFrameCrossDoc(
       nsIFrame* aAncestorFrame, nsIFrame* aFrame,
       nsIFrame* aCommonAncestor = nullptr);
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -4262,18 +4262,17 @@ Maybe<size_t> ContainerState::SetupMaskL
   }
   return Nothing();
 }
 
 static const ActiveScrolledRoot* GetASRForPerspective(
     const ActiveScrolledRoot* aASR, nsIFrame* aPerspectiveFrame) {
   for (const ActiveScrolledRoot* asr = aASR; asr; asr = asr->mParent) {
     nsIFrame* scrolledFrame = asr->mScrollableFrame->GetScrolledFrame();
-    if (nsLayoutUtils::IsAncestorFrameCrossDoc(scrolledFrame,
-                                               aPerspectiveFrame)) {
+    if (nsLayoutUtils::IsAncestorFrame(scrolledFrame, aPerspectiveFrame)) {
       return asr;
     }
   }
   return nullptr;
 }
 
 static CSSMaskLayerUserData* GetCSSMaskLayerUserData(Layer* aMaskLayer) {
   if (!aMaskLayer) {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -8495,17 +8495,17 @@ bool nsDisplayPerspective::CreateWebRend
   wr::StackingContextParams params;
   params.mTransformPtr = &perspectiveMatrix;
   params.reference_frame_kind = wr::WrReferenceFrameKind::Perspective;
   params.is_backface_visible = !BackfaceIsHidden();
   params.SetPreserve3D(preserve3D);
 
   Maybe<uint64_t> scrollingRelativeTo;
   for (auto* asr = GetActiveScrolledRoot(); asr; asr = asr->mParent) {
-    if (nsLayoutUtils::IsAncestorFrameCrossDoc(
+    if (nsLayoutUtils::IsAncestorFrame(
           asr->mScrollableFrame->GetScrolledFrame(), perspectiveFrame)) {
       scrollingRelativeTo.emplace(asr->GetViewId());
       break;
     }
   }
 
   // We put the perspective reference frame wrapping the transformed frame,
   // even though there may be arbitrarily nested scroll frames in between.