Bug 1466611 - Use cached layout viewport when appropriate, only draw for RCD-RSF. r?botond draft
authorKashav Madan <kmadan@mozilla.com>
Mon, 04 Jun 2018 18:02:04 -0400
changeset 803845 281d87d8f905c43da53d1e1c9330d0f18c1a4b9b
parent 803844 27d93c95fb9a022094f6c6f61af7e92406d5f71b
push id112210
push userbmo:kmadan@mozilla.com
push dateMon, 04 Jun 2018 22:04:22 +0000
reviewersbotond
bugs1466611
milestone62.0a1
Bug 1466611 - Use cached layout viewport when appropriate, only draw for RCD-RSF. r?botond Adds GetEffectiveLayoutViewport to use the cached layout viewport when APZ frame delay is enabled, similar to GetEffectiveScrollOffset / GetEffectiveZoom. MozReview-Commit-ID: 3CyLqJ3AyrH
gfx/layers/apz/public/APZSampler.h
gfx/layers/apz/src/APZSampler.cpp
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/AsyncPanZoomController.h
gfx/layers/composite/ContainerLayerComposite.cpp
--- a/gfx/layers/apz/public/APZSampler.h
+++ b/gfx/layers/apz/public/APZSampler.h
@@ -76,21 +76,21 @@ public:
    */
   LayerToParentLayerMatrix4x4 ComputeTransformForScrollThumb(
       const LayerToParentLayerMatrix4x4& aCurrentTransform,
       const LayerMetricsWrapper& aContent,
       const ScrollbarData& aThumbData,
       bool aScrollbarIsDescendant,
       AsyncTransformComponentMatrix* aOutClipTransform);
 
+  CSSRect GetCurrentAsyncLayoutViewport(const LayerMetricsWrapper& aLayer);
   ParentLayerPoint GetCurrentAsyncScrollOffset(const LayerMetricsWrapper& aLayer);
   AsyncTransform GetCurrentAsyncTransform(const LayerMetricsWrapper& aLayer);
   AsyncTransformComponentMatrix GetOverscrollTransform(const LayerMetricsWrapper& aLayer);
   AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll(const LayerMetricsWrapper& aLayer);
-  CSSRect GetCurrentAsyncViewport(const LayerMetricsWrapper& aLayer);
 
   void MarkAsyncTransformAppliedToContent(const LayerMetricsWrapper& aLayer);
   bool HasUnusedAsyncTransform(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.
--- a/gfx/layers/apz/src/APZSampler.cpp
+++ b/gfx/layers/apz/src/APZSampler.cpp
@@ -145,16 +145,26 @@ APZSampler::ComputeTransformForScrollThu
                                               aContent.GetTransform(),
                                               aContent.GetApzc(),
                                               aContent.Metrics(),
                                               aThumbData,
                                               aScrollbarIsDescendant,
                                               aOutClipTransform);
 }
 
+CSSRect
+APZSampler::GetCurrentAsyncLayoutViewport(const LayerMetricsWrapper& aLayer)
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
+
+  MOZ_ASSERT(aLayer.GetApzc());
+  return aLayer.GetApzc()->GetCurrentAsyncLayoutViewport(AsyncPanZoomController::eForCompositing);
+}
+
 ParentLayerPoint
 APZSampler::GetCurrentAsyncScrollOffset(const LayerMetricsWrapper& aLayer)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   AssertOnSamplerThread();
 
   MOZ_ASSERT(aLayer.GetApzc());
   return aLayer.GetApzc()->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForCompositing);
@@ -185,26 +195,16 @@ APZSampler::GetCurrentAsyncTransformWith
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   AssertOnSamplerThread();
 
   MOZ_ASSERT(aLayer.GetApzc());
   return aLayer.GetApzc()->GetCurrentAsyncTransformWithOverscroll(AsyncPanZoomController::eForCompositing);
 }
 
