Modify GrClipMaskManager to reflect logical constness

TBR=bsalomon@google.com
BUG=skia:

Review URL: https://codereview.chromium.org/1230023003
diff --git a/include/gpu/GrProcessorDataManager.h b/include/gpu/GrProcessorDataManager.h
index a58cb4e..ccc77d7 100644
--- a/include/gpu/GrProcessorDataManager.h
+++ b/include/gpu/GrProcessorDataManager.h
@@ -30,6 +30,11 @@
     }
 
 private:
+    uint32_t currentSaveMarker() const { return 0; }
+    void restoreToSaveMarker(/*uint32_t marker*/) {}
+
+    // For GrPipelineBuilder::AutoRestoreProcessorDataManager
+    friend class GrPipelineBuilder;
     static const uint32_t kNumProcessor = 1;
     static const uint32_t kDataIndicesPerProcessor = 1;
     static const uint32_t kPreAllocDataPerProcessor = 1;
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index fa9c30e..208581e 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -30,12 +30,14 @@
 namespace {
 // set up the draw state to enable the aa clipping mask. Besides setting up the
 // stage matrix this also alters the vertex layout
-void setup_drawstate_aaclip(GrPipelineBuilder* pipelineBuilder,
+void setup_drawstate_aaclip(const GrPipelineBuilder& pipelineBuilder,
                             GrTexture* result,
                             GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp,
+                            GrPipelineBuilder::AutoRestoreProcessorDataManager* arpdm,
                             const SkIRect &devBound) {
-    SkASSERT(pipelineBuilder && arfp);
-    arfp->set(pipelineBuilder);
+    SkASSERT(arfp && arpdm);
+    arfp->set(&pipelineBuilder);
+    arpdm->set(&pipelineBuilder);
 
     SkMatrix mat;
     // We use device coords to compute the texture coordinates. We set our matrix to be a
@@ -46,8 +48,8 @@
 
     SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height());
     // This could be a long-lived effect that is cached with the alpha-mask.
-    pipelineBuilder->addCoverageProcessor(
-        GrTextureDomainEffect::Create(pipelineBuilder->getProcessorDataManager(),
+    arfp->addCoverageProcessor(
+        GrTextureDomainEffect::Create(arpdm->getProcessorDataManager(),
                                       result,
                                       mat,
                                       GrTextureDomain::MakeTexelDomain(result, domainTexels),
@@ -58,7 +60,7 @@
 
 bool path_needs_SW_renderer(GrContext* context,
                             const GrDrawTarget* gpu,
-                            const GrPipelineBuilder* pipelineBuilder,
+                            const GrPipelineBuilder& pipelineBuilder,
                             const SkMatrix& viewMatrix,
                             const SkPath& origPath,
                             const GrStrokeInfo& stroke,
@@ -73,7 +75,7 @@
                                          GrPathRendererChain::kColorAntiAlias_DrawType :
                                          GrPathRendererChain::kColor_DrawType;
 
-    return NULL == context->getPathRenderer(gpu, pipelineBuilder, viewMatrix, *path, stroke,
+    return NULL == context->getPathRenderer(gpu, &pipelineBuilder, viewMatrix, *path, stroke,
                                             false, type);
 }
 }
@@ -92,7 +94,7 @@
  * 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(const GrPipelineBuilder& pipelineBuilder,
                                       const SkVector& clipToMaskOffset,
                                       const GrReducedClip::ElementList& elements) {
     // TODO: generalize this function so that when
@@ -121,7 +123,7 @@
     return false;
 }
 
-bool GrClipMaskManager::installClipEffects(GrPipelineBuilder* pipelineBuilder,
+bool GrClipMaskManager::installClipEffects(const GrPipelineBuilder& pipelineBuilder,
                                            GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp,
                                            const GrReducedClip::ElementList& elements,
                                            const SkVector& clipToRTOffset,
@@ -132,8 +134,8 @@
         boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY);
     }
 
-    arfp->set(pipelineBuilder);
-    GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
+    arfp->set(&pipelineBuilder);
+    GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
     GrReducedClip::ElementList::Iter iter(elements);
     bool failed = false;
     while (iter.get()) {
@@ -174,8 +176,8 @@
                 edgeType =
                         invert ? kInverseFillAA_GrProcessorEdgeType : kFillAA_GrProcessorEdgeType;
             } else {
-                edgeType =
-invert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProcessorEdgeType;
+                edgeType = invert ? kInverseFillBW_GrProcessorEdgeType :
+                                    kFillBW_GrProcessorEdgeType;
             }
             SkAutoTUnref<GrFragmentProcessor> fp;
             switch (iter.get()->getType()) {
@@ -199,7 +201,7 @@
                     break;
             }
             if (fp) {
-                pipelineBuilder->addCoverageProcessor(fp);
+                arfp->addCoverageProcessor(fp);
             } else {
                 failed = true;
                 break;
@@ -217,9 +219,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 // sort out what kind of clip mask needs to be created: alpha, stencil,
 // scissor, or entirely software
-bool GrClipMaskManager::setupClipping(GrPipelineBuilder* pipelineBuilder,
+bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder,
                                       GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp,
                                       GrPipelineBuilder::AutoRestoreStencil* ars,
+                                      GrPipelineBuilder::AutoRestoreProcessorDataManager* arpdm,
                                       GrScissorState* scissorState,
                                       const SkRect* devBounds) {
     fCurrClipMaskType = kNone_ClipMaskType;
@@ -232,13 +235,13 @@
     GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialState;
     SkIRect clipSpaceIBounds;
     bool requiresAA = false;
-    GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
+    GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
 
     // GrDrawTarget should have filtered this for us
     SkASSERT(rt);
 
     SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height());
-    const GrClip& clip = pipelineBuilder->clip();
+    const GrClip& clip = pipelineBuilder.clip();
     if (clip.isWideOpen(clipSpaceRTIBounds)) {
         this->setPipelineBuilderStencil(pipelineBuilder, ars);
         return true;
@@ -333,12 +336,12 @@
         }
 
         if (result) {
-            arfp->set(pipelineBuilder);
+            arfp->set(&pipelineBuilder);
             // The mask's top left coord should be pinned to the rounded-out top left corner of
             // clipSpace bounds. We determine the mask's position WRT to the render target here.
             SkIRect rtSpaceMaskBounds = clipSpaceIBounds;
             rtSpaceMaskBounds.offset(-clip.origin());
-            setup_drawstate_aaclip(pipelineBuilder, result, arfp, rtSpaceMaskBounds);
+            setup_drawstate_aaclip(pipelineBuilder, result, arfp, arpdm, rtSpaceMaskBounds);
             this->setPipelineBuilderStencil(pipelineBuilder, ars);
             return true;
         }
@@ -925,7 +928,7 @@
 }
 }
 
-void GrClipMaskManager::setPipelineBuilderStencil(GrPipelineBuilder* pipelineBuilder,
+void GrClipMaskManager::setPipelineBuilderStencil(const GrPipelineBuilder& pipelineBuilder,
                                                   GrPipelineBuilder::AutoRestoreStencil* ars) {
     // We make two copies of the StencilSettings here (except in the early
     // exit scenario. One copy from draw state to the stack var. Then another
@@ -938,18 +941,18 @@
 
     // The GrGpu client may not be using the stencil buffer but we may need to
     // enable it in order to respect a stencil clip.
-    if (pipelineBuilder->getStencil().isDisabled()) {
+    if (pipelineBuilder.getStencil().isDisabled()) {
         if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) {
             settings = basic_apply_stencil_clip_settings();
         } else {
             return;
         }
     } else {
-        settings = pipelineBuilder->getStencil();
+        settings = pipelineBuilder.getStencil();
     }
 
     int stencilBits = 0;
-    GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
+    GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
     GrStencilAttachment* stencilAttachment = rt->renderTargetPriv().attachStencilAttachment();
     if (stencilAttachment) {
         stencilBits = stencilAttachment->bits();
@@ -958,8 +961,8 @@
     SkASSERT(fClipTarget->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp());
     SkASSERT(fClipTarget->caps()->twoSidedStencilSupport() || !settings.isTwoSided());
     this->adjustStencilParams(&settings, fClipMode, stencilBits);
-    ars->set(pipelineBuilder);
-    pipelineBuilder->setStencil(settings);
+    ars->set(&pipelineBuilder);
+    ars->setStencil(settings);
 }
 
 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings,
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 842ff99..6dd735b 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -43,9 +43,10 @@
      * the manager when it must install additional effects to implement the
      * clip. devBounds is optional but can help optimize clipping.
      */
-    bool setupClipping(GrPipelineBuilder*,
+    bool setupClipping(const GrPipelineBuilder&,
                        GrPipelineBuilder::AutoRestoreFragmentProcessors*,
                        GrPipelineBuilder::AutoRestoreStencil*,
+                       GrPipelineBuilder::AutoRestoreProcessorDataManager*,
                        GrScissorState*,
                        const SkRect* devBounds);
 
@@ -86,7 +87,7 @@
 
     // Attempts to install a series of coverage effects to implement the clip. Return indicates
     // whether the element list was successfully converted to effects.
-    bool installClipEffects(GrPipelineBuilder*,
+    bool installClipEffects(const GrPipelineBuilder&,
                             GrPipelineBuilder::AutoRestoreFragmentProcessors*,
                             const GrReducedClip::ElementList&,
                             const SkVector& clipOffset,
@@ -125,7 +126,7 @@
                                 const SkIRect& clipSpaceIBounds,
                                 bool willUpload);
 
-    bool useSWOnlyPath(const GrPipelineBuilder*,
+    bool useSWOnlyPath(const GrPipelineBuilder&,
                        const SkVector& clipToMaskOffset,
                        const GrReducedClip::ElementList& elements);
 
@@ -161,7 +162,8 @@
      * Called prior to return control back the GrGpu in setupClipping. It updates the
      * GrPipelineBuilder with stencil settings that account for stencil-based clipping.
      */
-    void setPipelineBuilderStencil(GrPipelineBuilder*, GrPipelineBuilder::AutoRestoreStencil*);
+    void setPipelineBuilderStencil(const GrPipelineBuilder&,
+                                   GrPipelineBuilder::AutoRestoreStencil*);
 
     /**
      * Adjusts the stencil settings to account for interaction with stencil
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index ee668f0..4763ca7 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -135,7 +135,8 @@
     GrScissorState scissorState;
     GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
     GrPipelineBuilder::AutoRestoreStencil ars;
-    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, &batch->bounds())) {
+    GrPipelineBuilder::AutoRestoreProcessorDataManager arpdm;
+    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &arpdm, &scissorState, &batch->bounds())) {
         return;
     }
 
@@ -201,7 +202,8 @@
     GrScissorState scissorState;
     GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
     GrPipelineBuilder::AutoRestoreStencil ars;
-    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, NULL)) {
+    GrPipelineBuilder::AutoRestoreProcessorDataManager arpdm;
+    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &arpdm, &scissorState, NULL)) {
         return;
     }
 
@@ -230,7 +232,8 @@
     GrScissorState scissorState;
     GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
     GrPipelineBuilder::AutoRestoreStencil ars;
-    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, &devBounds)) {
+    GrPipelineBuilder::AutoRestoreProcessorDataManager arpdm;
+    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &arpdm, &scissorState, &devBounds)) {
        return;
     }
 
@@ -269,8 +272,8 @@
     GrScissorState scissorState;
     GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
     GrPipelineBuilder::AutoRestoreStencil ars;
-
-    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, NULL)) {
+    GrPipelineBuilder::AutoRestoreProcessorDataManager arpdm;
+    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &arpdm, &scissorState, NULL)) {
         return;
     }
 
@@ -504,13 +507,15 @@
 bool GrClipTarget::setupClip(GrPipelineBuilder* pipelineBuilder,
                              GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp,
                              GrPipelineBuilder::AutoRestoreStencil* ars,
+                             GrPipelineBuilder::AutoRestoreProcessorDataManager* arpdm,
                              GrScissorState* scissorState,
                              const SkRect* devBounds) {
-    return fClipMaskManager->setupClipping(pipelineBuilder,
-                                          arfp,
-                                          ars,
-                                          scissorState,
-                                          devBounds);
+    return fClipMaskManager->setupClipping(*pipelineBuilder,
+                                           arfp,
+                                           ars,
+                                           arpdm,
+                                           scissorState,
+                                           devBounds);
 }
 
 void GrClipTarget::purgeResources() {
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index cc9cda9..634a492 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -290,6 +290,7 @@
     virtual bool setupClip(GrPipelineBuilder*,
                            GrPipelineBuilder::AutoRestoreFragmentProcessors*,
                            GrPipelineBuilder::AutoRestoreStencil*,
+                           GrPipelineBuilder::AutoRestoreProcessorDataManager*,
                            GrScissorState*,
                            const SkRect* devBounds) = 0;
 
@@ -339,11 +340,12 @@
 private:
     GrClipMaskManager* clipMaskManager() override { return fClipMaskManager; }
 
-    virtual bool setupClip(GrPipelineBuilder*,
-                           GrPipelineBuilder::AutoRestoreFragmentProcessors*,
-                           GrPipelineBuilder::AutoRestoreStencil*,
-                           GrScissorState* scissorState,
-                           const SkRect* devBounds) override;
+    bool setupClip(GrPipelineBuilder*,
+                   GrPipelineBuilder::AutoRestoreFragmentProcessors*,
+                   GrPipelineBuilder::AutoRestoreStencil*,
+                   GrPipelineBuilder::AutoRestoreProcessorDataManager*,
+                   GrScissorState* scissorState,
+                   const SkRect* devBounds) override;
 
     typedef GrDrawTarget INHERITED;
 };
diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp
index 0b2d99a..97e7229 100644
--- a/src/gpu/GrPipelineBuilder.cpp
+++ b/src/gpu/GrPipelineBuilder.cpp
@@ -99,7 +99,8 @@
                                                     this->hasMixedSamples());
 }
 
-void GrPipelineBuilder::AutoRestoreFragmentProcessors::set(GrPipelineBuilder* pipelineBuilder) {
+void GrPipelineBuilder::AutoRestoreFragmentProcessors::set(
+                                                         const GrPipelineBuilder* pipelineBuilder) {
     if (fPipelineBuilder) {
         int m = fPipelineBuilder->numColorFragmentStages() - fColorEffectCnt;
         SkASSERT(m >= 0);
@@ -114,7 +115,7 @@
         }
         SkDEBUGCODE(--fPipelineBuilder->fBlockEffectRemovalCnt;)
     }
-    fPipelineBuilder = pipelineBuilder;
+    fPipelineBuilder = const_cast<GrPipelineBuilder*>(pipelineBuilder);
     if (NULL != pipelineBuilder) {
         fColorEffectCnt = pipelineBuilder->numColorFragmentStages();
         fCoverageEffectCnt = pipelineBuilder->numCoverageFragmentStages();
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index af98c36..60fcea8 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -110,6 +110,8 @@
     /**
      * 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 AutoRestoreFragmentProcessors : public ::SkNoncopyable {
     public:
@@ -127,14 +129,20 @@
 
         ~AutoRestoreFragmentProcessors() { this->set(NULL); }
 
-        void set(GrPipelineBuilder* ds);
+        void set(const GrPipelineBuilder* ds);
 
         bool isSet() const { return SkToBool(fPipelineBuilder); }
 
+        const GrFragmentProcessor* addCoverageProcessor(const GrFragmentProcessor* processor) {
+            SkASSERT(this->isSet());
+            return fPipelineBuilder->addCoverageProcessor(processor);
+        }
+
     private:
+        // notionally const (as marginalia)
         GrPipelineBuilder*    fPipelineBuilder;
-        int             fColorEffectCnt;
-        int             fCoverageEffectCnt;
+        int                   fColorEffectCnt;
+        int                   fCoverageEffectCnt;
     };
 
     /// @}
@@ -246,20 +254,22 @@
      * AutoRestoreStencil
      *
      * This simple struct saves and restores the stencil settings
+     * This class can transiently modify its "const" GrPipelineBuilder object but will restore it
+     * when done - so it is notionally "const" correct.
      */
     class AutoRestoreStencil : public ::SkNoncopyable {
     public:
         AutoRestoreStencil() : fPipelineBuilder(NULL) {}
 
-        AutoRestoreStencil(GrPipelineBuilder* ds) : fPipelineBuilder(NULL) { this->set(ds); }
+        AutoRestoreStencil(const GrPipelineBuilder* ds) : fPipelineBuilder(NULL) { this->set(ds); }
 
         ~AutoRestoreStencil() { this->set(NULL); }
 
-        void set(GrPipelineBuilder* ds) {
+        void set(const GrPipelineBuilder* ds) {
             if (fPipelineBuilder) {
                 fPipelineBuilder->setStencil(fStencilSettings);
             }
-            fPipelineBuilder = ds;
+            fPipelineBuilder = const_cast<GrPipelineBuilder*>(ds);
             if (ds) {
                 fStencilSettings = ds->getStencil();
             }
@@ -267,7 +277,13 @@
 
         bool isSet() const { return SkToBool(fPipelineBuilder); }
 
+        void setStencil(const GrStencilSettings& settings) {
+            SkASSERT(this->isSet());
+            fPipelineBuilder->setStencil(settings);
+        }
+
     private:
+        // notionally const (as marginalia)
         GrPipelineBuilder*  fPipelineBuilder;
         GrStencilSettings   fStencilSettings;
     };
@@ -399,6 +415,48 @@
     GrProcessorDataManager* getProcessorDataManager() { return fProcDataManager.get(); }
     const GrProcessorDataManager* processorDataManager() const { return fProcDataManager.get(); }
 
+    /**
+     * When this object is destroyed it will remove any additions to the GrProcessorDataManager
+     * owned by the GrPipelineBuilder
+     * This class can transiently modify its "const" GrPipelineBuilder object but will restore it
+     * when done - so it is notionally "const" correct.
+     */
+    class AutoRestoreProcessorDataManager : public ::SkNoncopyable {
+    public:
+        AutoRestoreProcessorDataManager() : fPipelineBuilder(NULL), fSaveMarker(0) {}
+
+        AutoRestoreProcessorDataManager(GrPipelineBuilder* ds)
+            : fPipelineBuilder(NULL)
+            , fSaveMarker(0) {
+            this->set(ds);
+        }
+
+        ~AutoRestoreProcessorDataManager() { this->set(NULL); }
+
+        void set(const GrPipelineBuilder* ds) {
+            if (fPipelineBuilder) {
+                fPipelineBuilder->getProcessorDataManager()->restoreToSaveMarker(/*fSaveMarker*/);
+            }
+            fPipelineBuilder = const_cast<GrPipelineBuilder*>(ds);
+            if (ds) {
+                fSaveMarker = ds->processorDataManager()->currentSaveMarker();
+            }
+        }
+
+        bool isSet() const { return SkToBool(fPipelineBuilder); }
+
+        GrProcessorDataManager* getProcessorDataManager() {
+            SkASSERT(this->isSet());
+            return fPipelineBuilder->getProcessorDataManager();
+        }
+
+    private:
+        // notionally const (as marginalia)
+        GrPipelineBuilder* fPipelineBuilder;
+        uint32_t fSaveMarker;
+    };
+
+
 private:
     // Calculating invariant color / coverage information is expensive, so we partially cache the
     // results.
@@ -435,7 +493,7 @@
 
     // 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(int fBlockEffectRemovalCnt;)
+    SkDEBUGCODE(mutable int fBlockEffectRemovalCnt;)
 
     typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;