Pass GrAppliedClip to pipeline creation.

This skips adding the clip's coverage processor to the GrPipelineBuilder before creating GrPipeline.

Change-Id: I1282dd8600701ab2b6a049abd8ad571abbbcbbe5
Reviewed-on: https://skia-review.googlesource.com/7020
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index ea3f0f2..96051ea 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -7,11 +7,12 @@
 
 #include "GrPipeline.h"
 
+#include "GrAppliedClip.h"
 #include "GrCaps.h"
-#include "GrRenderTargetContext.h"
 #include "GrGpu.h"
 #include "GrPipelineBuilder.h"
 #include "GrProcOptInfo.h"
+#include "GrRenderTargetContext.h"
 #include "GrRenderTargetOpList.h"
 #include "GrRenderTargetPriv.h"
 #include "GrXferProcessor.h"
@@ -30,8 +31,8 @@
     GrPipeline* pipeline = new (memory) GrPipeline;
     pipeline->fRenderTarget.reset(rt);
     SkASSERT(pipeline->fRenderTarget);
-    pipeline->fScissorState = *args.fScissor;
-    pipeline->fWindowRectsState = *args.fWindowRectsState;
+    pipeline->fScissorState = args.fAppliedClip->scissorState();
+    pipeline->fWindowRectsState = args.fAppliedClip->windowRectsState();
     pipeline->fUserStencilSettings = userStencil;
     pipeline->fDrawFace = builder.getDrawFace();
 
@@ -51,10 +52,10 @@
     if (builder.getUsesDistanceVectorField()) {
         pipeline->fFlags |= kUsesDistanceVectorField_Flag;
     }
