From 58ba18a382c7405ff418b64a40a382f68cc1fa87 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Thu, 10 Apr 2014 20:42:29 +1200 Subject: [PATCH] Bug 992486 - Part 5: Fix copying the front buffer to back buffer. r=roc --- gfx/layers/RotatedBuffer.cpp | 69 ++++++++++++++++------------- gfx/layers/RotatedBuffer.h | 3 +- gfx/layers/client/ContentClient.cpp | 56 +++++++++++------------ 3 files changed, 67 insertions(+), 61 deletions(-) diff --git a/gfx/layers/RotatedBuffer.cpp b/gfx/layers/RotatedBuffer.cpp index e4b2e012d832..e3b0c5f70fe5 100644 --- a/gfx/layers/RotatedBuffer.cpp +++ b/gfx/layers/RotatedBuffer.cpp @@ -228,8 +228,32 @@ RotatedContentBuffer::DrawTo(ThebesLayer* aLayer, DrawTarget* RotatedContentBuffer::BorrowDrawTargetForQuadrantUpdate(const nsIntRect& aBounds, - ContextSource aSource) + ContextSource aSource, + DrawIterator* aIter) { + nsIntRect bounds = aBounds; + if (aIter) { + // If an iterator was provided, then BeginPaint must have been run with + // PAINT_CAN_DRAW_ROTATED, and the draw region might cover multiple quadrants. + // Iterate over each of them, and return an appropriate buffer each time we find + // one that intersects the draw region. The iterator mCount value tracks which + // quadrants we have considered across multiple calls to this function. + aIter->mDrawRegion.SetEmpty(); + while (aIter->mCount < 4) { + nsIntRect quadrant = GetQuadrantRectangle((aIter->mCount & 1) ? LEFT : RIGHT, + (aIter->mCount & 2) ? TOP : BOTTOM); + aIter->mDrawRegion.And(aBounds, quadrant); + aIter->mCount++; + if (!aIter->mDrawRegion.IsEmpty()) { + break; + } + } + if (aIter->mDrawRegion.IsEmpty()) { + return nullptr; + } + bounds = aIter->mDrawRegion.GetBounds(); + } + if (!EnsureBuffer()) { return nullptr; } @@ -254,10 +278,10 @@ RotatedContentBuffer::BorrowDrawTargetForQuadrantUpdate(const nsIntRect& aBounds // Figure out which quadrant to draw in int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x; int32_t yBoundary = mBufferRect.YMost() - mBufferRotation.y; - XSide sideX = aBounds.XMost() <= xBoundary ? RIGHT : LEFT; - YSide sideY = aBounds.YMost() <= yBoundary ? BOTTOM : TOP; + XSide sideX = bounds.XMost() <= xBoundary ? RIGHT : LEFT; + YSide sideY = bounds.YMost() <= yBoundary ? BOTTOM : TOP; nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY); - NS_ASSERTION(quadrantRect.Contains(aBounds), "Messed up quadrants"); + NS_ASSERTION(quadrantRect.Contains(bounds), "Messed up quadrants"); mLoanedTransform = mLoanedDrawTarget->GetTransform(); mLoanedTransform.Translate(-quadrantRect.x, -quadrantRect.y); @@ -673,33 +697,18 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(const PaintState& aPaintState, return nullptr; } - const nsIntRegion* drawPtr; - if (aIter) { - // If an iterator was provided, then BeginPaint must have been run with - // PAINT_CAN_DRAW_ROTATED, and the draw region might cover multiple quadrants. - // Iterate over each of them, and return an appropriate buffer each time we find - // one that intersects the draw region. The iterator mCount value tracks which - // quadrants we have considered across multiple calls to this function. - aIter->mDrawRegion.SetEmpty(); - while (aIter->mCount < 4) { - nsIntRect quadrant = GetQuadrantRectangle((aIter->mCount & 1) ? LEFT : RIGHT, - (aIter->mCount & 2) ? TOP : BOTTOM); - aIter->mDrawRegion.And(aPaintState.mRegionToDraw, quadrant); - aIter->mCount++; - if (!aIter->mDrawRegion.IsEmpty()) { - break; - } - } - if (aIter->mDrawRegion.IsEmpty()) { - return nullptr; - } - drawPtr = &aIter->mDrawRegion; - } else { - drawPtr = &aPaintState.mRegionToDraw; + DrawTarget* result = BorrowDrawTargetForQuadrantUpdate(aPaintState.mRegionToDraw.GetBounds(), + BUFFER_BOTH, aIter); + if (!result) { + return nullptr; + } + const nsIntRegion* drawPtr = &aPaintState.mRegionToDraw; + if (aIter) { + // The iterators draw region currently only contains the bounds of the region, + // this makes it the precise region. + aIter->mDrawRegion.And(aIter->mDrawRegion, aPaintState.mRegionToDraw); + drawPtr = &aIter->mDrawRegion; } - - DrawTarget* result = BorrowDrawTargetForQuadrantUpdate(drawPtr->GetBounds(), - BUFFER_BOTH); if (aPaintState.mMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) { MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite); diff --git a/gfx/layers/RotatedBuffer.h b/gfx/layers/RotatedBuffer.h index 401cc271fd48..dc812208e46c 100644 --- a/gfx/layers/RotatedBuffer.h +++ b/gfx/layers/RotatedBuffer.h @@ -358,7 +358,8 @@ protected: */ gfx::DrawTarget* BorrowDrawTargetForQuadrantUpdate(const nsIntRect& aBounds, - ContextSource aSource); + ContextSource aSource, + DrawIterator* aIter); static bool IsClippingCheap(gfx::DrawTarget* aTarget, const nsIntRegion& aRegion); diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp index 78bd30ebbb89..2487cd680ca0 100644 --- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -499,39 +499,15 @@ void ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource, const nsIntRegion& aUpdateRegion) { - DrawTarget* destDT = - BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK); - if (!destDT) { - return; - } - - bool isClippingCheap = IsClippingCheap(destDT, aUpdateRegion); - if (isClippingCheap) { - gfxUtils::ClipToRegion(destDT, aUpdateRegion); - } - - aSource.DrawBufferWithRotation(destDT, BUFFER_BLACK, 1.0, CompositionOp::OP_SOURCE); - if (isClippingCheap) { - destDT->PopClip(); - } - // Flush the destination before the sources become inaccessible (Unlock). - destDT->Flush(); - ReturnDrawTargetToBuffer(destDT); - - if (aSource.HaveBufferOnWhite()) { - MOZ_ASSERT(HaveBufferOnWhite()); - DrawTarget* destDT = - BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE); - if (!destDT) { - return; - } - - bool isClippingCheap = IsClippingCheap(destDT, aUpdateRegion); + DrawIterator iter; + while (DrawTarget* destDT = + BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK, &iter)) { + bool isClippingCheap = IsClippingCheap(destDT, iter.mDrawRegion); if (isClippingCheap) { - gfxUtils::ClipToRegion(destDT, aUpdateRegion); + gfxUtils::ClipToRegion(destDT, iter.mDrawRegion); } - aSource.DrawBufferWithRotation(destDT, BUFFER_WHITE, 1.0, CompositionOp::OP_SOURCE); + aSource.DrawBufferWithRotation(destDT, BUFFER_BLACK, 1.0, CompositionOp::OP_SOURCE); if (isClippingCheap) { destDT->PopClip(); } @@ -539,6 +515,26 @@ ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource, destDT->Flush(); ReturnDrawTargetToBuffer(destDT); } + + if (aSource.HaveBufferOnWhite()) { + MOZ_ASSERT(HaveBufferOnWhite()); + DrawIterator whiteIter; + while (DrawTarget* destDT = + BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE, &whiteIter)) { + bool isClippingCheap = IsClippingCheap(destDT, whiteIter.mDrawRegion); + if (isClippingCheap) { + gfxUtils::ClipToRegion(destDT, whiteIter.mDrawRegion); + } + + aSource.DrawBufferWithRotation(destDT, BUFFER_WHITE, 1.0, CompositionOp::OP_SOURCE); + if (isClippingCheap) { + destDT->PopClip(); + } + // Flush the destination before the sources become inaccessible (Unlock). + destDT->Flush(); + ReturnDrawTargetToBuffer(destDT); + } + } } void