Bug 907048 - Skip colorlayer if other opacity layer just covers the colorlayer region, r=roc
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 10 Sep 2013 15:06:13 +0800
changeset 146401 a2013b29212c12e298c6ca56895056a53b59be39
parent 146400 8ddd8c297814d7e928547ca0e97d3476cf2d584d
child 146402 d660739f74981545b16aeee25fae6a4bcb10bc8a
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)
reviewersroc
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, r=roc
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