Bug 1275026: Part 1. Prevent infinit recursion in GenerateAndPushTextMask. r=jfkthame, a=sylvestre
authorcku <cku@mozilla.com>
Tue, 24 May 2016 12:14:57 +0800
changeset 333128 9f9dc77cc9e9708921171f750729a5b8ede5e250
parent 333127 b2f0425218851914b703b902ed56c6148b37b537
child 333129 bdadf0cd4efb548760b14f147b397e0dc84b461a
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame, sylvestre
bugs1275026
milestone48.0a2
Bug 1275026: Part 1. Prevent infinit recursion in GenerateAndPushTextMask. r=jfkthame, a=sylvestre MozReview-Commit-ID: 4tcMuW5i13F
layout/base/nsDisplayList.cpp
layout/base/nsLayoutUtils.cpp
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -486,20 +486,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
@@ -556,16 +561,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)
@@ -2448,21 +2455,16 @@ SetBackgroundClipRegion(DisplayListClipS
 }
 
 
 /*static*/ bool
 nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
                                                      nsIFrame* aFrame,
                                                      nsDisplayList* aList)
 {
-  if (aBuilder->IsForGenerateGlyphMask() ||
-      aBuilder->IsForPaintingSelectionBG()) {
-    return true;
-  }
-
   nsStyleContext* bgSC = nullptr;
   const nsStyleBackground* bg = nullptr;
   nsPresContext* presContext = aFrame->PresContext();
   bool isThemed = aFrame->IsThemed();
   if (!isThemed) {
     bgSC = GetBackgroundStyleContext(aFrame);
     if (bgSC) {
       bg = bgSC->StyleBackground();
@@ -2961,17 +2963,19 @@ nsDisplayBackgroundImage::PaintInternal(
   uint32_t flags = aBuilder->GetBackgroundPaintFlags();
   CheckForBorderItem(this, flags);
 
   nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
   gfxContext* ctx = aCtx->ThebesContext();
   uint8_t clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
 
   if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
-    GenerateAndPushTextMask(mFrame, aCtx, borderBox);
+    if (!GenerateAndPushTextMask(mFrame, aCtx, borderBox, aBuilder)) {
+      return;
+    }
   }
 
   image::DrawResult result =
     nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
                                     aBounds,
                                     borderBox,
                                     flags, aClipRect, mLayer,
                                     CompositionOp::OP_OVER);
@@ -3395,17 +3399,20 @@ nsDisplayBackgroundColor::Paint(nsDispla
 #else
   gfxContext* ctx = aCtx->ThebesContext();
   gfxRect bounds =
     nsLayoutUtils::RectToGfxRect(borderBox,
                                  mFrame->PresContext()->AppUnitsPerDevPixel());
 
   uint8_t clip = mBackgroundStyle->mImage.mLayers[0].mClip;
   if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
-    GenerateAndPushTextMask(mFrame, aCtx, borderBox);
+    if (!GenerateAndPushTextMask(mFrame, aCtx, borderBox, 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
@@ -3451,30 +3451,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)) {