Bug 1275026: Part 1. Prevent infinit recursion in GenerateAndPushTextMask r=jfkthame
authorcku <cku@mozilla.com>
Tue, 24 May 2016 12:14:57 +0800
changeset 337789 ae1d5238d9931f71bc79dcb1043a9465c50d8369
parent 337788 6d97fe2db56061d7c8f73d317c9e9da56f58bdfe
child 337790 dfb1d098cda6d2ec36d786b39e82d8ce5d6ecdc4
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1275026
milestone49.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 1275026: Part 1. Prevent infinit recursion in GenerateAndPushTextMask r=jfkthame MozReview-Commit-ID: 4tcMuW5i13F
layout/base/nsDisplayList.cpp
layout/base/nsLayoutUtils.cpp
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -487,20 +487,25 @@ AddAnimationsForProperty(nsIFrame* aFram
       continue;
     }
 
     AddAnimationForProperty(aFrame, *property, anim, aLayer, aData, aPending);
     effect->SetIsRunningOnCompositor(aProperty, true);
   }
 }
 
-static void
+static bool
 GenerateAndPushTextMask(nsIFrame* aFrame, nsRenderingContext* aContext,
-                        const nsRect& aFillRect)
-{
+                        const nsRect& aFillRect, nsDisplayListBuilder* aBuilder)
+{
+  if (aBuilder->IsForGenerateGlyphMask() ||
+      aBuilder->IsForPaintingSelectionBG()) {
+    return false;
+  }
+
   // The main function of enabling background-clip:text property value.
   // When a nsDisplayBackgroundImage detects "text" bg-clip style, it will call
   // this function to
   // 1. Paint background color of the selection text if any.
   // 2. Generate a mask by all descendant text frames
   // 3. Push the generated mask into aContext.
   //
   // TBD: we actually generate display list of aFrame twice here. It's better
@@ -557,16 +562,18 @@ GenerateAndPushTextMask(nsIFrame* aFrame
   // Push the generated mask into aContext, so that the caller can pop and
   // blend with it.
   Matrix maskTransform = ToMatrix(currentMatrix) *
                          Matrix::Translation(-drawRect.x, -drawRect.y);
   maskTransform.Invert();
 
   RefPtr<SourceSurface> maskSurface = maskDT->Snapshot();
   sourceCtx->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, 1.0, maskSurface, maskTransform);
+
+  return true;
 }
 
 /* static */ void
 nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
                                                          nsDisplayListBuilder* aBuilder,
                                                          nsDisplayItem* aItem,
                                                          nsIFrame* aFrame,
                                                          nsCSSProperty aProperty)
@@ -2467,21 +2474,16 @@ SetBackgroundClipRegion(DisplayListClipS
 
 /*static*/ bool
 nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
                                                      nsIFrame* aFrame,
                                                      const nsRect& aBackgroundRect,
                                                      nsDisplayList* aList,
                                                      bool aAllowWillPaintBorderOptimization)
 {
-  if (aBuilder->IsForGenerateGlyphMask() ||
-      aBuilder->IsForPaintingSelectionBG()) {
-    return true;
-  }
-
   nsStyleContext* bgSC = nullptr;
   const nsStyleBackground* bg = nullptr;
   nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
   nsPresContext* presContext = aFrame->PresContext();
   bool isThemed = aFrame->IsThemed();
   if (!isThemed) {
     bgSC = GetBackgroundStyleContext(aFrame);
     if (bgSC) {
@@ -2973,17 +2975,19 @@ nsDisplayBackgroundImage::PaintInternal(
                                         nsRect* aClipRect) {
   uint32_t flags = aBuilder->GetBackgroundPaintFlags();
   CheckForBorderItem(this, flags);
 
   gfxContext* ctx = aCtx->ThebesContext();
   uint8_t clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
 
   if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
-    GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect);
+    if (!GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect, aBuilder)) {
+      return;
+    }
   }
 
   nsCSSRendering::PaintBGParams params =
     nsCSSRendering::PaintBGParams::ForSingleLayer(*mFrame->PresContext(),
                                                   *aCtx,
                                                   aBounds, mBackgroundRect,
                                                   mFrame, flags, mLayer,
                                                   CompositionOp::OP_OVER);
@@ -3405,17 +3409,20 @@ nsDisplayBackgroundColor::Paint(nsDispla
 #else
   gfxContext* ctx = aCtx->ThebesContext();
   gfxRect bounds =
     nsLayoutUtils::RectToGfxRect(mBackgroundRect,
                                  mFrame->PresContext()->AppUnitsPerDevPixel());
 
   uint8_t clip = mBackgroundStyle->mImage.mLayers[0].mClip;
   if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
-    GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect);
+    if (!GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect, aBuilder)) {
+      return;
+    }
+
     ctx->SetColor(mColor);
     ctx->Rectangle(bounds, true);
     ctx->Fill();
     ctx->PopGroupAndBlend();
     return;
   }
 
   ctx->SetColor(mColor);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3476,30 +3476,16 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
 #endif
 
     nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(&builder, id);
 
     PROFILER_LABEL("nsLayoutUtils", "PaintFrame::BuildDisplayList",
       js::ProfileEntry::Category::GRAPHICS);
 
     aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list);
-#ifdef DEBUG
-    if (builder.IsForGenerateGlyphMask() || builder.IsForPaintingSelectionBG()) {
-      // PaintFrame is called to generate text glyph by
-      // nsDisplayBackgroundImage::Paint or nsDisplayBackgroundColor::Paint.
-      //
-      // Assert that we do not generate and put nsDisplayBackgroundImage or
-      // nsDisplayBackgroundColor into the list again, which would lead to
-      // infinite recursion.
-      for (nsDisplayItem* i = list.GetBottom(); i; i = i->GetAbove()) {
-        MOZ_ASSERT(nsDisplayItem::TYPE_BACKGROUND != i->GetType() &&
-                   nsDisplayItem::TYPE_BACKGROUND_COLOR != i->GetType());
-      }
-    }
-#endif
   }
 
   nsIAtom* frameType = aFrame->GetType();
 
   // For the viewport frame in print preview/page layout we want to paint
   // the grey background behind the page, not the canvas color.
   if (frameType == nsGkAtoms::viewportFrame &&
       nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {