--- a/gfx/layers/client/SingleTiledContentClient.cpp
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -137,43 +137,50 @@ ClientSingleTiledLayerBuffer::PaintThebe
gfxContentType content = GetContentType(&mode);
mFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(content);
if (mTile.IsPlaceholderTile()) {
mTile.SetTextureAllocator(this);
}
// The dirty region relative to the top-left of the tile.
+ nsIntRegion tileVisibleRegion = aNewValidRegion.MovedBy(-mTilingOrigin);
nsIntRegion tileDirtyRegion = paintRegion.MovedBy(-mTilingOrigin);
std::vector<RefPtr<TextureClient>> paintClients;
std::vector<CapturedTiledPaintState::Copy> paintCopies;
std::vector<CapturedTiledPaintState::Clear> paintClears;
nsIntRegion extraPainted;
RefPtr<TextureClient> backBufferOnWhite;
RefPtr<TextureClient> backBuffer =
mTile.GetBackBuffer(mCompositableClient,
tileDirtyRegion,
+ tileVisibleRegion,
content, mode,
extraPainted,
aFlags,
&backBufferOnWhite,
&paintCopies,
&paintClients);
// Mark the area we need to paint in the back buffer as invalid in the
// front buffer as they will become out of sync.
mTile.mInvalidFront.OrWith(tileDirtyRegion);
// Add backbuffer's invalid region to the dirty region to be painted.
// This will be empty if we were able to copy from the front in to the back.
- paintRegion.OrWith(mTile.mInvalidBack.MovedBy(mTilingOrigin));
- tileDirtyRegion.OrWith(mTile.mInvalidBack);
+ nsIntRegion tileInvalidRegion = mTile.mInvalidBack;
+ tileInvalidRegion.AndWith(tileVisibleRegion);
+ paintRegion.OrWith(tileInvalidRegion.MovedBy(mTilingOrigin));
+ tileDirtyRegion.OrWith(tileInvalidRegion);
+
+ // Mark the region we will be painting and the region we copied from the front buffer as
+ // needing to be uploaded to the compositor
mTile.mUpdateRect = tileDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
extraPainted.MoveBy(mTilingOrigin);
extraPainted.And(extraPainted, aNewValidRegion);
mPaintedRegion.OrWith(paintRegion);
mPaintedRegion.OrWith(extraPainted);
if (!backBuffer) {
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -517,16 +517,17 @@ CopyFrontToBack(TextureClient* aFront,
} else {
copy.CopyBuffer();
}
return true;
}
void
TileClient::ValidateBackBufferFromFront(const nsIntRegion& aDirtyRegion,
+ const nsIntRegion& aVisibleRegion,
nsIntRegion& aAddPaintedRegion,
TilePaintFlags aFlags,
std::vector<CapturedTiledPaintState::Copy>* aCopies,
std::vector<RefPtr<TextureClient>>* aClients)
{
if (mBackBuffer && mFrontBuffer) {
gfx::IntSize tileSize = mFrontBuffer->GetSize();
const IntRect tileRect = IntRect(0, 0, tileSize.width, tileSize.height);
@@ -535,16 +536,17 @@ TileClient::ValidateBackBufferFromFront(
// The dirty region means that we no longer need the front buffer, so
// discard it.
DiscardFrontBuffer();
} else {
// Region that needs copying.
nsIntRegion regionToCopy = mInvalidBack;
regionToCopy.Sub(regionToCopy, aDirtyRegion);
+ regionToCopy.And(regionToCopy, aVisibleRegion);
aAddPaintedRegion = regionToCopy;
if (regionToCopy.IsEmpty()) {
// Just redraw it all.
return;
}
@@ -552,20 +554,20 @@ TileClient::ValidateBackBufferFromFront(
// is unlikely that we'd save much by copying each individual rect of the
// region, but we can reevaluate this if it becomes an issue.
const IntRect rectToCopy = regionToCopy.GetBounds();
gfx::IntRect gfxRectToCopy(rectToCopy.X(), rectToCopy.Y(), rectToCopy.Width(), rectToCopy.Height());
if (CopyFrontToBack(mFrontBuffer, mBackBuffer, gfxRectToCopy, aFlags, aCopies, aClients)) {
if (mBackBufferOnWhite) {
MOZ_ASSERT(mFrontBufferOnWhite);
if (CopyFrontToBack(mFrontBufferOnWhite, mBackBufferOnWhite, gfxRectToCopy, aFlags, aCopies, aClients)) {
- mInvalidBack.SetEmpty();
+ mInvalidBack.Sub(mInvalidBack, aVisibleRegion);
}
} else {
- mInvalidBack.SetEmpty();
+ mInvalidBack.Sub(mInvalidBack, aVisibleRegion);
}
}
}
}
}
void
TileClient::DiscardFrontBuffer()
@@ -648,16 +650,17 @@ CreateBackBufferTexture(TextureClient* a
}
return texture.forget();
}
TextureClient*
TileClient::GetBackBuffer(CompositableClient& aCompositable,
const nsIntRegion& aDirtyRegion,
+ const nsIntRegion& aVisibleRegion,
gfxContentType aContent,
SurfaceMode aMode,
nsIntRegion& aAddPaintedRegion,
TilePaintFlags aFlags,
RefPtr<TextureClient>* aBackBufferOnWhite,
std::vector<CapturedTiledPaintState::Copy>* aCopies,
std::vector<RefPtr<TextureClient>>* aClients)
{
@@ -709,17 +712,17 @@ TileClient::GetBackBuffer(CompositableCl
if (!mBackBufferOnWhite) {
DiscardBackBuffer();
DiscardFrontBuffer();
return nullptr;
}
mInvalidBack = IntRect(IntPoint(), mBackBufferOnWhite->GetSize());
}
- ValidateBackBufferFromFront(aDirtyRegion, aAddPaintedRegion, aFlags, aCopies, aClients);
+ ValidateBackBufferFromFront(aDirtyRegion, aVisibleRegion, aAddPaintedRegion, aFlags, aCopies, aClients);
}
OpenMode lockMode = aFlags & TilePaintFlags::Async ? OpenMode::OPEN_READ_WRITE_ASYNC
: OpenMode::OPEN_READ_WRITE;
if (!mBackBuffer->IsLocked()) {
if (!mBackBuffer->Lock(lockMode)) {
gfxCriticalError() << "[Tiling:Client] Failed to lock a tile (B)";
@@ -1115,49 +1118,60 @@ ClientMultiTiledLayerBuffer::ValidateTil
if (!aTile.mAllocator) {
aTile.SetTextureAllocator(mManager->GetCompositorBridgeChild()->GetTexturePool(
mManager->AsShadowForwarder(),
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(content),
TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD | TextureFlags::NON_BLOCKING_READ_LOCK));
MOZ_ASSERT(aTile.mAllocator);
}
- nsIntRegion offsetScaledDirtyRegion = aDirtyRegion.MovedBy(-aTileOrigin);
- offsetScaledDirtyRegion.ScaleRoundOut(mResolution, mResolution);
+ nsIntRegion tileDirtyRegion = aDirtyRegion.MovedBy(-aTileOrigin);
+ tileDirtyRegion.ScaleRoundOut(mResolution, mResolution);
+
+ nsIntRegion tileVisibleRegion = mNewValidRegion.MovedBy(-aTileOrigin);
+ tileVisibleRegion.ScaleRoundOut(mResolution, mResolution);
std::vector<CapturedTiledPaintState::Copy> asyncPaintCopies;
std::vector<RefPtr<TextureClient>> asyncPaintClients;
nsIntRegion extraPainted;
RefPtr<TextureClient> backBufferOnWhite;
RefPtr<TextureClient> backBuffer =
aTile.GetBackBuffer(mCompositableClient,
- offsetScaledDirtyRegion,
+ tileDirtyRegion,
+ tileVisibleRegion,
content, mode,
extraPainted,
aFlags,
&backBufferOnWhite,
&asyncPaintCopies,
&asyncPaintClients);
// Mark the area we need to paint in the back buffer as invalid in the
// front buffer as they will become out of sync.
- aTile.mInvalidFront.OrWith(offsetScaledDirtyRegion);
+ aTile.mInvalidFront.OrWith(tileDirtyRegion);
+
+ // Add the backbuffer's invalid region intersected with the visible region to the
+ // dirty region we will be painting. This will be empty if we are able to copy
+ // from the front into the back.
+ nsIntRegion tileInvalidRegion = aTile.mInvalidBack;
+ tileInvalidRegion.AndWith(tileVisibleRegion);
- // Add backbuffer's invalid region to the dirty region to be painted.
- // This will be empty if we were able to copy from the front in to the back.
- nsIntRegion invalidBack = aTile.mInvalidBack;
- invalidBack.MoveBy(aTileOrigin);
- invalidBack.ScaleInverseRoundOut(mResolution, mResolution);
- invalidBack.AndWith(mNewValidRegion);
- aDirtyRegion.OrWith(invalidBack);
- offsetScaledDirtyRegion.OrWith(aTile.mInvalidBack);
+ nsIntRegion invalidRegion = tileInvalidRegion;
+ invalidRegion.MoveBy(aTileOrigin);
+ invalidRegion.ScaleInverseRoundOut(mResolution, mResolution);
- aTile.mUpdateRect = offsetScaledDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
+ tileDirtyRegion.OrWith(tileInvalidRegion);
+ aDirtyRegion.OrWith(invalidRegion);
+ // Mark the region we will be painting and the region we copied from the front buffer as
+ // needing to be uploaded to the compositor
+ aTile.mUpdateRect = tileDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
+
+ // Add the region we copied from the front buffer into the painted region
extraPainted.MoveBy(aTileOrigin);
extraPainted.And(extraPainted, mNewValidRegion);
mPaintedRegion.Or(mPaintedRegion, extraPainted);
if (!backBuffer) {
return false;
}
@@ -1177,17 +1191,17 @@ ClientMultiTiledLayerBuffer::ValidateTil
drawTarget = Factory::CreateDualDrawTarget(dt, dtOnWhite);
} else {
drawTarget = dt;
}
auto clear = CapturedTiledPaintState::Clear{
dt,
dtOnWhite,
- offsetScaledDirtyRegion
+ tileDirtyRegion
};
gfx::Tile paintTile;
paintTile.mTileOrigin = gfx::IntPoint(aTileOrigin.x, aTileOrigin.y);
if (aFlags & TilePaintFlags::Async) {
RefPtr<CapturedTiledPaintState> asyncPaint = new CapturedTiledPaintState();
@@ -1215,17 +1229,17 @@ ClientMultiTiledLayerBuffer::ValidateTil
}
mPaintTiles.push_back(paintTile);
mTilingOrigin.x = std::min(mTilingOrigin.x, paintTile.mTileOrigin.x);
mTilingOrigin.y = std::min(mTilingOrigin.y, paintTile.mTileOrigin.y);
// The new buffer is now validated, remove the dirty region from it.
- aTile.mInvalidBack.SubOut(offsetScaledDirtyRegion);
+ aTile.mInvalidBack.SubOut(tileDirtyRegion);
aTile.Flip();
return true;
}
/**
* This function takes the transform stored in aTransformToCompBounds
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -123,16 +123,17 @@ struct TileClient
* If getting the back buffer required copying pixels from the front buffer
* then the copied region is stored in aAddPaintedRegion so the host side
* knows to upload it.
*
* If nullptr is returned, aTextureClientOnWhite is undefined.
*/
TextureClient* GetBackBuffer(CompositableClient&,
const nsIntRegion& aDirtyRegion,
+ const nsIntRegion& aVisibleRegion,
gfxContentType aContent, SurfaceMode aMode,
nsIntRegion& aAddPaintedRegion,
TilePaintFlags aFlags,
RefPtr<TextureClient>* aTextureClientOnWhite,
std::vector<CapturedTiledPaintState::Copy>* aCopies,
std::vector<RefPtr<TextureClient>>* aClients);
void DiscardFrontBuffer();
@@ -165,16 +166,17 @@ struct TileClient
#endif
nsIntRegion mInvalidFront;
nsIntRegion mInvalidBack;
nsExpirationState mExpirationState;
private:
// Copies dirty pixels from the front buffer into the back buffer,
// and records the copied region in aAddPaintedRegion.
void ValidateBackBufferFromFront(const nsIntRegion &aDirtyRegion,
+ const nsIntRegion& aVisibleRegion,
nsIntRegion& aAddPaintedRegion,
TilePaintFlags aFlags,
std::vector<CapturedTiledPaintState::Copy>* aCopies,
std::vector<RefPtr<TextureClient>>* aClients);
};
/**
* This struct stores all the data necessary to perform a paint so that it