Bug 1346265 - Part 1. Pass gfxContext to nsCSSRendering::PaintGradient. draft
authorcku <cku@mozilla.com>
Mon, 13 Mar 2017 12:26:21 +0800
changeset 500363 10b105c7bc018608bf2e5a32206c8de1039b4d69
parent 500240 39607304b774591fa6e32c4b06158d869483c312
child 500364 c044240f6568f46c595a783e2f873117675816f0
push id49705
push userbmo:cku@mozilla.com
push dateFri, 17 Mar 2017 04:16:27 +0000
bugs1346265
milestone55.0a1
Bug 1346265 - Part 1. Pass gfxContext to nsCSSRendering::PaintGradient. If mask-mode is luminace, we will create a temporary context at [1]. It's obvious we do not use this gfxContext at all in PaintGradient path. This patch is trying to fix this problem by pass gfxContext, instead of RenderingContext, directly to PaintGraident. [1] https://hg.mozilla.org/mozilla-central/file/991f5724e58f/layout/painting/nsCSSRendering.cpp#l5811 MozReview-Commit-ID: LLmg4k6IEm3
layout/painting/nsCSSRendering.cpp
layout/painting/nsCSSRendering.h
layout/painting/nsImageRenderer.cpp
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -2897,17 +2897,17 @@ ClampColorStops(nsTArray<ColorStop>& aSt
   }
   if (aStops.LastElement().mPosition < 1) {
     aStops.AppendElement(ColorStop(1, false, aStops.LastElement().mColor));
   }
 }
 
 void
 nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
-                              nsRenderingContext& aRenderingContext,
+                              gfxContext& aContext,
                               nsStyleGradient* aGradient,
                               const nsRect& aDirtyRect,
                               const nsRect& aDest,
                               const nsRect& aFillArea,
                               const nsSize& aRepeatSize,
                               const CSSIntRect& aSrc,
                               const nsSize& aIntrinsicSize,
                               float aOpacity)
