Bug 793656 - Fix flickering during progressive tile updates. r=bgirard
authorChris Lord <chrislord.net@gmail.com>
Tue, 25 Sep 2012 20:13:40 +0100
changeset 108048 1ae26e279e17344fb692c899a5769cc9c31cb50f
parent 108047 50bb2e93c6cdd6cbfe749168373e1f41359f81ad
child 108049 f19c6f0992278635d279e8696e9702b70a00b643
push id15348
push userchrislord.net@gmail.com
push dateTue, 25 Sep 2012 19:13:58 +0000
treeherdermozilla-inbound@1ae26e279e17 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgirard
bugs793656
milestone18.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 793656 - Fix flickering during progressive tile updates. r=bgirard Force a single transaction when the resolution changes and for other updates, keep stale tiles within the visible region until the transaction is complete.
gfx/layers/basic/BasicTiledThebesLayer.cpp
--- a/gfx/layers/basic/BasicTiledThebesLayer.cpp
+++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp
@@ -235,17 +235,26 @@ BasicTiledThebesLayer::PaintThebes(gfxCo
     mValidRegion = nsIntRegion();
   }
 
   nsIntRegion regionToPaint = mVisibleRegion;
   regionToPaint.Sub(regionToPaint, mValidRegion);
   if (regionToPaint.IsEmpty())
     return;
 
-  if (gfxPlatform::UseProgressiveTilePainting()) {
+  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;
+  }
+
+  // Force immediate tile painting when the layer has changed resolution.
+  if (gfxPlatform::UseProgressiveTilePainting() &&
+      mTiledBuffer.GetResolution() == resolution) {
     nsIntRegionRectIterator it(regionToPaint);
     const nsIntRect* rect = it.Next();
     if (!rect)
       return;
 
     // Currently we start painting from the first rect of the invalid
     // region and convert that into a tile.
     // TODO: Use a smart tile prioritization such as:
@@ -260,48 +269,30 @@ BasicTiledThebesLayer::PaintThebes(gfxCo
       nsIntRect(paintTileStartX, paintTileStartY,
                 mTiledBuffer.GetTileLength(), mTiledBuffer.GetTileLength()));
 
     if (!maxPaint.Contains(regionToPaint)) {
       // 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.
       regionToPaint.And(regionToPaint, maxPaint);
       BasicManager()->SetRepeatTransaction();
-    }
 
-    // We want to continue to retain invalidated tiles that we're about to paint soon
-    // to prevent them from disapearing while doing progressive paint. However we only
-    // want to this if they were painted at the same resolution.
-    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;
+      // Make sure that tiles that fall outside of the visible region are discarded.
+      mValidRegion.And(mValidRegion, mVisibleRegion);
     }
 
-    nsIntRegion regionToRetain(mTiledBuffer.GetValidRegion());
-    if (false && mTiledBuffer.GetResolution() == resolution) {
-      // Retain stale tiles but keep them marked as invalid in mValidRegion
-      // so that they will be eventually repainted.
-      regionToRetain.And(regionToRetain, mVisibleRegion);
-      regionToRetain.Or(regionToRetain, regionToPaint);
-    } else {
-      regionToRetain = mValidRegion;
-      regionToRetain.Or(regionToRetain, regionToPaint);
-      mTiledBuffer.SetResolution(resolution);
-    }
-
-    // Paint and keep track of what we refreshed
-    mTiledBuffer.PaintThebes(this, regionToRetain, regionToPaint, aCallback, aCallbackData);
+    // Keep track of what we're about to refresh.
     mValidRegion.Or(mValidRegion, regionToPaint);
   } else {
-    mTiledBuffer.PaintThebes(this, mVisibleRegion, regionToPaint, aCallback, aCallbackData);
+    mTiledBuffer.SetResolution(resolution);
     mValidRegion = mVisibleRegion;
   }
 
+  mTiledBuffer.PaintThebes(this, mVisibleRegion, regionToPaint, aCallback, aCallbackData);
+
   mTiledBuffer.ReadLock();
   if (aMaskLayer) {
     static_cast<BasicImplData*>(aMaskLayer->ImplData())
       ->Paint(aContext, nullptr);
   }
 
   // Create a heap copy owned and released by the compositor. This is needed
   // since we're sending this over an async message and content needs to be