Add class GrProcessorSet which represents color and coverage FPs and a XPFactory.

Eventually ops can use this to hold their ops and create GrPipelines at flush time.

For now it is used by GrPipelineBuilder.

Change-Id: I0db3892032f2d07238e4c847a790678b3aab456f
Reviewed-on: https://skia-review.googlesource.com/7132
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 61dea745..8629ecd 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -144,6 +144,8 @@
   "$_src/gpu/GrPipelineBuilder.h",
   "$_src/gpu/GrPrimitiveProcessor.cpp",
   "$_src/gpu/GrPrimitiveProcessor.h",
+  "$_src/gpu/GrProcessorSet.cpp",
+  "$_src/gpu/GrProcessorSet.h",
   "$_src/gpu/GrProgramDesc.cpp",
   "$_src/gpu/GrProgramDesc.h",
   "$_src/gpu/GrProcessor.cpp",
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h
index 6897679..3b136ac 100644
--- a/include/gpu/GrPaint.h
+++ b/include/gpu/GrPaint.h
@@ -169,7 +169,7 @@
 private:
     GrPaint& operator=(const GrPaint&) = delete;
 
-    friend class GrPipelineBuilder;
+    friend class GrProcessorSet;
 
     bool internalIsConstantBlendedColor(GrColor paintColor, GrColor* constantColor) const;
 
diff --git a/include/gpu/GrProgramElement.h b/include/gpu/GrProgramElement.h
index 71905ac..0e065c2 100644
--- a/include/gpu/GrProgramElement.h
+++ b/include/gpu/GrProgramElement.h
@@ -117,6 +117,7 @@
 
     // Only this class can access addPendingExecution() and completedExecution().
     template <typename T> friend class GrPendingProgramElement;
+    friend class GrProcessorSet;
 
     typedef SkNoncopyable INHERITED;
 };
diff --git a/include/private/SkTemplates.h b/include/private/SkTemplates.h
index f50af8b..c45de75 100644
--- a/include/private/SkTemplates.h
+++ b/include/private/SkTemplates.h
@@ -204,6 +204,14 @@
      */
     T* get() const { return fArray; }
 
