Bug 1525181 - Lift the async transform representing visual viewport scrolling to the async zoom container. r=kats
authorBotond Ballo <botond@mozilla.com>
Wed, 27 Mar 2019 16:44:25 +0000
changeset 525215 1d3e04d06651621658961856131d6e7f35fd222c
parent 525214 1ebd5a9c9c387ab789f23c51ac1e7ed2855edaa9
child 525216 1477ba2341babf3e788109cf79ccbd528acc5d74
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1525181
milestone68.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 1525181 - Lift the async transform representing visual viewport scrolling to the async zoom container. r=kats This avoids having to place this transform separately onto scrollable and fixed layers. Differential Revision: https://phabricator.services.mozilla.com/D24594
gfx/layers/apz/public/APZSampler.h
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZSampler.cpp
gfx/layers/apz/src/APZUtils.h
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/AsyncPanZoomController.h
gfx/layers/composite/AsyncCompositionManager.cpp
--- a/gfx/layers/apz/public/APZSampler.h
+++ b/gfx/layers/apz/public/APZSampler.h
@@ -88,18 +88,16 @@ class APZSampler {
 
   CSSRect GetCurrentAsyncLayoutViewport(const LayerMetricsWrapper& aLayer);
   ParentLayerPoint GetCurrentAsyncScrollOffset(
       const LayerMetricsWrapper& aLayer);
   AsyncTransform GetCurrentAsyncTransform(const LayerMetricsWrapper& aLayer,
                                           AsyncTransformComponents aComponents);
   AsyncTransform GetCurrentAsyncTransformForFixedAdjustment(
       const LayerMetricsWrapper& aLayer);
-  AsyncTransform GetCurrentAsyncViewportRelativeTransform(
-      const LayerMetricsWrapper& aLayer);
   AsyncTransformComponentMatrix GetOverscrollTransform(
       const LayerMetricsWrapper& aLayer);
   AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll(
       const LayerMetricsWrapper& aLayer);
 
   void MarkAsyncTransformAppliedToContent(const LayerMetricsWrapper& aLayer);
   bool HasUnusedAsyncTransform(const LayerMetricsWrapper& aLayer);
 
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -3121,55 +3121,44 @@ LayerToParentLayerMatrix4x4 APZCTreeMana
   //
   //   root container layer
   //     async zoom container layer
   //       scrollable content layers (with scroll metadata)
   //       fixed content layers (no scroll metadta, annotated isFixedPosition)
   //     scrollbar layers
   //
   // The intended async transforms in this case are:
-  //  * On the async zoom container layer, the zoom portion of the root content
-  //    APZC's async transform.
+  //  * On the async zoom container layer, the "visual" portion of the root
+  //    content APZC's async transform (which includes the zoom, and async
+  //    scrolling of the visual viewport relative to the layout viewport).
   //  * On the scrollable layers bearing the root content APZC's scroll
-  //    metadata, the scroll portion of the root content APZC's async transform.
-  //  * On layers fixed with respect to the root content APZC, the async
-  //    transform of the visual viewport relative to the layout viewport.
+  //    metadata, the "layout" portion of the root content APZC's async
+  //    transform (which includes async scrolling of the layout viewport
+  //    relative to the visual viewport).
   if (AsyncPanZoomController* apzc = aNode->GetApzc()) {
     // Apply any additional async scrolling for testing purposes (used for
     // reftest-async-scroll and reftest-async-zoom).
     AutoApplyAsyncTestAttributes testAttributeApplier(apzc);
     // If the node represents scrollable content, apply the async transform
     // from its APZC.
     AsyncTransformComponents components =
         mUsingAsyncZoomContainer && apzc->IsRootContent()
-            ? AsyncTransformComponents{AsyncTransformComponent::eScroll}
-            : ScrollAndZoom;
+            ? AsyncTransformComponents{AsyncTransformComponent::eLayout}
+            : LayoutAndVisual;
     return aNode->GetTransform() *
            CompleteAsyncTransform(apzc->GetCurrentAsyncTransformWithOverscroll(
                AsyncPanZoomController::eForHitTesting, components));
   } else if (aNode->IsAsyncZoomContainer()) {
     if (AsyncPanZoomController* rootContent =
             FindRootContentApzcForLayersId(aNode->GetLayersId())) {
       return aNode->GetTransform() *
              CompleteAsyncTransform(
                  rootContent->GetCurrentAsyncTransformWithOverscroll(
                      AsyncPanZoomController::eForHitTesting,
-                     {AsyncTransformComponent::eZoom}));
-    }
-  } else if (mUsingAsyncZoomContainer &&
-             aNode->GetFixedPosTarget() !=
-                 ScrollableLayerGuid::NULL_SCROLL_ID) {
-    if (AsyncPanZoomController* rootContent =
-            FindRootContentApzcForLayersId(aNode->GetLayersId())) {
-      if (aNode->GetFixedPosTarget() == rootContent->GetGuid().mScrollId) {
-        return aNode->GetTransform() *
-               CompleteAsyncTransform(
-                   rootContent->GetCurrentAsyncViewportRelativeTransform(
-                       AsyncPanZoomController::eForHitTesting));
-      }
+                     {AsyncTransformComponent::eVisual}));
     }
   } else if (aNode->IsScrollThumbNode()) {
     // If the node represents a scrollbar thumb, compute and apply the
     // transformation that will be applied to the thumb in
     // AsyncCompositionManager.
     ScrollableLayerGuid guid{aNode->GetLayersId(), 0,
                              aNode->GetScrollTargetId()};
     if (RefPtr<HitTestingTreeNode> scrollTargetNode =
--- a/gfx/layers/apz/src/APZSampler.cpp
+++ b/gfx/layers/apz/src/APZSampler.cpp
@@ -167,26 +167,16 @@ AsyncTransform APZSampler::GetCurrentAsy
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   AssertOnSamplerThread();
 
   MOZ_ASSERT(aLayer.GetApzc());
   return aLayer.GetApzc()->GetCurrentAsyncTransformForFixedAdjustment(
       AsyncPanZoomController::eForCompositing);
 }
 
-AsyncTransform APZSampler::GetCurrentAsyncViewportRelativeTransform(
-    const LayerMetricsWrapper& aLayer) {
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  AssertOnSamplerThread();
-
-  MOZ_ASSERT(aLayer.GetApzc());
-  return aLayer.GetApzc()->GetCurrentAsyncViewportRelativeTransform(
-      AsyncPanZoomController::eForCompositing);
-}
-
 AsyncTransformComponentMatrix APZSampler::GetOverscrollTransform(
     const LayerMetricsWrapper& aLayer) {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   AssertOnSamplerThread();
 
   MOZ_ASSERT(aLayer.GetApzc());
   return aLayer.GetApzc()->GetOverscrollTransform(
       AsyncPanZoomController::eForCompositing);
--- a/gfx/layers/apz/src/APZUtils.h
+++ b/gfx/layers/apz/src/APZUtils.h
@@ -133,22 +133,22 @@ class MOZ_RAII AutoApplyAsyncTestAttribu
   explicit AutoApplyAsyncTestAttributes(AsyncPanZoomController*);
   ~AutoApplyAsyncTestAttributes();
 
  private:
   AsyncPanZoomController* mApzc;
   FrameMetrics mPrevFrameMetrics;
 };
 
-enum class AsyncTransformComponent { eScroll, eZoom };
+enum class AsyncTransformComponent { eLayout, eVisual };
 
 using AsyncTransformComponents = EnumSet<AsyncTransformComponent>;
 
-constexpr AsyncTransformComponents ScrollAndZoom(
-    AsyncTransformComponent::eScroll, AsyncTransformComponent::eZoom);
+constexpr AsyncTransformComponents LayoutAndVisual(
+    AsyncTransformComponent::eLayout, AsyncTransformComponent::eVisual);
 
 namespace apz {
 
 /**
  * Initializes the global state used in AsyncPanZoomController.
  * This is normally called when it is first needed in the constructor
  * of APZCTreeManager, but can be called manually to force it to be
  * initialized earlier.
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -3981,104 +3981,90 @@ CSSPoint AsyncPanZoomController::GetCurr
 AsyncTransform AsyncPanZoomController::GetCurrentAsyncViewportTransform(
     AsyncTransformConsumer aMode) const {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
 
   if (aMode == eForCompositing && mScrollMetadata.IsApzForceDisabled()) {
     return AsyncTransform();
   }
 
-  CSSRect lastPaintViewport;
+  CSSPoint lastPaintViewportOffset;
   if (mLastContentPaintMetrics.IsScrollable()) {
-    lastPaintViewport = mLastContentPaintMetrics.GetLayoutViewport();
-  }
-
-  CSSRect currentViewport = GetEffectiveLayoutViewport(aMode);
-  CSSPoint currentViewportOffset = currentViewport.TopLeft();
+    lastPaintViewportOffset =
+        mLastContentPaintMetrics.GetLayoutViewport().TopLeft();
+  }
+
+  CSSPoint currentViewportOffset = GetEffectiveLayoutViewport(aMode).TopLeft();
 
   // Unlike the visual viewport, the layout viewport does not change size
   // (in the sense of "number of CSS pixels of page content it covers")
   // when zooming, so the async transform of the layout viewport does not
   // have an async zoom component. (The translation still needs to be
   // multiplied by the non-async zoom, to get it into the correct coordinates.)
   CSSToParentLayerScale2D effectiveZoom =
       Metrics().LayersPixelsPerCSSPixel() * LayerToParentLayerScale(1.0f);
   ParentLayerPoint translation =
-      (currentViewportOffset - lastPaintViewport.TopLeft()) * effectiveZoom;
+      (currentViewportOffset - lastPaintViewportOffset) * effectiveZoom;
   LayerToParentLayerScale compositedAsyncZoom;
 
   return AsyncTransform(compositedAsyncZoom, -translation);
 }
 
 AsyncTransform AsyncPanZoomController::GetCurrentAsyncTransform(
     AsyncTransformConsumer aMode, AsyncTransformComponents aComponents) const {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
 
   if (aMode == eForCompositing && mScrollMetadata.IsApzForceDisabled()) {
     return AsyncTransform();
   }
 
   CSSToParentLayerScale2D effectiveZoom;
-  if (aComponents.contains(AsyncTransformComponent::eZoom)) {
+  if (aComponents.contains(AsyncTransformComponent::eVisual)) {
     effectiveZoom = GetEffectiveZoom(aMode);
   } else {
     effectiveZoom =
         Metrics().LayersPixelsPerCSSPixel() * LayerToParentLayerScale(1.0f);
   }
 
   LayerToParentLayerScale compositedAsyncZoom =
       (effectiveZoom / Metrics().LayersPixelsPerCSSPixel()).ToScaleFactor();
 
   ParentLayerPoint translation;
-  if (aComponents.contains(AsyncTransformComponent::eScroll)) {
-    CSSPoint lastPaintScrollOffset;
+  if (aComponents.contains(AsyncTransformComponent::eVisual)) {
+    CSSPoint lastPaintVisualOffset;
     if (mLastContentPaintMetrics.IsScrollable()) {
-      lastPaintScrollOffset = mLastContentPaintMetrics.GetScrollOffset();
+      lastPaintVisualOffset =
+          mLastContentPaintMetrics.GetScrollOffset() -
+          mLastContentPaintMetrics.GetLayoutViewport().TopLeft();
     }
 
-    CSSPoint currentScrollOffset = GetEffectiveScrollOffset(aMode);
-
-    translation = (currentScrollOffset - lastPaintScrollOffset) * effectiveZoom;
+    CSSPoint currentVisualOffset =
+        GetEffectiveScrollOffset(aMode) -
+        GetEffectiveLayoutViewport(aMode).TopLeft();
+
+    translation += 
+        (currentVisualOffset - lastPaintVisualOffset) * effectiveZoom;
+  }
+  if (aComponents.contains(AsyncTransformComponent::eLayout)) {
+    CSSPoint lastPaintLayoutOffset;
+    if (mLastContentPaintMetrics.IsScrollable()) {
+      lastPaintLayoutOffset =
+          mLastContentPaintMetrics.GetLayoutViewport().TopLeft();
+    }
+
+    CSSPoint currentLayoutOffset =
+        GetEffectiveLayoutViewport(aMode).TopLeft();
+
+    translation += 
+        (currentLayoutOffset - lastPaintLayoutOffset) * effectiveZoom;
   }
 
   return AsyncTransform(compositedAsyncZoom, -translation);
 }
 
-AsyncTransform AsyncPanZoomController::GetCurrentAsyncViewportRelativeTransform(
-    AsyncTransformConsumer aMode) const {
-  RecursiveMutexAutoLock lock(mRecursiveMutex);
-
-  if (aMode == eForCompositing && mScrollMetadata.IsApzForceDisabled()) {
-    return AsyncTransform();
-  }
-
-  CSSPoint lastPaintRelativeViewportOffset;
-  if (mLastContentPaintMetrics.IsScrollable()) {
-    lastPaintRelativeViewportOffset =
-        mLastContentPaintMetrics.GetScrollOffset() -
-        mLastContentPaintMetrics.GetLayoutViewport().TopLeft();
-  }
-
-  CSSPoint currentRelativeViewportOffset =
-      GetEffectiveScrollOffset(aMode) -
-      GetEffectiveLayoutViewport(aMode).TopLeft();
-
-  // Don't include the zoom, because that applies to both the visual and
-  // layout viewports so it's not part of the *relative* transform.
-  // The non-async part of the zoom is only calculated so that we can get
-  // the translation into the right coordinate space.
-  CSSToParentLayerScale2D effectiveZoom =
-      Metrics().LayersPixelsPerCSSPixel() * LayerToParentLayerScale(1.0f);
-  ParentLayerPoint translation =
-      (currentRelativeViewportOffset - lastPaintRelativeViewportOffset) *
-      effectiveZoom;
-
-  return AsyncTransform(LayerToParentLayerScale{}, -translation);
-}
-
 AsyncTransform
 AsyncPanZoomController::GetCurrentAsyncTransformForFixedAdjustment(
     AsyncTransformConsumer aMode) const {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
 
   // Use the layout viewport to adjust fixed position elements if and only if
   // it's larger than the visual viewport (assuming we're scrolling the RCD-RSF
   // with apz.allow_zooming enabled).
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -1108,42 +1108,32 @@ class AsyncPanZoomController {
    * in progress. That is, when this transform is multiplied with the layer's
    * existing transform, it will make the layer appear with the desired pan/zoom
    * amount.
    * The transform can have both scroll and zoom components; the caller can
    * request just one or the other, or both, via the |aComponents| parameter.
    */
   AsyncTransform GetCurrentAsyncTransform(
       AsyncTransformConsumer aMode,
-      AsyncTransformComponents aComponents = ScrollAndZoom) const;
-
-  /**
-   * Get the current async transform of the visual viewport relative to
-   * the layout viewport.
-   * We don't have an |aComponents| parameter here because the relative
-   * transform can only be a translation (the visual and layout viewports
-   * are zoomed together).
-   */
-  AsyncTransform GetCurrentAsyncViewportRelativeTransform(
-      AsyncTransformConsumer aMode) const;
+      AsyncTransformComponents aComponents = LayoutAndVisual) const;
 
   /**
    * Returns the incremental transformation corresponding to the async
    * panning/zooming of the larger of the visual or layout viewport.
    */
   AsyncTransform GetCurrentAsyncTransformForFixedAdjustment(
       AsyncTransformConsumer aMode) const;
 
   /**
    * Returns the same transform as GetCurrentAsyncTransform(), but includes
    * any transform due to axis over-scroll.
    */
   AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll(
       AsyncTransformConsumer aMode,
-      AsyncTransformComponents aComponents = ScrollAndZoom) const;
+      AsyncTransformComponents aComponents = LayoutAndVisual) const;
 
   /**
    * Returns the "zoom" bits of the transform. This includes both the rasterized
    * (layout device to layer scale) and async (layer scale to parent layer
    * scale) components of the zoom.
    */
   LayoutDeviceToParentLayerScale GetCurrentPinchZoomScale(
       AsyncTransformConsumer aMode) const;
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -376,42 +376,16 @@ static bool AsyncTransformShouldBeUnappl
     // don't intend to match.
     if (current && current.AsRefLayer() != nullptr) {
       break;
     }
   }
   return false;
 }
 
