From 4168a4671f9fd028b264991159380ee975b918c1 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 16 Sep 2013 10:20:30 +0800 Subject: [PATCH] Bug 907048 - Skip colorlayer if other opacity layer just covers the colorlayer region, r=roc --- .../composite/ContainerLayerComposite.cpp | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index 7c67a80285c1..977bc953d9ec 100644 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -47,6 +47,38 @@ HasOpaqueAncestorLayer(Layer* aLayer) return false; } +/** + * Returns a rectangle of content painted opaquely by aLayer. Very consertative; + * bails by returning an empty rect in any tricky situations. + */ +static nsIntRect +GetOpaqueRect(Layer* aLayer) +{ + nsIntRect result; + // Just bail if there's anything difficult to handle. + if (!aLayer->GetEffectiveTransform().IsIdentity() || + aLayer->GetEffectiveOpacity() != 1.0f || + aLayer->GetMaskLayer()) { + return result; + } + if (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) { + result = aLayer->GetEffectiveVisibleRegion().GetLargestRectangle(); + } else { + // Drill down into RefLayers because that's what we particularly care about; + // layer construction for aLayer will not have known about the opaqueness + // of any RefLayer subtrees. + RefLayer* refLayer = aLayer->AsRefLayer(); + if (refLayer && refLayer->GetFirstChild()) { + result = GetOpaqueRect(refLayer->GetFirstChild()); + } + } + const nsIntRect* clipRect = aLayer->GetEffectiveClipRect(); + if (clipRect) { + result.IntersectRect(result, *clipRect); + } + return result; +} + template void ContainerRender(ContainerT* aContainer, const nsIntPoint& aOffset, @@ -143,6 +175,23 @@ ContainerRender(ContainerT* aContainer, continue; } + if (i + 1 < children.Length() && + layerToRender->GetLayer()->GetEffectiveTransform().IsIdentity()) { + LayerComposite* nextLayer = static_cast(children.ElementAt(i + 1)->ImplData()); + nsIntRect nextLayerOpaqueRect; + if (nextLayer && nextLayer->GetLayer()) { + nextLayerOpaqueRect = GetOpaqueRect(nextLayer->GetLayer()); + } + if (!nextLayerOpaqueRect.IsEmpty()) { + nsIntRegion visibleRegion; + visibleRegion.Sub(layerToRender->GetShadowVisibleRegion(), nextLayerOpaqueRect); + layerToRender->SetShadowVisibleRegion(visibleRegion); + if (visibleRegion.IsEmpty()) { + continue; + } + } + } + nsIntRect clipRect = layerToRender->GetLayer()-> CalculateScissorRect(aClipRect, &aManager->GetWorldTransform()); if (clipRect.IsEmpty()) {