Pass GrCustomStage to key-generation functions and emitCode().

R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6819046

git-svn-id: http://skia.googlecode.com/svn/branches/gpu_dev@6182 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 8650f3c..c011747 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -33,6 +33,7 @@
       '<(skia_include_path)/gpu/GrResource.h',
       '<(skia_include_path)/gpu/GrScalar.h',
       '<(skia_include_path)/gpu/GrSurface.h',
+      '<(skia_include_path)/gpu/GrTBackendEffectFactory.h',
       '<(skia_include_path)/gpu/GrTextContext.h',
       '<(skia_include_path)/gpu/GrTexture.h',
       '<(skia_include_path)/gpu/GrTextureAccess.h',
diff --git a/include/gpu/GrBackendEffectFactory.h b/include/gpu/GrBackendEffectFactory.h
index 89562d5..c496f5a 100644
--- a/include/gpu/GrBackendEffectFactory.h
+++ b/include/gpu/GrBackendEffectFactory.h
@@ -10,14 +10,21 @@
 
 #include "GrTypes.h"
 #include "SkTemplates.h"
+#include "SkThread_platform.h"
 #include "GrNoncopyable.h"
 
-/** Given a GrEffect of a particular type, creates the corresponding
-    graphics-backend-specific GrGLEffect. Also tracks equivalence
-    of shaders generated via a key.
+/** Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific
+    effect object. Also tracks equivalence of shaders generated via a key. Each factory instance
+    is assigned a generation ID at construction. The ID of the return of GrEffect::getFactory()
+    is used as a type identifier. Thus a GrEffect subclass must return a singleton from
+    getFactory(). GrEffect subclasses should use the derived class GrTBackendEffectFactory that is
+    templated on the GrEffect subclass as their factory object. It requires that the GrEffect
+    subclass has a nested class (or typedef) GLEffect which is its GL implementation and a subclass
+    of GrGLEffect.
  */
 
 class GrEffect;
+class GrEffectStage;
 class GrGLEffect;
 class GrGLCaps;
 
@@ -35,7 +42,7 @@
         kTextureKeyBits = 6
     };
 
-    virtual EffectKey glEffectKey(const GrEffect&, const GrGLCaps&) const = 0;
+    virtual EffectKey glEffectKey(const GrEffectStage&, const GrGLCaps&) const = 0;
     virtual GrGLEffect* createGLInstance(const GrEffect&) const = 0;
 
     bool operator ==(const GrBackendEffectFactory& b) const {
@@ -71,59 +78,4 @@
     static int32_t fCurrEffectClassID;
 };
 
-template <typename EffectClass>
-class GrTBackendEffectFactory : public GrBackendEffectFactory {
-
-public:
-    typedef typename EffectClass::GLEffect GLEffect;
-
-    /** Returns a human-readable name that is accessible via GrEffect or
-        GrGLEffect and is consistent between the two of them.
-     */
-    virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); }
-
-    /** Returns a value that identifies the GLSL shader code generated by
-        a GrEffect. This enables caching of generated shaders. Part of the
-        id identifies the GrEffect subclass. The remainder is based
-        on the aspects of the GrEffect object's configuration that affect
-        GLSL code generation. */
-    virtual EffectKey glEffectKey(const GrEffect& effect, const GrGLCaps& caps) const SK_OVERRIDE {
-        GrAssert(kIllegalEffectClassID != fEffectClassID);
-        EffectKey effectKey = GLEffect::GenKey(effect, caps);
-        EffectKey textureKey = GLEffect::GenTextureKey(effect, caps);
-#if GR_DEBUG
-        static const EffectKey kIllegalIDMask = (uint16_t) (~((1U << kEffectKeyBits) - 1));
-        GrAssert(!(kIllegalIDMask & effectKey));
-
-        static const EffectKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTextureKeyBits) - 1));
-        GrAssert(!(kIllegalTextureKeyMask & textureKey));
-#endif
-        return fEffectClassID | (textureKey << kEffectKeyBits) | effectKey;
-    }
-
-    /** Returns a new instance of the appropriate *GL* implementation class
-        for the given GrEffect; caller is responsible for deleting
-        the object. */
-    virtual GLEffect* createGLInstance(const GrEffect& effect) const SK_OVERRIDE {
-        return SkNEW_ARGS(GLEffect, (*this, effect));
-    }
-
-    /** This class is a singleton. This function returns the single instance.
-     */
-    static const GrBackendEffectFactory& getInstance() {
-        static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem;
-        static const GrTBackendEffectFactory* gInstance;
-        if (!gInstance) {
-            gInstance = SkNEW_PLACEMENT(gInstanceMem.get(),
-                                        GrTBackendEffectFactory);
-        }
-        return *gInstance;
-    }
-
-protected:
-    GrTBackendEffectFactory() {
-        fEffectClassID = GenID() << (kEffectKeyBits + kTextureKeyBits) ;
-    }
-};
-
 #endif
diff --git a/include/gpu/GrEffect.h b/include/gpu/GrEffect.h
index d7209ff..0adc00b 100644
--- a/include/gpu/GrEffect.h
+++ b/include/gpu/GrEffect.h
@@ -10,10 +10,10 @@
 
 #include "GrRefCnt.h"
 #include "GrNoncopyable.h"
