Bug 1052751 - Part 1: Cull translated layers on the compositor. r=roc
authorBenoit Girard <b56girard@gmail.com>
Thu, 14 Aug 2014 11:46:21 -0400
changeset 200199 6e2e0518a548bd58887f36cb7c7fcb951289ba63
parent 200198 bb748fd4519df76342ce61c1dc921135066310f2
child 200200 293f3a5eabdb6bf213a762bca37b5b0a128e1dad
push id27337
push useremorley@mozilla.com
push dateTue, 19 Aug 2014 12:40:34 +0000
treeherdermozilla-central@a38daccaa557 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1052751
milestone34.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 1052751 - Part 1: Cull translated layers on the compositor. r=roc
gfx/layers/composite/ContainerLayerComposite.cpp
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -29,16 +29,19 @@
 #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTArray.h"                   // for nsAutoTArray
 #include "TextRenderer.h"               // for TextRenderer
 #include <vector>
 
+#define CULLING_LOG(...)
+// #define CULLING_LOG(...) printf_stderr("CULLING: " __VA_ARGS__)
+
 namespace mozilla {
 namespace layers {
 
 using namespace gfx;
 
 /**
  * Returns a rectangle of content painted opaquely by aLayer. Very consertative;
  * bails by returning an empty rect in any tricky situations.
@@ -47,16 +50,18 @@ static nsIntRect
 GetOpaqueRect(Layer* aLayer)
 {
   nsIntRect result;
   gfx::Matrix matrix;
   bool is2D = aLayer->GetBaseTransform().Is2D(&matrix);
 
   // Just bail if there's anything difficult to handle.
   if (!is2D || aLayer->GetMaskLayer() ||
+    aLayer->GetIsFixedPosition() ||
+    aLayer->GetIsStickyPosition() ||
     aLayer->GetEffectiveOpacity() != 1.0f ||
     matrix.HasNonIntegerTranslation()) {
     return result;
   }
 
   if (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) {
     result = aLayer->GetEffectiveVisibleRegion().GetLargestRectangle();
   } else {
@@ -316,40 +321,54 @@ ContainerPrepare(ContainerT* aContainer,
     }
 
     nsIntRect clipRect = layerToRender->GetLayer()->
         CalculateScissorRect(aClipRect, &aManager->GetWorldTransform());
     if (clipRect.IsEmpty()) {
       continue;
     }
 
+    CULLING_LOG("Preparing sublayer %p\n", layerToRender->GetLayer());
+
     nsIntRegion savedVisibleRegion;
     bool restoreVisibleRegion = false;
+    gfx::Matrix matrix;
+    bool is2D = layerToRender->GetLayer()->GetBaseTransform().Is2D(&matrix);
     if (i + 1 < children.Length() &&
-        layerToRender->GetLayer()->GetEffectiveTransform().IsIdentity()) {
+        is2D && !matrix.HasNonIntegerTranslation()) {
       LayerComposite* nextLayer = static_cast<LayerComposite*>(children.ElementAt(i + 1)->ImplData());
+      CULLING_LOG("Culling against %p\n", nextLayer->GetLayer());
       nsIntRect nextLayerOpaqueRect;
       if (nextLayer && nextLayer->GetLayer()) {
         nextLayerOpaqueRect = GetOpaqueRect(nextLayer->GetLayer());
+        gfx::Point point = matrix.GetTranslation();
+        nextLayerOpaqueRect.MoveBy(static_cast<int>(-point.x), static_cast<int>(-point.y));
+        CULLING_LOG("  point %i, %i\n", static_cast<int>(-point.x), static_cast<int>(-point.y));
+        CULLING_LOG("  opaque rect %i, %i, %i, %i\n", nextLayerOpaqueRect.x, nextLayerOpaqueRect.y, nextLayerOpaqueRect.width, nextLayerOpaqueRect.height);
       }
       if (!nextLayerOpaqueRect.IsEmpty()) {
+        CULLING_LOG("  draw\n");
         savedVisibleRegion = layerToRender->GetShadowVisibleRegion();
         nsIntRegion visibleRegion;
         visibleRegion.Sub(savedVisibleRegion, nextLayerOpaqueRect);
         if (visibleRegion.IsEmpty()) {
           continue;
         }
         layerToRender->SetShadowVisibleRegion(visibleRegion);
         restoreVisibleRegion = true;
+      } else {
+        CULLING_LOG("  skip\n");
       }
     }
     layerToRender->Prepare(clipRect);
     aContainer->mPrepared->mLayers.AppendElement(PreparedLayer(layerToRender, clipRect, restoreVisibleRegion, savedVisibleRegion));
   }
 
+  CULLING_LOG("Preparing container layer %p\n", aContainer->GetLayer());
+
   /**
    * Setup our temporary surface for rendering the contents of this container.
    */
 
   bool surfaceCopyNeeded;
   // DefaultComputeSupportsComponentAlphaChildren can mutate aContainer so call it unconditionally
   aContainer->DefaultComputeSupportsComponentAlphaChildren(&surfaceCopyNeeded);
   if (aContainer->UseIntermediateSurface()) {