Preserve front buffer texture clients for copies (
bug 1422392, r=nical)
We collect the back buffer texture clients to preserve while
async painting is happening, but if we do a buffer copy we
should preserve front buffer clients as well.
MozReview-Commit-ID: 9KbXkqjm34v
--- a/gfx/layers/client/SingleTiledContentClient.cpp
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -139,29 +139,31 @@ ClientSingleTiledLayerBuffer::PaintThebe
if (mTile.IsPlaceholderTile()) {
mTile.SetTextureAllocator(this);
}
// The dirty region relative to the top-left of the tile.
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,
content, mode,
extraPainted,
aFlags,
&backBufferOnWhite,
- &paintCopies);
+ &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));
@@ -288,16 +290,17 @@ ClientSingleTiledLayerBuffer::PaintThebe
ctx->SetMatrix(ctx->CurrentMatrix().PreTranslate(-mTilingOrigin.x, -mTilingOrigin.y));
aCallback(&mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
ctx = nullptr;
// Replay on the paint thread
RefPtr<CapturedTiledPaintState> capturedState =
new CapturedTiledPaintState(dt,
captureDT);
+ capturedState->mClients = std::move(paintClients);
capturedState->mClients.push_back(backBuffer);
if (backBufferOnWhite) {
capturedState->mClients.push_back(backBufferOnWhite);
}
capturedState->mCopies = std::move(paintCopies);
capturedState->mClears = std::move(paintClears);
PaintThread::Get()->PaintTiledContents(capturedState);
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -474,17 +474,18 @@ TileClient::Flip()
mInvalidBack = invalidFront;
}
static bool
CopyFrontToBack(TextureClient* aFront,
TextureClient* aBack,
const gfx::IntRect& aRectToCopy,
TilePaintFlags aFlags,
- std::vector<CapturedTiledPaintState::Copy>* aCopies)
+ std::vector<CapturedTiledPaintState::Copy>* aCopies,
+ std::vector<RefPtr<TextureClient>>* aClients)
{
bool asyncPaint = !!(aFlags & TilePaintFlags::Async);
OpenMode asyncFlags = asyncPaint ? OpenMode::OPEN_ASYNC : OpenMode::OPEN_NONE;
TextureClientAutoLock frontLock(aFront, OpenMode::OPEN_READ | asyncFlags);
if (!frontLock.Succeeded()) {
return false;
}
@@ -506,28 +507,30 @@ CopyFrontToBack(TextureClient* aFront,
return false;
}
auto copy = CapturedTiledPaintState::Copy{
frontBuffer, backBuffer, aRectToCopy, aRectToCopy.TopLeft()
};
if (asyncPaint && aCopies) {
+ aClients->push_back(aFront);
aCopies->push_back(copy);
} else {
copy.CopyBuffer();
}
return true;
}
void
TileClient::ValidateBackBufferFromFront(const nsIntRegion& aDirtyRegion,
nsIntRegion& aAddPaintedRegion,
TilePaintFlags aFlags,
- std::vector<CapturedTiledPaintState::Copy>* aCopies)
+ 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);
if (aDirtyRegion.Contains(tileRect)) {
// The dirty region means that we no longer need the front buffer, so
// discard it.
@@ -545,20 +548,20 @@ TileClient::ValidateBackBufferFromFront(
return;
}
// Copy the bounding rect of regionToCopy. As tiles are quite small, it
// 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)) {
+ if (CopyFrontToBack(mFrontBuffer, mBackBuffer, gfxRectToCopy, aFlags, aCopies, aClients)) {
if (mBackBufferOnWhite) {
MOZ_ASSERT(mFrontBufferOnWhite);
- if (CopyFrontToBack(mFrontBufferOnWhite, mBackBufferOnWhite, gfxRectToCopy, aFlags, aCopies)) {
+ if (CopyFrontToBack(mFrontBufferOnWhite, mBackBufferOnWhite, gfxRectToCopy, aFlags, aCopies, aClients)) {
mInvalidBack.SetEmpty();
}
}
}
}
}
}
@@ -650,17 +653,18 @@ CreateBackBufferTexture(TextureClient* a
TextureClient*
TileClient::GetBackBuffer(CompositableClient& aCompositable,
const nsIntRegion& aDirtyRegion,
gfxContentType aContent,
SurfaceMode aMode,
nsIntRegion& aAddPaintedRegion,
TilePaintFlags aFlags,
RefPtr<TextureClient>* aBackBufferOnWhite,
- std::vector<CapturedTiledPaintState::Copy>* aCopies)
+ std::vector<CapturedTiledPaintState::Copy>* aCopies,
+ std::vector<RefPtr<TextureClient>>* aClients)
{
if (!mAllocator) {
gfxCriticalError() << "[TileClient] Missing TextureClientAllocator.";
return nullptr;
}
if (aMode != SurfaceMode::SURFACE_COMPONENT_ALPHA) {
// It can happen that a component-alpha layer stops being on component alpha
// on the next frame, just drop the buffers on white if that happens.
@@ -705,17 +709,17 @@ TileClient::GetBackBuffer(CompositableCl
if (!mBackBufferOnWhite) {
DiscardBackBuffer();
DiscardFrontBuffer();
return nullptr;
}
mInvalidBack = IntRect(IntPoint(), mBackBufferOnWhite->GetSize());
}
- ValidateBackBufferFromFront(aDirtyRegion, aAddPaintedRegion, aFlags, aCopies);
+ ValidateBackBufferFromFront(aDirtyRegion, 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)";
@@ -1146,17 +1150,18 @@ ClientMultiTiledLayerBuffer::ValidateTil
RefPtr<TextureClient> backBufferOnWhite;
RefPtr<TextureClient> backBuffer =
aTile.GetBackBuffer(mCompositableClient,
offsetScaledDirtyRegion,
content, mode,
extraPainted,
aFlags,
&backBufferOnWhite,
- &mPaintCopies);
+ &mPaintCopies,
+ &mPaintTilesTextureClients);
// 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);
// 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;
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -127,17 +127,18 @@ struct TileClient
* If nullptr is returned, aTextureClientOnWhite is undefined.
*/
TextureClient* GetBackBuffer(CompositableClient&,
const nsIntRegion& aDirtyRegion,
gfxContentType aContent, SurfaceMode aMode,
nsIntRegion& aAddPaintedRegion,
TilePaintFlags aFlags,
RefPtr<TextureClient>* aTextureClientOnWhite,
- std::vector<CapturedTiledPaintState::Copy>* aCopies);
+ std::vector<CapturedTiledPaintState::Copy>* aCopies,
+ std::vector<RefPtr<TextureClient>>* aClients);
void DiscardFrontBuffer();
void DiscardBackBuffer();
/* We wrap the back buffer in a class that disallows assignment
* so that we can track when ever it changes so that we can update
* the expiry tracker for expiring the back buffers */
@@ -166,17 +167,18 @@ struct TileClient
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,
nsIntRegion& aAddPaintedRegion,
TilePaintFlags aFlags,
- std::vector<CapturedTiledPaintState::Copy>* aCopies);
+ std::vector<CapturedTiledPaintState::Copy>* aCopies,
+ std::vector<RefPtr<TextureClient>>* aClients);
};
/**
* This struct stores all the data necessary to perform a paint so that it
* doesn't need to be recalculated on every repeated transaction.
*/
struct BasicTiledLayerPaintData {
/*