Bug 992486 - Part 5: Fix copying the front buffer to back buffer. r=roc

This commit is contained in:
Matt Woodrow 2014-04-10 20:42:29 +12:00
parent bf1ea57aff
commit 15c07b67c1
3 changed files with 67 additions and 61 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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