Bug 810470. Part 8: Limit the BasicLayers background-caching optimization to cases where the destination context has an integer translation only, and snap the image rectangle. r=mattwoodrow

Previous patches in this bug enabled the nsDisplayCanvasBackground
background-caching optimization for the test 402807-1.html. That exposed
an existing bug where we don't snap the background image to pixel
boundaries when drawing through that path. This patch fixes it.
This patch also stops the IsSingleFixedPositionImage path from using
mDestRect, returning the rect as an out-parameter instead.

--HG--
extra : rebase_source : b7a496dfc7584dd8c73cddd0809fc5aa31992d53
This commit is contained in:
Robert O'Callahan 2012-11-14 17:35:18 -08:00
parent 7fc1422e17
commit b69838cecd
3 changed files with 20 additions and 10 deletions

View File

@ -1647,15 +1647,16 @@ RoundedBorderIntersectsRect(nsIFrame* aFrame,
//
// See also RoundedRectIntersectsRect.
static bool RoundedRectContainsRect(const nsRect& aRoundedRect,
const nscoord aRadii[8],
const nsRect& aContainedRect) {
const nscoord aRadii[8],
const nsRect& aContainedRect) {
nsRegion rgn = nsLayoutUtils::RoundedRectIntersectRect(aRoundedRect, aRadii, aContainedRect);
return rgn.Contains(aContainedRect);
}
bool
nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
const nsRect& aClipRect)
const nsRect& aClipRect,
gfxRect* aDestRect)
{
if (mIsThemed || !mBackgroundStyle)
return false;
@ -1683,7 +1684,7 @@ nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuil
return false;
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
mDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel);
*aDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel);
return true;
}

View File

@ -1866,7 +1866,9 @@ protected:
typedef class mozilla::layers::ImageLayer ImageLayer;
bool TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder, const nsRect& aClipRect);
bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
const nsRect& aClipRect,
gfxRect* aDestRect);
void ConfigureLayer(ImageLayer* aLayer);
// Cache the result of nsCSSRendering::FindBackground. Always null if

View File

@ -206,18 +206,25 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRefPtr<gfxContext> dest = aCtx->ThebesContext();
nsRefPtr<gfxASurface> surf;
nsRefPtr<gfxContext> ctx;
gfxRect destRect;
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
if (IsSingleFixedPositionImage(aBuilder, bgClipRect) && aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap()) {
if (IsSingleFixedPositionImage(aBuilder, bgClipRect, &destRect) &&
aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap() &&
!dest->CurrentMatrix().HasNonIntegerTranslation()) {
// Snap image rectangle to nearest pixel boundaries. This is the right way
// to snap for this context, because we checked HasNonIntegerTranslation above.
destRect.Round();
surf = static_cast<gfxASurface*>(GetUnderlyingFrame()->Properties().Get(nsIFrame::CachedBackgroundImage()));
nsRefPtr<gfxASurface> destSurf = dest->CurrentSurface();
if (surf && surf->GetType() == destSurf->GetType()) {
BlitSurface(dest, mDestRect, surf);
BlitSurface(dest, destRect, surf);
return;
}
surf = destSurf->CreateSimilarSurface(gfxASurface::CONTENT_COLOR_ALPHA, gfxIntSize(ceil(mDestRect.width), ceil(mDestRect.height)));
surf = destSurf->CreateSimilarSurface(gfxASurface::CONTENT_COLOR_ALPHA,
gfxIntSize(destRect.width, destRect.height));
if (surf) {
ctx = new gfxContext(surf);
ctx->Translate(-gfxPoint(mDestRect.x, mDestRect.y));
ctx->Translate(-gfxPoint(destRect.x, destRect.y));
context.Init(aCtx->DeviceContext(), ctx);
}
}
@ -229,7 +236,7 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
aBuilder->GetBackgroundPaintFlags(),
&bgClipRect, mLayer);
if (surf) {
BlitSurface(dest, mDestRect, surf);
BlitSurface(dest, destRect, surf);
GetUnderlyingFrame()->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get());
GetUnderlyingFrame()->AddStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);