Begin weaning GrClipMaskManager off of GrDrawTarget (take 2)

GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1754563003

Committed: https://skia.googlesource.com/skia/+/86c60758e9e4f9e203d7462cb22b2a245a0f51bd

Review URL: https://codereview.chromium.org/1754563003
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 3168424..70c65ed 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -8,7 +8,7 @@
 #include "GrClipMaskManager.h"
 #include "GrCaps.h"
 #include "GrDrawingManager.h"
-#include "GrDrawContext.h"
+#include "GrDrawContextPriv.h"
 #include "GrDrawTarget.h"
 #include "GrGpuResourcePriv.h"
 #include "GrPaint.h"
@@ -159,7 +159,8 @@
  * will be used on any element. If so, it returns true to indicate that the
  * entire clip should be rendered in SW and then uploaded en masse to the gpu.
  */
-bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder,
+bool GrClipMaskManager::UseSWOnlyPath(GrContext* context,
+                                      const GrPipelineBuilder& pipelineBuilder,
                                       const GrRenderTarget* rt,
                                       const SkVector& clipToMaskOffset,
                                       const GrReducedClip::ElementList& elements) {
@@ -179,7 +180,7 @@
         bool needsStencil = invert || 
                             SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op;
 
-        if (PathNeedsSWRenderer(this->getContext(), pipelineBuilder.getStencil().isDisabled(),
+        if (PathNeedsSWRenderer(context, pipelineBuilder.getStencil().isDisabled(),
                                 rt, translate, element, nullptr, needsStencil)) {
             return true;
         }
@@ -316,6 +317,42 @@
     }
 }
 
+bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilder,
+                                         GrPipelineBuilder::AutoRestoreStencil* ars,
+                                         const SkIRect& clipScissor,
+                                         const SkRect* devBounds,
+                                         GrAppliedClip* out) {
+    if (kRespectClip_StencilClipMode == fClipMode) {
+        fClipMode = kIgnoreClip_StencilClipMode;
+    }
+
+    GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
+
+    SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height());
+    SkIRect devBoundsScissor;
+    const SkIRect* scissor = &clipScissor;
+    bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds;
+    if (doDevBoundsClip) {
+        devBounds->roundOut(&devBoundsScissor);
+        if (devBoundsScissor.intersect(clipScissor)) {
+            scissor = &devBoundsScissor;
+        }
+    }
+
+    if (scissor->contains(clipSpaceRTIBounds)) {
+        // This counts as wide open
+        this->setPipelineBuilderStencil(pipelineBuilder, ars);
+        return true;
+    }
+
+    if (clipSpaceRTIBounds.intersect(*scissor)) {
+        out->fScissorState.set(clipSpaceRTIBounds);
+        this->setPipelineBuilderStencil(pipelineBuilder, ars);
+        return true;
+    }
+    return false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // sort out what kind of clip mask needs to be created: alpha, stencil,
 // scissor, or entirely software
@@ -439,21 +476,23 @@
             SkIntToScalar(-clipSpaceIBounds.fTop)
         };
 
-        if (this->useSWOnlyPath(pipelineBuilder, rt, clipToMaskOffset, elements)) {
+        if (UseSWOnlyPath(this->getContext(), pipelineBuilder, rt, clipToMaskOffset, elements)) {
             // The clip geometry is complex enough that it will be more efficient to create it
             // entirely in software
-            result.reset(this->createSoftwareClipMask(genID,
-                                                      initialState,
-                                                      elements,
-                                                      clipToMaskOffset,
-                                                      clipSpaceIBounds));
+            result.reset(CreateSoftwareClipMask(this->getContext(),
+                                                genID,
+                                                initialState,
+                                                elements,
+                                                clipToMaskOffset,
+                                                clipSpaceIBounds));
         } else {
-            result.reset(this->createAlphaClipMask(genID,
-                                                   initialState,
-                                                   elements,
-                                                   clipToMaskOffset,
-                                                   clipSpaceIBounds));
-            // If createAlphaClipMask fails it means useSWOnlyPath has a bug
+            result.reset(CreateAlphaClipMask(this->getContext(),
+                                             genID,
+                                             initialState,
+                                             elements,
+                                             clipToMaskOffset,
+                                             clipSpaceIBounds));
+            // If createAlphaClipMask fails it means UseSWOnlyPath has a bug
             SkASSERT(result);
         }
 
@@ -488,93 +527,67 @@
     return true;
 }
 
