Bug 1459312 - AsyncCompositionManager changes to apply the async zoom to the async zoom container layer if appropriate. r=kats
authorBotond Ballo <botond@mozilla.com>
Sat, 02 Feb 2019 23:53:15 +0000
changeset 456583 4d6a4c43775b78788ef78aba2b9cab7f7c043d41
parent 456582 c858a0fe0feab0168823813cece7c5bcedc25461
child 456584 11ac6c2ac639b725497a5f2541abe8e86e34427b
push id77350
push userbballo@mozilla.com
push dateSat, 02 Feb 2019 23:55:46 +0000
treeherderautoland@a03c30492ed7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1459312
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 1459312 - AsyncCompositionManager changes to apply the async zoom to the async zoom container layer if appropriate. r=kats Differential Revision: https://phabricator.services.mozilla.com/D13348
gfx/layers/apz/public/APZSampler.h
gfx/layers/apz/src/APZSampler.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
--- a/gfx/layers/apz/public/APZSampler.h
+++ b/gfx/layers/apz/public/APZSampler.h
@@ -94,16 +94,18 @@ class APZSampler {
   AsyncTransformComponentMatrix GetOverscrollTransform(
       const LayerMetricsWrapper& aLayer);
   AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll(
       const LayerMetricsWrapper& aLayer);
 
   void MarkAsyncTransformAppliedToContent(const LayerMetricsWrapper& aLayer);
   bool HasUnusedAsyncTransform(const LayerMetricsWrapper& aLayer);
 
+  ScrollableLayerGuid GetGuid(const LayerMetricsWrapper& aLayer);
+
   /**
    * This can be used to assert that the current thread is the
    * sampler thread (which samples the async transform).
    * This does nothing if thread assertions are disabled.
    */
   void AssertOnSamplerThread() const;
 
   /**
--- a/gfx/layers/apz/src/APZSampler.cpp
+++ b/gfx/layers/apz/src/APZSampler.cpp
@@ -205,16 +205,24 @@ bool APZSampler::HasUnusedAsyncTransform
   AsyncPanZoomController* apzc = aLayer.GetApzc();
   return apzc && !apzc->GetAsyncTransformAppliedToContent() &&
          !AsyncTransformComponentMatrix(
               apzc->GetCurrentAsyncTransform(
                   AsyncPanZoomController::eForCompositing))
               .IsIdentity();
 }
 
+ScrollableLayerGuid APZSampler::GetGuid(const LayerMetricsWrapper& aLayer) {
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
+
+  MOZ_ASSERT(aLayer.GetApzc());
+  return aLayer.GetApzc()->GetGuid();
+}
+
 void APZSampler::AssertOnSamplerThread() const {
   if (APZThreadUtils::GetThreadAssertionsEnabled()) {
     MOZ_ASSERT(IsSamplerThread());
   }
 }
 
 bool APZSampler::IsSamplerThread() const {
   if (mIsUsingWebRender) {
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -868,23 +868,58 @@ bool AsyncCompositionManager::ApplyAsync
   bool appliedTransform = false;
   std::stack<Maybe<ParentLayerIntRect>> stackDeferredClips;
 
   // Maps layers to their ClipParts. The parts are not stored individually
   // on the layer, but during AlignFixedAndStickyLayers we need access to
   // the individual parts for descendant layers.
   ClipPartsCache clipPartsCache;
 
+  Layer* zoomContainer = nullptr;
+  Maybe<LayerMetricsWrapper> zoomedMetrics;
+
   ForEachNode<ForwardIterator>(
       aLayer,
-      [&stackDeferredClips](Layer* layer) {
+      [&](Layer* layer) {
         stackDeferredClips.push(Maybe<ParentLayerIntRect>());
+
+        // If we encounter the async zoom container, find the corresponding
+        // APZC and stash it into |zoomedMetrics|.
+        // (We stash it in the form of a LayerMetricsWrapper because
+        // APZSampler requires going through that rather than using the APZC
+        // directly.)
+        // We do this on the way down the tree (i.e. here in the pre-action)
+        // so that by the time we encounter the layers with the RCD-RSF's
+        // scroll metadata (which will be descendants of the async zoom
+        // container), we can check for it and know we should only apply the
+        // scroll portion of the async transform to those layers (as the zoom
+        // portion will go on the async zoom container).
+        if (Maybe<ScrollableLayerGuid::ViewID> zoomedScrollId =
+                layer->IsAsyncZoomContainer()) {
+          zoomContainer = layer;
+          ForEachNode<ForwardIterator>(
+              LayerMetricsWrapper(layer),
+              [zoomedScrollId, &zoomedMetrics](LayerMetricsWrapper aWrapper) {
+                // Do not descend into layer subtrees with a different layers
+                // id.
+                if (aWrapper.AsRefLayer()) {
+                  return TraversalFlag::Skip;
+                }
+
+                if (aWrapper.Metrics().GetScrollId() == *zoomedScrollId) {
+                  zoomedMetrics = Some(aWrapper);
+                  MOZ_ASSERT(zoomedMetrics->GetApzc());
+                  return TraversalFlag::Abort;
+                }
+
+                return TraversalFlag::Continue;
+              });
+        }
       },
-      [this, &aOutFoundRoot, &stackDeferredClips, &appliedTransform,
-       &clipPartsCache](Layer* layer) {
+      [&](Layer* layer) {
         Maybe<ParentLayerIntRect> clipDeferredFromChildren =
             stackDeferredClips.top();
         stackDeferredClips.pop();
         LayerToParentLayerMatrix4x4 oldTransform =
             layer->GetTransformTyped() * AsyncTransformMatrix();
 
         AsyncTransformComponentMatrix combinedAsyncTransform;
         bool hasAsyncTransform = false;
@@ -957,18 +992,25 @@ bool AsyncCompositionManager::ApplyAsync
             AutoApplyAsyncTestAttributes testAttributeApplier(
                 wrapper.GetApzc());
 
             const FrameMetrics& metrics = wrapper.Metrics();
             MOZ_ASSERT(metrics.IsScrollable());
 
             hasAsyncTransform = true;
 
+            AsyncTransformComponents asyncTransformComponents =
+                (zoomedMetrics &&
+                 sampler->GetGuid(*zoomedMetrics) == sampler->GetGuid(wrapper))
+                    ? AsyncTransformComponents{AsyncTransformComponent::eScroll}
+                    : ScrollAndZoom;
+
             AsyncTransform asyncTransformWithoutOverscroll =
-                sampler->GetCurrentAsyncTransform(wrapper);
+                sampler->GetCurrentAsyncTransform(wrapper,
+                                                  asyncTransformComponents);
             AsyncTransformComponentMatrix overscrollTransform =
                 sampler->GetOverscrollTransform(wrapper);
             AsyncTransformComponentMatrix asyncTransform =
                 AsyncTransformComponentMatrix(asyncTransformWithoutOverscroll) *
                 overscrollTransform;
 
             if (!layer->IsScrollableWithoutContent()) {
               sampler->MarkAsyncTransformAppliedToContent(wrapper);
@@ -1123,16 +1165,31 @@ bool AsyncCompositionManager::ApplyAsync
               if (scrollClip.GetMaskLayerIndex()) {
                 size_t maskLayerIndex = scrollClip.GetMaskLayerIndex().value();
                 Layer* ancestorMaskLayer =
                     layer->GetAncestorMaskLayerAt(maskLayerIndex);
                 ancestorMaskLayers.AppendElement(ancestorMaskLayer);
               }
             }
           }
+
+          if (Maybe<ScrollableLayerGuid::ViewID> zoomedScrollId =
+                  layer->IsAsyncZoomContainer()) {
+            if (zoomedMetrics) {
+              AsyncTransform zoomTransform = sampler->GetCurrentAsyncTransform(
+                  *zoomedMetrics, {AsyncTransformComponent::eZoom});
+              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.
+            }
+          }
         }
 
         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