Bug 783368 - Prefer the critical display port, when set, in basic tiled layers. r=bgirard
authorChris Lord <chrislord.net@gmail.com>
Wed, 21 Nov 2012 22:34:18 +0000
changeset 113943 a79d36c9174b74127ce7579bd209ef4a57630505
parent 113942 7b0171b51aa37803f88aacf1fd734c14cd5b0765
child 113944 729f9f0d437f097661981e86f1e083a74d914cc5
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)
reviewersbgirard
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 - Prefer the critical display port, when set, in basic tiled layers. r=bgirard If a critical display port is set, only validate content within it when using basic tiled layers.
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/basic/BasicTiledThebesLayer.cpp
gfx/layers/ipc/CompositorParent.cpp
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -1306,20 +1306,22 @@ BasicShadowLayerManager::ProgressiveUpda
   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();
-    gfx::Rect displayPort((metrics.mDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
-                          (metrics.mDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
-                          metrics.mDisplayPort.width * devPixelRatioX,
-                          metrics.mDisplayPort.height * devPixelRatioY);
+    const gfx::Rect& metricsDisplayPort = metrics.mCriticalDisplayPort.IsEmpty() ?
+      metrics.mDisplayPort : metrics.mCriticalDisplayPort;
+    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,
       aViewport, aScaleX, aScaleY);
   }
 #endif
 
   return false;
--- a/gfx/layers/basic/BasicTiledThebesLayer.cpp
+++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp
@@ -383,50 +383,75 @@ BasicTiledThebesLayer::PaintThebes(gfxCo
     mValidRegion = nsIntRegion();
   }
 
   nsIntRegion invalidRegion = mVisibleRegion;
   invalidRegion.Sub(invalidRegion, mValidRegion);
   if (invalidRegion.IsEmpty())
     return;
 
+  // Calculate the transform required to convert screen space into layer space
+  gfx3DMatrix transform = GetEffectiveTransform();
+  // XXX Not sure if this code for intermediate surfaces is correct.
+  //     It rarely gets hit though, and shouldn't have terrible consequences
+  //     even if it is wrong.
+  for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
+    if (parent->UseIntermediateSurface()) {
+      transform.PreMultiply(parent->GetEffectiveTransform());
+    }
+  }
+  transform.Invert();
+
+  nsIntRect layerDisplayPort;
+  const gfx::Rect& criticalDisplayPort = GetParent()->GetFrameMetrics().mCriticalDisplayPort;
+  if (!criticalDisplayPort.IsEmpty()) {
+    // Find the critical display port in layer space.
+    gfxRect transformedCriticalDisplayPort = transform.TransformBounds(
+      gfxRect(criticalDisplayPort.x, criticalDisplayPort.y,
+              criticalDisplayPort.width, criticalDisplayPort.height));
+    transformedCriticalDisplayPort.RoundOut();
+    layerDisplayPort = nsIntRect(transformedCriticalDisplayPort.x,
+                                 transformedCriticalDisplayPort.y,
+                                 transformedCriticalDisplayPort.width,
+                                 transformedCriticalDisplayPort.height);
+
+    // Clip the invalid region to the critical display-port
+    invalidRegion.And(invalidRegion, layerDisplayPort);
+    if (invalidRegion.IsEmpty())
+      return;
+  }
+
   gfxSize resolution(1, 1);
   for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
     const FrameMetrics& metrics = parent->GetFrameMetrics();
     resolution.width *= metrics.mResolution.width;
     resolution.height *= metrics.mResolution.height;
   }
 
   // Only draw progressively when the resolution is unchanged.
   if (gfxPlatform::UseProgressiveTilePainting() &&
       !BasicManager()->HasShadowTarget() &&
       mTiledBuffer.GetResolution() == resolution) {
-    // Calculate the transform required to convert screen space into layer space
-    gfx3DMatrix transform = GetEffectiveTransform();
-    // XXX Not sure if this code for intermediate surfaces is correct.
-    //     It rarely gets hit though, and shouldn't have terrible consequences
-    //     even if it is wrong.
-    for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
-      if (parent->UseIntermediateSurface()) {
-        transform.PreMultiply(parent->GetEffectiveTransform());
-      }
-    }
-    transform.Invert();
-
     // Store the old valid region, then clear it before painting.
     // We clip the old valid region to the visible region, as it only gets
     // used to decide stale content (currently valid and previously visible)
     nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
     oldValidRegion.And(oldValidRegion, mVisibleRegion);
+    if (!layerDisplayPort.IsEmpty()) {
+      oldValidRegion.And(oldValidRegion, layerDisplayPort);
+    }
     mTiledBuffer.ClearPaintedRegion();
 
     // Make sure that tiles that fall outside of the visible region are
     // discarded on the first update.
     if (!BasicManager()->IsRepeatTransaction()) {
       mValidRegion.And(mValidRegion, mVisibleRegion);
+      if (!layerDisplayPort.IsEmpty()) {
+        mValidRegion.And(mValidRegion, layerDisplayPort);
+      }
     }
 
     // Calculate the scroll offset since the last transaction.
     gfx::Point scrollOffset(0, 0);
     Layer* primaryScrollable = BasicManager()->GetPrimaryScrollableLayer();
     if (primaryScrollable) {
       const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
       scrollOffset = metrics.mScrollOffset;
@@ -467,16 +492,19 @@ BasicTiledThebesLayer::PaintThebes(gfxCo
       // Paint the computed region and subtract it from the invalid region.
       mTiledBuffer.PaintThebes(this, validOrStale, regionToPaint, aCallback, aCallbackData);
       invalidRegion.Sub(invalidRegion, regionToPaint);
     } while (repeat);
   } else {
     mTiledBuffer.ClearPaintedRegion();
     mTiledBuffer.SetResolution(resolution);
     mValidRegion = mVisibleRegion;
+    if (!layerDisplayPort.IsEmpty()) {
+      mValidRegion.And(mValidRegion, layerDisplayPort);
+    }
     mTiledBuffer.PaintThebes(this, mValidRegion, invalidRegion, aCallback, aCallbackData);
   }
 
   mTiledBuffer.ReadLock();
 
   // Only paint the mask layer on the first transaction.
   if (aMaskLayer && !BasicManager()->IsRepeatTransaction()) {
     static_cast<BasicImplData*>(aMaskLayer->ImplData())
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -870,17 +870,18 @@ CompositorParent::TransformShadowTree(Ti
     } else if (!metrics.mContentRect.IsEqualEdges(mContentRect)) {
       mContentRect = metrics.mContentRect;
       SetPageRect(metrics.mScrollableRect);
     }
 
     // We synchronise the viewport information with Java after sending the above
     // notifications, so that Java can take these into account in its response.
     // Calculate the absolute display port to send to Java
-    gfx::Rect displayPortLayersPixels(metrics.mDisplayPort);
+    gfx::Rect displayPortLayersPixels(metrics.mCriticalDisplayPort.IsEmpty() ?
+                                      metrics.mDisplayPort : metrics.mCriticalDisplayPort);
     nsIntRect displayPortDevPixels(
       NS_lround(displayPortLayersPixels.x * devPixelRatioX),
       NS_lround(displayPortLayersPixels.y * devPixelRatioY),
       NS_lround(displayPortLayersPixels.width * devPixelRatioX),
       NS_lround(displayPortLayersPixels.height * devPixelRatioY));
 
     displayPortDevPixels.x += scrollOffsetDevPixels.x;
     displayPortDevPixels.y += scrollOffsetDevPixels.y;