-namespace {
-////////////////////////////////////////////////////////////////////////////////
-// Set a coverage drawing XPF on the pipelineBuilder for the given op and invertCoverage mode
-void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage,
-                              GrPipelineBuilder* pipelineBuilder) {
-    SkASSERT(op <= SkRegion::kLastOp);
-    pipelineBuilder->setCoverageSetOpXPFactory(op, invertCoverage);
-}
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder,
-                                    const SkMatrix& viewMatrix,
-                                    GrTexture* target,
-                                    const SkClipStack::Element* element,
-                                    GrPathRenderer* pr) {
-
-    GrRenderTarget* rt = target->asRenderTarget();
-    pipelineBuilder->setRenderTarget(rt);
-
-    // The color we use to draw does not matter since we will always be using a GrCoverageSetOpXP
-    // which ignores color.
-    GrColor color = GrColor_WHITE;
+static bool stencil_element(GrDrawContext* dc,
+                            const SkIRect* scissorRect,
+                            const GrStencilSettings& ss,
+                            const SkMatrix& viewMatrix,
+                            const SkClipStack::Element* element) {
 
     // TODO: Draw rrects directly here.
     switch (element->getType()) {
         case Element::kEmpty_Type:
             SkDEBUGFAIL("Should never get here with an empty element.");
             break;
-        case Element::kRect_Type: {
-            // TODO: Do rects directly to the accumulator using a aa-rect GrProcessor that covers
-            // the entire mask bounds and writes 0 outside the rect.
-            if (element->isAA()) {
-                SkRect devRect = element->getRect();
-                viewMatrix.mapRect(&devRect);
-
-                SkAutoTUnref<GrDrawBatch> batch(
-                        GrRectBatchFactory::CreateAAFill(color, viewMatrix, element->getRect(),
-                                                         devRect));
-
-                fDrawTarget->drawBatch(*pipelineBuilder, batch);
-            } else {
-                draw_non_aa_rect(fDrawTarget, *pipelineBuilder, color, viewMatrix,
-                                 element->getRect());
-            }
-            return true;
-        }
+        case Element::kRect_Type:
+            return dc->drawContextPriv().drawAndStencilRect(scissorRect, ss,
+                                                            element->getOp(),
+                                                            element->isInverseFilled(),
+                                                            element->isAA(),
+                                                            viewMatrix, element->getRect());
+            break;
         default: {
             SkPath path;
             element->asPath(&path);
             if (path.isInverseFillType()) {
                 path.toggleInverseFillType();
             }
-            GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
-            if (nullptr == pr) {
-                GrPathRendererChain::DrawType type;
-                type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
-                                         GrPathRendererChain::kColor_DrawType;
 
-                GrPathRenderer::CanDrawPathArgs canDrawArgs;
-                canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps();
-                canDrawArgs.fViewMatrix = &viewMatrix;
-                canDrawArgs.fPath = &path;
-                canDrawArgs.fStroke = &stroke;
-                canDrawArgs.fAntiAlias = element->isAA();;
-                canDrawArgs.fIsStencilDisabled = pipelineBuilder->getStencil().isDisabled();
-                canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled();
-
-                pr = this->getContext()->drawingManager()->getPathRenderer(canDrawArgs, false, type);
-            }
-            if (nullptr == pr) {
-                return false;
-            }
-            GrPathRenderer::DrawPathArgs args;
-            args.fTarget = fDrawTarget;
-            args.fResourceProvider = this->getContext()->resourceProvider();
-            args.fPipelineBuilder = pipelineBuilder;
-            args.fColor = color;
-            args.fViewMatrix = &viewMatrix;
-            args.fPath = &path;
-            args.fStroke = &stroke;
-            args.fAntiAlias = element->isAA();
-            pr->drawPath(args);
+            return dc->drawContextPriv().drawAndStencilPath(scissorRect, ss,
+                                                            element->getOp(),
+                                                            element->isInverseFilled(),
+                                                            element->isAA(), viewMatrix, path);
             break;
         }
     }
-    return true;
+
+    return false;
+}
+
+static void draw_element(GrDrawContext* dc,
+                         const GrClip& clip, // TODO: can this just always be WideOpen?
+                         const GrPaint &paint,
+                         const SkMatrix& viewMatrix,
+                         const SkClipStack::Element* element) {
+
+    // TODO: Draw rrects directly here.
+    switch (element->getType()) {
+        case Element::kEmpty_Type:
+            SkDEBUGFAIL("Should never get here with an empty element.");
+            break;
+        case Element::kRect_Type:
+            dc->drawRect(clip, paint, viewMatrix, element->getRect());
+            break;
+        default: {
+            SkPath path;
+            element->asPath(&path);
+            if (path.isInverseFillType()) {
+                path.toggleInverseFillType();
+            }
+
+            dc->drawPath(clip, paint, viewMatrix, path, GrStrokeInfo::FillInfo());
+            break;
+        }
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -588,32 +601,13 @@
     builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16);
 }
 
-GrTexture* GrClipMaskManager::createCachedMask(int width, int height, const GrUniqueKey& key,
-                                               bool renderTarget) {
-    GrSurfaceDesc desc;
-    desc.fWidth = width;
-    desc.fHeight = height;
-    desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
-    if (!renderTarget || this->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
-        desc.fConfig = kAlpha_8_GrPixelConfig;
-    } else {
-        desc.fConfig = kRGBA_8888_GrPixelConfig;
-    }
-
-    GrTexture* texture = this->resourceProvider()->createApproxTexture(desc, 0);
-    if (!texture) {
-        return nullptr;
-    }
-    texture->resourcePriv().setUniqueKey(key);
-    return texture;
-}
-
-GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
+GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
+                                                  int32_t elementsGenID,
                                                   GrReducedClip::InitialState initialState,
                                                   const GrReducedClip::ElementList& elements,
                                                   const SkVector& clipToMaskOffset,
                                                   const SkIRect& clipSpaceIBounds) {
-    GrResourceProvider* resourceProvider = this->resourceProvider();
+    GrResourceProvider* resourceProvider = context->resourceProvider();
     GrUniqueKey key;
     GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
     if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
@@ -621,15 +615,27 @@
     }
 
     // There's no texture in the cache. Let's try to allocate it then.
