Don't clear the rotated buffer if we incorrectly assume content will be COLOR_ALPHA. (bug 1126045 part 3, r=mattwoodrow)
authorDavid Anderson <danderson@mozilla.com>
Wed, 28 Jan 2015 15:34:45 -0800
changeset 226598 b4548456063048f2f42ee25b578df16a337a73d4
parent 226597 c41ac1e4405ea3a7fd5a127a888ac57d967fbdbb
child 226599 5969eb0fe8b534c73afb42c5d382d3198dc68fd5
push id28200
push userkwierso@gmail.com
push dateThu, 29 Jan 2015 23:01:46 +0000
treeherdermozilla-central@4380ed39de3a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1126045
milestone38.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
Don't clear the rotated buffer if we incorrectly assume content will be COLOR_ALPHA. (bug 1126045 part 3, r=mattwoodrow)
gfx/layers/RotatedBuffer.cpp
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -21,16 +21,17 @@
 #include "mozilla/gfx/Matrix.h"         // for Matrix
 #include "mozilla/gfx/Point.h"          // for Point, IntPoint
 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
 #include "mozilla/gfx/Types.h"          // for ExtendMode::ExtendMode::CLAMP, etc
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowableLayer
 #include "mozilla/layers/TextureClient.h"  // for TextureClient
 #include "nsSize.h"                     // for nsIntSize
 #include "gfx2DGlue.h"
+#include "nsLayoutUtils.h"              // for invalidation debugging
 
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
 
 nsIntRect
@@ -441,23 +442,24 @@ RotatedContentBuffer::BeginPaint(Painted
 
   bool canUseOpaqueSurface = aLayer->CanUseOpaqueSurface();
   ContentType layerContentType =
     canUseOpaqueSurface ? gfxContentType::COLOR :
                           gfxContentType::COLOR_ALPHA;
 
   SurfaceMode mode;
   nsIntRegion neededRegion;
-  bool canReuseBuffer;
   nsIntRect destBufferRect;
 
+  bool canReuseBuffer = HaveBuffer();
+
   while (true) {
     mode = aLayer->GetSurfaceMode();
     neededRegion = aLayer->GetVisibleRegion();
-    canReuseBuffer = HaveBuffer() && BufferSizeOkFor(neededRegion.GetBounds().Size());
+    canReuseBuffer &= BufferSizeOkFor(neededRegion.GetBounds().Size());
     result.mContentType = layerContentType;
 
     if (canReuseBuffer) {
       if (mBufferRect.Contains(neededRegion.GetBounds())) {
         // We don't need to adjust mBufferRect.
         destBufferRect = mBufferRect;
       } else if (neededRegion.GetBounds().Size() <= mBufferRect.Size()) {
         // The buffer's big enough but doesn't contain everything that's
@@ -483,47 +485,66 @@ RotatedContentBuffer::BeginPaint(Painted
       } else {
         result.mContentType = gfxContentType::COLOR;
       }
 #endif
     }
 
     if ((aFlags & PAINT_WILL_RESAMPLE) &&
         (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) ||
-         neededRegion.GetNumRects() > 1)) {
-      // The area we add to neededRegion might not be painted opaquely
+         neededRegion.GetNumRects() > 1))
+    {
+      // The area we add to neededRegion might not be painted opaquely.
       if (mode == SurfaceMode::SURFACE_OPAQUE) {
         result.mContentType = gfxContentType::COLOR_ALPHA;
         mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
       }
 
       // We need to validate the entire buffer, to make sure that only valid
-      // pixels are sampled
+      // pixels are sampled.
       neededRegion = destBufferRect;
     }
 
     // If we have an existing buffer, but the content type has changed or we
     // have transitioned into/out of component alpha, then we need to recreate it.
-    if (HaveBuffer() &&
+    if (canReuseBuffer &&
         (result.mContentType != BufferContentType() ||
-        (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) != HaveBufferOnWhite())) {
-
-      // We're effectively clearing the valid region, so we need to draw
-      // the entire needed region now.
-      result.mRegionToInvalidate = aLayer->GetValidRegion();
-      validRegion.SetEmpty();
-      Clear();
-      // Restart decision process with the cleared buffer. We can only go
-      // around the loop one more iteration, since mDTBuffer is null now.
+        (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) != HaveBufferOnWhite()))
+    {
+      // Restart the decision process; we won't re-enter since we guard on
+      // being able to re-use the buffer.
+      canReuseBuffer = false;
       continue;
     }
 
     break;
   }
 
+  if (HaveBuffer() &&
+      (result.mContentType != BufferContentType() ||
+      (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) != HaveBufferOnWhite()))
+  {
+    // We're effectively clearing the valid region, so we need to draw
+    // the entire needed region now.
+    canReuseBuffer = false;
+    result.mRegionToInvalidate = aLayer->GetValidRegion();
+    validRegion.SetEmpty();
+    Clear();
+
+#if defined(MOZ_DUMP_PAINTING)
+    if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
+      if (result.mContentType != BufferContentType()) {
+        printf_stderr("Invalidating entire rotated buffer (layer %p): content type changed\n", aLayer);
+      } else if ((mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) != HaveBufferOnWhite()) {
+        printf_stderr("Invalidating entire rotated buffer (layer %p): component alpha changed\n", aLayer);
+      }
+    }
+#endif
+  }
+
   NS_ASSERTION(destBufferRect.Contains(neededRegion.GetBounds()),
                "Destination rect doesn't contain what we need to paint");
 
   result.mRegionToDraw.Sub(neededRegion, validRegion);
 
   if (result.mRegionToDraw.IsEmpty())
     return result;