Implement record and replay painting for single tiled layers (bug 1422392, r=nical) draft
authorRyan Hunt <rhunt@eqrion.net>
Fri, 01 Dec 2017 15:51:19 -0500
changeset 708366 b2af9d7976f09178c4c74ed7254d5c4ab323e5bd
parent 708365 dd8d14f469f2a7d4f43c0a41373a6848f57f4b39
child 708367 dc59658bb31345275ac904cc94576588999c929f
push id92378
push userbmo:rhunt@eqrion.net
push dateWed, 06 Dec 2017 20:15:21 +0000
reviewersnical
bugs1422392
milestone59.0a1
Implement record and replay painting for single tiled layers (bug 1422392, r=nical) MozReview-Commit-ID: 5MfnVZv2E12
gfx/layers/client/SingleTiledContentClient.cpp
gfx/layers/client/SingleTiledContentClient.h
gfx/layers/client/TiledContentClient.cpp
--- 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