-    SkAutoTUnref<GrTexture> texture(this->createCachedMask(
-        clipSpaceIBounds.width(), clipSpaceIBounds.height(), key, true));
+    GrSurfaceDesc desc;
+    desc.fWidth = clipSpaceIBounds.width();
+    desc.fHeight = clipSpaceIBounds.height();
+    desc.fFlags = kRenderTarget_GrSurfaceFlag;
+    if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
+        desc.fConfig = kAlpha_8_GrPixelConfig;
+    } else {
+        desc.fConfig = kRGBA_8888_GrPixelConfig;
+    }
+
+    SkAutoTUnref<GrTexture> texture(resourceProvider->createApproxTexture(desc, 0));
     if (!texture) {
         return nullptr;
     }
 
-    // Set the matrix so that rendered clip elements are transformed to mask space from clip
-    // space.
-    const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
+    texture->resourcePriv().setUniqueKey(key);
+
+    SkAutoTUnref<GrDrawContext> dc(context->drawContext(texture->asRenderTarget()));
+    if (!dc) {
+        return nullptr;
+    }
 
     // The texture may be larger than necessary, this rect represents the part of the texture
     // we populate with a rasterization of the clip.
@@ -637,16 +643,18 @@
 
     // The scratch texture that we are drawing into can be substantially larger than the mask. Only
     // clear the part that we care about.
-    fDrawTarget->clear(&maskSpaceIBounds,
-                       GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
-                       true,
-                       texture->asRenderTarget());
+    dc->clear(&maskSpaceIBounds,
+              GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
+              true);
 
-    // When we use the stencil in the below loop it is important to have this clip installed.
+    // Set the matrix so that rendered clip elements are transformed to mask space from clip
+    // space.
+    const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
+
+    // It is important that we use maskSpaceIBounds as the stencil rect in the below loop.
     // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first
     // pass must not set values outside of this bounds or stencil values outside the rect won't be
     // cleared.
-    const GrClip clip(maskSpaceIBounds);
 
     // walk through each clip element and perform its set op
     for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
@@ -654,68 +662,54 @@
         SkRegion::Op op = element->getOp();
         bool invert = element->isInverseFilled();
         if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
