Implement record and replay painting for single tiled layers (
bug 1422392, r=nical)
MozReview-Commit-ID: 5MfnVZv2E12
--- a/gfx/layers/client/SingleTiledContentClient.cpp
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -42,16 +42,17 @@ SingleTiledContentClient::ClientSupports
int32_t maxTextureSize = aManager->GetMaxTextureSize();
return aSize.width <= maxTextureSize && aSize.height <= maxTextureSize;
}
ClientSingleTiledLayerBuffer::ClientSingleTiledLayerBuffer(ClientTiledPaintedLayer& aPaintedLayer,
CompositableClient& aCompositableClient,
ClientLayerManager* aManager)
: ClientTiledLayerBuffer(aPaintedLayer, aCompositableClient)
+ , mManager(aManager)
, mWasLastPaintProgressive(false)
, mFormat(gfx::SurfaceFormat::UNKNOWN)
{
}
void
ClientSingleTiledLayerBuffer::ReleaseTiles()
{
@@ -103,34 +104,34 @@ void
ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
const nsIntRegion& aPaintRegion,
const nsIntRegion& aDirtyRegion,
LayerManager::DrawPaintedLayerCallback aCallback,
void* aCallbackData,
TilePaintFlags aFlags)
{
mWasLastPaintProgressive = !!(aFlags & TilePaintFlags::Progressive);
+ bool asyncPaint = !!(aFlags & TilePaintFlags::Async);
// 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)
-;
+ 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);
@@ -234,17 +235,44 @@ ClientSingleTiledLayerBuffer::PaintThebe
}
}
if (dtOnWhite) {
dt = gfx::Factory::CreateDualDrawTarget(dt, dtOnWhite);
dtOnWhite = nullptr;
}
- {
+ if (asyncPaint) {
+ // Create a capture draw target
+ RefPtr<DrawTargetCapture> captureDT =
+ Factory::CreateCaptureDrawTarget(dt->GetBackendType(),
+ dt->GetSize(),
+ dt->GetFormat());
+
+ RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(captureDT);
+ if (!ctx) {
+ gfxDevCrash(gfx::LogReason::InvalidContext) << "SingleTiledContextClient context problem " << gfx::hexa(dt);
+ return;
+ }
+ 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.push_back(backBuffer);
+ if (backBufferOnWhite) {
+ capturedState->mClients.push_back(backBufferOnWhite);
+ }
+
+ PaintThread::Get()->PaintTiledContents(capturedState);
+ mManager->SetQueuedAsyncPaints();
+ } else {
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
if (!ctx) {
gfxDevCrash(gfx::LogReason::InvalidContext) << "SingleTiledContextClient context problem " << gfx::hexa(dt);
return;
}
ctx->SetMatrix(ctx->CurrentMatrix().PreTranslate(-mTilingOrigin.x, -mTilingOrigin.y));
aCallback(&mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
--- a/gfx/layers/client/SingleTiledContentClient.h
+++ b/gfx/layers/client/SingleTiledContentClient.h
@@ -80,16 +80,18 @@ public:
void ClearPaintedRegion() {
mPaintedRegion.SetEmpty();
}
private:
TileClient mTile;
+ RefPtr<ClientLayerManager> mManager;
+
nsIntRegion mPaintedRegion;
nsIntRegion mValidRegion;
bool mWasLastPaintProgressive;
/**
* While we're adding tiles, this is used to keep track of the position of
* the top-left of the top-left-most tile. When we come to wrap the tiles in
* TiledDrawTarget we subtract the value of this member from each tile's
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -505,17 +505,17 @@ CopyFrontToBack(TextureClient* aFront,
gfxWarning() << "[Tiling:Client] Failed to aquire the front buffer's draw target";
return false;
}
auto copy = CapturedTiledPaintState::Copy{
frontBuffer, backBuffer, aRectToCopy
};
- if (asyncPaint) {
+ if (asyncPaint && aCopies) {
aCopies->push_back(copy);
} else {
copy.CopyBuffer();
}
return true;
}
void