-/**
- * Given a fixed-position layer, check if it's fixed with respect to the
- * zoomed APZC.
- */
-static bool IsFixedToZoomContainer(Layer* aFixedLayer) {
-  ScrollableLayerGuid::ViewID targetId =
-      aFixedLayer->GetFixedPositionScrollContainerId();
-  MOZ_ASSERT(targetId != ScrollableLayerGuid::NULL_SCROLL_ID);
-  LayerMetricsWrapper result(aFixedLayer, LayerMetricsWrapper::StartAt::BOTTOM);
-  while (result) {
-    if (Maybe<ScrollableLayerGuid::ViewID> zoomedScrollId =
-            result.IsAsyncZoomContainer()) {
-      return *zoomedScrollId == targetId;
-    }
-    // Don't ascend into another layer tree. Scroll IDs are not unique
-    // across layer trees, and in any case position:fixed doesn't reach
-    // across documents.
-    if (result.AsRefLayer() != nullptr) {
-      break;
-    }
-
-    result = result.GetParent();
-  }
-  return false;
-}
-
 // If |aLayer| is fixed or sticky, returns the scroll id of the scroll frame
 // that it's fixed or sticky to. Otherwise, returns Nothing().
 static Maybe<ScrollableLayerGuid::ViewID> IsFixedOrSticky(Layer* aLayer) {
   bool isRootOfFixedSubtree = aLayer->GetIsFixedPosition() &&
                               !aLayer->GetParent()->GetIsFixedPosition();
   if (isRootOfFixedSubtree) {
     return Some(aLayer->GetFixedPositionScrollContainerId());
   }
@@ -1030,18 +1004,18 @@ bool AsyncCompositionManager::ApplyAsync
             const FrameMetrics& metrics = wrapper.Metrics();
             MOZ_ASSERT(metrics.IsScrollable());
 
             hasAsyncTransform = true;
 
             AsyncTransformComponents asyncTransformComponents =
                 (zoomedMetrics &&
                  sampler->GetGuid(*zoomedMetrics) == sampler->GetGuid(wrapper))
-                    ? AsyncTransformComponents{AsyncTransformComponent::eScroll}
-                    : ScrollAndZoom;
+                    ? AsyncTransformComponents{AsyncTransformComponent::eLayout}
+                    : LayoutAndVisual;
 
             AsyncTransform asyncTransformWithoutOverscroll =
                 sampler->GetCurrentAsyncTransform(wrapper,
                                                   asyncTransformComponents);
             AsyncTransformComponentMatrix overscrollTransform =
                 sampler->GetOverscrollTransform(wrapper);
             AsyncTransformComponentMatrix asyncTransform =
                 AsyncTransformComponentMatrix(asyncTransformWithoutOverscroll) *
@@ -1211,47 +1185,26 @@ bool AsyncCompositionManager::ApplyAsync
             if (zoomedMetrics) {
               // Since we're querying the root content APZC's async transform,
               // we need to make sure any additional async scrolling for test
               // purposes is applied as well.
               AutoApplyAsyncTestAttributes testAttributeApplier(
                   zoomedMetrics->GetApzc());
 
               AsyncTransform zoomTransform = sampler->GetCurrentAsyncTransform(
-                  *zoomedMetrics, {AsyncTransformComponent::eZoom});
+                  *zoomedMetrics, {AsyncTransformComponent::eVisual});
               hasAsyncTransform = true;
               combinedAsyncTransform *=
                   AsyncTransformComponentMatrix(zoomTransform);
             } else {
               // TODO: Is this normal? It happens on some pages, such as
               // about:config on mobile, for just one frame or so, before the
               // scroll metadata for zoomedScrollId appears in the layer tree.
             }
           }