-    if (args.fHasStencilClip) {
+    if (args.fAppliedClip->hasStencilClip()) {
         pipeline->fFlags |= kHasStencilClip_Flag;
     }
-    if (!userStencil->isDisabled(args.fHasStencilClip)) {
+    if (!userStencil->isDisabled(args.fAppliedClip->hasStencilClip())) {
         pipeline->fFlags |= kStencilEnabled_Flag;
     }
 
@@ -84,10 +85,9 @@
 
     const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() :
                                                        &GrPorterDuffXPFactory::SimpleSrcOverXP();
-    optFlags = xpForOpts->getOptimizations(args.fAnalysis,
-                                           userStencil->doesWrite(args.fHasStencilClip),
-                                           &overrideColor,
-                                           *args.fCaps);
+    optFlags = xpForOpts->getOptimizations(
+            args.fAnalysis, userStencil->doesWrite(args.fAppliedClip->hasStencilClip()),
+            &overrideColor, *args.fCaps);
 
     // When path rendering the stencil settings are not always set on the GrPipelineBuilder
     // so we must check the draw type. In cases where we will skip drawing we simply return a
@@ -122,6 +122,9 @@
     pipeline->fNumColorProcessors = builder.numColorFragmentProcessors() - firstColorProcessorIdx;
     int numTotalProcessors = pipeline->fNumColorProcessors +
                              builder.numCoverageFragmentProcessors() - firstCoverageProcessorIdx;
+    if (args.fAppliedClip->clipCoverageFragmentProcessor()) {
+        ++numTotalProcessors;
+    }
     pipeline->fFragmentProcessors.reset(numTotalProcessors);
     int currFPIdx = 0;
     for (int i = firstColorProcessorIdx; i < builder.numColorFragmentProcessors();
@@ -137,6 +140,10 @@
         pipeline->fFragmentProcessors[currFPIdx].reset(fp);
         usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
     }
+    if (const GrFragmentProcessor* fp = args.fAppliedClip->clipCoverageFragmentProcessor()) {
+        pipeline->fFragmentProcessors[currFPIdx].reset(fp);
+        usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
+    }
 
     // Setup info we need to pass to GrPrimitiveProcessors that are used with this GrPipeline.
     optimizations->fFlags = 0;
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 0013ce6..f00fbf3 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -26,6 +26,7 @@
 #include "effects/GrPorterDuffXferProcessor.h"
 #include "effects/GrSimpleTextureEffect.h"
 
+class GrAppliedClip;
 class GrDeviceCoordTexture;
 class GrOp;
 class GrPipelineBuilder;
@@ -70,12 +71,10 @@
 
     struct CreateArgs {
         const GrPipelineBuilder* fPipelineBuilder;
+        GrAppliedClip* fAppliedClip;
         GrRenderTargetContext* fRenderTargetContext;
         const GrCaps* fCaps;
         GrPipelineAnalysis fAnalysis;
-        const GrScissorState* fScissor;
-        const GrWindowRectsState* fWindowRectsState;
-        bool fHasStencilClip;
         GrXferProcessor::DstTexture fDstTexture;
     };
 
diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp
index fc67c33..fce8aa9 100644
--- a/src/gpu/GrPipelineBuilder.cpp
+++ b/src/gpu/GrPipelineBuilder.cpp
@@ -19,8 +19,6 @@
         : fFlags(0x0)
         , fUserStencilSettings(&GrUserStencilSettings::kUnused)
         , fDrawFace(GrDrawFace::kBoth) {
-    SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
-
     for (int i = 0; i < paint.numColorFragmentProcessors(); ++i) {
         fColorFragmentProcessors.emplace_back(paint.fColorFragmentProcessors[i].release());
     }
@@ -40,8 +38,6 @@
                    paint.usesDistanceVectorField());
 }
 
-//////////////////////////////////////////////////////////////////////////////s
-
 bool GrPipelineBuilder::willXPNeedDstTexture(const GrCaps& caps,
                                              const GrPipelineAnalysis& analysis) const {
     if (this->getXPFactory()) {
@@ -49,30 +45,3 @@
     }
     return GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(caps, analysis);
 }
-
-void GrPipelineBuilder::AutoRestoreFragmentProcessorState::set(
-                                                         const GrPipelineBuilder* pipelineBuilder) {
-    if (fPipelineBuilder) {
-        int m = fPipelineBuilder->numColorFragmentProcessors() - fColorEffectCnt;
-        SkASSERT(m >= 0);
-        fPipelineBuilder->fColorFragmentProcessors.pop_back_n(m);
-
-        int n = fPipelineBuilder->numCoverageFragmentProcessors() - fCoverageEffectCnt;
-        SkASSERT(n >= 0);
-        fPipelineBuilder->fCoverageFragmentProcessors.pop_back_n(n);
-
-        SkDEBUGCODE(--fPipelineBuilder->fBlockEffectRemovalCnt;)
-    }
-    fPipelineBuilder = const_cast<GrPipelineBuilder*>(pipelineBuilder);
-    if (nullptr != pipelineBuilder) {
-        fColorEffectCnt = pipelineBuilder->numColorFragmentProcessors();
-        fCoverageEffectCnt = pipelineBuilder->numCoverageFragmentProcessors();
-        SkDEBUGCODE(++pipelineBuilder->fBlockEffectRemovalCnt;)
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrPipelineBuilder::~GrPipelineBuilder() {
-    SkASSERT(0 == fBlockEffectRemovalCnt);
-}
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index 66459ae..fcc692a 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -37,8 +37,6 @@
      */
     GrPipelineBuilder(GrPaint&&, GrAAType);
 
-    virtual ~GrPipelineBuilder();
-
     ///////////////////////////////////////////////////////////////////////////
     /// @name Fragment Processors
     ///
@@ -61,44 +59,6 @@
         return fCoverageFragmentProcessors[idx].get();
     }
 
-    /**
-     * When this object is destroyed it will remove any color/coverage FPs from the pipeline builder
-     * that were added after its constructor.
-     * This class can transiently modify its "const" GrPipelineBuilder object but will restore it
-     * when done - so it is notionally "const" correct.
-     */
-    class AutoRestoreFragmentProcessorState : public ::SkNoncopyable {
-    public:
-        AutoRestoreFragmentProcessorState()
-            : fPipelineBuilder(nullptr)
-            , fColorEffectCnt(0)
-            , fCoverageEffectCnt(0) {}
-
-        AutoRestoreFragmentProcessorState(const GrPipelineBuilder& ds)
-            : fPipelineBuilder(nullptr)
-            , fColorEffectCnt(0)
-            , fCoverageEffectCnt(0) {
-            this->set(&ds);
-        }
-
-        ~AutoRestoreFragmentProcessorState() { this->set(nullptr); }
-
-        void set(const GrPipelineBuilder* ds);
-
-        bool isSet() const { return SkToBool(fPipelineBuilder); }
-
-        void addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
-            SkASSERT(this->isSet());
-            return fPipelineBuilder->addCoverageFragmentProcessor(std::move(processor));
-        }
-
-    private:
-        // notionally const (as marginalia)
-        GrPipelineBuilder*    fPipelineBuilder;
-        int                   fColorEffectCnt;
-        int                   fCoverageEffectCnt;
-    };
-
     /// @}
 
     ///////////////////////////////////////////////////////////////////////////
@@ -241,17 +201,6 @@
     bool usePLSDstRead(const GrDrawOp*) const;
 
 private:
-    // This exists solely for AutoRestoreFragmentProcessor, which itself exists solely to install
-    // an applied clip's FP. This will be removed soon.
-    void addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
-        SkASSERT(processor);
-        fCoverageFragmentProcessors.push_back(std::move(processor));
-    }
-
-    // Some of the auto restore objects assume that no effects are removed during their lifetime.
-    // This is used to assert that this condition holds.
-    SkDEBUGCODE(mutable int fBlockEffectRemovalCnt;)
-
     typedef SkSTArray<4, sk_sp<GrFragmentProcessor>> FragmentProcessorArray;
 
     uint32_t                                fFlags;
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 780e13b..e4bb34e 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -275,13 +275,6 @@
         return;
     }
 
