Bug 907048 - Skip colorlayer if other opacity layer just covers the colorlayer region, r=roc
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -42,16 +42,48 @@ HasOpaqueAncestorLayer(Layer* aLayer)
{
for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
return true;
}
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) {
+ result = GetOpaqueRect(refLayer->GetFirstChild());
+ }
+ }
+ const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
+ if (clipRect) {
+ result.IntersectRect(result, *clipRect);
+ }
+ return result;
+}
+
template<class ContainerT> void
ContainerRender(ContainerT* aContainer,
const nsIntPoint& aOffset,
LayerManagerComposite* aManager,
const nsIntRect& aClipRect)
{
/**
* Setup our temporary surface for rendering the contents of this container.
@@ -138,16 +170,33 @@ ContainerRender(ContainerT* aContainer,
for (uint32_t i = 0; i < children.Length(); i++) {
LayerComposite* layerToRender = static_cast<LayerComposite*>(children.ElementAt(i)->ImplData());
if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty() &&
!layerToRender->GetLayer()->AsContainerLayer()) {
continue;
}
+ if (i + 1 < children.Length() &&
+ layerToRender->GetLayer()->GetEffectiveTransform().IsIdentity()) {
+ LayerComposite* nextLayer = static_cast<LayerComposite*>(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()) {
continue;
}
layerToRender->RenderLayer(childOffset, clipRect);
// invariant: our GL context should be current here, I don't think we can