Bug 907048 - Skip colorlayer if other opacity layer just covers the colorlayer region
☠☠ backed out by 8ddd8c297814 ☠ ☠
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 10 Sep 2013 14:48:57 +0800
changeset 146399 6776e4836c045ca1dc9125a0b815436f71a67470
parent 146398 77cd72a836e60548db0ae4013fca6786f5ac8c8f
child 146400 8ddd8c297814d7e928547ca0e97d3476cf2d584d
push id25260
push userryanvm@gmail.com
push dateWed, 11 Sep 2013 00:29:30 +0000
treeherdermozilla-central@f73bed2856a8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs907048
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 907048 - Skip colorlayer if other opacity layer just covers the colorlayer region
gfx/layers/composite/ContainerLayerComposite.cpp
--- 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