Bug 814437 - Fix checkerboard measurement when using a critical displayport. r=bgirard
authorChris Lord <chrislord.net@gmail.com>
Thu, 29 Nov 2012 12:03:38 +0000
changeset 123579 78c67357c751b816e58f27db95a77767335d24f6
parent 123578 67720d8757c804d394ce2f5724b1c925b206af7b
child 123580 f039a331337f99a623667140c1d96b5554e71a22
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)
reviewersbgirard
bugs814437
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 814437 - Fix checkerboard measurement when using a critical displayport. r=bgirard The checkerboard measurement depended on the displayport coverage of the viewport, which was calculated in LayerRenderer. When using a critical displayport, this value changes, but this was not being accounted for. We have all the context we need for this Gecko-side, so move this code into LayerManagerOGL::ComputeRenderIntegrity and account for displayport coverage correctly.
gfx/layers/opengl/LayerManagerOGL.cpp
mobile/android/base/gfx/LayerRenderer.java
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -1697,42 +1697,110 @@ GetRegionArea(const nsIntRegion& aRegion
   int area = 0;
   nsIntRegionRectIterator it(aRegion);
   while (const nsIntRect* rect = it.Next()) {
     area += rect->width * rect->height;
   }
   return area;
 }
 
+static float
+GetDisplayportCoverage(const gfx::Rect& aDisplayPort,
+                       const gfx3DMatrix& aTransformToScreen,
+                       const nsIntRect& aScreenRect)
+{
+  gfxRect transformedDisplayport =
+    aTransformToScreen.TransformBounds(gfxRect(aDisplayPort.x,
+                                               aDisplayPort.y,
+                                               aDisplayPort.width,
+                                               aDisplayPort.height));
+  transformedDisplayport.RoundOut();
+  nsIntRect displayport = nsIntRect(transformedDisplayport.x,
+                                    transformedDisplayport.y,
+                                    transformedDisplayport.width,
+                                    transformedDisplayport.height);
+  if (!displayport.Contains(aScreenRect)) {
+    nsIntRegion coveredRegion;
+    coveredRegion.And(aScreenRect, displayport);
+    return GetRegionArea(coveredRegion) / (float)(aScreenRect.width * aScreenRect.height);
+  }
+
+  return 1.0f;
+}
+
 float
 LayerManagerOGL::ComputeRenderIntegrity()
 {
   // We only ever have incomplete rendering when progressive tiles are enabled.
-  if (!gfxPlatform::UseProgressiveTilePainting() || !GetRoot()) {
+  Layer* root = GetRoot();
+  if (!gfxPlatform::UseProgressiveTilePainting() || !root) {
     return 1.f;
   }
 
-  // XXX We assume that mWidgetSize represents the 'screen' area.
-  gfx3DMatrix transform;
-  nsIntRect screenRect(0, 0, mWidgetSize.width, mWidgetSize.height);
+  const FrameMetrics& rootMetrics = root->AsContainerLayer()->GetFrameMetrics();
+  nsIntRect screenRect(rootMetrics.mCompositionBounds.x,
+                       rootMetrics.mCompositionBounds.y,
+                       rootMetrics.mCompositionBounds.width,
+                       rootMetrics.mCompositionBounds.height);
+
+  float lowPrecisionMultiplier = 1.0f;
+  float highPrecisionMultiplier = 1.0f;
+#ifdef MOZ_ANDROID_OMTC
+  // Use the transform on the primary scrollable layer and its FrameMetrics
+  // to find out how much of the viewport the current displayport covers
+  bool hasLowPrecision = true;
+  Layer* primaryScrollable = GetPrimaryScrollableLayer();
+  if (primaryScrollable) {
+    // This is derived from the code in
+    // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
+    const gfx3DMatrix& rootTransform = root->GetTransform();
+    float devPixelRatioX = 1 / rootTransform.GetXScale();
+    float devPixelRatioY = 1 / rootTransform.GetYScale();
+
+    gfx3DMatrix transform = primaryScrollable->GetEffectiveTransform();
+    transform.ScalePost(devPixelRatioX, devPixelRatioY, 1);
+    const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
+
+    // Work out how much of the critical display-port covers the screen
+    if (!metrics.mCriticalDisplayPort.IsEmpty()) {
+      hasLowPrecision = true;
+      highPrecisionMultiplier =
+        GetDisplayportCoverage(metrics.mCriticalDisplayPort, transform, screenRect);
+    }
+
+    // Work out how much of the display-port covers the screen
+    if (!metrics.mDisplayPort.IsEmpty()) {
+      if (hasLowPrecision) {
+        lowPrecisionMultiplier =
+          GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
+      } else {
+        highPrecisionMultiplier =
+          GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
+      }
+    }
+  }
+#endif
+
   nsIntRegion screenRegion(screenRect);
   nsIntRegion lowPrecisionScreenRegion(screenRect);
-  ComputeRenderIntegrityInternal(GetRoot(), screenRegion,
+  gfx3DMatrix transform;
+  ComputeRenderIntegrityInternal(root, screenRegion,
                                  lowPrecisionScreenRegion, transform);
 
   if (!screenRegion.IsEqual(screenRect)) {
     // Calculate the area of the region. All rects in an nsRegion are
     // non-overlapping.
     float screenArea = screenRect.width * screenRect.height;
     float highPrecisionIntegrity = GetRegionArea(screenRegion) / screenArea;
     float lowPrecisionIntegrity = 1.f;
     if (!lowPrecisionScreenRegion.IsEqual(screenRect)) {
       lowPrecisionIntegrity = GetRegionArea(lowPrecisionScreenRegion) / screenArea;
     }
 
-    return (highPrecisionIntegrity + lowPrecisionIntegrity) / 2.f;
+    return ((highPrecisionIntegrity * highPrecisionMultiplier) +
+            (lowPrecisionIntegrity * lowPrecisionMultiplier)) / 2.f;
   }
 
   return 1.f;
 }
 
 } /* layers */
 } /* mozilla */
