This change will ultimately pull uniform color, and to a much lesser degree uniform coverage, into GPs.  There are still some loose ends because drawstate has the ability to override the GP, but fixing these cleanly will have to wait until we have deferred geometry in place and can make attribute / uniform decisions on the fly.

BUG=skia:

Review URL: https://codereview.chromium.org/746423007
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index e1a29f5..659857a 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -80,16 +80,23 @@
     class GLProcessor : public GrGLGeometryProcessor {
     public:
         GLProcessor(const GrGeometryProcessor&,
-                    const GrBatchTracker&) {}
+                    const GrBatchTracker&)
+            : fColor(GrColor_ILLEGAL) {}
 
         virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
             const CircleEdgeEffect& ce = args.fGP.cast<CircleEdgeEffect>();
+            GrGLGPBuilder* pb = args.fPB;
+            const BatchTracker& local = args.fBT.cast<BatchTracker>();
             GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
 
             GrGLVertToFrag v(kVec4f_GrSLType);
             args.fPB->addVarying("CircleEdge", &v);
             vsBuilder->codeAppendf("%s = %s;", v.vsOut(), ce.inCircleEdge()->fName);
 
+            // Setup pass through color
+            this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
+                                        &fColorUniform);
+
             // setup coord outputs
             vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ce.inPosition()->fName);
             vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ce.inPosition()->fName);
@@ -111,18 +118,29 @@
         }
 
         static void GenKey(const GrGeometryProcessor& processor,
-                           const GrBatchTracker&,
+                           const GrBatchTracker& bt,
                            const GrGLCaps&,
                            GrProcessorKeyBuilder* b) {
+            const BatchTracker& local = bt.cast<BatchTracker>();
             const CircleEdgeEffect& circleEffect = processor.cast<CircleEdgeEffect>();
-            b->add32(circleEffect.isStroked());
+            b->add32(circleEffect.isStroked() << 16 | local.fInputColorType);
         }
 
-        virtual void setData(const GrGLProgramDataManager&,
-                             const GrGeometryProcessor&,
-                             const GrBatchTracker&) SK_OVERRIDE {}
+        virtual void setData(const GrGLProgramDataManager& pdman,
+                             const GrPrimitiveProcessor& gp,
+                             const GrBatchTracker& bt) SK_OVERRIDE {
+            const BatchTracker& local = bt.cast<BatchTracker>();
+            if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+                GrGLfloat c[4];
+                GrColorToRGBAFloat(local.fColor, c);
+                pdman.set4fv(fColorUniform, 1, c);
+                fColor = local.fColor;
+            }
+        }
 
     private:
+        GrColor fColor;
+        UniformHandle fColorUniform;
         typedef GrGLGeometryProcessor INHERITED;
     };
 
@@ -136,6 +154,19 @@
         return SkNEW_ARGS(GLProcessor, (*this, bt));
     }
 
+    void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
+        BatchTracker* local = bt->cast<BatchTracker>();
+        local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+
+    }
+
+    bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+        const BatchTracker& mine = m.cast<BatchTracker>();
+        const BatchTracker& theirs = t.cast<BatchTracker>();
+        return CanCombineOutput(mine.fInputColorType, mine.fColor,
+                                theirs.fInputColorType, theirs.fColor);
+    }
+
 private:
     CircleEdgeEffect(GrColor color, bool stroke) : INHERITED(color) {
         this->initClassID<CircleEdgeEffect>();
@@ -154,6 +185,11 @@
         out->setUnknownSingleComponent();
     }
 
+    struct BatchTracker {
+        GrGPInput fInputColorType;
+        GrColor fColor;
+    };
+
     const GrAttribute* fInPosition;
     const GrAttribute* fInCircleEdge;
     bool fStroke;
@@ -201,11 +237,13 @@
     class GLProcessor : public GrGLGeometryProcessor {
     public:
         GLProcessor(const GrGeometryProcessor&,
-                    const GrBatchTracker&) {}
+                    const GrBatchTracker&)
+            : fColor(GrColor_ILLEGAL) {}
 
         virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
             const EllipseEdgeEffect& ee = args.fGP.cast<EllipseEdgeEffect>();
-
+            GrGLGPBuilder* pb = args.fPB;
+            const BatchTracker& local = args.fBT.cast<BatchTracker>();
             GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
 
             GrGLVertToFrag ellipseOffsets(kVec2f_GrSLType);
@@ -218,6 +256,10 @@
             vsBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(),
                                    ee.inEllipseRadii()->fName);
 
+            // Setup pass through color
+            this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
+                                        &fColorUniform);
+
             // setup coord outputs
             vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ee.inPosition()->fName);
             vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ee.inPosition()->fName);
@@ -254,19 +296,30 @@
         }
 
         static void GenKey(const GrGeometryProcessor& processor,
-                           const GrBatchTracker&,
+                           const GrBatchTracker& bt,
                            const GrGLCaps&,
                            GrProcessorKeyBuilder* b) {
+            const BatchTracker& local = bt.cast<BatchTracker>();
             const EllipseEdgeEffect& ellipseEffect = processor.cast<EllipseEdgeEffect>();
-            b->add32(ellipseEffect.isStroked());
+            b->add32(ellipseEffect.isStroked() << 16 | local.fInputColorType);
         }
 