-CSSRect
-APZSampler::GetCurrentAsyncViewport(const LayerMetricsWrapper& aLayer)
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  AssertOnSamplerThread();
-
-  MOZ_ASSERT(aLayer.GetApzc());
-  return aLayer.GetApzc()->GetCurrentAsyncViewport(AsyncPanZoomController::eForCompositing);
-}
-
 void
 APZSampler::MarkAsyncTransformAppliedToContent(const LayerMetricsWrapper& aLayer)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   AssertOnSamplerThread();
 
   MOZ_ASSERT(aLayer.GetApzc());
   aLayer.GetApzc()->MarkAsyncTransformAppliedToContent();
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -3726,16 +3726,28 @@ bool AsyncPanZoomController::AdvanceAnim
     APZThreadUtils::RunOnControllerThread(deferredTasks[i].forget());
   }
 
   // If any of the deferred tasks starts a new animation, it will request a
   // new composite directly, so we can just return requestAnimationFrame here.
   return requestAnimationFrame;
 }
 
+CSSRect
+AsyncPanZoomController::GetCurrentAsyncLayoutViewport(AsyncTransformConsumer aMode) const {
+  RecursiveMutexAutoLock lock(mRecursiveMutex);
+  if (!mFrameMetrics.IsRootContent()) {
+    return CSSRect();
+  }
+  if (aMode == eForCompositing && mScrollMetadata.IsApzForceDisabled()) {
+    return mLastContentPaintMetrics.GetViewport();
+  }
+  return GetEffectiveLayoutViewport(aMode);
+}
+
 ParentLayerPoint
 AsyncPanZoomController::GetCurrentAsyncScrollOffset(AsyncTransformConsumer aMode) const
 {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
 
   if (aMode == eForCompositing && mScrollMetadata.IsApzForceDisabled()) {
     return mLastContentPaintMetrics.GetScrollOffset() * mLastContentPaintMetrics.GetZoom();
   }
@@ -3797,16 +3809,25 @@ AsyncPanZoomController::GetCurrentAsyncT
 
   LayerToParentLayerScale compositedAsyncZoom =
       (effectiveZoom / mFrameMetrics.LayersPixelsPerCSSPixel()).ToScaleFactor();
   return AsyncTransform(
     LayerToParentLayerScale(compositedAsyncZoom.scale * mTestAsyncZoom.scale),
     -translation);
 }
 
+CSSRect
+AsyncPanZoomController::GetEffectiveLayoutViewport(AsyncTransformConsumer aMode) const
+{
+  if (gfxPrefs::APZFrameDelayEnabled() && aMode == eForCompositing) {
+    return mCompositedLayoutViewport;
+  }
+  return mFrameMetrics.GetViewport();
+}
+
 CSSPoint
 AsyncPanZoomController::GetEffectiveScrollOffset(AsyncTransformConsumer aMode) const
 {
   if (gfxPrefs::APZFrameDelayEnabled() && aMode == eForCompositing) {
     return mCompositedScrollOffset;
   }
   return mFrameMetrics.GetScrollOffset();
 }
@@ -3815,31 +3836,23 @@ CSSToParentLayerScale2D
 AsyncPanZoomController::GetEffectiveZoom(AsyncTransformConsumer aMode) const
 {
   if (gfxPrefs::APZFrameDelayEnabled() && aMode == eForCompositing) {
     return mCompositedZoom;
   }
   return mFrameMetrics.GetZoom();
 }
 
-CSSRect
-AsyncPanZoomController::GetCurrentAsyncViewport(AsyncTransformConsumer aMode) const {
-  RecursiveMutexAutoLock lock(mRecursiveMutex);
-  if (aMode == eForCompositing && mScrollMetadata.IsApzForceDisabled()) {
-    return mLastContentPaintMetrics.GetViewport();
-  }
-  return mFrameMetrics.GetViewport();
-}
-
 bool
 AsyncPanZoomController::SampleCompositedAsyncTransform()
 {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
   if (mCompositedScrollOffset != mFrameMetrics.GetScrollOffset() ||
       mCompositedZoom != mFrameMetrics.GetZoom()) {
+    mCompositedLayoutViewport = mFrameMetrics.GetViewport();
     mCompositedScrollOffset = mFrameMetrics.GetScrollOffset();
     mCompositedZoom = mFrameMetrics.GetZoom();
     return true;
   }
   return false;
 }
 
 AsyncTransformComponentMatrix
@@ -4088,16 +4101,17 @@ void AsyncPanZoomController::NotifyLayer
     // Initialize our internal state to something sane when the content
     // that was just painted is something we knew nothing about previously
     CancelAnimation();
 
     mScrollMetadata = aScrollMetadata;
     mExpectedGeckoMetrics = aLayerMetrics;
     ShareCompositorFrameMetrics();
 
