Make GrPaint have a variable sized array of color and coverage stages rather than a fixed size.

R=robertphillips@google.com, jvanverth@google.com

Author: bsalomon@google.com

Review URL: https://chromiumcodereview.appspot.com/18686007

git-svn-id: http://skia.googlecode.com/svn/trunk@10062 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h
index 25ec699..9e326f0 100644
--- a/include/gpu/GrPaint.h
+++ b/include/gpu/GrPaint.h
@@ -43,11 +43,6 @@
  */
 class GrPaint {
 public:
-    enum {
-        kMaxColorStages     = 3,
-        kMaxCoverageStages  = 1,
-    };
-
     GrPaint() { this->reset(); }
 
     GrPaint(const GrPaint& paint) { *this = paint; }
@@ -111,63 +106,43 @@
     }
 
     /**
-     * Specifies a stage of the color pipeline. Usually the texture matrices of color stages apply
-     * to the primitive's positions. Some GrContext calls take explicit coords as an array or a
-     * rect. In this case these are the pre-matrix coords to colorStage(0).
+     * Appends an additional color effect to the color computation.
      */
-    GrEffectStage* colorStage(int i) {
-        GrAssert((unsigned)i < kMaxColorStages);
-        return fColorStages + i;
-    }
-
-    const GrEffectStage& getColorStage(int i) const {
-        GrAssert((unsigned)i < kMaxColorStages);
-        return fColorStages[i];
-    }
-
-    bool isColorStageEnabled(int i) const {
-        GrAssert((unsigned)i < kMaxColorStages);
-        return (NULL != fColorStages[i].getEffect());
+    const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
+        GrAssert(NULL != effect);
+        SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1));
+        return effect;
     }
 
     /**
-     * Specifies a stage of the coverage pipeline. Coverage stages' texture matrices are always
-     * applied to the primitive's position, never to explicit texture coords.
+     * Appends an additional coverage effect to the coverage computation.
      */
-    GrEffectStage* coverageStage(int i) {
-        GrAssert((unsigned)i < kMaxCoverageStages);
-        return fCoverageStages + i;
+    const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
+        GrAssert(NULL != effect);
+        SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1));
+        return effect;
     }
 
-    const GrEffectStage& getCoverageStage(int i) const {
-        GrAssert((unsigned)i < kMaxCoverageStages);
-        return fCoverageStages[i];
-    }
+    /**
+     * Helpers for adding color or coverage effects that sample a texture. The matrix is applied
+     * to the src space position to compute texture coordinates.
+     */
+    void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix);
+    void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix);
 
-    bool isCoverageStageEnabled(int i) const {
-        GrAssert((unsigned)i < kMaxCoverageStages);
-        return (NULL != fCoverageStages[i].getEffect());
-    }
+    void addColorTextureEffect(GrTexture* texture,
+                               const SkMatrix& matrix,
+                               const GrTextureParams& params);
+    void addCoverageTextureEffect(GrTexture* texture,
+                                  const SkMatrix& matrix,
+                                  const GrTextureParams& params);
 
-    bool hasCoverageStage() const {
-        for (int i = 0; i < kMaxCoverageStages; ++i) {
-            if (this->isCoverageStageEnabled(i)) {
-                return true;
-            }
-        }
-        return false;
-    }
+    int numColorStages() const { return fColorStages.count(); }
+    int numCoverageStages() const { return fCoverageStages.count(); }
+    int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
 
