Bug 1290149 - Copy intersecting region from old frontbuffer to new backbuffer when single tile layer visible region changes; r?mstange
MozReview-Commit-ID: 96AhbNyw6pg
--- a/gfx/layers/client/SingleTiledContentClient.cpp
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -106,18 +106,29 @@ ClientSingleTiledLayerBuffer::PaintThebe
bool aIsProgressive)
{
mWasLastPaintProgressive = aIsProgressive;
// Compare layer valid region size to current backbuffer size, discard if not matching.
gfx::IntSize size = aNewValidRegion.GetBounds().Size();
gfx::IntPoint origin = aNewValidRegion.GetBounds().TopLeft();
nsIntRegion paintRegion = aPaintRegion;
+
+ RefPtr<TextureClient> discardedFrontBuffer = nullptr;
+ RefPtr<TextureClient> discardedFrontBufferOnWhite = nullptr;
+ nsIntRegion discardedValidRegion;
+
if (mSize != size ||
mTilingOrigin != origin) {
+ discardedFrontBuffer = mTile.mFrontBuffer;
+ discardedFrontBufferOnWhite = mTile.mFrontBufferOnWhite;
+ discardedValidRegion = mValidRegion;
+
+ TILING_LOG("TILING %p: Single-tile valid region changed. Discarding buffers.\n", &mPaintedLayer)
+;
ResetPaintedAndValidState();
mSize = size;
mTilingOrigin = origin;
paintRegion = aNewValidRegion;
}
SurfaceMode mode;
gfxContentType content = GetContentType(&mode);
@@ -165,16 +176,55 @@ ClientSingleTiledLayerBuffer::PaintThebe
dtOnWhite->FillRect(gfx::Rect(rect.x, rect.y, rect.width, rect.height),
gfx::ColorPattern(gfx::Color(1.0, 1.0, 1.0, 1.0)));
} else {
dt->ClearRect(gfx::Rect(rect.x, rect.y, rect.width, rect.height));
}
}
}
+ // If the old frontbuffer was discarded then attempt to copy what we
+ // can from it to the new backbuffer.
+ if (discardedFrontBuffer) {
+ nsIntRegion copyableRegion;
+ copyableRegion.And(aNewValidRegion, discardedValidRegion);
+ copyableRegion.SubOut(aDirtyRegion);
+
+ if (!copyableRegion.IsEmpty()) {
+ TextureClientAutoLock frontLock(discardedFrontBuffer,
+ OpenMode::OPEN_READ);
+ if (frontLock.Succeeded()) {
+ for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
+ const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
+ const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
+ discardedFrontBuffer->CopyToTextureClient(backBuffer, &rect, &dest);
+ }
+ }
+
+ if (discardedFrontBufferOnWhite && backBufferOnWhite) {
+ TextureClientAutoLock frontOnWhiteLock(discardedFrontBufferOnWhite,
+ OpenMode::OPEN_READ);
+ if (frontOnWhiteLock.Succeeded()) {
+ for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
+ const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
+ const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
+
+ discardedFrontBufferOnWhite->CopyToTextureClient(backBufferOnWhite,
+ &rect, &dest);
+ }
+ }
+ }
+
+ TILING_LOG("TILING %p: Region copied from discarded frontbuffer %s\n", &mPaintedLayer, Stringify(copyableRegion).c_str());
+
+ // We don't need to repaint valid content that was just copied.
+ paintRegion.SubOut(copyableRegion);
+ }
+ }
+
if (dtOnWhite) {
dt = gfx::Factory::CreateDualDrawTarget(dt, dtOnWhite);
dtOnWhite = nullptr;
}
{
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
if (!ctx) {