Bug 615794. Part 2: Remove some usage of gfxUtils::ClipToRegionSnapped since snapping the visible region may not be correct. r=jrmuizel a=blocking

This commit is contained in:
Robert O'Callahan
2011-01-04 23:35:57 +13:00
parent af40a3a245
commit ac35706ad5

View File

@@ -429,11 +429,17 @@ protected:
Buffer mBuffer;
};
static void
/**
* Clips to the smallest device-pixel-aligned rectangle containing aRect
* in user space.
* Returns true if the clip is "perfect", i.e. we actually clipped exactly to
* aRect.
*/
static PRBool
ClipToContain(gfxContext* aContext, const nsIntRect& aRect)
{
gfxRect deviceRect =
aContext->UserToDevice(gfxRect(aRect.x, aRect.y, aRect.width, aRect.height));
gfxRect userRect(aRect.x, aRect.y, aRect.width, aRect.height);
gfxRect deviceRect = aContext->UserToDevice(userRect);
deviceRect.RoundOut();
gfxMatrix currentMatrix = aContext->CurrentMatrix();
@@ -442,6 +448,8 @@ ClipToContain(gfxContext* aContext, const nsIntRect& aRect)
aContext->Rectangle(deviceRect);
aContext->Clip();
aContext->SetMatrix(currentMatrix);
return aContext->DeviceToUser(deviceRect) == userRect;
}
static nsIntRegion
@@ -468,6 +476,29 @@ SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget)
!(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA));
}
static PRBool
PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const nsIntRegion& aRegion)
{
// If we need to call PushGroup, we should clip to the smallest possible
// area first to minimize the size of the temporary surface.
PRBool didCompleteClip = ClipToContain(aContext, aRegion.GetBounds());
gfxASurface::gfxContentType contentType = gfxASurface::CONTENT_COLOR_ALPHA;
PRBool needsClipToVisibleRegion = PR_FALSE;
if (aLayer->CanUseOpaqueSurface() &&
((didCompleteClip && aRegion.GetNumRects() == 1) ||
!aContext->CurrentMatrix().HasNonIntegerTranslation())) {
// If the layer is opaque in its visible region we can push a CONTENT_COLOR
// group. We need to make sure that only pixels inside the layer's visible
// region are copied back to the destination. Remember if we've already
// clipped precisely to the visible region.
needsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
contentType = gfxASurface::CONTENT_COLOR;
}
aContext->PushGroupAndCopyBackground(contentType);
return needsClipToVisibleRegion;
}
void
BasicThebesLayer::Paint(gfxContext* aContext,
LayerManager::DrawThebesLayerCallback aCallback,
@@ -475,8 +506,6 @@ BasicThebesLayer::Paint(gfxContext* aContext,
{
NS_ASSERTION(BasicManager()->InDrawing(),
"Can only draw in drawing phase");
gfxContext* target = BasicManager()->GetTarget();
NS_ASSERTION(target, "We shouldn't be called if there's no target");
nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface();
PRBool canUseOpaqueSurface = CanUseOpaqueSurface();
@@ -492,25 +521,30 @@ BasicThebesLayer::Paint(gfxContext* aContext,
mValidRegion.SetEmpty();
mBuffer.Clear();
nsIntRegion toDraw = IntersectWithClip(mVisibleRegion, target);
nsIntRegion toDraw = IntersectWithClip(mVisibleRegion, aContext);
if (!toDraw.IsEmpty()) {
if (!aCallback) {
BasicManager()->SetTransactionIncomplete();
return;
}
target->Save();
gfxUtils::ClipToRegionSnapped(target, toDraw);
aContext->Save();
PRBool needsClipToVisibleRegion = PR_FALSE;
if (opacity != 1.0) {
target->PushGroupAndCopyBackground(contentType);
needsClipToVisibleRegion = PushGroupForLayer(aContext, this, toDraw);
}
SetAntialiasingFlags(this, target);
aCallback(this, target, toDraw, nsIntRegion(), aCallbackData);
SetAntialiasingFlags(this, aContext);
aCallback(this, aContext, toDraw, nsIntRegion(), aCallbackData);
if (opacity != 1.0) {
target->PopGroupToSource();
target->Paint(opacity);
aContext->PopGroupToSource();
if (needsClipToVisibleRegion) {
gfxUtils::ClipToRegion(aContext, toDraw);
}
aContext->Paint(opacity);
}
target->Restore();
aContext->Restore();
}
return;
}
@@ -543,7 +577,7 @@ BasicThebesLayer::Paint(gfxContext* aContext,
}
}
mBuffer.DrawTo(this, target, opacity);
mBuffer.DrawTo(this, aContext, opacity);
}
static PRBool
@@ -1331,14 +1365,10 @@ BasicLayerManager::PaintLayer(Layer* aLayer,
pushedTargetOpaqueRect = PR_TRUE;
}
PRBool needsClipToVisibleRegion = PR_FALSE;
if (needsGroup) {
// If we need to call PushGroup, we should clip to the smallest possible
// area first to minimize the size of the temporary surface.
ClipToContain(mTarget, aLayer->GetEffectiveVisibleRegion().GetBounds());
gfxASurface::gfxContentType type = aLayer->CanUseOpaqueSurface()
? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA;
mTarget->PushGroupAndCopyBackground(type);
needsClipToVisibleRegion =
PushGroupForLayer(mTarget, aLayer, aLayer->GetEffectiveVisibleRegion());
}
/* Only paint ourself, or our children - This optimization relies on this! */
@@ -1362,10 +1392,9 @@ BasicLayerManager::PaintLayer(Layer* aLayer,
if (needsGroup) {
mTarget->PopGroupToSource();
// If the layer is opaque in its visible region we pushed a CONTENT_COLOR
// group. We need to make sure that only pixels inside the layer's visible
// region are copied back to the destination.
gfxUtils::ClipToRegionSnapped(mTarget, aLayer->GetEffectiveVisibleRegion());
if (needsClipToVisibleRegion) {
gfxUtils::ClipToRegion(mTarget, aLayer->GetEffectiveVisibleRegion());
}
mTarget->Paint(aLayer->GetEffectiveOpacity());
}