-
-            GrPathRenderer* pr = GetPathRenderer(this->getContext(),
+#ifdef SK_DEBUG
+            GrPathRenderer* pr = GetPathRenderer(context,
                                                  texture, translate, element);
             if (Element::kRect_Type != element->getType() && !pr) {
-                // useSWOnlyPath should now filter out all cases where gpu-side mask merging would
-                // be performed (i.e., pr would be NULL for a non-rect path). See https://bug.skia.org/4519
-                // for rationale and details.
+                // UseSWOnlyPath should now filter out all cases where gpu-side mask merging would
+                // be performed (i.e., pr would be NULL for a non-rect path).
+                // See https://bug.skia.org/4519 for rationale and details.
                 SkASSERT(0);
-                continue;
+            }
+#endif
+
+            // draw directly into the result with the stencil set to make the pixels affected
+            // by the clip shape be non-zero.
+            GR_STATIC_CONST_SAME_STENCIL(kStencilInElement,
+                                         kReplace_StencilOp,
+                                         kReplace_StencilOp,
+                                         kAlways_StencilFunc,
+                                         0xffff,
+                                         0xffff,
+                                         0xffff)
+            if (!stencil_element(dc, &maskSpaceIBounds, kStencilInElement,
+                                 translate, element)) {
+                texture->resourcePriv().removeUniqueKey();
+                return nullptr;
             }
 
-            {
-                GrPipelineBuilder pipelineBuilder;
-
-                pipelineBuilder.setClip(clip);
-                pipelineBuilder.setRenderTarget(texture->asRenderTarget());
-                SkASSERT(pipelineBuilder.getStencil().isDisabled());
-
-                // draw directly into the result with the stencil set to make the pixels affected
-                // by the clip shape be non-zero.
-                GR_STATIC_CONST_SAME_STENCIL(kStencilInElement,
-                                             kReplace_StencilOp,
-                                             kReplace_StencilOp,
-                                             kAlways_StencilFunc,
-                                             0xffff,
-                                             0xffff,
-                                             0xffff);
-                pipelineBuilder.setStencil(kStencilInElement);
-                set_coverage_drawing_xpf(op, invert, &pipelineBuilder);
-
-                if (!this->drawElement(&pipelineBuilder, translate, texture, element, pr)) {
-                    texture->resourcePriv().removeUniqueKey();
-                    return nullptr;
-                }
-            }
-
-            {
-                GrPipelineBuilder backgroundPipelineBuilder;
-                backgroundPipelineBuilder.setRenderTarget(texture->asRenderTarget());
-
-                set_coverage_drawing_xpf(op, !invert, &backgroundPipelineBuilder);
-                // Draw to the exterior pixels (those with a zero stencil value).
-                GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement,
-                                             kZero_StencilOp,
-                                             kZero_StencilOp,
-                                             kEqual_StencilFunc,
-                                             0xffff,
-                                             0x0000,
-                                             0xffff);
-                backgroundPipelineBuilder.setStencil(kDrawOutsideElement);
-
-                // The color passed in here does not matter since the coverageSetOpXP won't read it.
-                draw_non_aa_rect(fDrawTarget, backgroundPipelineBuilder, GrColor_WHITE, translate,
-                                 SkRect::Make(clipSpaceIBounds));
+            // Draw to the exterior pixels (those with a zero stencil value).
+            GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement,
+                                         kZero_StencilOp,
+                                         kZero_StencilOp,
+                                         kEqual_StencilFunc,
+                                         0xffff,
+                                         0x0000,
+                                         0xffff);
+            if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, kDrawOutsideElement,
+                                                          op, !invert, false,
+                                                          translate,
+                                                          SkRect::Make(clipSpaceIBounds))) {
+                texture->resourcePriv().removeUniqueKey();
+                return nullptr;
             }
         } else {
-            GrPipelineBuilder pipelineBuilder;
-
             // all the remaining ops can just be directly draw into the accumulation buffer
-            set_coverage_drawing_xpf(op, false, &pipelineBuilder);
-            // The color passed in here does not matter since the coverageSetOpXP won't read it.
-            this->drawElement(&pipelineBuilder, translate, texture, element);
+            GrPaint paint;
+            paint.setAntiAlias(element->isAA());
+            paint.setCoverageSetOpXPFactory(op, false);
+
+            draw_element(dc, GrClip::WideOpen(), paint, translate, element);
         }
     }
 
@@ -1081,14 +1075,15 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID,
+GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context,
+                                                     int32_t elementsGenID,
                                                      GrReducedClip::InitialState initialState,
                                                      const GrReducedClip::ElementList& elements,
                                                      const SkVector& clipToMaskOffset,
                                                      const SkIRect& clipSpaceIBounds) {
     GrUniqueKey key;
     GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
-    GrResourceProvider* resourceProvider = this->resourceProvider();
+    GrResourceProvider* resourceProvider = context->resourceProvider();
     if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
         return texture;
     }
@@ -1097,7 +1092,7 @@
     // the top left corner of the resulting rect to the top left of the texture.
     SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
 
-    GrSWMaskHelper helper(this->getContext());
+    GrSWMaskHelper helper(context);
 
     // Set the matrix so that rendered clip elements are transformed to mask space from clip
     // space.
@@ -1141,11 +1136,17 @@
     }
 
     // Allocate clip mask texture
-    GrTexture* result = this->createCachedMask(clipSpaceIBounds.width(), clipSpaceIBounds.height(),
-                                               key, false);
-    if (nullptr == result) {
+    GrSurfaceDesc desc;
+    desc.fWidth = clipSpaceIBounds.width();
+    desc.fHeight = clipSpaceIBounds.height();
+    desc.fConfig = kAlpha_8_GrPixelConfig;
+
+    GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0);
+    if (!result) {
         return nullptr;
     }
+    result->resourcePriv().setUniqueKey(key);
+
     helper.toTexture(result);
 
     return result;