Bug 783368 - Send the correct display port when rendering low precision. r=kats,bgirard
authorChris Lord <chrislord.net@gmail.com>
Wed, 21 Nov 2012 22:34:19 +0000
changeset 113948 3f1b3e8b8ac7e6ca19d82000be81d6bece3e94bf
parent 113947 7d09617883c7457cd72e3b125c7a6addf4a3eeec
child 113949 808c7d0aedecf74eab53ffcce3207359653e3c05
push id18466
push userchrislord.net@gmail.com
push dateWed, 21 Nov 2012 22:34:39 +0000
treeherdermozilla-inbound@c4d013240eac [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, bgirard
bugs783368
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 783368 - Send the correct display port when rendering low precision. r=kats,bgirard When doing a low precision update, send the display-port instead of the critical display port so that more appropriate cancelling decisions can be made.
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/basic/BasicLayers.h
gfx/layers/basic/BasicTiledThebesLayer.cpp
mobile/android/base/gfx/GeckoLayerClient.java
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -1294,37 +1294,39 @@ BasicShadowLayerManager::ClearCachedReso
   }
   BasicLayerManager::ClearCachedResources(aSubtree);
 }
 
 bool
 BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
                                                    gfx::Rect& aViewport,
                                                    float& aScaleX,
-                                                   float& aScaleY)
+                                                   float& aScaleY,
+                                                   bool aDrawingCritical)
 {
 #ifdef MOZ_WIDGET_ANDROID
   Layer* primaryScrollable = GetPrimaryScrollableLayer();
   if (primaryScrollable) {
     const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
 
     // This is derived from the code in
     // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
     const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
     float devPixelRatioX = 1 / rootTransform.GetXScale();
     float devPixelRatioY = 1 / rootTransform.GetYScale();
-    const gfx::Rect& metricsDisplayPort = metrics.mCriticalDisplayPort.IsEmpty() ?
-      metrics.mDisplayPort : metrics.mCriticalDisplayPort;
+    const gfx::Rect& metricsDisplayPort =
+      (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
+        metrics.mCriticalDisplayPort : metrics.mDisplayPort;
     gfx::Rect displayPort((metricsDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
                           (metricsDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
                           metricsDisplayPort.width * devPixelRatioX,
                           metricsDisplayPort.height * devPixelRatioY);
 
     return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
-      aHasPendingNewThebesContent, displayPort, devPixelRatioX,
+      aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
       aViewport, aScaleX, aScaleY);
   }
 #endif
 
   return false;
 }
 
 already_AddRefed<ThebesLayer>
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -279,26 +279,28 @@ public:
   bool GetRepeatTransaction() { return mRepeatTransaction; }
 
   bool IsRepeatTransaction() { return mIsRepeatTransaction; }
 
   /**
    * Called for each iteration of a progressive tile update. Fills
    * aViewport, aScaleX and aScaleY with the current scale and viewport
    * being used to composite the layers in this manager, to determine what area
-   * intersects with the target render rectangle.
+   * intersects with the target render rectangle. aDrawingCritical will be
+   * true if the current drawing operation is using the critical displayport.
    * Returns true if the update should continue, or false if it should be
    * cancelled.
    * This is only called if gfxPlatform::UseProgressiveTilePainting() returns
    * true.
    */
   bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
                                  gfx::Rect& aViewport,
                                  float& aScaleX,
-                                 float& aScaleY);
+                                 float& aScaleY,
+                                 bool aDrawingCritical);
 
 private:
   /**
    * Forward transaction results to the parent context.
    */
   void ForwardTransaction();
 
   // The bounds of |mTarget| in device pixels.
