Added registerChild; transforms, textures, glKey automatically handled.

BUG=skia:

Review URL: https://codereview.chromium.org/1266633003
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index e3cfa78..b990f9b 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -135,6 +135,10 @@
     SkDEBUGCODE(transform->setInProcessor();)
 }
 
+void GrFragmentProcessor::registerChildProcessor(GrFragmentProcessor* child) {
+    fChildProcessors.push_back(child);
+}
+
 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
     if (fCoordTransforms.count() != that.fCoordTransforms.count()) {
         return false;
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index cb82ea5..d5cf039 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -152,7 +152,7 @@
 GrBicubicEffect::~GrBicubicEffect() {
 }
 
-void GrBicubicEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void GrBicubicEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                         GrProcessorKeyBuilder* b) const {
     GrGLBicubicEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrBicubicEffect.h b/src/gpu/effects/GrBicubicEffect.h
index 86118f7..810e443 100644
--- a/src/gpu/effects/GrBicubicEffect.h
+++ b/src/gpu/effects/GrBicubicEffect.h
@@ -27,8 +27,6 @@
 
     const char* name() const override { return "Bicubic"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
     const GrTextureDomain& domain() const { return fDomain; }
@@ -94,6 +92,9 @@
                     const SkMatrix &matrix, const SkShader::TileMode tileModes[2]);
     GrBicubicEffect(GrProcessorDataManager*, GrTexture*, const SkScalar coefficients[16],
                     const SkMatrix &matrix, const SkRect& domain);
+
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor&) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 704eb0c..c99351d 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -146,7 +146,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrConfigConversionEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void GrConfigConversionEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                                  GrProcessorKeyBuilder* b) const {
     GrGLConfigConversionEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrConfigConversionEffect.h b/src/gpu/effects/GrConfigConversionEffect.h
index d87d009..ba21c16 100644
--- a/src/gpu/effects/GrConfigConversionEffect.h
+++ b/src/gpu/effects/GrConfigConversionEffect.h
@@ -38,8 +38,6 @@
 
     const char* name() const override { return "Config Conversion"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
     bool swapsRedAndBlue() const { return fSwapRedAndBlue; }
@@ -61,6 +59,8 @@
                              PMConversion pmConversion,
                              const SkMatrix& matrix);
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor&) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
diff --git a/src/gpu/effects/GrConstColorProcessor.cpp b/src/gpu/effects/GrConstColorProcessor.cpp
index e98a1ff..a909104 100644
--- a/src/gpu/effects/GrConstColorProcessor.cpp
+++ b/src/gpu/effects/GrConstColorProcessor.cpp
@@ -85,7 +85,7 @@
     }
 }
 
-void GrConstColorProcessor::getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder* b) const {
+void GrConstColorProcessor::onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder* b) const {
     b->add32(fMode);
 }
 
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 69c5862..9c73e47 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -24,7 +24,7 @@
 
     const char* name() const override { return "AARect"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
 
     GrGLFragmentProcessor* createGLInstance() const override;
 
@@ -152,7 +152,7 @@
     b->add32(aare.getEdgeType());
 }
 
-void AARectEffect::getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
+void AARectEffect::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
     GLAARectEffect::GenKey(*this, caps, b);
 }
 
@@ -302,7 +302,7 @@
     inout->mulByUnknownSingleComponent();
 }
 
-void GrConvexPolyEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void GrConvexPolyEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                            GrProcessorKeyBuilder* b) const {
     GrGLConvexPolyEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrConvexPolyEffect.h b/src/gpu/effects/GrConvexPolyEffect.h
index d1fdd0f..d18ed51 100644
--- a/src/gpu/effects/GrConvexPolyEffect.h
+++ b/src/gpu/effects/GrConvexPolyEffect.h
@@ -69,13 +69,13 @@
 
     const SkScalar* getEdges() const { return fEdges; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
 private:
     GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[]);
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor& other) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 0f32c9c..f99afc8 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -194,7 +194,7 @@
 GrConvolutionEffect::~GrConvolutionEffect() {
 }
 
-void GrConvolutionEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void GrConvolutionEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                         GrProcessorKeyBuilder* b) const {
     GrGLConvolutionEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrConvolutionEffect.h b/src/gpu/effects/GrConvolutionEffect.h
index 066da19..e65c4c4 100644
--- a/src/gpu/effects/GrConvolutionEffect.h
+++ b/src/gpu/effects/GrConvolutionEffect.h
@@ -63,8 +63,6 @@
 
     const char* name() const override { return "Convolution"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
     enum {
@@ -100,6 +98,8 @@
                         bool useBounds,
                         float bounds[2]);
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor&) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 76c285f..08a1e46 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -487,7 +487,7 @@
     this->addTextureAccess(&fBackgroundAccess);
 }
 
-void GrCustomXferFP::getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
+void GrCustomXferFP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
     GLCustomXferFP::GenKey(*this, caps, b);
 }
 