-#include "GrBackendEffectFactory.h"
 #include "GrEffectUnitTest.h"
 #include "GrTextureAccess.h"
 
+class GrBackendEffectFactory;
 class GrContext;
 class GrTexture;
 class SkString;
@@ -33,8 +33,6 @@
 public:
     SK_DECLARE_INST_COUNT(GrEffect)
 
-    typedef GrBackendEffectFactory::EffectKey EffectKey;
-
     explicit GrEffect(int numTextures);
     virtual ~GrEffect();
 
@@ -77,7 +75,7 @@
 
     /** Human-meaningful string to identify this effect; may be embedded
         in generated shader code. */
-    const char* name() const { return this->getFactory().name(); }
+    const char* name() const;
 
     int numTextures() const { return fNumTextures; }
 
diff --git a/include/gpu/GrEffectStage.h b/include/gpu/GrEffectStage.h
index bf7215e..5cd0af3 100644
--- a/include/gpu/GrEffectStage.h
+++ b/include/gpu/GrEffectStage.h
@@ -11,6 +11,7 @@
 #ifndef GrEffectStage_DEFINED
 #define GrEffectStage_DEFINED
 
+#include "GrBackendEffectFactory.h"
 #include "GrEffect.h"
 #include "GrMatrix.h"
 #include "GrTypes.h"
diff --git a/src/effects/SkBlendImageFilter.cpp b/src/effects/SkBlendImageFilter.cpp
index 39d7fd3..fb0e4d0 100644
--- a/src/effects/SkBlendImageFilter.cpp
+++ b/src/effects/SkBlendImageFilter.cpp
@@ -13,6 +13,7 @@
 #include "SkGr.h"
 #include "SkGrPixelRef.h"
 #include "gl/GrGLEffect.h"
+#include "GrTBackendEffectFactory.h"
 #endif
 
 namespace {
@@ -117,14 +118,14 @@
     virtual ~GrGLBlendEffect();
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    static inline EffectKey GenKey(const GrEffect& s, const GrGLCaps&);
+    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
 
 private:
     typedef GrGLEffect INHERITED;
@@ -246,7 +247,7 @@
 }
 
 void GrGLBlendEffect::emitCode(GrGLShaderBuilder* builder,
-                               const GrEffect&,
+                               const GrEffectStage&,
                                EffectKey,
                                const char* vertexCoords,
                                const char* outputColor,
@@ -278,7 +279,7 @@
     }
 }
 
-GrGLEffect::EffectKey GrGLBlendEffect::GenKey(const GrEffect& s, const GrGLCaps&) {
-    return static_cast<const GrBlendEffect&>(s).mode();
+GrGLEffect::EffectKey GrGLBlendEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
+    return static_cast<const GrBlendEffect&>(*s.getEffect()).mode();
 }
 #endif
diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp
index dc93a24..58d2673 100644
--- a/src/effects/SkColorMatrixFilter.cpp
+++ b/src/effects/SkColorMatrixFilter.cpp
@@ -320,6 +320,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrEffect.h"
+#include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
 
 class ColorMatrixEffect : public GrEffect {
@@ -342,7 +343,7 @@
     class GLEffect : public GrGLEffect {
     public:
         // this class always generates the same code.
-        static EffectKey GenKey(const GrEffect& s, const GrGLCaps&) { return 0; }
+        static EffectKey GenKey(const GrEffectStage&, const GrGLCaps&) { return 0; }
 
         GLEffect(const GrBackendEffectFactory& factory,
                  const GrEffect& effect)
@@ -352,7 +353,7 @@
         }
 
         virtual void emitCode(GrGLShaderBuilder* builder,
-                              const GrEffect&,
+                              const GrEffectStage&,
                               EffectKey,
                               const char* vertexCoords,
                               const char* outputColor,
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index e25ab9f..2f403c1 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -14,10 +14,10 @@
 #include "SkTypes.h"
 
 #if SK_SUPPORT_GPU
-#include "GrBackendEffectFactory.h"
 #include "effects/GrSingleTextureEffect.h"
 #include "gl/GrGLEffect.h"
 #include "GrEffect.h"
+#include "GrTBackendEffectFactory.h"
 
 class GrGLDiffuseLightingEffect;
 class GrGLSpecularLightingEffect;
@@ -949,14 +949,14 @@
     virtual ~GrGLLightingEffect();
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    static inline EffectKey GenKey(const GrEffect& s, const GrGLCaps& caps);
+    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
 
     /**
      * Subclasses of GrGLLightingEffect must call INHERITED::setData();
@@ -1072,7 +1072,7 @@
 }
 
 void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder,
-                                  const GrEffect&,
+                                  const GrEffectStage&,
                                   EffectKey,
                                   const char* vertexCoords,
                                   const char* outputColor,
@@ -1167,9 +1167,9 @@
     GrGLSLMulVarBy4f(code, 2, outputColor, inputColor);
 }
 
-GrGLEffect::EffectKey GrGLLightingEffect::GenKey(const GrEffect& s,
-                                                      const GrGLCaps& caps) {
-    return static_cast<const GrLightingEffect&>(s).light()->type();
+GrGLEffect::EffectKey GrGLLightingEffect::GenKey(const GrEffectStage& s,
+                                                 const GrGLCaps& caps) {
+    return static_cast<const GrLightingEffect&>(*s.getEffect()).light()->type();
 }
 
 void GrGLLightingEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index 524a4bb..1097273 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -18,7 +18,7 @@
 #include "gl/GrGLEffect.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
-#include "GrBackendEffectFactory.h"
+#include "GrTBackendEffectFactory.h"
 
 class GrGLMagnifierEffect;
 
@@ -78,7 +78,7 @@
                         const GrEffect& effect);
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
@@ -87,7 +87,7 @@
 
     virtual void setData(const GrGLUniformManager& uman, const GrEffectStage& stage) SK_OVERRIDE;
 
-    static inline EffectKey GenKey(const GrEffect&, const GrGLCaps&);
+    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
 
 private:
 
@@ -107,7 +107,7 @@
 }
 
 void GrGLMagnifierEffect::emitCode(GrGLShaderBuilder* builder,
-                                   const GrEffect&,
+                                   const GrEffectStage&,
                                    EffectKey,
                                    const char* vertexCoords,
                                    const char* outputColor,
@@ -167,8 +167,7 @@
     uman.set2f(fInsetVar, zoom.x_inset(), zoom.y_inset());
 }
 
-GrGLEffect::EffectKey GrGLMagnifierEffect::GenKey(const GrEffect& s,
-                                                       const GrGLCaps& caps) {
+GrGLEffect::EffectKey GrGLMagnifierEffect::GenKey(const GrEffectStage&, const GrGLCaps&) {
     return 0;
 }
 
diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp
index ed0a00b..f8d1c09 100644
--- a/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -14,6 +14,7 @@
 
 #if SK_SUPPORT_GPU
 #include "gl/GrGLEffect.h"
+#include "GrTBackendEffectFactory.h"
 #endif
 
 SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(const SkISize& kernelSize, const SkScalar* kernel, SkScalar gain, SkScalar bias, const SkIPoint& target, TileMode tileMode, bool convolveAlpha, SkImageFilter* input)
@@ -284,14 +285,14 @@
     GrGLMatrixConvolutionEffect(const GrBackendEffectFactory& factory,
                                 const GrEffect& effect);
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    static inline EffectKey GenKey(const GrEffect& s, const GrGLCaps& caps);
+    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
 
     virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
 
@@ -348,7 +349,7 @@
 }
 
 void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
-                                           const GrEffect&,
+                                           const GrEffectStage&,
                                            EffectKey,
                                            const char* vertexCoords,
                                            const char* outputColor,
@@ -417,9 +418,9 @@
 
 };
 
-GrGLEffect::EffectKey GrGLMatrixConvolutionEffect::GenKey(const GrEffect& s,
-                                                        const GrGLCaps& caps) {
-    const GrMatrixConvolutionEffect& m = static_cast<const GrMatrixConvolutionEffect&>(s);
+GrGLEffect::EffectKey GrGLMatrixConvolutionEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
+    const GrMatrixConvolutionEffect& m =
+        static_cast<const GrMatrixConvolutionEffect&>(*s.getEffect());
     EffectKey key = encodeXY(m.kernelSize().width(), m.kernelSize().height());
     key |= m.tileMode() << 7;
     key |= m.convolveAlpha() ? 1 << 9 : 0;
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 6b09914..0e6a318 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -13,7 +13,7 @@
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
 #include "GrTexture.h"
-#include "GrGpu.h"
+#include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
 #include "effects/Gr1DKernelEffect.h"
 #endif
@@ -272,14 +272,14 @@
                           const GrEffect& effect);
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    static inline EffectKey GenKey(const GrEffect& s, const GrGLCaps& caps);
+    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
 
     virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
 
@@ -303,7 +303,7 @@
 }
 
 void GrGLMorphologyEffect::emitCode(GrGLShaderBuilder* builder,
-                                    const GrEffect&,
+                                    const GrEffectStage&,
                                     EffectKey,
                                     const char* vertexCoords,
                                     const char* outputColor,
@@ -342,9 +342,8 @@
     GrGLSLMulVarBy4f(code, 2, outputColor, inputColor);
 }
 
-GrGLEffect::EffectKey GrGLMorphologyEffect::GenKey(const GrEffect& s,
-                                                        const GrGLCaps& caps) {
-    const GrMorphologyEffect& m = static_cast<const GrMorphologyEffect&>(s);
+GrGLEffect::EffectKey GrGLMorphologyEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
+    const GrMorphologyEffect& m = static_cast<const GrMorphologyEffect&>(*s.getEffect());
     EffectKey key = static_cast<EffectKey>(m.radius());
     key |= (m.type() << 8);
     return key;
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 71b4d16..0ae7e19 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -217,6 +217,7 @@
 #if SK_SUPPORT_GPU
 
 #include "GrEffect.h"
+#include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
 #include "SkGr.h"
 
@@ -250,7 +251,7 @@
                          const GrEffect& effect);
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
@@ -259,7 +260,7 @@
 
     virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE {}
 
-    static EffectKey GenKey(const GrEffect&, const GrGLCaps&);
+    static EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
 
 private:
 
@@ -272,7 +273,7 @@
  }
 
 void GLColorTableEffect::emitCode(GrGLShaderBuilder* builder,
-                                  const GrEffect&,
+                                  const GrEffectStage&,
                                   EffectKey,
                                   const char* vertexCoords,
                                   const char* outputColor,
@@ -316,8 +317,7 @@
     code->appendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
 }
 
-GrGLEffect::EffectKey GLColorTableEffect::GenKey(const GrEffect& s,
-                                                        const GrGLCaps& caps) {
+GrGLEffect::EffectKey GLColorTableEffect::GenKey(const GrEffectStage&, const GrGLCaps&) {
     return 0;
 }
 
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index 0e08ec0..524db76 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -474,6 +474,8 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrTBackendEffectFactory.h"
+
 /////////////////////////////////////////////////////////////////////
 
 class GrGLLinearGradient : public GrGLGradientEffect {
@@ -486,14 +488,14 @@
     virtual ~GrGLLinearGradient() { }
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    static EffectKey GenKey(const GrEffect& s, const GrGLCaps& caps) { return 0; }
+    static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps) { return 0; }
 
 private:
 
@@ -551,7 +553,7 @@
 /////////////////////////////////////////////////////////////////////
 
 void GrGLLinearGradient::emitCode(GrGLShaderBuilder* builder,
-                                  const GrEffect&,
+                                  const GrEffectStage&,
                                   EffectKey,
                                   const char* vertexCoords,
                                   const char* outputColor,
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index 6fa29a7..4766af6 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -473,6 +473,8 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrTBackendEffectFactory.h"
+
 class GrGLRadialGradient : public GrGLGradientEffect {
 public:
 
@@ -481,14 +483,14 @@
     virtual ~GrGLRadialGradient() { }
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    static EffectKey GenKey(const GrEffect& s, const GrGLCaps& caps) { return 0; }
+    static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps) { return 0; }
 
 private:
 
@@ -549,7 +551,7 @@
 /////////////////////////////////////////////////////////////////////
 
 void GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder,
-                                  const GrEffect&,
+                                  const GrEffectStage&,
                                   EffectKey,
                                   const char* vertexCoords,
                                   const char* outputColor,
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index b264075..b64e15d 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -382,6 +382,8 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrTBackendEffectFactory.h"
+
 class GrGLSweepGradient : public GrGLGradientEffect {
 public:
 
@@ -390,14 +392,14 @@
     virtual ~GrGLSweepGradient() { }
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    static EffectKey GenKey(const GrEffect& s, const GrGLCaps& caps) { return 0; }
+    static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps) { return 0; }
 
 private:
 
@@ -455,7 +457,7 @@
 /////////////////////////////////////////////////////////////////////
 
 void GrGLSweepGradient::emitCode(GrGLShaderBuilder* builder,
-                                 const GrEffect&,
+                                 const GrEffectStage&,
                                  EffectKey,
                                  const char* vertexCoords,
                                  const char* outputColor,
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index 396981f..acd0eee 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -315,6 +315,8 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrTBackendEffectFactory.h"
+
 // For brevity
 typedef GrGLUniformManager::UniformHandle UniformHandle;
 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
@@ -327,7 +329,7 @@
     virtual ~GrGLConical2Gradient() { }
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
@@ -335,7 +337,7 @@
                           const TextureSamplerArray&) SK_OVERRIDE;
     virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
 
-    static EffectKey GenKey(const GrEffect& s, const GrGLCaps& caps);
+    static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps);
 
 protected:
 
@@ -466,7 +468,7 @@
 }
 
 void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
-                                    const GrEffect&,
+                                    const GrEffectStage&,
                                     EffectKey,
                                     const char* vertexCoords,
                                     const char* outputColor,
@@ -666,8 +668,8 @@
     }
 }
 
-GrEffect::EffectKey GrGLConical2Gradient::GenKey(const GrEffect& s, const GrGLCaps& caps) {
-    return (static_cast<const GrConical2Gradient&>(s).isDegenerate());
+GrGLEffect::EffectKey GrGLConical2Gradient::GenKey(const GrEffectStage& s, const GrGLCaps&) {
+    return (static_cast<const GrConical2Gradient&>(*s.getEffect()).isDegenerate());
 }
 
 /////////////////////////////////////////////////////////////////////
diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp
index 2aac667..9357b11 100644
--- a/src/effects/gradients/SkTwoPointRadialGradient.cpp
+++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp
@@ -349,6 +349,8 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrTBackendEffectFactory.h"
+
 // For brevity
 typedef GrGLUniformManager::UniformHandle UniformHandle;
 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
@@ -362,7 +364,7 @@
     virtual ~GrGLRadial2Gradient() { }
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
@@ -370,7 +372,7 @@
                           const TextureSamplerArray&) SK_OVERRIDE;
     virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
 
-    static EffectKey GenKey(const GrEffect& s, const GrGLCaps& caps);
+    static EffectKey GenKey(const GrEffectStage&, const GrGLCaps& caps);
 
 protected:
 
@@ -499,7 +501,7 @@
 }
 
 void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder,
-                                   const GrEffect&,
+                                   const GrEffectStage&,
                                    EffectKey,
                                    const char* vertexCoords,
                                    const char* outputColor,
@@ -640,8 +642,8 @@
     }
 }
 
-GrEffect::EffectKey GrGLRadial2Gradient::GenKey(const GrEffect& s, const GrGLCaps& caps) {
-    return (static_cast<const GrRadial2Gradient&>(s).isDegenerate());
+GrGLEffect::EffectKey GrGLRadial2Gradient::GenKey(const GrEffectStage& s, const GrGLCaps&) {
+    return (static_cast<const GrRadial2Gradient&>(*s.getEffect()).isDegenerate());
 }
 
 /////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 54372ce..3c6c3a3 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -8,6 +8,7 @@
 #ifndef GrDrawState_DEFINED
 #define GrDrawState_DEFINED
 
+#include "GrBackendEffectFactory.h"
 #include "GrColor.h"
 #include "GrMatrix.h"
 #include "GrRefCnt.h"
diff --git a/src/gpu/GrEffect.cpp b/src/gpu/GrEffect.cpp
index 6423aef..09032bf 100644
--- a/src/gpu/GrEffect.cpp
+++ b/src/gpu/GrEffect.cpp
@@ -5,8 +5,9 @@
  * found in the LICENSE file.
  */
 
-#include "GrContext.h"
 #include "GrEffect.h"
+#include "GrBackendEffectFactory.h"
+#include "GrContext.h"
 #include "GrMemoryPool.h"
 #include "SkTLS.h"
 
@@ -49,6 +50,11 @@
     return false;
 }
 
+const char* GrEffect::name() const {
+    return this->getFactory().name();
+}
+
+
 bool GrEffect::isEqual(const GrEffect& s) const {
     if (this->numTextures() != s.numTextures()) {
         return false;
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index edb0aa5..0860645 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "GrConfigConversionEffect.h"
+#include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
 
 class GrGLConfigConversionEffect : public GrGLEffect {
@@ -18,7 +19,7 @@
     }
 
     virtual void emitCode(GrGLShaderBuilder* builder,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
@@ -59,8 +60,9 @@
         GrGLSLMulVarBy4f(&builder->fFSCode, 2, outputColor, inputColor);
     }
 
-    static inline EffectKey GenKey(const GrEffect& s, const GrGLCaps&) {
-        const GrConfigConversionEffect& effect = static_cast<const GrConfigConversionEffect&>(s);
+    static inline EffectKey GenKey(const GrEffectStage& s, const GrGLCaps&) {
+        const GrConfigConversionEffect& effect =
+            static_cast<const GrConfigConversionEffect&>(*s.getEffect());
         return static_cast<int>(effect.swapsRedAndBlue()) | (effect.pmConversion() << 1);
     }
 
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 5e0c7f6..d0d9f5d 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -9,7 +9,7 @@
 #include "gl/GrGLEffect.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
-#include "GrBackendEffectFactory.h"
+#include "GrTBackendEffectFactory.h"
 
 // For brevity
 typedef GrGLUniformManager::UniformHandle UniformHandle;
@@ -20,7 +20,7 @@
     GrGLConvolutionEffect(const GrBackendEffectFactory&, const GrEffect&);
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
@@ -29,7 +29,7 @@
 
     virtual void setData(const GrGLUniformManager& uman, const GrEffectStage&) SK_OVERRIDE;
 
-    static inline EffectKey GenKey(const GrEffect&, const GrGLCaps&);
+    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
 
 private:
     int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
@@ -52,7 +52,7 @@
 }
 
 void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
-                                     const GrEffect&,
+                                     const GrEffectStage&,
                                      EffectKey,
                                      const char* vertexCoords,
                                      const char* outputColor,
@@ -107,9 +107,8 @@
     uman.set1fv(fKernelUni, 0, this->width(), conv.kernel());
 }
 
-GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrEffect& s,
-                                                         const GrGLCaps& caps) {
-    return static_cast<const GrConvolutionEffect&>(s).radius();
+GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
+    return static_cast<const GrConvolutionEffect&>(*s.getEffect()).radius();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/effects/GrSingleTextureEffect.cpp b/src/gpu/effects/GrSingleTextureEffect.cpp
index 514e926..8866153 100644
--- a/src/gpu/effects/GrSingleTextureEffect.cpp
+++ b/src/gpu/effects/GrSingleTextureEffect.cpp
@@ -9,7 +9,7 @@
 #include "gl/GrGLEffect.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
-#include "GrBackendEffectFactory.h"
+#include "GrTBackendEffectFactory.h"
 #include "GrTexture.h"
 
 class GrGLSingleTextureEffect : public GrGLEffect {
@@ -19,7 +19,7 @@
     }
 
     virtual void emitCode(GrGLShaderBuilder* builder,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
@@ -31,7 +31,7 @@
         builder->fFSCode.append(";\n");
     }
 
-    static inline EffectKey GenKey(const GrEffect&, const GrGLCaps&) { return 0; }
+    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&) { return 0; }
 
 private:
 
diff --git a/src/gpu/effects/GrTextureDomainEffect.cpp b/src/gpu/effects/GrTextureDomainEffect.cpp
index ab98e5e..fcfae14 100644
--- a/src/gpu/effects/GrTextureDomainEffect.cpp
+++ b/src/gpu/effects/GrTextureDomainEffect.cpp
@@ -6,15 +6,15 @@
  */
 
 #include "GrTextureDomainEffect.h"
+#include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
-#include "GrBackendEffectFactory.h"
 
 class GrGLTextureDomainEffect : public GrGLEffect {
 public:
     GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrEffect&);
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffect&,
+                          const GrEffectStage&,
                           EffectKey,
                           const char* vertexCoords,
                           const char* outputColor,
@@ -23,7 +23,7 @@
 
     virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
 
-    static inline EffectKey GenKey(const GrEffect&, const GrGLCaps&) { return 0; }
+    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&) { return 0; }
 
 private:
     GrGLUniformManager::UniformHandle fNameUni;
@@ -38,7 +38,7 @@
 }
 
 void GrGLTextureDomainEffect::emitCode(GrGLShaderBuilder* builder,
-                                       const GrEffect&,
+                                       const GrEffectStage&,
                                        EffectKey,
                                        const char* vertexCoords,
                                        const char* outputColor,
diff --git a/src/gpu/gl/GrGLEffect.h b/src/gpu/gl/GrGLEffect.h
index 74d3f0f..30b8455 100644
--- a/src/gpu/gl/GrGLEffect.h
+++ b/src/gpu/gl/GrGLEffect.h
@@ -8,14 +8,13 @@
 #ifndef GrGLEffect_DEFINED
 #define GrGLEffect_DEFINED
 
-#include "GrAllocator.h"
-#include "GrEffectStage.h"
+#include "GrBackendEffectFactory.h"
 #include "GrGLProgram.h"
 #include "GrGLShaderBuilder.h"
 #include "GrGLShaderVar.h"
 #include "GrGLSL.h"
 
-struct GrGLInterface;
+class GrEffectStage;
 class GrGLTexture;
 
 /** @file
@@ -23,7 +22,7 @@
     include/gpu/GrEffect.h. Objects of type GrGLEffect are responsible for emitting the
     GLSL code that implements a GrEffect and for uploading uniforms at draw time. They also
     must have a function:
-        static inline EffectKey GenKey(const GrEffect&, const GrGLCaps&)
+        static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&)
     that is used to implement a program cache. When two GrEffects produce the same key this means
     that their GrGLEffects would emit the same GLSL code.
 
@@ -33,7 +32,8 @@
 class GrGLEffect {
 
 public:
-    typedef GrEffect::EffectKey EffectKey;
+    typedef GrBackendEffectFactory::EffectKey EffectKey;
+
     enum {
         // the number of bits in EffectKey available to GenKey
         kEffectKeyBits = GrBackendEffectFactory::kEffectKeyBits,
@@ -50,7 +50,7 @@
         stages.
 
         @param builder      Interface used to emit code in the shaders.
-        @param effect       The effect that generated this program stage.
+        @param stage        The effect stage that generated this program stage.
         @param key          The key that was computed by EffectKey() from the generating GrEffect.
         @param vertexCoords A vec2 of texture coordinates in the VS, which may be altered. This will
                             be removed soon and stages will be responsible for computing their own
@@ -67,7 +67,7 @@
                             reads in the generated code.
         */
     virtual void emitCode(GrGLShaderBuilder* builder,
-                          const GrEffect& effect,
+                          const GrEffectStage& stage,
                           EffectKey key,
                           const char* vertexCoords,
                           const char* outputColor,
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 35867c2..f9912aa 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -53,8 +53,8 @@
 
 GrGLProgram* GrGLProgram::Create(const GrGLContextInfo& gl,
                                  const Desc& desc,
-                                 const GrEffect** effects) {
-    GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, effects));
+                                 const GrEffectStage* stages[]) {
+    GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, stages));
     if (!program->succeeded()) {
         delete program;
         program = NULL;
@@ -64,7 +64,7 @@
 
 GrGLProgram::GrGLProgram(const GrGLContextInfo& gl,
                          const Desc& desc,
-                         const GrEffect** effects)
+                         const GrEffectStage* stages[])
 : fContextInfo(gl)
 , fUniformManager(gl) {
     fDesc = desc;
@@ -86,7 +86,7 @@
         fTextureOrigin[s] = GrSurface::kBottomLeft_Origin;
     }
 