--- a/gfx/layers/basic/BasicTiledThebesLayer.cpp
+++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp
@@ -273,31 +273,32 @@ BasicTiledThebesLayer::ComputeProgressiv
                                                       const gfxSize& aResolution,
                                                       bool aIsRepeated)
 {
   aRegionToPaint = aInvalidRegion;
 
   // If this is a low precision buffer, we force progressive updates. The
   // assumption is that the contents is less important, so visual coherency
   // is lower priority than speed.
-  bool forceProgressive = aTiledBuffer.IsLowPrecision();
+  bool drawingLowPrecision = aTiledBuffer.IsLowPrecision();
 
   // Find out if we have any non-stale content to update.
   nsIntRegion freshRegion;
   if (!mFirstPaint) {
     freshRegion.And(aInvalidRegion, aOldValidRegion);
     freshRegion.Sub(aInvalidRegion, freshRegion);
   }
 
   // Find out the current view transform to determine which tiles to draw
   // first, and see if we should just abort this paint. Aborting is usually
   // caused by there being an incoming, more relevant paint.
   gfx::Rect viewport;
   float scaleX, scaleY;
-  if (BasicManager()->ProgressiveUpdateCallback(!freshRegion.IsEmpty(), viewport, scaleX, scaleY)) {
+  if (BasicManager()->ProgressiveUpdateCallback(!freshRegion.IsEmpty(), viewport,
+                                                scaleX, scaleY, !drawingLowPrecision)) {
     SAMPLE_MARKER("Abort painting");
     aRegionToPaint.SetEmpty();
     return aIsRepeated;
   }
 
   // Transform the screen coordinates into local layer coordinates.
   nsIntRect roundedTransformedViewport =
     RoundedTransformViewportBounds(viewport, aScrollOffset, aResolution,
@@ -362,17 +363,17 @@ BasicTiledThebesLayer::ComputeProgressiv
   if (!aRegionToPaint.Contains(aInvalidRegion)) {
     // The region needed to paint is larger then our progressive chunk size
     // therefore update what we want to paint and ask for a new paint transaction.
 
     // If we're drawing stale, visible content, make sure that it happens
     // in one go by repeating this work without calling the painted
     // callback. The remaining content is then drawn tile-by-tile in
     // multiple transactions.
-    if (!forceProgressive && paintVisible && drawingStale) {
+    if (!drawingLowPrecision && paintVisible && drawingStale) {
       repeatImmediately = true;
     } else {
       BasicManager()->SetRepeatTransaction();
     }
   }
 
   return repeatImmediately;
 }
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -71,16 +71,17 @@ 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 boolean mProgressiveUpdateIsCurrent;
 
     /* 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.
@@ -354,46 +355,51 @@ 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) {
+                                                           float x, float y, float width, float height,
+                                                           float resolution, boolean 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, displayPort.resolution)) {
-            Log.d(LOGTAG, "Aborting draw due to resolution change");
-            mProgressiveUpdateData.abort = true;
-            return mProgressiveUpdateData;
-        }
-
         // 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 (Math.abs(displayPort.getLeft() - x) <= 2 &&
-            Math.abs(displayPort.getTop() - y) <= 2 &&
-            Math.abs(displayPort.getBottom() - (y + height)) <= 2 &&
-            Math.abs(displayPort.getRight() - (x + width)) <= 2) {
+        if (!lowPrecision) {
+            mProgressiveUpdateIsCurrent =
+              Math.abs(displayPort.getLeft() - x) <= 2 &&
+              Math.abs(displayPort.getTop() - y) <= 2 &&
+              Math.abs(displayPort.getBottom() - (y + height)) <= 2 &&
+              Math.abs(displayPort.getRight() - (x + width)) <= 2;
+        }
+        if (mProgressiveUpdateIsCurrent) {
+            return mProgressiveUpdateData;
+        }
+
+        // Always abort updates if the resolution has changed. There's no use
+        // in drawing at the incorrect resolution.
+        if (!FloatUtils.fuzzyEquals(resolution, displayPort.resolution)) {
+            Log.d(LOGTAG, "Aborting draw due to resolution change");
+            mProgressiveUpdateData.abort = true;
             return mProgressiveUpdateData;
         }
 
         // 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.
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -2588,23 +2588,23 @@ AndroidBridge::GetDisplayPort(bool aPage
         return NS_OK;
     AutoLocalJNIFrame jniFrame(env, 0);
     mLayerClient->GetDisplayPort(&jniFrame, aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, metrics, displayPort);
 
     return NS_OK;
 }
 
 bool
-AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, gfx::Rect& aViewport, float& aScaleX, float& aScaleY)
+AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY)
 {
     AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return false;
 
-    return client->ProgressiveUpdateCallback(aHasPendingNewThebesContent, aDisplayPort, aDisplayResolution, aViewport, aScaleX, aScaleY);
+    return client->ProgressiveUpdateCallback(aHasPendingNewThebesContent, aDisplayPort, aDisplayResolution, aDrawingCritical, aViewport, aScaleX, aScaleY);
 }
 
 void
 AndroidBridge::NotifyPaintedRect(float top, float left, float bottom, float right)
 {
     JNIEnv* env = GetJNIEnv();
     if (!env)
         return;
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -155,17 +155,17 @@ public:
     static void NotifyIMEEnabled(int aState, const nsAString& aTypeHint,
                                  const nsAString& aModeHint, const nsAString& aActionHint);
 
     static void NotifyIMEChange(const PRUnichar *aText, uint32_t aTextLen, int aStart, int aEnd, int aNewEnd);
 
     nsresult TakeScreenshot(nsIDOMWindow *window, int32_t srcX, int32_t srcY, int32_t srcW, int32_t srcH, int32_t dstY, int32_t dstX, int32_t dstW, int32_t dstH, int32_t bufW, int32_t bufH, int32_t tabId, int32_t token, jobject buffer);
     nsresult GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
 
-    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
+    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
 
     static void NotifyPaintedRect(float top, float left, float bottom, float right);
 
     void AcknowledgeEventSync();
 
     void EnableLocation(bool aEnable);
     void EnableLocationHighAccuracy(bool aEnable);
 
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -359,17 +359,17 @@ AndroidGeckoLayerClient::InitGeckoLayerC
 
     jViewportClass = GetClassGlobalRef(jEnv, "org/mozilla/gecko/gfx/ImmutableViewportMetrics");
     jViewportCtor = GetMethodID(jEnv, jViewportClass, "<init>", "(FFFFFFFFFFFFF)V");
 
     jDisplayportClass = GetClassGlobalRef(jEnv, "org/mozilla/gecko/gfx/DisplayPortMetrics");
     jDisplayportPosition = GetFieldID(jEnv, jDisplayportClass, "mPosition", "Landroid/graphics/RectF;");
     jDisplayportResolution = GetFieldID(jEnv, jDisplayportClass, "resolution", "F");
     jProgressiveUpdateCallbackMethod = getMethod("progressiveUpdateCallback",
-                                                 "(ZFFFFF)Lorg/mozilla/gecko/gfx/ProgressiveUpdateData;");
+                                                 "(ZFFFFFZ)Lorg/mozilla/gecko/gfx/ProgressiveUpdateData;");
 
 #endif
 }
 
 void
 AndroidLayerRendererFrame::InitLayerRendererFrameClass(JNIEnv *jEnv)
 {
 #ifdef MOZ_ANDROID_OMTC
@@ -848,32 +848,34 @@ AndroidGeckoLayerClient::SyncViewportInf
     aScrollOffset = nsIntPoint(viewTransform.GetX(env), viewTransform.GetY(env));
     aScaleX = aScaleY = viewTransform.GetScale(env);
 }
 
 bool
 AndroidGeckoLayerClient::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
                                                    const gfx::Rect& aDisplayPort,
                                                    float aDisplayResolution,
+                                                   bool aDrawingCritical,
                                                    gfx::Rect& aViewport,
                                                    float& aScaleX,
                                                    float& aScaleY)
 {
     JNIEnv *env = AndroidBridge::GetJNIEnv();
     if (!env)
         return false;
 
     AutoJObject progressiveUpdateDataJObj(env, env->CallObjectMethod(wrapped_obj,
                                                                      jProgressiveUpdateCallbackMethod,
                                                                      aHasPendingNewThebesContent,
                                                                      (float)aDisplayPort.x,
                                                                      (float)aDisplayPort.y,
                                                                      (float)aDisplayPort.width,
                                                                      (float)aDisplayPort.height,
-                                                                     aDisplayResolution));
+                                                                     aDisplayResolution,
+                                                                     !aDrawingCritical));
     if (env->ExceptionCheck()) {
         env->ExceptionDescribe();
         env->ExceptionClear();
         return false;
     }
 
     NS_ABORT_IF_FALSE(progressiveUpdateDataJObj, "No progressive update data!");
 
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -254,17 +254,17 @@ public:
 
     AndroidGeckoLayerClient() {}
     AndroidGeckoLayerClient(jobject jobj) { Init(jobj); }
 
     void SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
     void SetPageRect(const gfx::Rect& aCssPageRect);
     void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
                           nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
-    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
+    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
     bool CreateFrame(AutoLocalJNIFrame *jniFrame, AndroidLayerRendererFrame& aFrame);
     bool ActivateProgram(AutoLocalJNIFrame *jniFrame);
     bool DeactivateProgram(AutoLocalJNIFrame *jniFrame);
     void GetDisplayPort(AutoLocalJNIFrame *jniFrame, bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
 
 protected:
     static jclass jGeckoLayerClientClass;
     static jmethodID jSetFirstPaintViewport;