From 36f52dc8db178306fc15e5f11765d4aed8b52005 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 17 Sep 2010 12:29:52 -0700 Subject: [PATCH] Bug 584494. Avoid clipping in BasicThebesLayer when not necessary. r=cjones a2.0=blocking2.0:betaN --- gfx/layers/Layers.h | 14 ++++++++++---- gfx/layers/basic/BasicLayers.cpp | 19 ++++++++++++++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 3b6256579fa..35d513cb922 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -495,10 +495,16 @@ public: } /** * CONSTRUCTION PHASE ONLY - * Tell this layer which region will be visible. It is the responsibility - * of the caller to ensure that content outside this region does not - * contribute to the final visible window. This can be an - * overapproximation to the true visible region. + * Tell this layer which region will be visible. The visible region + * is a region which contains all the contents of the layer that can + * actually affect the rendering of the window. It can exclude areas + * that are covered by opaque contents of other layers, and it can + * exclude areas where this layer simply contains no content at all. + * (This can be an overapproximation to the "true" visible region.) + * + * There is no general guarantee that drawing outside the bounds of the + * visible region will be ignored. So if a layer draws outside the bounds + * of its visible region, it needs to ensure that what it draws is valid. */ virtual void SetVisibleRegion(const nsIntRegion& aRegion) { diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 2b67fc27284..e34eeec4484 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -492,6 +492,15 @@ BasicThebesLayer::Paint(gfxContext* aContext, mBuffer.DrawTo(this, canUseOpaqueSurface, target, aOpacity); } +static PRBool +IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion) +{ + // Assume clipping is cheap if the context just has an integer + // translation, and the visible region is simple. + return !aTarget->CurrentMatrix().HasNonIntegerTranslation() && + aRegion.GetNumRects() <= 1; +} + void BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer, PRBool aIsOpaqueContent, @@ -499,7 +508,15 @@ BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer, float aOpacity) { aTarget->Save(); - gfxUtils::ClipToRegion(aTarget, aLayer->GetVisibleRegion()); + // If the entire buffer is valid, we can just draw the whole thing, + // no need to clip. But we'll still clip if clipping is cheap --- + // that might let us copy a smaller region of the buffer. + if (!aLayer->GetValidRegion().Contains(BufferRect()) || + IsClippingCheap(aTarget, aLayer->GetVisibleRegion())) { + // We don't want to draw invalid stuff, so we need to clip. Might as + // well clip to the smallest area possible --- the visible region. + gfxUtils::ClipToRegion(aTarget, aLayer->GetVisibleRegion()); + } if (aIsOpaqueContent) { aTarget->SetOperator(gfxContext::OPERATOR_SOURCE); }