-        virtual void setData(const GrGLProgramDataManager&,
-                             const GrGeometryProcessor&,
-                             const GrBatchTracker&) SK_OVERRIDE {
+        virtual void setData(const GrGLProgramDataManager& pdman,
+                             const GrPrimitiveProcessor& gp,
+                             const GrBatchTracker& bt) SK_OVERRIDE {
+            const BatchTracker& local = bt.cast<BatchTracker>();
+            if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+                GrGLfloat c[4];
+                GrColorToRGBAFloat(local.fColor, c);
+                pdman.set4fv(fColorUniform, 1, c);
+                fColor = local.fColor;
+            }
         }
 
     private:
+        GrColor fColor;
+        UniformHandle fColorUniform;
+
         typedef GrGLGeometryProcessor INHERITED;
     };
 
@@ -280,6 +333,18 @@
         return SkNEW_ARGS(GLProcessor, (*this, bt));
     }
 
+    void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
+        BatchTracker* local = bt->cast<BatchTracker>();
+        local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+    }
+
+    bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+        const BatchTracker& mine = m.cast<BatchTracker>();
+        const BatchTracker& theirs = t.cast<BatchTracker>();
+        return CanCombineOutput(mine.fInputColorType, mine.fColor,
+                                theirs.fInputColorType, theirs.fColor);
+    }
+
 private:
     EllipseEdgeEffect(GrColor color, bool stroke) : INHERITED(color) {
         this->initClassID<EllipseEdgeEffect>();
@@ -300,6 +365,11 @@
         out->setUnknownSingleComponent();
     }
 
+    struct BatchTracker {
+        GrGPInput fInputColorType;
+        GrColor fColor;
+    };
+
     const GrAttribute* fInPosition;
     const GrAttribute* fInEllipseOffset;
     const GrAttribute* fInEllipseRadii;
@@ -351,11 +421,13 @@
     class GLProcessor : public GrGLGeometryProcessor {
     public:
         GLProcessor(const GrGeometryProcessor&,
-                    const GrBatchTracker&) {}
+                    const GrBatchTracker&)
+            : fColor(GrColor_ILLEGAL) {}
 
         virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
             const DIEllipseEdgeEffect& ee = args.fGP.cast<DIEllipseEdgeEffect>();
-
+            GrGLGPBuilder* pb = args.fPB;
+            const BatchTracker& local = args.fBT.cast<BatchTracker>();
             GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
 
             GrGLVertToFrag offsets0(kVec2f_GrSLType);
@@ -368,6 +440,10 @@
             vsBuilder->codeAppendf("%s = %s;", offsets1.vsOut(),
                                    ee.inEllipseOffsets1()->fName);
 
+            // Setup pass through color
+            this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
+                                        &fColorUniform);
+
             // setup coord outputs
             vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ee.inPosition()->fName);
             vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ee.inPosition()->fName);
@@ -418,20 +494,30 @@
         }
 
         static void GenKey(const GrGeometryProcessor& processor,
-                           const GrBatchTracker&,
+                           const GrBatchTracker& bt,
                            const GrGLCaps&,
                            GrProcessorKeyBuilder* b) {
+            const BatchTracker& local = bt.cast<BatchTracker>();
             const DIEllipseEdgeEffect& ellipseEffect = processor.cast<DIEllipseEdgeEffect>();
-
-            b->add32(ellipseEffect.getMode());
+            b->add32(ellipseEffect.getMode() << 16 | local.fInputColorType);
         }
 
-        virtual void setData(const GrGLProgramDataManager&,
-                             const GrGeometryProcessor&,
-                             const GrBatchTracker&) SK_OVERRIDE {
+        virtual void setData(const GrGLProgramDataManager& pdman,
+                             const GrPrimitiveProcessor& gp,
+                             const GrBatchTracker& bt) SK_OVERRIDE {
+            const BatchTracker& local = bt.cast<BatchTracker>();
+            if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+                GrGLfloat c[4];
+                GrColorToRGBAFloat(local.fColor, c);
+                pdman.set4fv(fColorUniform, 1, c);
+                fColor = local.fColor;
+            }
         }
 
     private:
+        GrColor fColor;
+        UniformHandle fColorUniform;
+
         typedef GrGLGeometryProcessor INHERITED;
     };
 
@@ -445,6 +531,18 @@
         return SkNEW_ARGS(GLProcessor, (*this, bt));
     }
 
+    void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
+        BatchTracker* local = bt->cast<BatchTracker>();
+        local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+    }
+
+    bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+        const BatchTracker& mine = m.cast<BatchTracker>();
+        const BatchTracker& theirs = t.cast<BatchTracker>();
+        return CanCombineOutput(mine.fInputColorType, mine.fColor,
+                                theirs.fInputColorType, theirs.fColor);
+    }
+
 private:
     DIEllipseEdgeEffect(GrColor color, Mode mode) : INHERITED(color) {
         this->initClassID<DIEllipseEdgeEffect>();
@@ -465,6 +563,11 @@
         out->setUnknownSingleComponent();
     }
 
+    struct BatchTracker {
+        GrGPInput fInputColorType;
+        GrColor fColor;
+    };
+
     const GrAttribute* fInPosition;
     const GrAttribute* fInEllipseOffsets0;
     const GrAttribute* fInEllipseOffsets1;