Simplify copying the front buffer to the back buffer (bug 1399692 part 5, r=bas) draft
authorRyan Hunt <rhunt@eqrion.net>
Mon, 23 Oct 2017 18:27:53 -0400
changeset 695946 f3f76c0a394d30ddb01e0e63ff992a80f967a25a
parent 695945 1e7f2e8659f332ad5a691dd36dc1fc626f83a540
child 695947 c0b28ba4fbcd0d28e5cc94b5b36dfc59fd249c4b
push id88593
push userbmo:rhunt@eqrion.net
push dateFri, 10 Nov 2017 01:41:10 +0000
reviewersbas
bugs1399692
milestone58.0a1
Simplify copying the front buffer to the back buffer (bug 1399692 part 5, r=bas) To sync the back buffer with the front buffer, we set the back buffer rect and rotation to the front buffer's, and then copy over the pixels that different. We used to do the updating of the rect and rotation before BeginPaint, but that isn't necessary and we can move it to be with the copying of pixels. MozReview-Commit-ID: HzBKvMZkn1
gfx/layers/client/ContentClient.cpp
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -158,17 +158,16 @@ ContentClient::BeginPaint(PaintedLayer* 
   bool canDrawRotated = aFlags & PAINT_CAN_DRAW_ROTATED;
   IntRect drawBounds = result.mRegionToDraw.GetBounds();
 
   if (dest.mCanReuseBuffer) {
     MOZ_ASSERT(mBuffer);
 
     if (mBuffer->Lock(lockMode)) {
       // Do not modify result.mRegionToDraw or result.mContentType after this call.
-      // Do not modify the back buffer's bufferRect, bufferRotation, or didSelfCopy.
       FinalizeFrame(result.mRegionToDraw);
 
       if (!mBuffer->AdjustTo(dest.mBufferRect,
                              drawBounds,
                              canHaveRotation,
                              canDrawRotated)) {
         dest.mBufferRect = ComputeBufferRect(dest.mNeededRegion.GetBounds());
         dest.mCanReuseBuffer = false;
@@ -848,38 +847,20 @@ ContentClientDoubleBuffered::SwapBuffers
   mFrontAndBackBufferDiffer = true;
 }
 
 ContentClient::PaintState
 ContentClientDoubleBuffered::BeginPaint(PaintedLayer* aLayer,
                                         uint32_t aFlags)
 {
   mIsNewBuffer = false;
-
   if (!mFrontBuffer || !mBuffer) {
     mFrontAndBackBufferDiffer = false;
   }
 
-  if (mFrontAndBackBufferDiffer) {
-    if (mFrontBuffer->DidSelfCopy()) {
-      // We can't easily draw our front buffer into us, since we're going to be
-      // copying stuff around anyway it's easiest if we just move our situation
-      // to non-rotated while we're at it. If this situation occurs we'll have
-      // hit a self-copy path in PaintThebes before as well anyway.
-      gfx::IntRect backBufferRect = mBuffer->BufferRect();
-      backBufferRect.MoveTo(mFrontBuffer->BufferRect().TopLeft());
-
-      mBuffer->SetBufferRect(backBufferRect);
-      mBuffer->SetBufferRotation(IntPoint(0,0));
-    } else {
-      mBuffer->SetBufferRect(mFrontBuffer->BufferRect());
-      mBuffer->SetBufferRotation(mFrontBuffer->BufferRotation());
-    }
-  }
-
   return ContentClient::BeginPaint(aLayer, aFlags);
 }
 
 RefPtr<RotatedBuffer>
 ContentClientDoubleBuffered::GetFrontBuffer() const
 {
   return mFrontBuffer;
 }
@@ -887,50 +868,60 @@ ContentClientDoubleBuffered::GetFrontBuf
 // Sync front/back buffers content
 // After executing, the new back buffer has the same (interesting) pixels as
 // the new front buffer, and mValidRegion et al. are correct wrt the new
 // back buffer (i.e. as they were for the old back buffer)
 void
 ContentClientDoubleBuffered::FinalizeFrame(const nsIntRegion& aRegionToDraw)
 {
   if (!mFrontAndBackBufferDiffer) {
-    MOZ_ASSERT(!mFrontBuffer->DidSelfCopy(), "If we have to copy the world, then our buffers are different, right?");
+    MOZ_ASSERT(!mFrontBuffer || !mFrontBuffer->DidSelfCopy(),
+               "If the front buffer did a self copy then our front and back buffer must be different.");
     return;
   }
-  MOZ_ASSERT(mFrontBuffer);
-  if (!mFrontBuffer) {
+
+  MOZ_ASSERT(mFrontBuffer && mBuffer);
+  if (!mFrontBuffer || !mBuffer) {
     return;
   }
 
   MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): reading back <x=%d,y=%d,w=%d,h=%d>",
                   this,
                   mFrontUpdatedRegion.GetBounds().x,
                   mFrontUpdatedRegion.GetBounds().y,
                   mFrontUpdatedRegion.GetBounds().Width(),
                   mFrontUpdatedRegion.GetBounds().Height()));
 
   mFrontAndBackBufferDiffer = false;
 
+  // Move the back buffer rect and rotation to the front buffer rect and rotation
+  // so that we can update the pixels that changed between frames
+  gfx::IntRect backBufferRect = mBuffer->BufferRect();
+  backBufferRect.MoveTo(mFrontBuffer->BufferRect().TopLeft());
+  mBuffer->SetBufferRect(backBufferRect);
+  mBuffer->SetBufferRotation(mFrontBuffer->BufferRotation());
+
+  // Calculate the region to update
   nsIntRegion updateRegion = mFrontUpdatedRegion;
   if (mFrontBuffer->DidSelfCopy()) {
+    // If we did an unrotate operation on the front buffer we might as well
+    // unrotate as well because we will be reading back the whole front buffer
+    mBuffer->SetBufferRotation(IntPoint(0,0));
+
     mFrontBuffer->ClearDidSelfCopy();
     updateRegion = mBuffer->BufferRect();
   }
 
   // No point in sync'ing what we are going to draw over anyway. And if there is
   // nothing to sync at all, there is nothing to do and we can go home early.
   updateRegion.Sub(updateRegion, aRegionToDraw);
   if (updateRegion.IsEmpty()) {
     return;
   }
 
-  if (!mBuffer) {
-    return;
-  }
-
   if (mFrontBuffer->Lock(OpenMode::OPEN_READ_ONLY)) {
     mBuffer->UpdateDestinationFrom(*mFrontBuffer, updateRegion.GetBounds());
     mFrontBuffer->Unlock();
   }
 }
 
 } // namespace layers
 } // namespace mozilla