diff --git a/src/gpu/effects/GrCustomXfermodePriv.h b/src/gpu/effects/GrCustomXfermodePriv.h
index ab9d041..2a4006b 100644
--- a/src/gpu/effects/GrCustomXfermodePriv.h
+++ b/src/gpu/effects/GrCustomXfermodePriv.h
@@ -29,8 +29,6 @@
 public:
     GrCustomXferFP(GrProcessorDataManager*, SkXfermode::Mode mode, GrTexture* background);
 
-    void getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; 
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
     const char* name() const override { return "Custom Xfermode"; }
@@ -39,6 +37,8 @@
     const GrTextureAccess&  backgroundAccess() const { return fBackgroundAccess; }
 
 private:
+    void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
+
     bool onIsEqual(const GrFragmentProcessor& other) const override; 
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp
index e870140..6d39450 100644
--- a/src/gpu/effects/GrDitherEffect.cpp
+++ b/src/gpu/effects/GrDitherEffect.cpp
@@ -25,8 +25,6 @@
 
     const char* name() const override { return "Dither"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
 private:
@@ -35,6 +33,8 @@
         this->setWillReadFragmentPosition();
     }
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     // All dither effects are equal
     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
 
@@ -92,7 +92,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void DitherEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void DitherEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                      GrProcessorKeyBuilder* b) const {
     GLDitherEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index fb1b39c..625a3e9 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -155,7 +155,7 @@
 GrMatrixConvolutionEffect::~GrMatrixConvolutionEffect() {
 }
 
-void GrMatrixConvolutionEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void GrMatrixConvolutionEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                                   GrProcessorKeyBuilder* b) const {
     GrGLMatrixConvolutionEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.h b/src/gpu/effects/GrMatrixConvolutionEffect.h
index 7a95df3..ff0a51e 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.h
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.h
@@ -65,8 +65,6 @@
 
     const char* name() const override { return "MatrixConvolution"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
 private:
@@ -81,6 +79,8 @@
                               GrTextureDomain::Mode tileMode,
                               bool convolveAlpha);
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor&) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp
index 3b373cb..1fb54ae 100644
--- a/src/gpu/effects/GrOvalEffect.cpp
+++ b/src/gpu/effects/GrOvalEffect.cpp
@@ -23,8 +23,6 @@
 
     const char* name() const override { return "Circle"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
     const SkPoint& getCenter() const { return fCenter; }
@@ -35,6 +33,8 @@
 private:
     CircleEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius);
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor&) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
@@ -170,7 +170,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-void CircleEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void CircleEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                      GrProcessorKeyBuilder* b) const {
     GLCircleEffect::GenKey(*this, caps, b);
 }
@@ -190,8 +190,6 @@
 
     const char* name() const override { return "Ellipse"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
     const SkPoint& getCenter() const { return fCenter; }
@@ -202,6 +200,8 @@
 private:
     EllipseEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor&) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
@@ -345,7 +345,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-void EllipseEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void EllipseEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                      GrProcessorKeyBuilder* b) const {
     GLEllipseEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index dcc8944..271a997 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -49,8 +49,6 @@
 
     const char* name() const override { return "CircularRRect"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
     const SkRRect& getRRect() const { return fRRect; }
@@ -62,6 +60,8 @@
 private:
     CircularRRectEffect(GrPrimitiveEdgeType, uint32_t circularCornerFlags, const SkRRect&);
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor& other) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
@@ -361,7 +361,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
-void CircularRRectEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void CircularRRectEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                             GrProcessorKeyBuilder* b) const {
     GLCircularRRectEffect::GenKey(*this, caps, b);
 }
@@ -380,8 +380,6 @@
 
     const char* name() const override { return "EllipticalRRect"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
     const SkRRect& getRRect() const { return fRRect; }
@@ -391,6 +389,8 @@
 private:
     EllipticalRRectEffect(GrPrimitiveEdgeType, const SkRRect&);
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor& other) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
@@ -609,7 +609,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
-void EllipticalRRectEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void EllipticalRRectEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                               GrProcessorKeyBuilder* b) const {
     GLEllipticalRRectEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp
index 066ccf7..e3389bb 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/GrSimpleTextureEffect.cpp
@@ -37,7 +37,7 @@
     this->updateInvariantOutputForModulation(inout);
 }
 
-void GrSimpleTextureEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void GrSimpleTextureEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                               GrProcessorKeyBuilder* b) const {
     GrGLSimpleTextureEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrSimpleTextureEffect.h b/src/gpu/effects/GrSimpleTextureEffect.h
index 70d3622..c86b136 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.h
+++ b/src/gpu/effects/GrSimpleTextureEffect.h
@@ -53,8 +53,6 @@
 
     const char* name() const override { return "SimpleTexture"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
 private:
@@ -76,6 +74,8 @@
         this->initClassID<GrSimpleTextureEffect>();
     }
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor& other) const override { return true; }
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index bbc5dc9..7cc454e 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -255,7 +255,7 @@
 
 }
 
