Bug 1323912 - Part 5. Apply opacity in mask layer painting path. r=mstange
authorcku <cku@mozilla.com>
Tue, 03 Jan 2017 17:12:32 +0800
changeset 328032 39ca4e6d2eb2e59c4fda35e40bb0ae19b3177c63
parent 328031 dc22594f021497215362df65b7e9ccc4c409b628
child 328033 4fd4d2b90556008374c8bde162e72e8ebaad9901
push id31162
push userkwierso@gmail.com
push dateFri, 06 Jan 2017 01:24:21 +0000
treeherdermozilla-central@53193729a50b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1323912
milestone53.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 1323912 - Part 5. Apply opacity in mask layer painting path. r=mstange MozReview-Commit-ID: HX2Tcum2smO
layout/painting/nsDisplayList.cpp
layout/svg/nsSVGIntegrationUtils.cpp
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -7346,21 +7346,19 @@ bool nsDisplayMask::ShouldPaintOnMaskLay
 {
   if (!aManager->IsCompositingCheap()) {
     return false;
   }
 
   nsSVGUtils::MaskUsage maskUsage;
   nsSVGUtils::DetermineMaskUsage(mFrame, mHandleOpacity, maskUsage);
 
-  // XXX Bug 1323912. nsSVGIntegrationUtils::PaintMask can not handle opacity
-  // correctly. Turn it off before bug fixed.
   // XXX Temporary disable paint clip-path onto mask before figure out
   // performance regression(bug 1325550).
-  if (maskUsage.opacity != 1.0 || maskUsage.shouldApplyClipPath) {
+  if (maskUsage.shouldApplyClipPath) {
     return false;
   }
 
   if (!nsSVGIntegrationUtils::IsMaskResourceReady(mFrame)) {
     return false;
   }
 
   if (gfxPrefs::DrawMaskLayer()) {
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -720,32 +720,47 @@ nsSVGIntegrationUtils::IsMaskResourceRea
       return false;
     }
   }
 
   // Either all mask resources are ready, or no mask resource is needed.
   return true;
 }
 
+class AutoPopGroup
+{
+public:
+  AutoPopGroup() : mContext(nullptr) { }
+
+  ~AutoPopGroup() {
+    if (mContext) {
+      mContext->PopGroupAndBlend();
+    }
+  }
+
+  void SetContext(gfxContext* aContext) {
+    mContext = aContext;
+  }
+
+private:
+  gfxContext* mContext;
+};
+
 DrawResult
 nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
 {
   nsSVGUtils::MaskUsage maskUsage;
   nsSVGUtils::DetermineMaskUsage(aParams.frame, aParams.handleOpacity,
                                  maskUsage);
 
   nsIFrame* frame = aParams.frame;
   if (!ValidateSVGFrame(frame)) {
     return DrawResult::SUCCESS;
   }
 
-  // XXX Bug 1323912.
-  MOZ_ASSERT(maskUsage.opacity == 1.0,
-             "nsSVGIntegrationUtils::PaintMask can not handle opacity now.");
-
   gfxContext& ctx = aParams.ctx;
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
   nsSVGEffects::EffectProperties effectProperties =
     nsSVGEffects::GetEffectProperties(firstFrame);
 
   DrawResult result = DrawResult::SUCCESS;
   RefPtr<DrawTarget> maskTarget = ctx.GetDrawTarget();
@@ -757,16 +772,25 @@ nsSVGIntegrationUtils::PaintMask(const P
     //
     // Create one extra draw target for drawing positioned mask, so that we do
     // not have to copy the content of maskTarget before painting
     // clip-path into it.
     maskTarget = maskTarget->CreateSimilarDrawTarget(maskTarget->GetSize(),
                                                      SurfaceFormat::A8);
   }
 
+  nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
+  AutoPopGroup autoPop;
+  bool shouldPushOpacity = (maskUsage.opacity != 1.0) &&
+                           (maskFrames.Length() != 1);
+  if (shouldPushOpacity) {
+    ctx.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, maskUsage.opacity);
+    autoPop.SetContext(&ctx);
+  }
+
   gfxContextMatrixAutoSaveRestore matSR;
   nsPoint offsetToBoundingBox;
   nsPoint offsetToUserSpace;
 
   // Paint clip-path-basic-shape onto ctx
   gfxContextAutoSaveRestore basicShapeSR;
   if (maskUsage.shouldApplyBasicShape) {
     matSR.SetContext(&ctx);
@@ -788,19 +812,18 @@ nsSVGIntegrationUtils::PaintMask(const P
 
   // Paint mask onto ctx.
   if (maskUsage.shouldGenerateMaskLayer) {
     matSR.Restore();
     matSR.SetContext(&ctx);
 
     SetupContextMatrix(frame, aParams, offsetToBoundingBox,
                        offsetToUserSpace);
-    nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
-
-    result = PaintMaskSurface(aParams, maskTarget, 1.0,
+    result = PaintMaskSurface(aParams, maskTarget,
+                              shouldPushOpacity ?  1.0 : maskUsage.opacity,
                               firstFrame->StyleContext(), maskFrames,
                               ctx.CurrentMatrix(), offsetToUserSpace);
     if (result != DrawResult::SUCCESS) {
       return result;
     }
   }
 
   // Paint clip-path onto ctx.