-    this->genProgram(effects);
+    this->genProgram(stages);
 }
 
 GrGLProgram::~GrGLProgram() {
@@ -500,7 +500,7 @@
     return true;
 }
 
-bool GrGLProgram::genProgram(const GrEffect** effects) {
+bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
     GrAssert(0 == fProgramID);
 
     GrGLShaderBuilder builder(fContextInfo, fUniformManager);
@@ -624,7 +624,7 @@
                 }
 
                 builder.setCurrentStage(s);
-                fEffects[s] = GenStageCode(effects[s],
+                fEffects[s] = GenStageCode(*stages[s],
                                            fDesc.fStages[s],
                                            &fUniforms.fStages[s],
                                            inColor.size() ? inColor.c_str() : NULL,
@@ -729,7 +729,7 @@
                         inCoverage.append("4");
                     }
                     builder.setCurrentStage(s);
-                    fEffects[s] = GenStageCode(effects[s],
+                    fEffects[s] = GenStageCode(*stages[s],
                                                fDesc.fStages[s],
                                                &fUniforms.fStages[s],
                                                inCoverage.size() ? inCoverage.c_str() : NULL,
@@ -896,14 +896,15 @@
 // Stage code generation
 
 // TODO: Move this function to GrGLShaderBuilder
-GrGLEffect* GrGLProgram::GenStageCode(const GrEffect* effect,
-                                            const StageDesc& desc,
-                                            StageUniforms* uniforms,
-                                            const char* fsInColor, // NULL means no incoming color
-                                            const char* fsOutColor,
-                                            const char* vsInCoord,
-                                            GrGLShaderBuilder* builder) {
+GrGLEffect* GrGLProgram::GenStageCode(const GrEffectStage& stage,
+                                      const StageDesc& desc,
+                                      StageUniforms* uniforms,
+                                      const char* fsInColor, // NULL means no incoming color
+                                      const char* fsOutColor,
+                                      const char* vsInCoord,
+                                      GrGLShaderBuilder* builder) {
 
+    const GrEffect* effect = stage.getEffect();
     GrGLEffect* glEffect = effect->getFactory().createGLInstance(*effect);
 
     /// Vertex Shader Stuff
@@ -956,7 +957,7 @@
     builder->fVSCode.appendf("\t{ // %s\n", glEffect->name());
     builder->fFSCode.appendf("\t{ // %s \n", glEffect->name());
     glEffect->emitCode(builder,
-                       *effect,
+                       stage,
                        desc.fEffectKey,
                        varyingVSName,
                        fsOutColor,
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 5fad7cc..000ebe8 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -43,7 +43,7 @@
 
     static GrGLProgram* Create(const GrGLContextInfo& gl,
                                const Desc& desc,
-                               const GrEffect** effects);
+                               const GrEffectStage* stages[]);
 
     virtual ~GrGLProgram();
 
@@ -163,24 +163,24 @@
 
     GrGLProgram(const GrGLContextInfo& gl,
                 const Desc& desc,
-                const GrEffect** effects);
+                const GrEffectStage* stages[]);
 
     bool succeeded() const { return 0 != fProgramID; }
 
     /**
      *  This is the heavy initialization routine for building a GLProgram.
      */
-    bool genProgram(const GrEffect** effects);
+    bool genProgram(const GrEffectStage* stages[]);
 
     void genInputColor(GrGLShaderBuilder* builder, SkString* inColor);
 
-    static GrGLEffect* GenStageCode(const GrEffect* effect,
-                                          const StageDesc& desc, // TODO: Eliminate this
-                                          StageUniforms* stageUniforms, // TODO: Eliminate this
-                                          const char* fsInColor, // NULL means no incoming color
-                                          const char* fsOutColor,
-                                          const char* vsInCoord,
-                                          GrGLShaderBuilder* builder);
+    static GrGLEffect* GenStageCode(const GrEffectStage& stage,
+                                    const StageDesc& desc, // TODO: Eliminate this
+                                    StageUniforms* stageUniforms, // TODO: Eliminate this
+                                    const char* fsInColor, // NULL means no incoming color
+                                    const char* fsOutColor,
+                                    const char* vsInCoord,
+                                    GrGLShaderBuilder* builder);
 
     void genGeometryShader(GrGLShaderBuilder* segments) const;
 
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index d659cf7..ec7199b 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -153,9 +153,10 @@
     GrGLSLModulate4f(out, modulation, lookup.c_str());
 }
 
-GrEffect::EffectKey GrGLShaderBuilder::KeyForTextureAccess(const GrTextureAccess& access,
-                                                           const GrGLCaps& caps) {
-    GrEffect::EffectKey key = 0;
+GrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess(
+                                                            const GrTextureAccess& access,
+                                                            const GrGLCaps& caps) {
+    GrBackendEffectFactory::EffectKey key = 0;
 
     // Assume that swizzle support implies that we never have to modify a shader to adjust
     // for texture format/swizzle settings.
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index b67f2f0..8f5d695 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -9,6 +9,7 @@
 #define GrGLShaderBuilder_DEFINED
 
 #include "GrAllocator.h"
+#include "GrBackendEffectFactory.h"
 #include "GrEffect.h"
 #include "gl/GrGLShaderVar.h"
 #include "gl/GrGLSL.h"
@@ -122,8 +123,8 @@
     /** Generates a EffectKey for the shader code based on the texture access parameters and the
         capabilities of the GL context.  This is useful for keying the shader programs that may
         have multiple representations, based on the type/format of textures used. */
-    static GrEffect::EffectKey KeyForTextureAccess(const GrTextureAccess& access,
-                                                   const GrGLCaps& caps);
+    static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&,
+                                                                 const GrGLCaps&);
 
     /** If texture swizzling is available using tex parameters then it is preferred over mangling
         the generated shader code. This potentially allows greater reuse of cached shaders. */
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 466c4a7..f56d783 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -163,7 +163,7 @@
         ProgramCache(const GrGLContextInfo& gl);
 
         void abandon();
-        GrGLProgram* getProgram(const GrGLProgram::Desc& desc, const GrEffect** stages);
+        GrGLProgram* getProgram(const GrGLProgram::Desc& desc, const GrEffectStage* stages[]);
     private:
         enum {
             kKeySize = sizeof(ProgramDesc),
@@ -237,7 +237,6 @@
     void buildProgram(bool isPoints,
                       BlendOptFlags blendOpts,
                       GrBlendCoeff dstCoeff,
-                      const GrEffect** effects,
                       ProgramDesc* desc);
 
     // Inits GrDrawTarget::Caps, subclass may enable additional caps.
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index ba36abe..6d6110d 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -33,7 +33,7 @@
 }
 
 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc,
-                                               const GrEffect** stages) {
+                                               const GrEffectStage* stages[]) {
     Entry newEntry;
     newEntry.fKey.setKeyData(desc.asKey());
 
@@ -345,11 +345,14 @@
             return false;
         }
 
-        const GrEffect* effects[GrDrawState::kNumStages];
+        const GrEffectStage* stages[GrDrawState::kNumStages];
+        for (int i = 0; i < GrDrawState::kNumStages; ++i) {
+            stages[i] = drawState.isStageEnabled(i) ? &drawState.getStage(i) : NULL;
+        }
         GrGLProgram::Desc desc;
-        this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, effects, &desc);
+        this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, &desc);
 
-        fCurrentProgram.reset(fProgramCache->getProgram(desc, effects));
+        fCurrentProgram.reset(fProgramCache->getProgram(desc, stages));
         if (NULL == fCurrentProgram.get()) {
             GrAssert(!"Failed to create program!");
             return false;
@@ -558,30 +561,9 @@
     fHWGeometryState.fArrayPtrsDirty = false;
 }
 
-namespace {
-
-void setup_effect(GrGLProgram::Desc::StageDesc* stageDesc,
-                  const GrEffectStage& stage,
-                  const GrGLCaps& caps,
-                  const GrEffect** effects,
-                  GrGLProgram* program, int index) {
-    const GrEffect* effect = stage.getEffect();
-    if (effect) {
-        const GrBackendEffectFactory& factory = effect->getFactory();
-        stageDesc->fEffectKey = factory.glEffectKey(*effect, caps);
-        effects[index] = effect;
-    } else {
-        stageDesc->fEffectKey = 0;
-        effects[index] = NULL;
-    }
-}
-
-}
-
 void GrGpuGL::buildProgram(bool isPoints,
                            BlendOptFlags blendOpts,
                            GrBlendCoeff dstCoeff,
-                           const GrEffect** effects,
                            ProgramDesc* desc) {
     const GrDrawState& drawState = this->getDrawState();
 
@@ -687,12 +669,11 @@
                 // This will go away when effects manage their own texture matrix.
                 stageDesc.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit;
             }
-            setup_effect(&stageDesc, stage, this->glCaps(), effects, fCurrentProgram.get(), s);
-
+            const GrBackendEffectFactory& factory = effect->getFactory();
+            stageDesc.fEffectKey = factory.glEffectKey(stage, this->glCaps());
         } else {
             stageDesc.fOptFlags  = 0;
             stageDesc.fEffectKey = 0;
-            effects[s] = NULL;
         }
     }
 
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index c77c670..9c001fb 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -32,13 +32,10 @@
 }
 
 typedef GrGLProgram::StageDesc StageDesc;