-void GrTextureDomainEffect::getGLProcessorKey(const GrGLSLCaps& caps,
+void GrTextureDomainEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
                                               GrProcessorKeyBuilder* b) const {
     GrGLTextureDomainEffect::GenKey(*this, caps, b);
 }
diff --git a/src/gpu/effects/GrTextureDomain.h b/src/gpu/effects/GrTextureDomain.h
index 77c6ce3..7cf75d6 100644
--- a/src/gpu/effects/GrTextureDomain.h
+++ b/src/gpu/effects/GrTextureDomain.h
@@ -169,8 +169,6 @@
 
     const char* name() const override { return "TextureDomain"; }
 
-    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
-
     GrGLFragmentProcessor* createGLInstance() const override;
 
     const GrTextureDomain& textureDomain() const { return fTextureDomain; }
@@ -187,6 +185,8 @@
                           GrTextureParams::FilterMode,
                           GrCoordSet);
 
+    void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
+
     bool onIsEqual(const GrFragmentProcessor&) const override;
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
diff --git a/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/gpu/effects/GrYUVtoRGBEffect.cpp
index 3bfc216..7d77c1f 100644
--- a/src/gpu/effects/GrYUVtoRGBEffect.cpp
+++ b/src/gpu/effects/GrYUVtoRGBEffect.cpp
@@ -102,11 +102,6 @@
         typedef GrGLFragmentProcessor INHERITED;
     };
 
-    virtual void getGLProcessorKey(const GrGLSLCaps& caps,
-                                   GrProcessorKeyBuilder* b) const override {
-        GLProcessor::GenKey(*this, caps, b);
-    }
-
     GrGLFragmentProcessor* createGLInstance() const override {
         return SkNEW_ARGS(GLProcessor, (*this));
     }
@@ -131,6 +126,11 @@
         this->addTextureAccess(&fVAccess);
     }
 
+    virtual void onGetGLProcessorKey(const GrGLSLCaps& caps,
+                                     GrProcessorKeyBuilder* b) const override {
+        GLProcessor::GenKey(*this, caps, b);
+    }
+
     bool onIsEqual(const GrFragmentProcessor& sBase) const override {
         const YUVtoRGBEffect& s = sBase.cast<YUVtoRGBEffect>();
         return fColorSpace == s.getColorSpace();
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 7eb4fe1..2522f7a 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -115,7 +115,9 @@
     for (int s = 0; s < pipeline.numFragmentStages(); ++s) {
         const GrPendingFragmentStage& fps = pipeline.getFragmentStage(s);
         const GrFragmentProcessor& fp = *fps.processor();
+
         fp.getGLProcessorKey(*gpu->glCaps().glslCaps(), &b);
+
         //**** use glslCaps here?
         if (!get_meta_key(fp, gpu->glCaps(), primProc.getTransformKey(fp.coordTransforms()), &b)) {
             glDesc->key().reset();
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 9c0e7ab..daa2480 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -179,6 +179,18 @@
     return fGpu->ctxInfo();
 }
 
+static void append_gr_fp_coord_transforms(const GrFragmentProcessor* processor,
+                                          SkTArray<const GrCoordTransform*, true>* procCoords) {
+    // add the coord transforms of this processor
+    for (int i = 0; i < processor->numTransforms(); ++i) {
+        procCoords->push_back(&processor->coordTransform(i));
+    }
+    // recursively add the coord transforms of this processor's child processors
+    for (int i = 0; i < processor->numChildProcessors(); ++i) {
+        append_gr_fp_coord_transforms(processor->childProcessor(i), procCoords);
+    }
+}
+
 bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
     // First we loop over all of the installed processors and collect coord transforms.  These will
     // be sent to the GrGLPrimitiveProcessor in its emitCode function
@@ -189,11 +201,10 @@
     for (int i = 0; i < this->pipeline().numFragmentStages(); i++) {
         const GrFragmentProcessor* processor = this->pipeline().getFragmentStage(i).processor();
         SkSTArray<2, const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
-        for (int t = 0; t < processor->numTransforms(); t++) {
-            procCoords.push_back(&processor->coordTransform(t));
-        }
 
-        totalTextures += processor->numTextures();
+        append_gr_fp_coord_transforms(processor, &procCoords);
+
+        totalTextures += processor->numTexturesIncludeChildProcs();
         if (totalTextures >= maxTextureUnits) {
             GrCapsDebugf(fGpu->caps(), "Program would use too many texture units\n");
             return false;
@@ -284,7 +295,7 @@
     const GrFragmentProcessor& fp = *fs.processor();
     ifp->fGLProc.reset(fp.createGLInstance());
 
-    SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
+    SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTexturesIncludeChildProcs());
     this->emitSamplers(fp, &samplers, ifp);
 
     GrGLFragmentProcessor::EmitArgs args(this, fp, outColor, inColor, fOutCoords[index], samplers);