-    // TODO: this is the only remaining usage of the AutoRestoreFragmentProcessorState - remove it
-    GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
-    if (appliedClip.clipCoverageFragmentProcessor()) {
-        arfps.set(&pipelineBuilder);
-        arfps.addCoverageFragmentProcessor(sk_ref_sp(appliedClip.clipCoverageFragmentProcessor()));
-    }
-
     if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
         if (!renderTargetContext->accessRenderTarget()) {
             return;
@@ -296,6 +289,7 @@
 
     GrPipeline::CreateArgs args;
     args.fPipelineBuilder = &pipelineBuilder;
+    args.fAppliedClip = &appliedClip;
     args.fRenderTargetContext = renderTargetContext;
     args.fCaps = this->caps();
     op->initPipelineAnalysis(&args.fAnalysis);
@@ -324,9 +318,10 @@
     args.fAnalysis.fCoveragePOI.addProcessors(
             sk_sp_address_as_pointer_address(pipelineBuilder.fCoverageFragmentProcessors.begin()),
             pipelineBuilder.numCoverageFragmentProcessors());
-    args.fScissor = &appliedClip.scissorState();
-    args.fWindowRectsState = &appliedClip.windowRectsState();
-    args.fHasStencilClip = appliedClip.hasStencilClip();
+    if (const GrFragmentProcessor* clipFP = appliedClip.clipCoverageFragmentProcessor()) {
+        args.fAnalysis.fCoveragePOI.addProcessors(&clipFP, 1);
+    }
+
     if (!renderTargetContext->accessRenderTarget()) {
         return;
     }
diff --git a/tests/GpuSampleLocationsTest.cpp b/tests/GpuSampleLocationsTest.cpp
index 094a3fc..b4c4fe5 100644
--- a/tests/GpuSampleLocationsTest.cpp
+++ b/tests/GpuSampleLocationsTest.cpp
@@ -12,10 +12,11 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrAppliedClip.h"
+#include "GrPipelineBuilder.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetPriv.h"
 #include "GrTypesPriv.h"
-#include "GrPipelineBuilder.h"
 #include "gl/GrGLGpu.h"
 #include "gl/debug/DebugGLTestContext.h"
 
@@ -96,13 +97,12 @@
     GrWindowRectsState dummyWindows;
     GrPipelineOptimizations dummyOverrides;
 
+    GrAppliedClip dummyAppliedClip(SkRect::MakeLargest());
     GrPipeline::CreateArgs args;
     args.fPipelineBuilder = &dummyBuilder;
     args.fRenderTargetContext = dc;
     args.fCaps = dc->caps();
-    args.fScissor = &dummyScissor;
-    args.fWindowRectsState = &dummyWindows;
-    args.fHasStencilClip = false;
+    args.fAppliedClip = &dummyAppliedClip;
     args.fDstTexture = GrXferProcessor::DstTexture();
 
     GrPipeline::CreateAt(storage, args, &dummyOverrides);