-
-          if (zoomedMetrics && layer->GetIsFixedPosition() &&
-              !layer->GetParent()->GetIsFixedPosition() &&
-              IsFixedToZoomContainer(layer)) {
-            // Since we're querying the root content APZC's async transform,
-            // we need to make sure any additional async scrolling for test
-            // purposes is applied as well.
-            AutoApplyAsyncTestAttributes testAttributeApplier(
-                zoomedMetrics->GetApzc());
-
-            LayerToParentLayerMatrix4x4 currentTransform;
-            LayerToParentLayerMatrix4x4 previousTransform =
-                CSSTransformMatrix() *
-                CompleteAsyncTransform(
-                    sampler->GetCurrentAsyncViewportRelativeTransform(
-                        *zoomedMetrics));
-            AdjustFixedOrStickyLayer(zoomContainer, layer,
-                                     sampler->GetGuid(*zoomedMetrics).mScrollId,
-                                     previousTransform, currentTransform,
-                                     fixedLayerMargins, clipPartsCache);
-          }
         }
 
         bool clipChanged = (hasAsyncTransform || clipDeferredFromChildren ||
                             layer->GetScrolledClipRect());
         if (clipChanged) {
           // Intersect the two clip parts and apply them to the layer.
           // During ApplyAsyncContentTransformTree on an ancestor layer,
           // AlignFixedAndStickyLayers may overwrite this with a new clip it