+    mCompositedLayoutViewport = mFrameMetrics.GetViewport();
     mCompositedScrollOffset = mFrameMetrics.GetScrollOffset();
     mCompositedZoom = mFrameMetrics.GetZoom();
 
     if (mFrameMetrics.GetDisplayPortMargins() != ScreenMargin()) {
       // A non-zero display port margin here indicates a displayport has
       // been set by a previous APZC for the content at this guid. The
       // scrollable rect may have changed since then, making the margins
       // wrong, so we need to calculate a new display port.
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -903,18 +903,20 @@ private:
   FrameMetrics& mLastContentPaintMetrics;  // for convenience, refers to mLastContentPaintMetadata.mMetrics
   // The last metrics used for a content repaint request.
   FrameMetrics mLastPaintRequestMetrics;
   // The metrics that we expect content to have. This is updated when we
   // request a content repaint, and when we receive a shadow layers update.
   // This allows us to transform events into Gecko's coordinate space.
   FrameMetrics mExpectedGeckoMetrics;
 
-  // These variables cache the scroll offset and zoom stored in |mFrameMetrics|
-  // the last time SampleCompositedAsyncTransform() was called.
+  // These variables cache the layout viewport, scroll offset, and zoom stored
+  // in |mFrameMetrics| the last time SampleCompositedAsyncTransform() was
+  // called.
+  CSSRect mCompositedLayoutViewport;
   CSSPoint mCompositedScrollOffset;
   CSSToParentLayerScale2D mCompositedZoom;
 
   AxisX mX;
   AxisY mY;
 
   // This flag is set to true when we are in a axis-locked pan as a result of
   // the touch-action CSS property.
@@ -987,16 +989,22 @@ public:
    * regardless of mForceDisableApz.
    */
   enum AsyncTransformConsumer {
     eForHitTesting,
     eForCompositing,
   };
 
   /**
+   * Get the current layout viewport of the scrollable frame corresponding to
+   * this APZC.
+   */
+  CSSRect GetCurrentAsyncLayoutViewport(AsyncTransformConsumer aMode) const;
+
+  /**
    * Get the current scroll offset of the scrollable frame corresponding
    * to this APZC, including the effects of any asynchronous panning and
    * zooming, in ParentLayer pixels.
    */
   ParentLayerPoint GetCurrentAsyncScrollOffset(AsyncTransformConsumer aMode) const;
 
   /**
    * Get the current scroll offset of the scrollable frame corresponding
@@ -1020,43 +1028,38 @@ public:
   AsyncTransform GetCurrentAsyncTransform(AsyncTransformConsumer aMode) const;
 
   /**
    * Returns the same transform as GetCurrentAsyncTransform(), but includes
    * any transform due to axis over-scroll.
    */
   AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll(AsyncTransformConsumer aMode) const;
 
-  /**
-   * Get the current viewport of the scrollable frame corresponding to this
-   * APZC.
-   */
-  CSSRect GetCurrentAsyncViewport(AsyncTransformConsumer aMode) const;
-
 private:
   /**
    * Samples the composited async transform, making the result of
    * |GetCurrentAsyncTransform(eForCompositing)| and similar functions reflect
    * the async scroll offset and zoom stored in |mFrameMetrics|.
    *
    * Returns true if the newly sampled value is different from the previously
    * sampled value.
    *
    * (This is only relevant when |gfxPrefs::APZFrameDelayEnabled() == true|.
    * Otherwise, GetCurrentAsyncTransform() always reflects what's stored in
    * |mFrameMetrics| immediately, without any delay.)
    */
   bool SampleCompositedAsyncTransform();
 
   /*
-   * Helper functions to query the async scroll offset and zoom either
-   * directly from |mFrameMetrics|, or from cached variables that store
-   * the scroll offset and zoom from the last time it was sampled by
-   * calling SampleCompositedAsyncTransform(), depending on who is asking.
+   * Helper functions to query the async layout viewport, scroll offset, and
+   * zoom either directly from |mFrameMetrics|, or from cached variables that
+   * store the required value from the last time it was sampled by calling
+   * SampleCompositedAsyncTransform(), depending on who is asking.
    */
+  CSSRect GetEffectiveLayoutViewport(AsyncTransformConsumer aMode) const;
   CSSPoint GetEffectiveScrollOffset(AsyncTransformConsumer aMode) const;
   CSSToParentLayerScale2D GetEffectiveZoom(AsyncTransformConsumer aMode) const;
 
   /* ===================================================================
    * The functions and members in this section are used to manage
    * the state that tracks what this APZC is doing with the input events.
    */
 protected:
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -301,37 +301,40 @@ RenderMinimap(ContainerT* aContainer,
   LayerMetricsWrapper wrapper(aLayer, 0);
   if (!wrapper.GetApzc()) {
     return;
   }
   const FrameMetrics& fm = wrapper.Metrics();
   MOZ_ASSERT(fm.IsScrollable());
 
   ParentLayerPoint scrollOffset = aSampler->GetCurrentAsyncScrollOffset(wrapper);
-  CSSRect viewport = aSampler->GetCurrentAsyncViewport(wrapper);
+  CSSRect viewport = aSampler->GetCurrentAsyncLayoutViewport(wrapper);
 
   // Options
   const int verticalPadding = 10;
   const int horizontalPadding = 5;
   gfx::Color backgroundColor(0.3f, 0.3f, 0.3f, 0.3f);
   gfx::Color tileActiveColor(1, 1, 1, 0.4f);
   gfx::Color tileBorderColor(0, 0, 0, 0.1f);
   gfx::Color pageBorderColor(0, 0, 0);
   gfx::Color criticalDisplayPortColor(1.f, 1.f, 0);
   gfx::Color displayPortColor(0, 1.f, 0);
   gfx::Color layoutPortColor(1.f, 0, 0);
   gfx::Color visualPortColor(0, 0, 1.f, 0.3f);
 
   // Rects
   ParentLayerRect compositionBounds = fm.GetCompositionBounds();
   LayerRect scrollRect = fm.GetScrollableRect() * fm.LayersPixelsPerCSSPixel();
-  LayerRect layoutRect = viewport * fm.LayersPixelsPerCSSPixel();
   LayerRect visualRect = ParentLayerRect(scrollOffset, compositionBounds.Size()) / LayerToParentLayerScale(1);
   LayerRect dp = (fm.GetDisplayPort() + fm.GetScrollOffset()) * fm.LayersPixelsPerCSSPixel();
+  Maybe<LayerRect> layoutRect;
   Maybe<LayerRect> cdp;
+  if (!viewport.IsEmpty()) {
+    layoutRect = Some(viewport * fm.LayersPixelsPerCSSPixel());
+  }
   if (!fm.GetCriticalDisplayPort().IsEmpty()) {
     cdp = Some((fm.GetCriticalDisplayPort() + fm.GetScrollOffset()) * fm.LayersPixelsPerCSSPixel());
   }
 
   // Don't render trivial minimap. They can show up from textboxes and other tiny frames.
   if (visualRect.Width() < 64 && visualRect.Height() < 64) {
     return;
   }
@@ -372,19 +375,22 @@ RenderMinimap(ContainerT* aContainer,
   compositor->SlowDrawRect(r, displayPortColor, clipRect, aContainer->GetEffectiveTransform());
 
   // Render the critical displayport if there is one
   if (cdp) {
     r = transform.TransformBounds(cdp->ToUnknownRect());
     compositor->SlowDrawRect(r, criticalDisplayPortColor, clipRect, aContainer->GetEffectiveTransform());
   }
 
-  // Render the layout viewport.
-  r = transform.TransformBounds(layoutRect.ToUnknownRect());
-  compositor->SlowDrawRect(r, layoutPortColor, clipRect, aContainer->GetEffectiveTransform());
+  // Render the layout viewport if it exists (which is only in the root
+  // content APZC).
+  if (layoutRect) {
+    r = transform.TransformBounds(layoutRect->ToUnknownRect());
+    compositor->SlowDrawRect(r, layoutPortColor, clipRect, aContainer->GetEffectiveTransform());
+  }
 
   // Render the visual viewport.
   r = transform.TransformBounds(visualRect.ToUnknownRect());
   compositor->SlowDrawRect(r, visualPortColor, clipRect, aContainer->GetEffectiveTransform(), 2);
 }
 
 template<class ContainerT> void
 RenderLayers(ContainerT* aContainer, LayerManagerComposite* aManager,