-// TODO: Effects should be able to register themselves for inclusion in the
-// randomly generated shaders. They should be able to configure themselves
-// randomly.
-const GrEffect* create_random_effect(StageDesc* stageDesc,
-                                          GrRandom* random,
-                                          GrContext* context,
-                                          GrTexture* dummyTextures[]) {
+
+const GrEffect* create_random_effect(GrRandom* random,
+                                     GrContext* context,
+                                     GrTexture* dummyTextures[]) {
 
     // The new code uses SkRandom not GrRandom.
     // TODO: Remove GrRandom.
@@ -118,7 +115,7 @@
             pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
         }
 
-        SkAutoTUnref<const GrEffect> effects[GrDrawState::kNumStages];
+        GrEffectStage stages[GrDrawState::kNumStages];
 
         for (int s = 0; s < GrDrawState::kNumStages; ++s) {
             StageDesc& stageDesc = pdesc.fStages[s];
@@ -141,22 +138,23 @@
 
             if (stageDesc.isEnabled()) {
                 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
-                effects[s].reset(create_random_effect(&stageDesc,
-                                                      &random,
-                                                      getContext(),
-                                                      dummyTextures));
-                if (NULL != effects[s]) {
+                SkAutoTUnref<const GrEffect> effect(create_random_effect(&random,
+                                                                         getContext(),
+                                                                         dummyTextures));
+                stages[s].setEffect(effect.get());
+                if (NULL != stages[s].getEffect()) {
                     stageDesc.fEffectKey =
-                        effects[s]->getFactory().glEffectKey(*effects[s], this->glCaps());
+                        stages[s].getEffect()->getFactory().glEffectKey(stages[s], this->glCaps());
                 }
             }
         }
-        GR_STATIC_ASSERT(sizeof(effects) ==
-                         GrDrawState::kNumStages * sizeof(GrEffect*));
-        const GrEffect** stages = reinterpret_cast<const GrEffect**>(&effects);
+        const GrEffectStage* stagePtrs[GrDrawState::kNumStages];
+        for (int s = 0; s < GrDrawState::kNumStages; ++s) {
+            stagePtrs[s] = &stages[s];
+        }
         SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this->glContextInfo(),
                                                               pdesc,
-                                                              stages));
+                                                              stagePtrs));
         if (NULL == program.get()) {
             return false;
         }