Bug 814864 - Only draw low precision tiles when necessary. r=kats
authorChris Lord <chrislord.net@gmail.com>
Thu, 29 Nov 2012 13:08:41 +0000
changeset 123585 dcd9afd94fe7a865544a810e6c472485c35b39a3
parent 123584 8df524ad81939550730b6bec200254c1b27eaa01
child 123586 b25eef2a982badfac52f1c2d2e819ad82d6f1539
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs814864
milestone20.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 814864 - Only draw low precision tiles when necessary. r=kats Use DisplayPortCalculator.aboutToCheckerboard to determine if we're in risk of checkerboarding while drawing tiles, and only then enable low precision rendering. This makes sure that we don't spend time doing low precision rendering when it isn't going to be of benefit (and thus decreases the likelihood of the user seeing low precision tiles unnecessarily).
mobile/android/base/gfx/GeckoLayerClient.java
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -71,17 +71,19 @@ public class GeckoLayerClient
     /* Used by robocop for testing purposes */
     private DrawListener mDrawListener;
 
     /* Used as a temporary ViewTransform by syncViewportInfo */
     private final ViewTransform mCurrentViewTransform;
 
     /* Used as the return value of progressiveUpdateCallback */
     private final ProgressiveUpdateData mProgressiveUpdateData;
