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 108165 1ae26e279e17344fb692c899a5769cc9c31cb50f
parent 108164 50bb2e93c6cdd6cbfe749168373e1f41359f81ad
child 108166 f19c6f0992278635d279e8696e9702b70a00b643
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersbgirard
bugs793656
milestone18.0a1
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