Bug 1134762 - Clean-up UseFastPath logic to avoid OOM error. r=kats
☠☠ backed out by 2f1af783edd1 ☠ ☠
authorBenoit Girard <b56girard@gmail.com>
Wed, 18 Feb 2015 15:27:40 -0500
changeset 258771 ca73b950e612af5a0395380a8e676ea2c993136d
parent 258770 b465cd661b6beb01fc6e76d35ad5b80b66747082
child 258772 bc5168c2922d017babf46cab931dc7f8ad7c82c6
push id721
push userjlund@mozilla.com
push dateTue, 21 Apr 2015 23:03:33 +0000
treeherdermozilla-release@d27c9211ebb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1134762
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
Bug 1134762 - Clean-up UseFastPath logic to avoid OOM error. r=kats
gfx/layers/client/ClientTiledPaintedLayer.cpp
gfx/layers/client/ClientTiledPaintedLayer.h
--- a/gfx/layers/client/ClientTiledPaintedLayer.cpp
+++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp
@@ -214,52 +214,75 @@ ClientTiledPaintedLayer::IsScrollingOnCo
          !FuzzyEqualsAdditive(compositorMetrics.GetScrollOffset().y,
                               aParentMetrics.GetScrollOffset().y,
                               COORDINATE_EPSILON);
 }
 
 bool
 ClientTiledPaintedLayer::UseFastPath()
 {
+  // The fast path doesn't allow rendering at low resolution. It will draw the low-res
+  // area at full resolution and cause OOM.
+  if (gfxPrefs::UseLowPrecisionBuffer()) {
+    return false;
+  }
+
   LayerMetricsWrapper scrollAncestor;
   GetAncestorLayers(&scrollAncestor, nullptr);
   if (!scrollAncestor) {
     return true;
   }
   const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
 
   bool multipleTransactionsNeeded = gfxPlatform::GetPlatform()->UseProgressivePaint()
-                                 || gfxPrefs::UseLowPrecisionBuffer()
                                  || !parentMetrics.GetCriticalDisplayPort().IsEmpty();
   bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition();
   bool isScrollable = parentMetrics.IsScrollable();
 
-  return !multipleTransactionsNeeded || isFixed || !isScrollable
-#if !defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ)
-         || !IsScrollingOnCompositor(parentMetrics)
+  return !multipleTransactionsNeeded || isFixed || !isScrollable;
+}
+
+bool
+ClientTiledPaintedLayer::UseProgressiveDraw() {
+  // Don't draw progressively in a reftest scenario (that's what the HasShadowTarget() check is for).
+  if (!gfxPlatform::GetPlatform()->UseProgressivePaint() || ClientManager()->HasShadowTarget()) {
+    return false;
+  }
+
+  // XXX We probably want to disable progressive drawing for non active APZ layers in the future
+  //     but we should wait for a proper test case before making this change.
+
+#if 0 //!defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ)
+  LayerMetricsWrapper scrollAncestor;
+  GetAncestorLayers(&scrollAncestor, nullptr);
+  if (!scrollAncestor) {
+    return true;
+  }
+  const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
+
+  return !IsScrollingOnCompositor(parentMetrics);
+#else
+  return true;
 #endif
-         ;
 }
 
 bool
 ClientTiledPaintedLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion,
                                             const nsIntRegion& aVisibleRegion,
                                             LayerManager::DrawPaintedLayerCallback aCallback,
                                             void* aCallbackData)
 {
   // If we have no high-precision stuff to draw, or we have started drawing low-precision
   // already, then we shouldn't do anything there.
   if (aInvalidRegion.IsEmpty() || mPaintData.mLowPrecisionPaintCount != 0) {
     return false;
   }
 
-  // Only draw progressively when the resolution is unchanged, and we're not
-  // in a reftest scenario (that's what the HasShadowManager() check is for).
-  if (gfxPlatform::GetPlatform()->UseProgressivePaint() &&
-      !ClientManager()->HasShadowTarget() &&
+  // Only draw progressively when the resolution is unchanged
+  if (UseProgressiveDraw() &&
       mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) {
     // Store the old valid region, then clear it before painting.
     // We clip the old valid region to the visible region, as it only gets
     // used to decide stale content (currently valid and previously visible)
     nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
     oldValidRegion.And(oldValidRegion, aVisibleRegion);
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
       oldValidRegion.And(oldValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
@@ -413,46 +436,30 @@ ClientTiledPaintedLayer::RenderLayer()
   }
 
   if (!ClientManager()->IsRepeatTransaction()) {
     // Only paint the mask layer on the first transaction.
     if (GetMaskLayer()) {
       ToClientLayer(GetMaskLayer())->RenderLayer();
     }
 
-    // For more complex cases we need to calculate a bunch of metrics before we
-    // can do the paint.
-    BeginPaint();
-    if (mPaintData.mPaintFinished) {
-      return;
-    }
-
     // In some cases we can take a fast path and just be done with it.
     if (UseFastPath()) {
       TILING_LOG("TILING %p: Taking fast-path\n", this);
       mValidRegion = neededRegion;
-
-      // Make sure that tiles that fall outside of the visible region or outside of the
-      // critical displayport are discarded on the first update. Also make sure that we
-      // only draw stuff inside the critical displayport on the first update.
-      if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
-        mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
-        invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
-      }
-
-      if (invalidRegion.IsEmpty()) {
-        EndPaint();
-        return;
-      }
-
-      mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
       mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, callback, data);
       ClientManager()->Hold(this);
       mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
-      EndPaint();
+      return;
+    }
+
+    // For more complex cases we need to calculate a bunch of metrics before we
+    // can do the paint.
+    BeginPaint();
+    if (mPaintData.mPaintFinished) {
       return;
     }
 
     // Make sure that tiles that fall outside of the visible region or outside of the
     // critical displayport are discarded on the first update. Also make sure that we
     // only draw stuff inside the critical displayport on the first update.
     mValidRegion.And(mValidRegion, neededRegion);
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
--- a/gfx/layers/client/ClientTiledPaintedLayer.h
+++ b/gfx/layers/client/ClientTiledPaintedLayer.h
@@ -102,16 +102,23 @@ private:
   bool UseFastPath();
 
   /**
    * Check if the layer is being scrolled by APZ on the compositor.
    */
   bool IsScrollingOnCompositor(const FrameMetrics& aParentMetrics);
 
   /**
+   * Check if we should use progressive draw on this layer. We will
+   * disable progressive draw based on a preference or if the layer
+   * is not being scrolled.
+   */
+  bool UseProgressiveDraw();
+
+  /**
    * Helper function to do the high-precision paint.
    * This function returns true if it updated the paint buffer.
    */
   bool RenderHighPrecision(nsIntRegion& aInvalidRegion,
                            const nsIntRegion& aVisibleRegion,
                            LayerManager::DrawPaintedLayerCallback aCallback,
                            void* aCallbackData);