@@ -2915,17 +2915,16 @@ nsCSSRendering::PaintGradient(nsPresCont
   PROFILER_LABEL("nsCSSRendering", "PaintGradient",
     js::ProfileEntry::Category::GRAPHICS);
 
   Telemetry::AutoTimer<Telemetry::GRADIENT_DURATION, Telemetry::Microsecond> gradientTimer;
   if (aDest.IsEmpty() || aFillArea.IsEmpty()) {
     return;
   }
 
-  gfxContext *ctx = aRenderingContext.ThebesContext();
   nscoord appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
   gfxSize srcSize = gfxSize(gfxFloat(aIntrinsicSize.width)/appUnitsPerDevPixel,
                             gfxFloat(aIntrinsicSize.height)/appUnitsPerDevPixel);
 
   bool cellContainsFill = aDest.Contains(aFillArea);
 
   // Compute "gradient line" start and end relative to the intrinsic size of
   // the gradient.
@@ -3258,17 +3257,17 @@ nsCSSRendering::PaintGradient(nsPresCont
   nsTArray<gfx::GradientStop> rawStops(stops.Length());
   rawStops.SetLength(stops.Length());
   for(uint32_t i = 0; i < stops.Length(); i++) {
     rawStops[i].color = stops[i].mColor;
     rawStops[i].color.a *= aOpacity;
     rawStops[i].offset = stopScale * (stops[i].mPosition - stopOrigin);
   }
   RefPtr<mozilla::gfx::GradientStops> gs =
-    gfxGradientCache::GetOrCreateGradientStops(ctx->GetDrawTarget(),
+    gfxGradientCache::GetOrCreateGradientStops(aContext.GetDrawTarget(),
                                                rawStops,
                                                isRepeat ? gfx::ExtendMode::REPEAT : gfx::ExtendMode::CLAMP);
   gradientPattern->SetColorStops(gs);
 
   // Paint gradient tiles. This isn't terribly efficient, but doing it this
   // way is simple and sure to get pixel-snapping right. We could speed things
   // up by drawing tiles into temporary surfaces and copying those to the
   // destination, but after pixel-snapping tiles may not all be the same size.
@@ -3276,17 +3275,17 @@ nsCSSRendering::PaintGradient(nsPresCont
   if (!dirty.IntersectRect(aDirtyRect, aFillArea))
     return;
 
   gfxRect areaToFill =
     nsLayoutUtils::RectToGfxRect(aFillArea, appUnitsPerDevPixel);
   gfxRect dirtyAreaToFill = nsLayoutUtils::RectToGfxRect(dirty, appUnitsPerDevPixel);
   dirtyAreaToFill.RoundOut();
 
-  gfxMatrix ctm = ctx->CurrentMatrix();
+  gfxMatrix ctm = aContext.CurrentMatrix();
   bool isCTMPreservingAxisAlignedRectangles = ctm.PreservesAxisAlignedRectangles();
 
   // xStart/yStart are the top-left corner of the top-left tile.
   nscoord xStart = FindTileStart(dirty.x, aDest.x, aRepeatSize.width);
   nscoord yStart = FindTileStart(dirty.y, aDest.y, aRepeatSize.height);
   nscoord xEnd = forceRepeatToCoverTiles ? xStart + aDest.width : dirty.XMost();
   nscoord yEnd = forceRepeatToCoverTiles ? yStart + aDest.height : dirty.YMost();
 
@@ -3304,51 +3303,51 @@ nsCSSRendering::PaintGradient(nsPresCont
       // Try snapping the fill rect. Snap its top-left and bottom-right
       // independently to preserve the orientation.
       gfxPoint snappedFillRectTopLeft = fillRect.TopLeft();
       gfxPoint snappedFillRectTopRight = fillRect.TopRight();
       gfxPoint snappedFillRectBottomRight = fillRect.BottomRight();
       // Snap three points instead of just two to ensure we choose the
       // correct orientation if there's a reflection.
       if (isCTMPreservingAxisAlignedRectangles &&
-          ctx->UserToDevicePixelSnapped(snappedFillRectTopLeft, true) &&
-          ctx->UserToDevicePixelSnapped(snappedFillRectBottomRight, true) &&
-          ctx->UserToDevicePixelSnapped(snappedFillRectTopRight, true)) {
+          aContext.UserToDevicePixelSnapped(snappedFillRectTopLeft, true) &&
+          aContext.UserToDevicePixelSnapped(snappedFillRectBottomRight, true) &&
+          aContext.UserToDevicePixelSnapped(snappedFillRectTopRight, true)) {
         if (snappedFillRectTopLeft.x == snappedFillRectBottomRight.x ||
             snappedFillRectTopLeft.y == snappedFillRectBottomRight.y) {
           // Nothing to draw; avoid scaling by zero and other weirdness that
           // could put the context in an error state.
           continue;
         }
         // Set the context's transform to the transform that maps fillRect to
         // snappedFillRect. The part of the gradient that was going to
         // exactly fill fillRect will fill snappedFillRect instead.
         gfxMatrix transform = gfxUtils::TransformRectToRect(fillRect,
             snappedFillRectTopLeft, snappedFillRectTopRight,
             snappedFillRectBottomRight);
-        ctx->SetMatrix(transform);
+        aContext.SetMatrix(transform);
       }
-      ctx->NewPath();
-      ctx->Rectangle(fillRect);
+      aContext.NewPath();
+      aContext.Rectangle(fillRect);
 
       gfxRect dirtyFillRect = fillRect.Intersect(dirtyAreaToFill);
       gfxRect fillRectRelativeToTile = dirtyFillRect - tileRect.TopLeft();
       Color edgeColor;
       if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR && !isRepeat &&
           RectIsBeyondLinearGradientEdge(fillRectRelativeToTile, matrix, stops,
                                          gradientStart, gradientEnd, &edgeColor)) {
         edgeColor.a *= aOpacity;
-        ctx->SetColor(edgeColor);
+        aContext.SetColor(edgeColor);
       } else {
-        ctx->SetMatrix(
-          ctx->CurrentMatrix().Copy().Translate(tileRect.TopLeft()));
-        ctx->SetPattern(gradientPattern);
+        aContext.SetMatrix(
+          aContext.CurrentMatrix().Copy().Translate(tileRect.TopLeft()));
+        aContext.SetPattern(gradientPattern);
       }
-      ctx->Fill();
-      ctx->SetMatrix(ctm);
+      aContext.Fill();
+      aContext.SetMatrix(ctm);
     }
   }
 }
 
 static CompositionOp
 DetermineCompositionOp(const nsCSSRendering::PaintBGParams& aParams,
                        const nsStyleImageLayers& aLayers,
                        uint32_t aLayerIndex)
--- a/layout/painting/nsCSSRendering.h
+++ b/layout/painting/nsCSSRendering.h
@@ -232,17 +232,17 @@ struct nsCSSRendering {
    * aFill is the rect on the destination to be covered by repeated tiling of
    * the gradient.
    * aSrc is the part of the gradient to be rendered into a tile (aDest), if
    * aSrc and aDest are different sizes, the image will be scaled to map aSrc
    * onto aDest.
    * aIntrinsicSize is the size of the source gradient.
    */
   static void PaintGradient(nsPresContext* aPresContext,
-                            nsRenderingContext& aRenderingContext,
+                            gfxContext& aContext,
                             nsStyleGradient* aGradient,
                             const nsRect& aDirtyRect,
                             const nsRect& aDest,
                             const nsRect& aFill,
                             const nsSize& aRepeatSize,
                             const mozilla::CSSIntRect& aSrc,
                             const nsSize& aIntrinsiceSize,
                             float aOpacity = 1.0);
--- a/layout/painting/nsImageRenderer.cpp
+++ b/layout/painting/nsImageRenderer.cpp
@@ -503,17 +503,17 @@ nsImageRenderer::Draw(nsPresContext*    
                                            aDest, aFill, aRepeatSize,
                                            aAnchor, aDirtyRect,
                                            ConvertImageRendererToDrawFlags(mFlags),
                                            mExtendMode, aOpacity);
       break;
     }
     case eStyleImageType_Gradient:
     {
-      nsCSSRendering::PaintGradient(aPresContext, aRenderingContext,
+      nsCSSRendering::PaintGradient(aPresContext, *ctx,
                                     mGradientData, aDirtyRect,
                                     aDest, aFill, aRepeatSize, aSrc, mSize,
                                     aOpacity);
       break;
     }
     case eStyleImageType_Element:
     {
       RefPtr<gfxDrawable> drawable = DrawableForElement(aDest,