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:
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user