-    bool hasColorStage() const {
-        for (int i = 0; i < kMaxColorStages; ++i) {
-            if (this->isColorStageEnabled(i)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    bool hasStage() const { return this->hasColorStage() || this->hasCoverageStage(); }
+    const GrEffectStage& getColorStage(int s) const { return fColorStages[s]; }
+    const GrEffectStage& getCoverageStage(int s) const { return fCoverageStages[s]; }
 
     GrPaint& operator=(const GrPaint& paint) {
         fSrcBlendCoeff = paint.fSrcBlendCoeff;
@@ -181,16 +156,9 @@
         fColorFilterColor = paint.fColorFilterColor;
         fColorFilterXfermode = paint.fColorFilterXfermode;
 
-        for (int i = 0; i < kMaxColorStages; ++i) {
-            if (paint.isColorStageEnabled(i)) {
-                fColorStages[i] = paint.fColorStages[i];
-            }
-        }
-        for (int i = 0; i < kMaxCoverageStages; ++i) {
-            if (paint.isCoverageStageEnabled(i)) {
-                fCoverageStages[i] = paint.fCoverageStages[i];
-            }
-        }
+        fColorStages = paint.fColorStages;
+        fCoverageStages = paint.fCoverageStages;
+
         return *this;
     }
 
@@ -206,15 +174,6 @@
         this->resetColorFilter();
     }
 
-    // internal use
-    // GrPaint's textures and masks map to the first N stages
-    // of GrDrawTarget in that order (textures followed by masks)
-    enum {
-        kFirstColorStage = 0,
-        kFirstCoverageStage = kMaxColorStages,
-        kTotalStages = kFirstColorStage + kMaxColorStages + kMaxCoverageStages,
-    };
-
 private:
     /**
      * Called when the source coord system from which geometry is rendered changes. It ensures that
@@ -222,48 +181,40 @@
      * from the previous coord system to the new coord system.
      */
     void localCoordChange(const SkMatrix& oldToNew) {
-        for (int i = 0; i < kMaxColorStages; ++i) {
-            if (this->isColorStageEnabled(i)) {
-                fColorStages[i].localCoordChange(oldToNew);
-            }
+        for (int i = 0; i < fColorStages.count(); ++i) {
+            fColorStages[i].localCoordChange(oldToNew);
         }
-        for (int i = 0; i < kMaxCoverageStages; ++i) {
-            if (this->isCoverageStageEnabled(i)) {
-                fCoverageStages[i].localCoordChange(oldToNew);
-            }
+        for (int i = 0; i < fCoverageStages.count(); ++i) {
+            fCoverageStages[i].localCoordChange(oldToNew);
         }
     }
 
     bool localCoordChangeInverse(const SkMatrix& newToOld) {
         SkMatrix oldToNew;
         bool computed = false;
-        for (int i = 0; i < kMaxColorStages; ++i) {
-            if (this->isColorStageEnabled(i)) {
-                if (!computed && !newToOld.invert(&oldToNew)) {
-                    return false;
-                } else {
-                    computed = true;
-                }
-                fColorStages[i].localCoordChange(oldToNew);
+        for (int i = 0; i < fColorStages.count(); ++i) {
+            if (!computed && !newToOld.invert(&oldToNew)) {
+                return false;
+            } else {
+                computed = true;
             }
+            fColorStages[i].localCoordChange(oldToNew);
         }
-        for (int i = 0; i < kMaxCoverageStages; ++i) {
-            if (this->isCoverageStageEnabled(i)) {
-                if (!computed && !newToOld.invert(&oldToNew)) {
-                    return false;
-                } else {
-                    computed = true;
-                }
-                fCoverageStages[i].localCoordChange(oldToNew);
+        for (int i = 0; i < fCoverageStages.count(); ++i) {
+            if (!computed && !newToOld.invert(&oldToNew)) {
+                return false;
+            } else {
+                computed = true;
             }
+            fCoverageStages[i].localCoordChange(oldToNew);
         }
         return true;
     }
 
     friend class GrContext; // To access above two functions
 
-    GrEffectStage               fColorStages[kMaxColorStages];
-    GrEffectStage               fCoverageStages[kMaxCoverageStages];
+    SkSTArray<4, GrEffectStage> fColorStages;
+    SkSTArray<2, GrEffectStage> fCoverageStages;
 
     GrBlendCoeff                fSrcBlendCoeff;
     GrBlendCoeff                fDstBlendCoeff;
@@ -295,12 +246,8 @@
     }
 
     void resetStages() {
-        for (int i = 0; i < kMaxColorStages; ++i) {
-            fColorStages[i].reset();
-        }
-        for (int i = 0; i < kMaxCoverageStages; ++i) {
-            fCoverageStages[i].reset();
-        }
+        fColorStages.reset();
+        fCoverageStages.reset();
     }
 };
 
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 0dd363f..b0b1559 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -152,7 +152,6 @@
                                                Usage usage) SK_OVERRIDE;
 
     SkDrawProcs* initDrawForText(GrTextContext*);
-    bool bindDeviceAsTexture(GrPaint* paint);
 
     // sets the render target, clip, and matrix on GrContext. Use forceIdenity to override
     // SkDraw's matrix and draw in device coords.
@@ -178,12 +177,12 @@
                             const SkRect&,
                             const SkMatrix&,
                             const GrTextureParams& params,
-                            GrPaint* grPaint);
+                            const SkPaint& paint);
     void drawTiledBitmap(const SkBitmap& bitmap,
                          const SkRect& srcRect,
                          const SkMatrix& m,
                          const GrTextureParams& params,
-                         GrPaint* grPaint);
+                         const SkPaint& paint);
 
     /**
      * Returns non-initialized instance.