--- a/mobile/android/base/gfx/LayerRenderer.java
+++ b/mobile/android/base/gfx/LayerRenderer.java
@@ -593,56 +593,18 @@ public class LayerRenderer implements Ta
             /* Draw the horizontal scrollbar. */
             if (mPageRect.width() > mFrameMetrics.getWidth())
                 mHorizScrollLayer.draw(mPageContext);
 
             /* Measure how much of the screen is checkerboarding */
             Layer rootLayer = mView.getLayerClient().getRoot();
             if ((rootLayer != null) &&
                 (mProfileRender || PanningPerfAPI.isRecordingCheckerboard())) {
-                // Find out how much of the viewport area is valid
-                Rect viewport = RectUtils.round(mPageContext.viewport);
-                Region validRegion = rootLayer.getValidRegion(mPageContext);
-
-                /* restrict the viewport to page bounds so we don't
-                 * count overscroll as checkerboard */
-                if (!viewport.intersect(mAbsolutePageRect)) {
-                    /* if the rectangles don't intersect
-                       intersect() doesn't change viewport
-                       so we set it to empty by hand */
-                    viewport.setEmpty();
-                }
-                validRegion.op(viewport, Region.Op.INTERSECT);
-
-                // Check if we have total checkerboarding (there's visible
-                // page area and the valid region doesn't intersect with the
-                // viewport).
-                int screenArea = viewport.width() * viewport.height();
-                float checkerboard = (screenArea > 0 &&
-                  validRegion.quickReject(viewport)) ? 1.0f : 0.0f;
-
-                if (screenArea > 0 && checkerboard < 1.0f) {
-                    validRegion.op(viewport, Region.Op.REVERSE_DIFFERENCE);
-
-                    // XXX The assumption here is that a Region never has overlapping
-                    //     rects. This is true, as evidenced by reading the SkRegion
-                    //     source, but is not mentioned in the Android documentation,
-                    //     and so is liable to change.
-                    //     If it does change, this code will need to be reevaluated.
-                    Rect r = new Rect();
-                    int checkerboardArea = 0;
-                    for (RegionIterator i = new RegionIterator(validRegion); i.next(r);) {
-                        checkerboardArea += r.width() * r.height();
-                    }
-
-                    checkerboard = checkerboardArea / (float)screenArea;
-
-                    // Add any incomplete rendering in the screen area
-                    checkerboard += (1.0 - checkerboard) * (1.0 - GeckoAppShell.computeRenderIntegrity());
-                }
+                // Calculate the incompletely rendered area of the page
+                float checkerboard =  1.0f - GeckoAppShell.computeRenderIntegrity();
 
                 PanningPerfAPI.recordCheckerboard(checkerboard);
 
                 mCompleteFramesRendered += 1.0f - checkerboard;
                 mFramesRendered ++;
 
                 if (mFrameStartTime - mProfileOutputTime > 1000) {
                     mProfileOutputTime = mFrameStartTime;