+    T* begin() { return fArray; }
+
+    const T* begin() const { return fArray; }
+
+    T* end() { return fArray + fCount; }
+
+    const T* end() const { return fArray + fCount; }
+
     /** Return the nth element in the array
      */
     T&  operator[](int index) const {
diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp
index fce8aa9..ce38718 100644
--- a/src/gpu/GrPipelineBuilder.cpp
+++ b/src/gpu/GrPipelineBuilder.cpp
@@ -18,18 +18,10 @@
 GrPipelineBuilder::GrPipelineBuilder(GrPaint&& paint, GrAAType aaType)
         : fFlags(0x0)
         , fUserStencilSettings(&GrUserStencilSettings::kUnused)
-        , fDrawFace(GrDrawFace::kBoth) {
-    for (int i = 0; i < paint.numColorFragmentProcessors(); ++i) {
-        fColorFragmentProcessors.emplace_back(paint.fColorFragmentProcessors[i].release());
-    }
-
-    for (int i = 0; i < paint.numCoverageFragmentProcessors(); ++i) {
-        fCoverageFragmentProcessors.emplace_back(paint.fCoverageFragmentProcessors[i].release());
-    }
-
-    fXPFactory = paint.getXPFactory();
-
+        , fDrawFace(GrDrawFace::kBoth)
+        , fProcessors(std::move(paint)) {
     this->setState(GrPipelineBuilder::kHWAntialias_Flag, GrAATypeIsHW(aaType));
+    // The processors have been moved out of paint, but its flags should still be unmodified.
     this->setState(GrPipelineBuilder::kDisableOutputConversionToSRGB_Flag,
                    paint.getDisableOutputConversionToSRGB());
     this->setState(GrPipelineBuilder::kAllowSRGBInputs_Flag,
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index fcc692a..e0c4d3d 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -8,26 +8,19 @@
 #ifndef GrPipelineBuilder_DEFINED
 #define GrPipelineBuilder_DEFINED
 
-#include "GrBlend.h"
-#include "GrCaps.h"
 #include "GrGpuResourceRef.h"
-#include "GrProcOptInfo.h"
+#include "GrProcessorSet.h"
 #include "GrRenderTarget.h"
 #include "GrUserStencilSettings.h"
 #include "GrXferProcessor.h"
-#include "SkMatrix.h"
-#include "SkRefCnt.h"
-#include "effects/GrCoverageSetOpXP.h"
-#include "effects/GrDisableColorXP.h"
-#include "effects/GrPorterDuffXferProcessor.h"
-#include "effects/GrSimpleTextureEffect.h"
 
-class GrDrawOp;
 class GrCaps;
+class GrDrawOp;
 class GrPaint;
+struct GrPipelineAnalysis;
 class GrTexture;
 
-class GrPipelineBuilder : public SkNoncopyable {
+class GrPipelineBuilder : private SkNoncopyable {
 public:
     /**
      * Initializes the GrPipelineBuilder based on a GrPaint and MSAA availability. Note
@@ -47,16 +40,21 @@
     /// feed their output to the GrXferProcessor which controls blending.
     ////
 
-    int numColorFragmentProcessors() const { return fColorFragmentProcessors.count(); }
-    int numCoverageFragmentProcessors() const { return fCoverageFragmentProcessors.count(); }
-    int numFragmentProcessors() const { return this->numColorFragmentProcessors() +
-                                               this->numCoverageFragmentProcessors(); }
+    int numColorFragmentProcessors() const { return fProcessors.numColorFragmentProcessors(); }
+    int numCoverageFragmentProcessors() const {
+        return fProcessors.numCoverageFragmentProcessors();
+    }
+    int numFragmentProcessors() const { return fProcessors.numFragmentProcessors(); }
 
     const GrFragmentProcessor* getColorFragmentProcessor(int idx) const {
-        return fColorFragmentProcessors[idx].get();
+        return fProcessors.colorFragmentProcessor(idx);
     }
     const GrFragmentProcessor* getCoverageFragmentProcessor(int idx) const {
-        return fCoverageFragmentProcessors[idx].get();
+        return fProcessors.coverageFragmentProcessor(idx);
+    }
+
+    void analyzeFragmentProcessors(GrPipelineAnalysis* analysis) const {
+        fProcessors.analyzeFragmentProcessors(analysis);
     }
 
     /// @}
@@ -65,7 +63,7 @@
     /// @name Blending
     ////
 
-    const GrXPFactory* getXPFactory() const { return fXPFactory; }
+    const GrXPFactory* getXPFactory() const { return fProcessors.xpFactory(); }
 
     /**
      * Checks whether the xp will need destination in a texture to correctly blend.
@@ -201,20 +199,10 @@
     bool usePLSDstRead(const GrDrawOp*) const;
 
 private:
-    typedef SkSTArray<4, sk_sp<GrFragmentProcessor>> FragmentProcessorArray;
-
-    uint32_t                                fFlags;
-    const GrUserStencilSettings*            fUserStencilSettings;
-    GrDrawFace                              fDrawFace;
-    const GrXPFactory*                      fXPFactory;
-    FragmentProcessorArray                  fColorFragmentProcessors;
-    FragmentProcessorArray                  fCoverageFragmentProcessors;
-
-    friend class GrPipeline;
-    // This gives the GrRenderTargetOpList raw access to fColorFragmentProcessors &
-    // fCoverageFragmentProcessors
-    // TODO: that access seems a little dodgy
-    friend class GrRenderTargetOpList;
+    uint32_t fFlags;
+    const GrUserStencilSettings* fUserStencilSettings;
+    GrDrawFace fDrawFace;
+    GrProcessorSet fProcessors;
 };
 
 #endif
diff --git a/src/gpu/GrProcessorSet.cpp b/src/gpu/GrProcessorSet.cpp
new file mode 100644
index 0000000..0d72d9b
--- /dev/null
+++ b/src/gpu/GrProcessorSet.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrProcessorSet.h"
+
+GrProcessorSet::GrProcessorSet(GrPaint&& paint) {
+    fXPFactory = paint.fXPFactory;
+    fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
+    fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
+    int i = 0;
+    for (auto& fp : paint.fColorFragmentProcessors) {
+        fFragmentProcessors[i++] = fp.release();
+    }
+    for (auto& fp : paint.fCoverageFragmentProcessors) {
+        fFragmentProcessors[i++] = fp.release();
+    }
+}
diff --git a/src/gpu/GrProcessorSet.h b/src/gpu/GrProcessorSet.h
new file mode 100644
index 0000000..684fb26
--- /dev/null
+++ b/src/gpu/GrProcessorSet.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrProcessorSet_DEFINED
+#define GrProcessorSet_DEFINED
+
+#include "GrFragmentProcessor.h"
+#include "GrPaint.h"
+#include "GrPipeline.h"
+#include "SkTemplates.h"
+
+class GrXPFactory;
+
+class GrProcessorSet : private SkNoncopyable {
+public:
+    GrProcessorSet(GrPaint&& paint);
+
+    ~GrProcessorSet() {
+        // We are deliberately not using sk_sp here because this will be updated to work with
+        // "pending execution" refs.
+        for (auto fp : fFragmentProcessors) {
+            fp->unref();
+        }
+    }
+
+    int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
+    int numCoverageFragmentProcessors() const {
+        return fFragmentProcessors.count() - fColorFragmentProcessorCnt;
+    }
+    int numFragmentProcessors() const { return fFragmentProcessors.count(); }
+
+    const GrFragmentProcessor* colorFragmentProcessor(int idx) const {
+        SkASSERT(idx < fColorFragmentProcessorCnt);
+        return fFragmentProcessors[idx];
+    }
+    const GrFragmentProcessor* coverageFragmentProcessor(int idx) const {
+        return fFragmentProcessors[idx + fColorFragmentProcessorCnt];
+    }
+
+    const GrXPFactory* xpFactory() const { return fXPFactory; }
+
+    void analyzeFragmentProcessors(GrPipelineAnalysis* analysis) const {
+        const GrFragmentProcessor* const* fps = fFragmentProcessors.get();
+        analysis->fColorPOI.addProcessors(fps, fColorFragmentProcessorCnt);
+        fps += fColorFragmentProcessorCnt;
+        analysis->fCoveragePOI.addProcessors(fps, this->numCoverageFragmentProcessors());
+    }
+
+private:
+    const GrXPFactory* fXPFactory = nullptr;
+    SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
+    int fColorFragmentProcessorCnt;
+};
+
+#endif
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index e4bb34e..0a34019 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -264,8 +264,7 @@
 void GrRenderTargetOpList::addDrawOp(const GrPipelineBuilder& pipelineBuilder,
                                      GrRenderTargetContext* renderTargetContext,
                                      const GrClip& clip,
-                                     std::unique_ptr<GrDrawOp>
-                                             op) {
+                                     std::unique_ptr<GrDrawOp> op) {
     // Setup clip
     SkRect bounds;
     op_bounds(&bounds, op.get());
@@ -312,12 +311,7 @@
             return;
         }
     }
-    args.fAnalysis.fColorPOI.addProcessors(
-            sk_sp_address_as_pointer_address(pipelineBuilder.fColorFragmentProcessors.begin()),
-            pipelineBuilder.numColorFragmentProcessors());
-    args.fAnalysis.fCoveragePOI.addProcessors(
-            sk_sp_address_as_pointer_address(pipelineBuilder.fCoverageFragmentProcessors.begin()),
-            pipelineBuilder.numCoverageFragmentProcessors());
+    pipelineBuilder.analyzeFragmentProcessors(&args.fAnalysis);
     if (const GrFragmentProcessor* clipFP = appliedClip.clipCoverageFragmentProcessor()) {
         args.fAnalysis.fCoveragePOI.addProcessors(&clipFP, 1);
     }