Bug 1447880. Paint nsDisplayMasks directly instead of using a BasicLayerManager. r=mstange
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Fri, 14 Sep 2018 10:42:38 -0400
changeset 493519 5cd110df8612bd173908ec93846b70f53bd9bde7
parent 493518 e3136af29c895b613def401aa30525735aff48ae
child 493520 8d4ed588ff4064d00d306438e95c295ba2d78743
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1447880
milestone64.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 1447880. Paint nsDisplayMasks directly instead of using a BasicLayerManager. r=mstange This allows us to invalidate individual items inside of the mask instead of treating the mask and it's children as a single item. Differential Revision: https://phabricator.services.mozilla.com/D6224
gfx/layers/wr/WebRenderCommandBuilder.cpp
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
layout/svg/nsSVGIntegrationUtils.cpp
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -902,26 +902,24 @@ Grouper::PaintContainerItem(DIGroup* aGr
       aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext, aRecorder);
       aContext->GetDrawTarget()->PopLayer();
       GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), aItem->GetPerFrameKey());
       aContext->GetDrawTarget()->FlushItem(aItemBounds);
       break;
     }
     case DisplayItemType::TYPE_MASK: {
       GP("Paint Mask\n");
-      // We don't currently support doing invalidation inside nsDisplayMask
-      // for now just paint it as a single item
-      BlobItemData* data = GetBlobItemDataForGroup(aItem, aGroup);
-      if (data->mLayerManager->GetRoot()) {
-        data->mLayerManager->BeginTransaction();
-        static_cast<nsDisplayMask*>(aItem)->PaintAsLayer(mDisplayListBuilder,
-                                                       aContext, data->mLayerManager);
-        if (data->mLayerManager->InTransaction()) {
-          data->mLayerManager->AbortTransaction();
-        }
+      auto maskItem = static_cast<nsDisplayMask*>(aItem);
+      if (maskItem->IsValidMask()) {
+        maskItem->PaintWithContentsPaintCallback(mDisplayListBuilder, aContext, [&] {
+          GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), aItem->GetPerFrameKey());
+          aContext->GetDrawTarget()->FlushItem(aItemBounds);
+          aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext, aRecorder);
+          GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), aItem->GetPerFrameKey());
+          });
         aContext->GetDrawTarget()->FlushItem(aItemBounds);
       }
       break;
     }
     case DisplayItemType::TYPE_FILTER: {
       GP("Paint Filter\n");
       // We don't currently support doing invalidation inside nsDisplayFilter
       // for now just paint it as a single item
@@ -1105,18 +1103,17 @@ Grouper::ConstructItemInsideInactive(Web
                                      wr::DisplayListBuilder& aBuilder,
                                      wr::IpcResourceUpdateQueue& aResources,
                                      DIGroup* aGroup, nsDisplayItem* aItem,
                                      const StackingContextHelper& aSc)
 {
   nsDisplayList* children = aItem->GetChildren();
   BlobItemData* data = GetBlobItemDataForGroup(aItem, aGroup);
 
-  if (aItem->GetType() == DisplayItemType::TYPE_FILTER ||
-      aItem->GetType() == DisplayItemType::TYPE_MASK) {
+  if (aItem->GetType() == DisplayItemType::TYPE_FILTER) {
     gfx::Size scale(1, 1);
     // If ComputeDifferences finds any change, we invalidate the entire container item.
     // This is needed because blob merging requires the entire item to be within the invalid region.
     data->mInvalid = BuildLayer(aItem, data, mDisplayListBuilder, scale);
   } else if (aItem->GetType() == DisplayItemType::TYPE_TRANSFORM) {
     nsDisplayTransform* transformItem = static_cast<nsDisplayTransform*>(aItem);
     const Matrix4x4Flagged& t = transformItem->GetTransform();
     Matrix t2d;
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -9899,16 +9899,53 @@ nsDisplayMask::PaintAsLayer(nsDisplayLis
 
   nsSVGIntegrationUtils::PaintMaskAndClipPath(params);
 
   context->PopClip();
 
   nsDisplayMaskGeometry::UpdateDrawResult(this, imgParams.result);
 }
 
+void
+nsDisplayMask::PaintWithContentsPaintCallback(nsDisplayListBuilder* aBuilder,
+                                              gfxContext* aCtx,
+                                              const std::function<void()>& aPaintChildren)
+{
+  // Clip the drawing target by mVisibleRect, which contains the visible
+  // region of the target frame and its out-of-flow and inflow descendants.
+  gfxContext* context = aCtx;
+
+  Rect bounds =
+    NSRectToRect(GetPaintRect(), mFrame->PresContext()->AppUnitsPerDevPixel());
+  bounds.RoundOut();
+  context->Clip(bounds);
+
+  imgDrawingParams imgParams(aBuilder->ShouldSyncDecodeImages()
+                               ? imgIContainer::FLAG_SYNC_DECODE
+                               : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
+  nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
+  nsSVGIntegrationUtils::PaintFramesParams params(*aCtx,
+                                                  mFrame,
+                                                  GetPaintRect(),
+                                                  borderArea,
+                                                  aBuilder,
+                                                  nullptr,
+                                                  mHandleOpacity,
+                                                  imgParams);
+
+  ComputeMaskGeometry(params);
+
+  nsSVGIntegrationUtils::PaintMaskAndClipPath(params, aPaintChildren);
+
+  context->PopClip();
+
+  nsDisplayMaskGeometry::UpdateDrawResult(this, imgParams.result);
+}
+
+
 bool
 nsDisplayMask::CreateWebRenderCommands(
   mozilla::wr::DisplayListBuilder& aBuilder,
   mozilla::wr::IpcResourceUpdateQueue& aResources,
   const StackingContextHelper& aSc,
   mozilla::layers::WebRenderLayerManager* aManager,
   nsDisplayListBuilder* aDisplayListBuilder)
 {
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -6785,16 +6785,21 @@ public:
 #endif
 
   bool IsValidMask();
 
   void PaintAsLayer(nsDisplayListBuilder* aBuilder,
                     gfxContext* aCtx,
                     LayerManager* aManager);
 
+  void PaintWithContentsPaintCallback(nsDisplayListBuilder* aBuilder,
+                                      gfxContext* aCtx,
+                                      const std::function<void()>& aPaintChildren);
+
+
   /*
    * Paint mask onto aMaskContext in mFrame's coordinate space and
    * return whether the mask layer was painted successfully.
    */
   bool PaintMask(nsDisplayListBuilder* aBuilder,
                  gfxContext* aMaskContext,
                  bool* aMaskPainted = nullptr);
 
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -977,17 +977,17 @@ void PaintMaskAndClipPathInternal(const 
       MOZ_ASSERT(maskUsage.opacity != 1.0f);
 
       matSR.SetContext(&context);
       MoveContextOriginToUserSpace(firstFrame, aParams);
       shouldPushMask = true;
     }
 
     if (shouldPushMask) {
-      if (aParams.layerManager->GetRoot()->GetContentFlags() &
+      if (aParams.layerManager && aParams.layerManager->GetRoot()->GetContentFlags() &
           Layer::CONTENT_COMPONENT_ALPHA) {
         context.PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA,
                                            opacityApplied
                                              ? 1.0
                                              : maskUsage.opacity,
                                            maskSurface, maskTransform);
       } else {
         context.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA,