Bug 1253860 - Skip paints for main thread scrolls if we can ask APZ to handle the scrolling for us. r?mstange draft
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 09 Mar 2016 18:29:16 -0500
changeset 338735 b6a5dccf57190ae1cfc0ce4ac5202ffccc193178
parent 338734 f4c460f2332d4a0e3a0b19bc0c199b6a668dfd71
child 338736 afba06d59ada9c0d23cf64b895dbdcc044cf3062
push id12574
push userkgupta@mozilla.com
push dateWed, 09 Mar 2016 23:29:35 +0000
reviewersmstange
bugs1253860
milestone48.0a1
Bug 1253860 - Skip paints for main thread scrolls if we can ask APZ to handle the scrolling for us. r?mstange MozReview-Commit-ID: 7uJdwztZT4e
layout/generic/nsGfxScrollFrame.cpp
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -58,17 +58,19 @@
 #include "nsIFrameInlines.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "AsyncScrollBase.h"
 #include "UnitTransforms.h"
 #include "nsPluginFrame.h"
 #include <mozilla/layers/AxisPhysicsModel.h>
 #include <mozilla/layers/AxisPhysicsMSDModel.h>
+#include "mozilla/layers/LayerTransactionChild.h"
 #include "mozilla/layers/ScrollLinkedEffectDetector.h"
+#include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/unused.h"
 #include <algorithm>
 #include <cstdlib> // for std::abs(int/long)
 #include <cmath> // for std::abs(float/double)
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layout;
@@ -2671,35 +2673,54 @@ ScrollFrameHelper::ScrollToImpl(nsPoint 
   // Update frame position for scrolling
   mScrolledFrame->SetPosition(mScrollPort.TopLeft() - pt);
   mLastScrollOrigin = aOrigin;
   mLastSmoothScrollOrigin = nullptr;
   mScrollGeneration = ++sScrollGenerationCounter;
 
   ScrollVisual();
 
-  if (LastScrollOrigin() == nsGkAtoms::apz && gfxPrefs::APZPaintSkipping()) {
-    // If this was an apz scroll and the displayport (relative to the
-    // scrolled frame) hasn't changed, then this won't trigger
-    // any painting, so no need to schedule one.
+  bool schedulePaint = true;
+  if (nsLayoutUtils::AsyncPanZoomEnabled(mOuter) && gfxPrefs::APZPaintSkipping()) {
+    // If APZ is enabled with paint-skipping, there are certain conditions in
+    // which we can skip paints:
+    // 1) If APZ triggered this scroll, and the tile-aligned displayport is
+    //    unchanged.
+    // 2) If non-APZ triggered this scroll, but we can handle it by just asking
+    //    APZ to update the scroll position. Again we make this conditional on
+    //    the tile-aligned displayport being unchanged.
+    // We do the displayport check first since it's common to all scenarios,
+    // and then if the displayport is unchanged, we check if APZ triggered,
+    // or can handle, this scroll. If so, we set schedulePaint to false and
+    // skip the paint.
     nsRect displayPort;
-    DebugOnly<bool> usingDisplayPort =
+    bool usingDisplayPort =
       nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort);
-    NS_ASSERTION(usingDisplayPort, "Must have a displayport for apz scrolls!");
-
     displayPort.MoveBy(-mScrolledFrame->GetPosition());
 
-    if (!displayPort.IsEqualEdges(oldDisplayPort)) {
-      mOuter->SchedulePaint();
-
-      if (needImageVisibilityUpdate) {
-        presContext->PresShell()->ScheduleImageVisibilityUpdate();
+    if (usingDisplayPort && displayPort.IsEqualEdges(oldDisplayPort)) {
+      if (LastScrollOrigin() == nsGkAtoms::apz) {
+        schedulePaint = false;
+      } else if (mScrollableByAPZ) {
+        nsIWidget* widget = presContext->GetNearestWidget();
+        LayerManager* manager = widget ? widget->GetLayerManager() : nullptr;
+        ShadowLayerForwarder* forwarder = manager ? manager->AsShadowForwarder() : nullptr;
+        if (forwarder && forwarder->HasShadowManager()) {
+          mozilla::layers::FrameMetrics::ViewID id;
+          DebugOnly<bool> success = nsLayoutUtils::FindIDFor(mOuter->GetContent(), &id);
+          MOZ_ASSERT(success); // we have a displayport, we better have an ID
+          forwarder->GetShadowManager()->SendUpdateScrollOffset(id,
+              mScrollGeneration, CSSPoint::FromAppUnits(GetScrollPosition()));
+          schedulePaint = false;
+        }
       }
     }
-  } else {
+  }
+
+  if (schedulePaint) {
     mOuter->SchedulePaint();
 
     if (needImageVisibilityUpdate) {
       presContext->PresShell()->ScheduleImageVisibilityUpdate();
     }
   }
 
   if (mOuter->ChildrenHavePerspective()) {