Bug 1323912 - Part 5. Apply opacity in mask layer painting path. draft
authorcku <cku@mozilla.com>
Tue, 03 Jan 2017 17:12:32 +0800
changeset 456120 68f9e28692502d37a13fe5e87478b08339d6768d
parent 456119 d09f4c0a6c3f97351805560bcf4b2e9df11681ec
child 456121 e3e3864855658043dd0575a0288ce11c99141f3e
push id40410
push userbmo:cku@mozilla.com
push dateThu, 05 Jan 2017 02:50:43 +0000
bugs1323912
milestone53.0a1
Bug 1323912 - Part 5. Apply opacity in mask layer painting path. 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.