-    private RectF mProgressiveUpdateDisplayPort;
+    private DisplayPortMetrics mProgressiveUpdateDisplayPort;
+    private boolean mLastProgressiveUpdateWasLowPrecision;
+    private boolean mProgressiveUpdateWasInDanger;
 
     /* This is written by the compositor thread and read by the UI thread. */
     private volatile boolean mCompositorCreated;
 
     private boolean mForceRedraw;
 
     /* The current viewport metrics.
      * This is volatile so that we can read and write to it from different threads.
@@ -111,17 +113,19 @@ public class GeckoLayerClient
         mContext = context;
         mScreenSize = new IntSize(0, 0);
         mWindowSize = new IntSize(0, 0);
         mDisplayPort = new DisplayPortMetrics();
         mRecordDrawTimes = true;
         mDrawTimingQueue = new DrawTimingQueue();
         mCurrentViewTransform = new ViewTransform(0, 0, 1);
         mProgressiveUpdateData = new ProgressiveUpdateData();
-        mProgressiveUpdateDisplayPort = new RectF();
+        mProgressiveUpdateDisplayPort = new DisplayPortMetrics();
+        mLastProgressiveUpdateWasLowPrecision = false;
+        mProgressiveUpdateWasInDanger = false;
         mCompositorCreated = false;
 
         mForceRedraw = true;
         DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
         mViewportMetrics = new ImmutableViewportMetrics(displayMetrics);
         mZoomConstraints = new ZoomConstraints(false);
 
         mPanZoomController = new PanZoomController(this, mEventDispatcher);
@@ -358,49 +362,80 @@ public class GeckoLayerClient
     // This is called on the Gecko thread to determine if we're still interested
     // in the update of this display-port to continue. We can return true here
     // to abort the current update and continue with any subsequent ones. This
     // is useful for slow-to-render pages when the display-port starts lagging
     // behind enough that continuing to draw it is wasted effort.
     public ProgressiveUpdateData progressiveUpdateCallback(boolean aHasPendingNewThebesContent,
                                                            float x, float y, float width, float height,
                                                            float resolution, boolean lowPrecision) {
+        // Skip all low precision draws until we're at risk of checkerboarding
+        if (lowPrecision && !mProgressiveUpdateWasInDanger) {
+            mProgressiveUpdateData.abort = true;
+            return mProgressiveUpdateData;
+        }
+
+        // Reset the checkerboard risk flag
+        if (!lowPrecision && mLastProgressiveUpdateWasLowPrecision) {
+            mProgressiveUpdateWasInDanger = false;
+        }
+        mLastProgressiveUpdateWasLowPrecision = lowPrecision;
+
         // Grab a local copy of the last display-port sent to Gecko and the
         // current viewport metrics to avoid races when accessing them.
         DisplayPortMetrics displayPort = mDisplayPort;
         ImmutableViewportMetrics viewportMetrics = mViewportMetrics;
         mProgressiveUpdateData.setViewport(viewportMetrics);
         mProgressiveUpdateData.abort = false;
 
         // Always abort updates if the resolution has changed. There's no use
         // in drawing at the incorrect resolution.
         if (!FloatUtils.fuzzyEquals(resolution, viewportMetrics.zoomFactor)) {
             Log.d(LOGTAG, "Aborting draw due to resolution change");
             mProgressiveUpdateData.abort = true;
             return mProgressiveUpdateData;
         }
 
+        // Store the high precision displayport for comparison when doing low
+        // precision updates.
+        if (!lowPrecision) {
+            if (!FloatUtils.fuzzyEquals(resolution, mProgressiveUpdateDisplayPort.resolution) ||
+                !FloatUtils.fuzzyEquals(x, mProgressiveUpdateDisplayPort.getLeft()) ||
+                !FloatUtils.fuzzyEquals(y, mProgressiveUpdateDisplayPort.getTop()) ||
+                !FloatUtils.fuzzyEquals(x + width, mProgressiveUpdateDisplayPort.getRight()) ||
+                !FloatUtils.fuzzyEquals(y + height, mProgressiveUpdateDisplayPort.getBottom())) {
+                mProgressiveUpdateDisplayPort =
+                    new DisplayPortMetrics(x, y, x+width, y+height, resolution);
+            }
+        }
+
         // XXX All sorts of rounding happens inside Gecko that becomes hard to
         //     account exactly for. Given we align the display-port to tile
         //     boundaries (and so they rarely vary by sub-pixel amounts), just
         //     check that values are within a couple of pixels of the
         //     display-port bounds.
 
         // Never abort drawing if we can't be sure we've sent a more recent
         // display-port. If we abort updating when we shouldn't, we can end up
         // with blank regions on the screen and we open up the risk of entering
         // an endless updating cycle.
-        if (!lowPrecision) {
-            mProgressiveUpdateDisplayPort.set(x, y, x + width, y + height);
+        if (Math.abs(displayPort.getLeft() - mProgressiveUpdateDisplayPort.getLeft()) <= 2 &&
+            Math.abs(displayPort.getTop() - mProgressiveUpdateDisplayPort.getTop()) <= 2 &&
+            Math.abs(displayPort.getBottom() - mProgressiveUpdateDisplayPort.getBottom()) <= 2 &&
+            Math.abs(displayPort.getRight() - mProgressiveUpdateDisplayPort.getRight()) <= 2) {
+            return mProgressiveUpdateData;
         }
-        if (Math.abs(displayPort.getLeft() - mProgressiveUpdateDisplayPort.left) <= 2 &&
-            Math.abs(displayPort.getTop() - mProgressiveUpdateDisplayPort.top) <= 2 &&
-            Math.abs(displayPort.getBottom() - mProgressiveUpdateDisplayPort.bottom) <= 2 &&
-            Math.abs(displayPort.getRight() - mProgressiveUpdateDisplayPort.right) <= 2) {
-            return mProgressiveUpdateData;
+
+        if (!lowPrecision && !mProgressiveUpdateWasInDanger) {
+            // If we're not doing low precision draws and we're about to
+            // checkerboard, give up and move onto low precision drawing.
+            if (DisplayPortCalculator.aboutToCheckerboard(viewportMetrics,
+                  mPanZoomController.getVelocityVector(), mProgressiveUpdateDisplayPort)) {
+                mProgressiveUpdateWasInDanger = true;
+            }
         }
 
         // Abort updates when the display-port no longer contains the visible
         // area of the page (that is, the viewport cropped by the page
         // boundaries).
         // XXX This makes the assumption that we never let the visible area of
         //     the page fall outside of the display-port.
         if (Math.max(viewportMetrics.viewportRectLeft, viewportMetrics.pageRectLeft) + 1 < x ||