Let them eat GrEffectRef.

Changes the remaining existing code that operates on naked GrEffects to GrEffectRef.
Review URL: https://codereview.appspot.com/7124058

git-svn-id: http://skia.googlecode.com/svn/trunk@7321 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrBackendEffectFactory.h b/include/gpu/GrBackendEffectFactory.h
index 437bcdd..a291387 100644
--- a/include/gpu/GrBackendEffectFactory.h
+++ b/include/gpu/GrBackendEffectFactory.h
@@ -23,7 +23,7 @@
     of GrGLEffect.
  */
 
-class GrEffect;
+class GrEffectRef;
 class GrEffectStage;
 class GrGLEffect;
 class GrGLCaps;
@@ -44,7 +44,7 @@
     };
 
     virtual EffectKey glEffectKey(const GrEffectStage&, const GrGLCaps&) const = 0;
-    virtual GrGLEffect* createGLInstance(const GrEffect&) const = 0;
+    virtual GrGLEffect* createGLInstance(const GrEffectRef&) const = 0;
 
     bool operator ==(const GrBackendEffectFactory& b) const {
         return fEffectClassID == b.fEffectClassID;
diff --git a/include/gpu/GrEffect.h b/include/gpu/GrEffect.h
index 507bd57..0e6aab0 100644
--- a/include/gpu/GrEffect.h
+++ b/include/gpu/GrEffect.h
@@ -34,6 +34,9 @@
     GrEffect* get() { return fEffect; }
     const GrEffect* get() const { return fEffect; }
 
+    const GrEffect* operator-> () { return fEffect; }
+    const GrEffect* operator-> () const { return fEffect; }
+
     void* operator new(size_t size);
     void operator delete(void* target);
 
@@ -58,8 +61,11 @@
     GrEffect subclass objects should be created by factory functions that return GrEffectRef.
     There is no public way to wrap a GrEffect in a GrEffectRef. Thus, a factory should be a static
     member function of a GrEffect subclass.
+
+    Because almost no code should ever handle a GrEffect outside of a GrEffectRef, we privately
+    inherit from GrRefCnt to help prevent accidental direct ref'ing/unref'ing of effects.
   */
-class GrEffect : public GrRefCnt {
+class GrEffect : private GrRefCnt {
 public:
     SK_DECLARE_INST_COUNT(GrEffect)
 
@@ -113,16 +119,16 @@
         computed by the GrBackendEffectFactory:
             effectA.getFactory().glEffectKey(effectA) == effectB.getFactory().glEffectKey(effectB).
      */
-    bool isEqual(const GrEffect& other) const {
-        if (&this->getFactory() != &other.getFactory()) {
+    bool isEqual(const GrEffectRef& other) const {
+        if (&this->getFactory() != &other->getFactory()) {
             return false;
         }
         bool result = this->onIsEqual(other);
 #if GR_DEBUG
         if (result) {
-            GrAssert(this->numTextures() == other.numTextures());
+            GrAssert(this->numTextures() == other->numTextures());
             for (int i = 0; i < this->numTextures(); ++i) {
-                GrAssert(*fTextureAccesses[i] == *other.fTextureAccesses[i]);
+                GrAssert(*fTextureAccesses[i] == *other->fTextureAccesses[i]);
             }
         }
 #endif
@@ -154,6 +160,11 @@
     void* operator new(size_t size);
     void operator delete(void* target);
 
+    /** These use non-standard names because GrEffects should only be ref'ed an unref'ed deep in
+        the bowels. Rendering code should use GrEffectRef. */
+    void addRef() { this->ref(); }
+    void subRef() { this->unref(); }
+
 protected:
     /**
      * Subclasses call this from their constructor to register GrTextureAcceses. The effect subclass
@@ -164,7 +175,8 @@
 
     GrEffect() : fEffectRef(NULL) {};
 
-    /** This should be called by GrEffect subclass factories */
+    /** This should be called by GrEffect subclass factories. See the comment on AutoEffectUnref for
+        an example factory function. */
     static GrEffectRef* CreateEffectRef(GrEffect* effect) {
         if (NULL == effect->fEffectRef) {
             effect->fEffectRef = SkNEW_ARGS(GrEffectRef, (effect));
@@ -175,16 +187,41 @@
         return effect->fEffectRef;
     }
 
+    /** Helper used in subclass factory functions to unref the effect after it has been wrapped in a
+        GrEffectRef. E.g.:
+
+        class EffectSubclass : public GrEffect {
+        public:
+            GrEffectRef* Create(ParamType1 param1, ParamType2 param2, ...) {
+                AutoEffectUnref effect(SkNEW_ARGS(EffectSubclass, (param1, param2, ...)));
+                return CreateEffectRef(effect);
+            }
+     */
+    class AutoEffectUnref {
+    public:
+        AutoEffectUnref(GrEffect* effect) : fEffect(effect) { }
+        ~AutoEffectUnref() { fEffect->subRef(); }
+        operator GrEffect*() { return fEffect; }
+    private:
+        GrEffect* fEffect;
+    };
+
+    /** Helper for getting the GrEffect out of a GrEffectRef and down-casting to a GrEffect subclass
+      */
+    template <typename T>
+    static const T& CastEffect(const GrEffectRef& effectRef) {
+        GrAssert(NULL != effectRef.get());
+        return *static_cast<const T*>(effectRef.get());
+    }
+
 private:
 
     /** Subclass implements this to support isEqual(). It will only be called if it is known that
-        the two effects are of the same subclass (i.e. they return the same object
-        from getFactory()).*/
-    virtual bool onIsEqual(const GrEffect& other) const = 0;
+        the two effects are of the same subclass (i.e. they return the same object from
+        getFactory()).*/
+    virtual bool onIsEqual(const GrEffectRef& other) const = 0;
 
-    void EffectRefDestroyed() {
-        fEffectRef = NULL;
-    }
+    void EffectRefDestroyed() { fEffectRef = NULL; }
 
     friend class GrEffectRef; // to call GrEffectRef destroyed
 
diff --git a/include/gpu/GrEffectStage.h b/include/gpu/GrEffectStage.h
index 0060152..c09cd45 100644
--- a/include/gpu/GrEffectStage.h
+++ b/include/gpu/GrEffectStage.h
@@ -39,7 +39,7 @@
             return false;
         }
 
-        if (!this->getEffect()->isEqual(*other.getEffect())) {
+        if (!(*this->getEffect())->isEqual(*other.getEffect())) {
             return false;
         }
 
@@ -112,14 +112,7 @@
         return EffectRef;
     }
 
-    // TODO: Push GrEffectRef deeper and make this getter return it rather than GrEffect.
-    const GrEffect* getEffect() const {
-        if (NULL != fEffectRef) {
-            return fEffectRef->get();
-        } else {
-            return NULL;
-        }
-    }
+    const GrEffectRef* getEffect() const { return fEffectRef; }
 
 private:
     SkMatrix            fCoordChangeMatrix;
@@ -129,4 +122,3 @@
 };
 
 #endif
-
diff --git a/include/gpu/GrTBackendEffectFactory.h b/include/gpu/GrTBackendEffectFactory.h
index 52dbc64..7ea7e39 100644
--- a/include/gpu/GrTBackendEffectFactory.h
+++ b/include/gpu/GrTBackendEffectFactory.h
@@ -34,7 +34,7 @@
                                   const GrGLCaps& caps) const SK_OVERRIDE {
         GrAssert(kIllegalEffectClassID != fEffectClassID);
         EffectKey effectKey = GLEffect::GenKey(stage, caps);
-        EffectKey textureKey = GLEffect::GenTextureKey(*stage.getEffect(), caps);
+        EffectKey textureKey = GLEffect::GenTextureKey(stage.getEffect(), caps);
 #if GR_DEBUG
         static const EffectKey kIllegalIDMask = (uint16_t) (~((1U << kEffectKeyBits) - 1));
         GrAssert(!(kIllegalIDMask & effectKey));
@@ -48,7 +48,7 @@
     /** 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 {
+    virtual GLEffect* createGLInstance(const GrEffectRef& effect) const SK_OVERRIDE {
         return SkNEW_ARGS(GLEffect, (*this, effect));
     }
 
diff --git a/src/effects/SkBicubicImageFilter.cpp b/src/effects/SkBicubicImageFilter.cpp
index cb85c81..36a4e47 100644
--- a/src/effects/SkBicubicImageFilter.cpp
+++ b/src/effects/SkBicubicImageFilter.cpp
@@ -161,16 +161,16 @@
     typedef GrGLBicubicEffect GLEffect;
 
     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
 
     static GrEffectRef* Create(GrTexture* tex, const SkScalar coefficients[16]) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrBicubicEffect, (tex, coefficients)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrBicubicEffect, (tex, coefficients)));
         return CreateEffectRef(effect);
     }
 
 private:
     GrBicubicEffect(GrTexture*, const SkScalar coefficients[16]);
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
     float    fCoefficients[16];
 
     GR_DECLARE_EFFECT_TEST;
@@ -181,7 +181,7 @@
 class GrGLBicubicEffect : public GrGLEffect {
 public:
     GrGLBicubicEffect(const GrBackendEffectFactory& factory,
-                                const GrEffect& effect);
+                      const GrEffectRef& effect);
     virtual void emitCode(GrGLShaderBuilder*,
                           const GrEffectStage&,
                           EffectKey,
@@ -206,7 +206,7 @@
 };
 
 GrGLBicubicEffect::GrGLBicubicEffect(const GrBackendEffectFactory& factory,
-                                     const GrEffect& effect)
+                                     const GrEffectRef& effect)
     : INHERITED(factory)
     , fCoefficientsUni(GrGLUniformManager::kInvalidUniformHandle)
     , fImageIncrementUni(GrGLUniformManager::kInvalidUniformHandle) {
@@ -265,8 +265,7 @@
 }
 
 GrGLEffect::EffectKey GrGLBicubicEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
-    const GrBicubicEffect& m =
-        static_cast<const GrBicubicEffect&>(*s.getEffect());
+    const GrBicubicEffect& m = GetEffectFromStage<GrBicubicEffect>(s);
     EffectKey matrixKey = GrGLEffectMatrix::GenKey(m.getMatrix(),
                                                    s.getCoordChangeMatrix(),
                                                    m.texture(0));
@@ -275,8 +274,7 @@
 
 void GrGLBicubicEffect::setData(const GrGLUniformManager& uman,
                                 const GrEffectStage& stage) {
-    const GrBicubicEffect& effect =
-        static_cast<const GrBicubicEffect&>(*stage.getEffect());
+    const GrBicubicEffect& effect = GetEffectFromStage<GrBicubicEffect>(stage);
     GrTexture& texture = *effect.texture(0);
     float imageIncrement[2];
     imageIncrement[0] = 1.0f / texture.width();
@@ -307,9 +305,8 @@
     return GrTBackendEffectFactory<GrBicubicEffect>::getInstance();
 }
 
-bool GrBicubicEffect::onIsEqual(const GrEffect& sBase) const {
-    const GrBicubicEffect& s =
-        static_cast<const GrBicubicEffect&>(sBase);
+bool GrBicubicEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrBicubicEffect& s = CastEffect<GrBicubicEffect>(sBase);
     return this->texture(0) == s.texture(0) &&
            !memcmp(fCoefficients, s.coefficients(), 16);
 }
diff --git a/src/effects/SkBlendImageFilter.cpp b/src/effects/SkBlendImageFilter.cpp
index 43915b3..840912c 100644
--- a/src/effects/SkBlendImageFilter.cpp
+++ b/src/effects/SkBlendImageFilter.cpp
@@ -116,7 +116,7 @@
 class GrGLBlendEffect : public GrGLEffect {
 public:
     GrGLBlendEffect(const GrBackendEffectFactory& factory,
-                    const GrEffect& effect);
+                    const GrEffectRef& effect);
     virtual ~GrGLBlendEffect();
 
     virtual void emitCode(GrGLShaderBuilder*,
@@ -146,7 +146,7 @@
     static GrEffectRef* Create(SkBlendImageFilter::Mode mode,
                                GrTexture* foreground,
                                GrTexture* background) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrBlendEffect, (mode, foreground, background)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrBlendEffect, (mode, foreground, background)));
         return CreateEffectRef(effect);
     }
 
@@ -161,7 +161,7 @@
     void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
 
 private:
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground, GrTexture* background);
     GrTextureAccess             fForegroundAccess;
@@ -246,8 +246,8 @@
 GrBlendEffect::~GrBlendEffect() {
 }
 
-bool GrBlendEffect::onIsEqual(const GrEffect& sBase) const {
-    const GrBlendEffect& s = static_cast<const GrBlendEffect&>(sBase);
+bool GrBlendEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrBlendEffect& s = CastEffect<GrBlendEffect>(sBase);
     return fForegroundAccess.getTexture() == s.fForegroundAccess.getTexture() &&
            fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture() &&
            fMode == s.fMode;
@@ -272,9 +272,9 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrGLBlendEffect::GrGLBlendEffect(const GrBackendEffectFactory& factory, const GrEffect& effect)
+GrGLBlendEffect::GrGLBlendEffect(const GrBackendEffectFactory& factory, const GrEffectRef& effect)
     : INHERITED(factory),
-      fMode(static_cast<const GrBlendEffect&>(effect).mode()) {
+      fMode(CastEffect<GrBlendEffect>(effect).mode()) {
 }
 
 GrGLBlendEffect::~GrGLBlendEffect() {
@@ -327,7 +327,7 @@
 }
 
 void GrGLBlendEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-    const GrBlendEffect& blend = static_cast<const GrBlendEffect&>(*stage.getEffect());
+    const GrBlendEffect& blend = GetEffectFromStage<GrBlendEffect>(stage);
     GrTexture* fgTex = blend.texture(0);
     GrTexture* bgTex = blend.texture(1);
     fForegroundEffectMatrix.setData(uman,
@@ -342,7 +342,7 @@
 }
 
 GrGLEffect::EffectKey GrGLBlendEffect::GenKey(const GrEffectStage& stage, const GrGLCaps&) {
-    const GrBlendEffect& blend = static_cast<const GrBlendEffect&>(*stage.getEffect());
+    const GrBlendEffect& blend = GetEffectFromStage<GrBlendEffect>(stage);
 
     GrTexture* fgTex = blend.texture(0);
     GrTexture* bgTex = blend.texture(1);
diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp
index 06fb4ef..dfd9566 100644
--- a/src/effects/SkColorMatrixFilter.cpp
+++ b/src/effects/SkColorMatrixFilter.cpp
@@ -326,7 +326,7 @@
 class ColorMatrixEffect : public GrEffect {
 public:
     static GrEffectRef* Create(const SkColorMatrix& matrix) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(ColorMatrixEffect, (matrix)));
+        AutoEffectUnref effect(SkNEW_ARGS(ColorMatrixEffect, (matrix)));
         return CreateEffectRef(effect);
     }
 
@@ -389,7 +389,7 @@
         static EffectKey GenKey(const GrEffectStage&, const GrGLCaps&) { return 0; }
 
         GLEffect(const GrBackendEffectFactory& factory,
-                 const GrEffect& effect)
+                 const GrEffectRef& effect)
         : INHERITED(factory)
         , fMatrixHandle(GrGLUniformManager::kInvalidUniformHandle)
         , fVectorHandle(GrGLUniformManager::kInvalidUniformHandle) {}
@@ -425,8 +425,7 @@
 
         virtual void setData(const GrGLUniformManager& uniManager,
                              const GrEffectStage& stage) SK_OVERRIDE {
-            const ColorMatrixEffect& cme =
-                static_cast<const ColorMatrixEffect&>(*stage.getEffect());
+            const ColorMatrixEffect& cme = GetEffectFromStage<ColorMatrixEffect>(stage);
             const float* m = cme.fMatrix.fMat;
             // The GL matrix is transposed from SkColorMatrix.
             GrGLfloat mt[]  = {
@@ -451,8 +450,8 @@
 private:
     ColorMatrixEffect(const SkColorMatrix& matrix) : fMatrix(matrix) {}
 
-    virtual bool onIsEqual(const GrEffect& s) const {
-        const ColorMatrixEffect& cme = static_cast<const ColorMatrixEffect&>(s);
+    virtual bool onIsEqual(const GrEffectRef& s) const {
+        const ColorMatrixEffect& cme = CastEffect<ColorMatrixEffect>(s);
         return cme.fMatrix == fMatrix;
     }
 
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 17abe28..895dd98 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -201,7 +201,7 @@
 class GrGLDisplacementMapEffect : public GrGLEffect {
 public:
     GrGLDisplacementMapEffect(const GrBackendEffectFactory& factory,
-                              const GrEffect& effect);
+                              const GrEffectRef& effect);
     virtual ~GrGLDisplacementMapEffect();
 
     virtual void emitCode(GrGLShaderBuilder*,
@@ -235,11 +235,11 @@
     static GrEffectRef* Create(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
                                SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
                                SkScalar scale, GrTexture* displacement, GrTexture* color) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrDisplacementMapEffect, (xChannelSelector,
-                                                                           yChannelSelector,
-                                                                           scale,
-                                                                           displacement,
-                                                                           color)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrDisplacementMapEffect, (xChannelSelector,
+                                                                    yChannelSelector,
+                                                                    scale,
+                                                                    displacement,
+                                                                    color)));
         return CreateEffectRef(effect);
     }
 
@@ -258,7 +258,7 @@
     void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
 
 private:
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
                             SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
@@ -361,8 +361,8 @@
 GrDisplacementMapEffect::~GrDisplacementMapEffect() {
 }
 
-bool GrDisplacementMapEffect::onIsEqual(const GrEffect& sBase) const {
-    const GrDisplacementMapEffect& s = static_cast<const GrDisplacementMapEffect&>(sBase);
+bool GrDisplacementMapEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrDisplacementMapEffect& s = CastEffect<GrDisplacementMapEffect>(sBase);
     return fDisplacementAccess.getTexture() == s.fDisplacementAccess.getTexture() &&
            fColorAccess.getTexture() == s.fColorAccess.getTexture() &&
            fXChannelSelector == s.fXChannelSelector &&
@@ -410,10 +410,11 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendEffectFactory& factory, const GrEffect& effect)
+GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendEffectFactory& factory,
+                                                     const GrEffectRef& effect)
     : INHERITED(factory)
-    , fXChannelSelector(static_cast<const GrDisplacementMapEffect&>(effect).xChannelSelector())
-    , fYChannelSelector(static_cast<const GrDisplacementMapEffect&>(effect).yChannelSelector()) {
+    , fXChannelSelector(CastEffect<GrDisplacementMapEffect>(effect).xChannelSelector())
+    , fYChannelSelector(CastEffect<GrDisplacementMapEffect>(effect).yChannelSelector()) {
 }
 
 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() {
@@ -502,7 +503,7 @@
 }
 
 void GrGLDisplacementMapEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-    const GrDisplacementMapEffect& displacementMap = static_cast<const GrDisplacementMapEffect&>(*stage.getEffect());
+    const GrDisplacementMapEffect& displacementMap = GetEffectFromStage<GrDisplacementMapEffect>(stage);
     GrTexture* displTex = displacementMap.texture(0);
     GrTexture* colorTex = displacementMap.texture(1);
     fDisplacementEffectMatrix.setData(uman,
@@ -523,7 +524,7 @@
 GrGLEffect::EffectKey GrGLDisplacementMapEffect::GenKey(const GrEffectStage& stage,
                                                         const GrGLCaps&) {
     const GrDisplacementMapEffect& displacementMap =
-        static_cast<const GrDisplacementMapEffect&>(*stage.getEffect());
+        GetEffectFromStage<GrDisplacementMapEffect>(stage);
 
     GrTexture* displTex = displacementMap.texture(0);
     GrTexture* colorTex = displacementMap.texture(1);
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index 780a3a4..81a686a 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -317,7 +317,7 @@
     }
 
 protected:
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
 private:
     typedef GrSingleTextureEffect INHERITED;
@@ -331,10 +331,10 @@
                                const SkLight* light,
                                SkScalar surfaceScale,
                                SkScalar kd) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrDiffuseLightingEffect, (texture,
-                                                                           light,
-                                                                           surfaceScale,
-                                                                           kd)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrDiffuseLightingEffect, (texture,
+                                                                    light,
+                                                                    surfaceScale,
+                                                                    kd)));
         return CreateEffectRef(effect);
     }
 
@@ -346,7 +346,7 @@
     SkScalar kd() const { return fKD; }
 
 private:
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     GrDiffuseLightingEffect(GrTexture* texture,
                             const SkLight* light,
@@ -365,11 +365,11 @@
                                SkScalar surfaceScale,
                                SkScalar ks,
                                SkScalar shininess) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrSpecularLightingEffect, (texture,
-                                                                            light,
-                                                                            surfaceScale,
-                                                                            ks,
-                                                                            shininess)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrSpecularLightingEffect, (texture,
+                                                                     light,
+                                                                     surfaceScale,
+                                                                     ks,
+                                                                     shininess)));
         return CreateEffectRef(effect);
     }
     static const char* Name() { return "SpecularLighting"; }
@@ -381,7 +381,7 @@
     SkScalar shininess() const { return fShininess; }
 
 private:
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     GrSpecularLightingEffect(GrTexture* texture,
                              const SkLight* light,
@@ -980,7 +980,7 @@
 class GrGLLightingEffect  : public GrGLEffect {
 public:
     GrGLLightingEffect(const GrBackendEffectFactory& factory,
-                       const GrEffect& effect);
+                       const GrEffectRef& effect);
     virtual ~GrGLLightingEffect();
 
     virtual void emitCode(GrGLShaderBuilder*,
@@ -1015,7 +1015,7 @@
 class GrGLDiffuseLightingEffect  : public GrGLLightingEffect {
 public:
     GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory,
-                              const GrEffect& effect);
+                              const GrEffectRef& effect);
     virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
     virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
 
@@ -1030,7 +1030,7 @@
 class GrGLSpecularLightingEffect  : public GrGLLightingEffect {
 public:
     GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory,
-                               const GrEffect& effect);
+                               const GrEffectRef& effect);
     virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
     virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
 
@@ -1054,8 +1054,8 @@
     fLight->unref();
 }
 
-bool GrLightingEffect::onIsEqual(const GrEffect& sBase) const {
-    const GrLightingEffect& s = static_cast<const GrLightingEffect&>(sBase);
+bool GrLightingEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrLightingEffect& s = CastEffect<GrLightingEffect>(sBase);
     return this->texture(0) == s.texture(0) &&
            fLight->isEqual(*s.fLight) &&
            fSurfaceScale == s.fSurfaceScale;
@@ -1071,9 +1071,8 @@
     return GrTBackendEffectFactory<GrDiffuseLightingEffect>::getInstance();
 }
 
-bool GrDiffuseLightingEffect::onIsEqual(const GrEffect& sBase) const {
-    const GrDiffuseLightingEffect& s =
-        static_cast<const GrDiffuseLightingEffect&>(sBase);
+bool GrDiffuseLightingEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrDiffuseLightingEffect& s = CastEffect<GrDiffuseLightingEffect>(sBase);
     return INHERITED::onIsEqual(sBase) &&
             this->kd() == s.kd();
 }
@@ -1094,11 +1093,11 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 GrGLLightingEffect::GrGLLightingEffect(const GrBackendEffectFactory& factory,
-                                       const GrEffect& effect)
+                                       const GrEffectRef& effect)
     : INHERITED(factory)
     , fImageIncrementUni(kInvalidUniformHandle)
     , fSurfaceScaleUni(kInvalidUniformHandle) {
-    const GrLightingEffect& m = static_cast<const GrLightingEffect&>(effect);
+    const GrLightingEffect& m = CastEffect<GrLightingEffect>(effect);
     fLight = m.light()->createGLLight();
 }
 
@@ -1207,8 +1206,8 @@
 
 GrGLEffect::EffectKey GrGLLightingEffect::GenKey(const GrEffectStage& s,
                                                  const GrGLCaps& caps) {
-    const GrLightingEffect& effect = static_cast<const GrLightingEffect&>(*s.getEffect());
-    EffectKey key = static_cast<const GrLightingEffect&>(*s.getEffect()).light()->type();
+    const GrLightingEffect& effect = GetEffectFromStage<GrLightingEffect>(s);
+    EffectKey key = effect.light()->type();
     key <<= GrGLEffectMatrix::kKeyBits;
     EffectKey matrixKey = GrGLEffectMatrix::GenKey(effect.getMatrix(),
                                                    s.getCoordChangeMatrix(),
@@ -1217,7 +1216,7 @@
 }
 
 void GrGLLightingEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-    const GrLightingEffect& effect =static_cast<const GrLightingEffect&>(*stage.getEffect());
+    const GrLightingEffect& effect = GetEffectFromStage<GrLightingEffect>(stage);
     GrTexture* texture = effect.texture(0);
     float ySign = texture->origin() == GrSurface::kTopLeft_Origin ? -1.0f : 1.0f;
     uman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
@@ -1234,7 +1233,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory,
-                                                     const GrEffect& effect)
+                                                     const GrEffectRef& effect)
     : INHERITED(factory, effect)
     , fKDUni(kInvalidUniformHandle) {
 }
@@ -1266,8 +1265,7 @@
 void GrGLDiffuseLightingEffect::setData(const GrGLUniformManager& uman,
                                         const GrEffectStage& stage) {
     INHERITED::setData(uman, stage);
-    const GrDiffuseLightingEffect& effect =
-        static_cast<const GrDiffuseLightingEffect&>(*stage.getEffect());
+    const GrDiffuseLightingEffect& effect = GetEffectFromStage<GrDiffuseLightingEffect>(stage);
     uman.set1f(fKDUni, effect.kd());
 }
 
@@ -1283,9 +1281,8 @@
     return GrTBackendEffectFactory<GrSpecularLightingEffect>::getInstance();
 }
 
-bool GrSpecularLightingEffect::onIsEqual(const GrEffect& sBase) const {
-    const GrSpecularLightingEffect& s =
-        static_cast<const GrSpecularLightingEffect&>(sBase);
+bool GrSpecularLightingEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrSpecularLightingEffect& s = CastEffect<GrSpecularLightingEffect>(sBase);
     return INHERITED::onIsEqual(sBase) &&
            this->ks() == s.ks() &&
            this->shininess() == s.shininess();
@@ -1307,7 +1304,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory,
-                                            const GrEffect& effect)
+                                                       const GrEffectRef& effect)
     : GrGLLightingEffect(factory, effect)
     , fKSUni(kInvalidUniformHandle)
     , fShininessUni(kInvalidUniformHandle) {
@@ -1344,8 +1341,7 @@
 void GrGLSpecularLightingEffect::setData(const GrGLUniformManager& uman,
                                          const GrEffectStage& stage) {
     INHERITED::setData(uman, stage);
-    const GrSpecularLightingEffect& effect =
-        static_cast<const GrSpecularLightingEffect&>(*stage.getEffect());
+    const GrSpecularLightingEffect& effect = GetEffectFromStage<GrSpecularLightingEffect>(stage);
     uman.set1f(fKSUni, effect.ks());
     uman.set1f(fShininessUni, effect.shininess());
 }
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index bcf0baf..f5d9030 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -33,13 +33,13 @@
                                float yZoom,
                                float xInset,
                                float yInset) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrMagnifierEffect, (texture,
-                                                                     xOffset,
-                                                                     yOffset,
-                                                                     xZoom,
-                                                                     yZoom,
-                                                                     xInset,
-                                                                     yInset)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrMagnifierEffect, (texture,
+                                                              xOffset,
+                                                              yOffset,
+                                                              xZoom,
+                                                              yZoom,
+                                                              xInset,
+                                                              yInset)));
         return CreateEffectRef(effect);
     }
 
@@ -75,7 +75,7 @@
         , fXInset(xInset)
         , fYInset(yInset) {}
 
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     GR_DECLARE_EFFECT_TEST;
 
@@ -94,8 +94,7 @@
 
 class GrGLMagnifierEffect : public GrGLEffect {
 public:
-    GrGLMagnifierEffect(const GrBackendEffectFactory& factory,
-                        const GrEffect& effect);
+    GrGLMagnifierEffect(const GrBackendEffectFactory& factory, const GrEffectRef& effect);
 
     virtual void emitCode(GrGLShaderBuilder*,
                           const GrEffectStage&,
@@ -120,8 +119,7 @@
     typedef GrGLEffect INHERITED;
 };
 
-GrGLMagnifierEffect::GrGLMagnifierEffect(const GrBackendEffectFactory& factory,
-                                         const GrEffect& effect)
+GrGLMagnifierEffect::GrGLMagnifierEffect(const GrBackendEffectFactory& factory, const GrEffectRef&)
     : INHERITED(factory)
     , fOffsetVar(GrGLUniformManager::kInvalidUniformHandle)
     , fZoomVar(GrGLUniformManager::kInvalidUniformHandle)
@@ -184,8 +182,7 @@
 
 void GrGLMagnifierEffect::setData(const GrGLUniformManager& uman,
                                   const GrEffectStage& stage) {
-    const GrMagnifierEffect& zoom = static_cast<const GrMagnifierEffect&>(*stage.getEffect());
-
+    const GrMagnifierEffect& zoom = GetEffectFromStage<GrMagnifierEffect>(stage);
     uman.set2f(fOffsetVar, zoom.x_offset(), zoom.y_offset());
     uman.set2f(fZoomVar, zoom.x_zoom(), zoom.y_zoom());
     uman.set2f(fInsetVar, zoom.x_inset(), zoom.y_inset());
@@ -193,7 +190,7 @@
 }
 
 GrGLEffect::EffectKey GrGLMagnifierEffect::GenKey(const GrEffectStage& stage, const GrGLCaps&) {
-    const GrMagnifierEffect& zoom = static_cast<const GrMagnifierEffect&>(*stage.getEffect());
+    const GrMagnifierEffect& zoom = GetEffectFromStage<GrMagnifierEffect>(stage);
     return GrGLEffectMatrix::GenKey(zoom.getMatrix(),
                                     stage.getCoordChangeMatrix(),
                                     zoom.texture(0));
@@ -232,8 +229,8 @@
     return GrTBackendEffectFactory<GrMagnifierEffect>::getInstance();
 }
 
-bool GrMagnifierEffect::onIsEqual(const GrEffect& sBase) const {
-     const GrMagnifierEffect& s = static_cast<const GrMagnifierEffect&>(sBase);
+bool GrMagnifierEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrMagnifierEffect& s = CastEffect<GrMagnifierEffect>(sBase);
     return (this->texture(0) == s.texture(0) &&
             this->fXOffset == s.fXOffset &&
             this->fYOffset == s.fYOffset &&
diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp
index 50933ee..9efb0a3 100644
--- a/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -255,14 +255,14 @@
                                const SkIPoint& target,
                                TileMode tileMode,
                                bool convolveAlpha) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrMatrixConvolutionEffect, (texture,
-                                                                             kernelSize,
-                                                                             kernel,
-                                                                             gain,
-                                                                             bias,
-                                                                             target,
-                                                                             tileMode,
-                                                                             convolveAlpha)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrMatrixConvolutionEffect, (texture,
+                                                                      kernelSize,
+                                                                      kernel,
+                                                                      gain,
+                                                                      bias,
+                                                                      target,
+                                                                      tileMode,
+                                                                      convolveAlpha)));
         return CreateEffectRef(effect);
     }
     virtual ~GrMatrixConvolutionEffect();
@@ -298,7 +298,7 @@
                               TileMode tileMode,
                               bool convolveAlpha);
 
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     SkISize  fKernelSize;
     float   *fKernel;
@@ -316,7 +316,7 @@
 class GrGLMatrixConvolutionEffect : public GrGLEffect {
 public:
     GrGLMatrixConvolutionEffect(const GrBackendEffectFactory& factory,
-                                const GrEffect& effect);
+                                const GrEffectRef& effect);
     virtual void emitCode(GrGLShaderBuilder*,
                           const GrEffectStage&,
                           EffectKey,
@@ -348,14 +348,14 @@
 };
 
 GrGLMatrixConvolutionEffect::GrGLMatrixConvolutionEffect(const GrBackendEffectFactory& factory,
-                                                         const GrEffect& effect)
+                                                         const GrEffectRef& effect)
     : INHERITED(factory)
     , fKernelUni(GrGLUniformManager::kInvalidUniformHandle)
     , fImageIncrementUni(GrGLUniformManager::kInvalidUniformHandle)
     , fTargetUni(GrGLUniformManager::kInvalidUniformHandle)
     , fGainUni(GrGLUniformManager::kInvalidUniformHandle)
     , fBiasUni(GrGLUniformManager::kInvalidUniformHandle) {
-    const GrMatrixConvolutionEffect& m = static_cast<const GrMatrixConvolutionEffect&>(effect);
+    const GrMatrixConvolutionEffect& m = CastEffect<GrMatrixConvolutionEffect>(effect);
     fKernelSize = m.kernelSize();
     fTileMode = m.tileMode();
     fConvolveAlpha = m.convolveAlpha();
@@ -454,8 +454,7 @@
 };
 
 GrGLEffect::EffectKey GrGLMatrixConvolutionEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
-    const GrMatrixConvolutionEffect& m =
-        static_cast<const GrMatrixConvolutionEffect&>(*s.getEffect());
+    const GrMatrixConvolutionEffect& m = GetEffectFromStage<GrMatrixConvolutionEffect>(s);
     EffectKey key = encodeXY(m.kernelSize().width(), m.kernelSize().height());
     key |= m.tileMode() << 7;
     key |= m.convolveAlpha() ? 1 << 9 : 0;
@@ -468,8 +467,7 @@
 
 void GrGLMatrixConvolutionEffect::setData(const GrGLUniformManager& uman,
                                           const GrEffectStage& stage) {
-    const GrMatrixConvolutionEffect& effect =
-        static_cast<const GrMatrixConvolutionEffect&>(*stage.getEffect());
+    const GrMatrixConvolutionEffect& effect = GetEffectFromStage<GrMatrixConvolutionEffect>(stage);
     GrTexture& texture = *effect.texture(0);
     // the code we generated was for a specific kernel size
     GrAssert(effect.kernelSize() == fKernelSize);
@@ -519,9 +517,8 @@
     return GrTBackendEffectFactory<GrMatrixConvolutionEffect>::getInstance();
 }
 
-bool GrMatrixConvolutionEffect::onIsEqual(const GrEffect& sBase) const {
-    const GrMatrixConvolutionEffect& s =
-        static_cast<const GrMatrixConvolutionEffect&>(sBase);
+bool GrMatrixConvolutionEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrMatrixConvolutionEffect& s = CastEffect<GrMatrixConvolutionEffect>(sBase);
     return this->texture(0) == s.texture(0) &&
            fKernelSize == s.kernelSize() &&
            !memcmp(fKernel, s.kernel(), fKernelSize.width() * fKernelSize.height() * sizeof(float)) &&
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index c409435..746f966 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -244,7 +244,7 @@
     };
 
     static GrEffectRef* Create(GrTexture* tex, Direction dir, int radius, MorphologyType type) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrMorphologyEffect, (tex, dir, radius, type)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrMorphologyEffect, (tex, dir, radius, type)));
         return CreateEffectRef(effect);
     }
 
@@ -264,7 +264,7 @@
     MorphologyType fType;
 
 private:
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     GrMorphologyEffect(GrTexture*, Direction, int radius, MorphologyType);
 
@@ -277,8 +277,7 @@
 
 class GrGLMorphologyEffect  : public GrGLEffect {
 public:
-    GrGLMorphologyEffect (const GrBackendEffectFactory& factory,
-                          const GrEffect& effect);
+    GrGLMorphologyEffect (const GrBackendEffectFactory&, const GrEffectRef&);
 
     virtual void emitCode(GrGLShaderBuilder*,
                           const GrEffectStage&,
@@ -304,10 +303,10 @@
 };
 
 GrGLMorphologyEffect::GrGLMorphologyEffect(const GrBackendEffectFactory& factory,
-                                           const GrEffect& effect)
+                                           const GrEffectRef& effect)
     : INHERITED(factory)
     , fImageIncrementUni(GrGLUniformManager::kInvalidUniformHandle) {
-    const GrMorphologyEffect& m = static_cast<const GrMorphologyEffect&>(effect);
+    const GrMorphologyEffect& m = CastEffect<GrMorphologyEffect>(effect);
     fRadius = m.radius();
     fType = m.type();
 }
@@ -354,7 +353,7 @@
 }
 
 GrGLEffect::EffectKey GrGLMorphologyEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
-    const GrMorphologyEffect& m = static_cast<const GrMorphologyEffect&>(*s.getEffect());
+    const GrMorphologyEffect& m = GetEffectFromStage<GrMorphologyEffect>(s);
     EffectKey key = static_cast<EffectKey>(m.radius());
     key |= (m.type() << 8);
     key <<= GrGLEffectMatrix::kKeyBits;
@@ -365,7 +364,7 @@
 }
 
 void GrGLMorphologyEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-    const Gr1DKernelEffect& kern = static_cast<const Gr1DKernelEffect&>(*stage.getEffect());
+    const Gr1DKernelEffect& kern = GetEffectFromStage<Gr1DKernelEffect>(stage);
     GrTexture& texture = *kern.texture(0);
     // the code we generated was for a specific kernel radius
     GrAssert(kern.radius() == fRadius);
@@ -401,9 +400,8 @@
     return GrTBackendEffectFactory<GrMorphologyEffect>::getInstance();
 }
 
-bool GrMorphologyEffect::onIsEqual(const GrEffect& sBase) const {
-    const GrMorphologyEffect& s =
-        static_cast<const GrMorphologyEffect&>(sBase);
+bool GrMorphologyEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrMorphologyEffect& s = CastEffect<GrMorphologyEffect>(sBase);
     return (this->texture(0) == s.texture(0) &&
             this->radius() == s.radius() &&
             this->direction() == s.direction() &&
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index afb4a99..dcdb39f 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -227,7 +227,7 @@
 class ColorTableEffect : public GrEffect {
 public:
     static GrEffectRef* Create(GrTexture* texture, unsigned flags) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(ColorTableEffect, (texture, flags)));
+        AutoEffectUnref effect(SkNEW_ARGS(ColorTableEffect, (texture, flags)));
         return CreateEffectRef(effect);
     }
 
@@ -241,7 +241,7 @@
     typedef GLColorTableEffect GLEffect;
 
 private:
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     explicit ColorTableEffect(GrTexture* texture, unsigned flags);
 
@@ -256,8 +256,7 @@
 
 class GLColorTableEffect : public GrGLEffect {
 public:
-    GLColorTableEffect(const GrBackendEffectFactory& factory,
-                         const GrEffect& effect);
+    GLColorTableEffect(const GrBackendEffectFactory&, const GrEffectRef&);
 
     virtual void emitCode(GrGLShaderBuilder*,
                           const GrEffectStage&,
@@ -276,8 +275,7 @@
     typedef GrGLEffect INHERITED;
 };
 
-GLColorTableEffect::GLColorTableEffect(
-    const GrBackendEffectFactory& factory, const GrEffect& effect)
+GLColorTableEffect::GLColorTableEffect(const GrBackendEffectFactory& factory, const GrEffectRef&)
     : INHERITED(factory) {
  }
 
@@ -345,8 +343,8 @@
     return GrTBackendEffectFactory<ColorTableEffect>::getInstance();
 }
 
-bool ColorTableEffect::onIsEqual(const GrEffect& sBase) const {
-    return this->texture(0) == sBase.texture(0);
+bool ColorTableEffect::onIsEqual(const GrEffectRef& sBase) const {
+    return this->texture(0) == sBase->texture(0);
 }
 
 void ColorTableEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index 7645024..1880425 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -727,7 +727,7 @@
 }
 
 void GrGLGradientEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-    const GrGradientEffect& e = static_cast<const GrGradientEffect&>(*stage.getEffect());
+    const GrGradientEffect& e = GetEffectFromStage<GrGradientEffect>(stage);
     const GrTexture* texture = e.texture(0);
     fEffectMatrix.setData(uman, e.getMatrix(), stage.getCoordChangeMatrix(), texture);
 
@@ -739,7 +739,7 @@
 }
 
 GrGLEffect::EffectKey GrGLGradientEffect::GenMatrixKey(const GrEffectStage& s) {
-    const GrGradientEffect& e = static_cast<const GrGradientEffect&>(*s.getEffect());
+    const GrGradientEffect& e = GetEffectFromStage<GrGradientEffect>(s);
     const GrTexture* texture = e.texture(0);
     return GrGLEffectMatrix::GenKey(e.getMatrix(), s.getCoordChangeMatrix(), texture);
 }
@@ -829,8 +829,8 @@
     }
 }
 
-bool GrGradientEffect::onIsEqual(const GrEffect& effect) const {
-    const GrGradientEffect& s = static_cast<const GrGradientEffect&>(effect);
+bool GrGradientEffect::onIsEqual(const GrEffectRef& effect) const {
+    const GrGradientEffect& s = CastEffect<GrGradientEffect>(effect);
     return fTextureAccess.getTexture() == s.fTextureAccess.getTexture()  &&
            fTextureAccess.getParams().getTileModeX() ==
                 s.fTextureAccess.getParams().getTileModeX() &&
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index 1828905..a34e4ab 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -255,7 +255,7 @@
                                     SkScalar** stops,
                                     SkShader::TileMode* tm);
 
-    virtual bool onIsEqual(const GrEffect& effect) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef& effect) const SK_OVERRIDE;
 
 private:
 
@@ -335,4 +335,3 @@
 #endif
 
 #endif
-
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index 6bb0329..1848571 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -456,8 +456,7 @@
 class GrGLLinearGradient : public GrGLGradientEffect {
 public:
 
-    GrGLLinearGradient(const GrBackendEffectFactory& factory,
-                       const GrEffect&)
+    GrGLLinearGradient(const GrBackendEffectFactory& factory, const GrEffectRef&)
                        : INHERITED (factory) { }
 
     virtual ~GrGLLinearGradient() { }
@@ -488,7 +487,7 @@
                                const SkLinearGradient& shader,
                                const SkMatrix& matrix,
                                SkShader::TileMode tm) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrLinearGradient, (ctx, shader, matrix, tm)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrLinearGradient, (ctx, shader, matrix, tm)));
         return CreateEffectRef(effect);
     }
 
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index c380ec1..3062105 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -479,7 +479,7 @@
 public:
 
     GrGLRadialGradient(const GrBackendEffectFactory& factory,
-                       const GrEffect&) : INHERITED (factory) { }
+                       const GrEffectRef&) : INHERITED (factory) { }
     virtual ~GrGLRadialGradient() { }
 
     virtual void emitCode(GrGLShaderBuilder*,
@@ -508,7 +508,7 @@
                                const SkRadialGradient& shader,
                                const SkMatrix& matrix,
                                SkShader::TileMode tm) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrRadialGradient, (ctx, shader, matrix, tm)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrRadialGradient, (ctx, shader, matrix, tm)));
         return CreateEffectRef(effect);
     }
 
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index 3a1a599..3cdac85 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -388,7 +388,7 @@
 public:
 
     GrGLSweepGradient(const GrBackendEffectFactory& factory,
-                      const GrEffect&) : INHERITED (factory) { }
+                      const GrEffectRef&) : INHERITED (factory) { }
     virtual ~GrGLSweepGradient() { }
 
     virtual void emitCode(GrGLShaderBuilder*,
@@ -416,7 +416,7 @@
     static GrEffectRef* Create(GrContext* ctx,
                                const SkSweepGradient& shader,
                                const SkMatrix& matrix) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrSweepGradient, (ctx, shader, matrix)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrSweepGradient, (ctx, shader, matrix)));
         return CreateEffectRef(effect);
     }
     virtual ~GrSweepGradient() { }
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index 23b976a..bef29c0 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -325,7 +325,7 @@
 public:
 
     GrGLConical2Gradient(const GrBackendEffectFactory& factory,
-                         const GrEffect&);
+                         const GrEffectRef&);
     virtual ~GrGLConical2Gradient() { }
 
     virtual void emitCode(GrGLShaderBuilder*,
@@ -373,7 +373,7 @@
                                const SkTwoPointConicalGradient& shader,
                                const SkMatrix& matrix,
                                SkShader::TileMode tm) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrConical2Gradient, (ctx, shader, matrix, tm)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrConical2Gradient, (ctx, shader, matrix, tm)));
         return CreateEffectRef(effect);
     }
 
@@ -393,8 +393,8 @@
     typedef GrGLConical2Gradient GLEffect;
 
 private:
-    virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
-        const GrConical2Gradient& s = static_cast<const GrConical2Gradient&>(sBase);
+    virtual bool onIsEqual(const GrEffectRef& sBase) const SK_OVERRIDE {
+        const GrConical2Gradient& s = CastEffect<GrConical2Gradient>(sBase);
         return (INHERITED::onIsEqual(sBase) &&
                 this->fCenterX1 == s.fCenterX1 &&
                 this->fRadius0 == s.fRadius0 &&
@@ -456,9 +456,8 @@
 
 /////////////////////////////////////////////////////////////////////
 
-GrGLConical2Gradient::GrGLConical2Gradient(
-        const GrBackendEffectFactory& factory,
-        const GrEffect& baseData)
+GrGLConical2Gradient::GrGLConical2Gradient(const GrBackendEffectFactory& factory,
+                                           const GrEffectRef& baseData)
     : INHERITED(factory)
     , fVSParamUni(kInvalidUniformHandle)
     , fFSParamUni(kInvalidUniformHandle)
@@ -468,8 +467,7 @@
     , fCachedRadius(-SK_ScalarMax)
     , fCachedDiffRadius(-SK_ScalarMax) {
 
-    const GrConical2Gradient& data =
-        static_cast<const GrConical2Gradient&>(baseData);
+    const GrConical2Gradient& data = CastEffect<GrConical2Gradient>(baseData);
     fIsDegenerate = data.isDegenerate();
 }
 
@@ -645,7 +643,7 @@
 
 void GrGLConical2Gradient::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
     INHERITED::setData(uman, stage);
-    const GrConical2Gradient& data = static_cast<const GrConical2Gradient&>(*stage.getEffect());
+    const GrConical2Gradient& data = GetEffectFromStage<GrConical2Gradient>(stage);
     GrAssert(data.isDegenerate() == fIsDegenerate);
     SkScalar centerX1 = data.center();
     SkScalar radius0 = data.radius();
@@ -685,7 +683,7 @@
     };
 
     EffectKey key = GenMatrixKey(s);
-    if (static_cast<const GrConical2Gradient&>(*s.getEffect()).isDegenerate()) {
+    if (GetEffectFromStage<GrConical2Gradient>(s).isDegenerate()) {
         key |= kIsDegenerate;
     }
     return key;
diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp
index fb5c69e..b1c1303 100644
--- a/src/effects/gradients/SkTwoPointRadialGradient.cpp
+++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp
@@ -384,8 +384,7 @@
 
 public:
 
-    GrGLRadial2Gradient(const GrBackendEffectFactory& factory,
-                        const GrEffect&);
+    GrGLRadial2Gradient(const GrBackendEffectFactory& factory, const GrEffectRef&);
     virtual ~GrGLRadial2Gradient() { }
 
     virtual void emitCode(GrGLShaderBuilder*,
@@ -432,7 +431,7 @@
                                const SkTwoPointRadialGradient& shader,
                                const SkMatrix& matrix,
                                SkShader::TileMode tm) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrRadial2Gradient, (ctx, shader, matrix, tm)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrRadial2Gradient, (ctx, shader, matrix, tm)));
         return CreateEffectRef(effect);
     }
 
@@ -452,8 +451,8 @@
     typedef GrGLRadial2Gradient GLEffect;
 
 private:
-    virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
-        const GrRadial2Gradient& s = static_cast<const GrRadial2Gradient&>(sBase);
+    virtual bool onIsEqual(const GrEffectRef& sBase) const SK_OVERRIDE {
+        const GrRadial2Gradient& s = CastEffect<GrRadial2Gradient>(sBase);
         return (INHERITED::onIsEqual(sBase) &&
                 this->fCenterX1 == s.fCenterX1 &&
                 this->fRadius0 == s.fRadius0 &&
@@ -516,9 +515,8 @@
 
 /////////////////////////////////////////////////////////////////////
 
-GrGLRadial2Gradient::GrGLRadial2Gradient(
-        const GrBackendEffectFactory& factory,
-        const GrEffect& baseData)
+GrGLRadial2Gradient::GrGLRadial2Gradient(const GrBackendEffectFactory& factory,
+                                         const GrEffectRef& baseData)
     : INHERITED(factory)
     , fVSParamUni(kInvalidUniformHandle)
     , fFSParamUni(kInvalidUniformHandle)
@@ -528,8 +526,7 @@
     , fCachedRadius(-SK_ScalarMax)
     , fCachedPosRoot(0) {
 
-    const GrRadial2Gradient& data =
-        static_cast<const GrRadial2Gradient&>(baseData);
+    const GrRadial2Gradient& data = CastEffect<GrRadial2Gradient>(baseData);
     fIsDegenerate = data.isDegenerate();
 }
 
@@ -646,7 +643,7 @@
 
 void GrGLRadial2Gradient::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
     INHERITED::setData(uman, stage);
-    const GrRadial2Gradient& data = static_cast<const GrRadial2Gradient&>(*stage.getEffect());
+    const GrRadial2Gradient& data = GetEffectFromStage<GrRadial2Gradient>(stage);
     GrAssert(data.isDegenerate() == fIsDegenerate);
     SkScalar centerX1 = data.center();
     SkScalar radius0 = data.radius();
@@ -684,7 +681,7 @@
     };
 
     EffectKey key = GenMatrixKey(s);
-    if (static_cast<const GrRadial2Gradient&>(*s.getEffect()).isDegenerate()) {
+    if (GetEffectFromStage<GrRadial2Gradient>(s).isDegenerate()) {
         key |= kIsDegenerate;
     }
     return key;
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 9739199..077d246 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -200,10 +200,10 @@
     GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kReset_ASRInit);
     GrDrawState* drawState = target->drawState();
     drawState->setRenderTarget(rt);
-    SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::Create(texture,
-                                                               direction,
-                                                               radius,
-                                                               sigma));
+    SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGuassian(texture,
+                                                                       direction,
+                                                                       radius,
+                                                                       sigma));
     drawState->stage(0)->setEffect(conv);
     target->drawSimpleRect(rect, NULL);
 }
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index e7609d8..70fdff9 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -757,7 +757,7 @@
     GrAssert(NULL != drawState.getRenderTarget());
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
         if (drawState.isStageEnabled(s)) {
-            const GrEffect* effect = drawState.getStage(s).getEffect();
+            const GrEffectRef& effect = *drawState.getStage(s).getEffect();
             int numTextures = effect->numTextures();
             for (int t = 0; t < numTextures; ++t) {
                 GrTexture* texture = effect->texture(t);
@@ -840,9 +840,9 @@
     // Run through the color stages
     int stageCnt = drawState.getFirstCoverageStage();
     for (int s = 0; s < stageCnt; ++s) {
-        const GrEffect* effect = drawState.getStage(s).getEffect();
+        const GrEffectRef* effect = drawState.getStage(s).getEffect();
         if (NULL != effect) {
-            effect->getConstantColorComponents(&color, &validComponentFlags);
+            (*effect)->getConstantColorComponents(&color, &validComponentFlags);
         }
     }
 
@@ -866,9 +866,9 @@
             }
         }
         for (int s = drawState.getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
-            const GrEffect* effect = drawState.getStage(s).getEffect();
+            const GrEffectRef* effect = drawState.getStage(s).getEffect();
             if (NULL != effect) {
-                effect->getConstantColorComponents(&color, &validComponentFlags);
+                (*effect)->getConstantColorComponents(&color, &validComponentFlags);
             }
         }
     }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index cedb7d4..7ceefe8 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1520,7 +1520,7 @@
         return;
     }
 
-    GrTexture* devTex = grPaint.getColorStage(kBitmapTextureIdx).getEffect()->texture(0);
+    GrTexture* devTex = (*grPaint.getColorStage(kBitmapTextureIdx).getEffect())->texture(0);
     SkASSERT(NULL != devTex);
 
     SkImageFilter* filter = paint.getImageFilter();
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 309dcd8..2271b10 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -16,8 +16,8 @@
 class GrGLConfigConversionEffect : public GrGLEffect {
 public:
     GrGLConfigConversionEffect(const GrBackendEffectFactory& factory,
-                               const GrEffect& s) : INHERITED (factory) {
-        const GrConfigConversionEffect& effect = static_cast<const GrConfigConversionEffect&>(s);
+                               const GrEffectRef& s) : INHERITED (factory) {
+        const GrConfigConversionEffect& effect = CastEffect<GrConfigConversionEffect>(s);
         fSwapRedAndBlue = effect.swapsRedAndBlue();
         fPMConversion = effect.pmConversion();
     }
@@ -68,7 +68,7 @@
 
     void setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
         const GrConfigConversionEffect& effect =
-            static_cast<const GrConfigConversionEffect&>(*stage.getEffect());
+            GetEffectFromStage<GrConfigConversionEffect>(stage);
         fEffectMatrix.setData(uman,
                               effect.getMatrix(),
                               stage.getCoordChangeMatrix(),
@@ -76,8 +76,7 @@
     }
 
     static inline EffectKey GenKey(const GrEffectStage& s, const GrGLCaps&) {
-        const GrConfigConversionEffect& effect =
-            static_cast<const GrConfigConversionEffect&>(*s.getEffect());
+        const GrConfigConversionEffect& effect = GetEffectFromStage<GrConfigConversionEffect>(s);
         EffectKey key = static_cast<EffectKey>(effect.swapsRedAndBlue()) |
                         (effect.pmConversion() << 1);
         key <<= GrGLEffectMatrix::kKeyBits;
@@ -116,9 +115,9 @@
     return GrTBackendEffectFactory<GrConfigConversionEffect>::getInstance();
 }
 
-bool GrConfigConversionEffect::onIsEqual(const GrEffect& s) const {
-    const GrConfigConversionEffect& other = static_cast<const GrConfigConversionEffect&>(s);
-    return this->texture(0) == s.texture(0) &&
+bool GrConfigConversionEffect::onIsEqual(const GrEffectRef& s) const {
+    const GrConfigConversionEffect& other = CastEffect<GrConfigConversionEffect>(s);
+    return this->texture(0) == s->texture(0) &&
            other.fSwapRedAndBlue == fSwapRedAndBlue &&
            other.fPMConversion == fPMConversion;
 }
@@ -142,11 +141,11 @@
     } else {
         swapRB = random->nextBool();
     }
-    SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrConfigConversionEffect,
-                                             (textures[GrEffectUnitTest::kSkiaPMTextureIdx],
-                                              swapRB,
-                                              pmConv,
-                                              GrEffectUnitTest::TestMatrix(random))));
+    AutoEffectUnref effect(SkNEW_ARGS(GrConfigConversionEffect,
+                                      (textures[GrEffectUnitTest::kSkiaPMTextureIdx],
+                                       swapRB,
+                                       pmConv,
+                                       GrEffectUnitTest::TestMatrix(random))));
     return CreateEffectRef(effect);
 }
 
@@ -214,18 +213,18 @@
         // We then verify that two reads produced the same values.
 
         GrPaint paint;
-        SkAutoTUnref<GrEffect> pmToUPM1(SkNEW_ARGS(GrConfigConversionEffect, (dataTex,
-                                                                              false,
-                                                                              *pmToUPMRule,
-                                                                              SkMatrix::I())));
-        SkAutoTUnref<GrEffect> upmToPM(SkNEW_ARGS(GrConfigConversionEffect, (readTex,
-                                                                             false,
-                                                                             *upmToPMRule,
-                                                                             SkMatrix::I())));
-        SkAutoTUnref<GrEffect> pmToUPM2(SkNEW_ARGS(GrConfigConversionEffect, (tempTex,
-                                                                              false,
-                                                                              *pmToUPMRule,
-                                                                              SkMatrix::I())));
+        AutoEffectUnref pmToUPM1(SkNEW_ARGS(GrConfigConversionEffect, (dataTex,
+                                                                       false,
+                                                                       *pmToUPMRule,
+                                                                       SkMatrix::I())));
+        AutoEffectUnref upmToPM(SkNEW_ARGS(GrConfigConversionEffect, (readTex,
+                                                                      false,
+                                                                      *upmToPMRule,
+                                                                      SkMatrix::I())));
+        AutoEffectUnref pmToUPM2(SkNEW_ARGS(GrConfigConversionEffect, (tempTex,
+                                                                       false,
+                                                                       *pmToUPMRule,
+                                                                       SkMatrix::I())));
 
         SkAutoTUnref<GrEffectRef> pmToUPMEffect1(CreateEffectRef(pmToUPM1));
         SkAutoTUnref<GrEffectRef> upmToPMEffect(CreateEffectRef(upmToPM));
@@ -280,10 +279,10 @@
             // The PM conversions assume colors are 0..255
             return false;
         }
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrConfigConversionEffect, (texture,
-                                                                            swapRedAndBlue,
-                                                                            pmConversion,
-                                                                            matrix)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrConfigConversionEffect, (texture,
+                                                                     swapRedAndBlue,
+                                                                     pmConversion,
+                                                                     matrix)));
         stage->setEffect(CreateEffectRef(effect))->unref();
         return true;
     }
diff --git a/src/gpu/effects/GrConfigConversionEffect.h b/src/gpu/effects/GrConfigConversionEffect.h
index 3845d32..08e5f71 100644
--- a/src/gpu/effects/GrConfigConversionEffect.h
+++ b/src/gpu/effects/GrConfigConversionEffect.h
@@ -66,7 +66,7 @@
                             PMConversion pmConversion,
                             const SkMatrix& matrix);
 
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     bool            fSwapRedAndBlue;
     PMConversion    fPMConversion;
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 82c908a..ffa5427 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -18,7 +18,7 @@
 
 class GrGLConvolutionEffect : public GrGLEffect {
 public:
-    GrGLConvolutionEffect(const GrBackendEffectFactory&, const GrEffect&);
+    GrGLConvolutionEffect(const GrBackendEffectFactory&, const GrEffectRef&);
 
     virtual void emitCode(GrGLShaderBuilder*,
                           const GrEffectStage&,
@@ -44,12 +44,11 @@
 };
 
 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrBackendEffectFactory& factory,
-                                             const GrEffect& effect)
+                                             const GrEffectRef& effect)
     : INHERITED(factory)
     , fKernelUni(kInvalidUniformHandle)
     , fImageIncrementUni(kInvalidUniformHandle) {
-    const GrConvolutionEffect& c =
-        static_cast<const GrConvolutionEffect&>(effect);
+    const GrConvolutionEffect& c = CastEffect<GrConvolutionEffect>(effect);
     fRadius = c.radius();
 }
 
@@ -91,7 +90,7 @@
 }
 
 void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-    const GrConvolutionEffect& conv = static_cast<const GrConvolutionEffect&>(*stage.getEffect());
+    const GrConvolutionEffect& conv = GetEffectFromStage<GrConvolutionEffect>(stage);
     GrTexture& texture = *conv.texture(0);
     // the code we generated was for a specific kernel radius
     GrAssert(conv.radius() == fRadius);
@@ -112,8 +111,8 @@
 }
 
 GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
-    const GrConvolutionEffect& conv = static_cast<const GrConvolutionEffect&>(*s.getEffect());
-    EffectKey key = static_cast<const GrConvolutionEffect&>(*s.getEffect()).radius();
+    const GrConvolutionEffect& conv = GetEffectFromStage<GrConvolutionEffect>(s);
+    EffectKey key = conv.radius();
     key <<= GrGLEffectMatrix::kKeyBits;
     EffectKey matrixKey = GrGLEffectMatrix::GenKey(conv.getMatrix(),
                                                    s.getCoordChangeMatrix(),
@@ -167,8 +166,8 @@
     return GrTBackendEffectFactory<GrConvolutionEffect>::getInstance();
 }
 
-bool GrConvolutionEffect::onIsEqual(const GrEffect& sBase) const {
-     const GrConvolutionEffect& s = static_cast<const GrConvolutionEffect&>(sBase);
+bool GrConvolutionEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrConvolutionEffect& s = CastEffect<GrConvolutionEffect>(sBase);
     return (this->texture(0) == s.texture(0) &&
             this->radius() == s.radius() &&
             this->direction() == s.direction() &&
@@ -193,4 +192,3 @@
 
     return GrConvolutionEffect::Create(textures[texIdx], dir, radius,kernel);
 }
-
diff --git a/src/gpu/effects/GrConvolutionEffect.h b/src/gpu/effects/GrConvolutionEffect.h
index 944d34f..7345ae4 100644
--- a/src/gpu/effects/GrConvolutionEffect.h
+++ b/src/gpu/effects/GrConvolutionEffect.h
@@ -23,22 +23,22 @@
 
     /// Convolve with an arbitrary user-specified kernel
     static GrEffectRef* Create(GrTexture* tex, Direction dir, int halfWidth, const float* kernel) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrConvolutionEffect, (tex,
-                                                                       dir,
-                                                                       halfWidth,
-                                                                       kernel)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex,
+                                                                dir,
+                                                                halfWidth,
+                                                                kernel)));
         return CreateEffectRef(effect);
     }
 
     /// Convolve with a Gaussian kernel
-    static GrEffectRef* Create(GrTexture* tex,
-                               Direction dir,
-                               int halfWidth,
-                               float gaussianSigma) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrConvolutionEffect, (tex,
-                                                                       dir,
-                                                                       halfWidth,
-                                                                       gaussianSigma)));
+    static GrEffectRef* CreateGuassian(GrTexture* tex,
+                                       Direction dir,
+                                       int halfWidth,
+                                       float gaussianSigma) {
+        AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex,
+                                                                dir,
+                                                                halfWidth,
+                                                                gaussianSigma)));
         return CreateEffectRef(effect);
     }
 
@@ -82,7 +82,7 @@
                         int halfWidth,
                         float gaussianSigma);
 
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     GR_DECLARE_EFFECT_TEST;
 
diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp
index 69ab13e..b674879 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/GrSimpleTextureEffect.cpp
@@ -15,7 +15,7 @@
 
 class GrGLSimpleTextureEffect : public GrGLEffect {
 public:
-    GrGLSimpleTextureEffect(const GrBackendEffectFactory& factory, const GrEffect&)
+    GrGLSimpleTextureEffect(const GrBackendEffectFactory& factory, const GrEffectRef&)
     : INHERITED (factory) {}
 
     virtual void emitCode(GrGLShaderBuilder* builder,
@@ -37,16 +37,14 @@
     }
 
     static inline EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) {
-        const GrSimpleTextureEffect& ste =
-            static_cast<const GrSimpleTextureEffect&>(*stage.getEffect());
+        const GrSimpleTextureEffect& ste = GetEffectFromStage<GrSimpleTextureEffect>(stage);
         return GrGLEffectMatrix::GenKey(ste.getMatrix(),
                                         stage.getCoordChangeMatrix(),
                                         ste.texture(0));
     }
 
     virtual void setData(const GrGLUniformManager& uman, const GrEffectStage& stage) SK_OVERRIDE {
-        const GrSimpleTextureEffect& ste =
-            static_cast<const GrSimpleTextureEffect&>(*stage.getEffect());
+        const GrSimpleTextureEffect& ste = GetEffectFromStage<GrSimpleTextureEffect>(stage);
         fEffectMatrix.setData(uman, ste.getMatrix(), stage.getCoordChangeMatrix(), ste.texture(0));
     }
 
diff --git a/src/gpu/effects/GrSimpleTextureEffect.h b/src/gpu/effects/GrSimpleTextureEffect.h
index 5ccbe33..b7466b4 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.h
+++ b/src/gpu/effects/GrSimpleTextureEffect.h
@@ -21,18 +21,18 @@
 public:
     /* unfiltered, clamp mode */
     static GrEffectRef* Create(GrTexture* tex, const SkMatrix& matrix) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix)));
         return CreateEffectRef(effect);
     }
 
     /* clamp mode */
     static GrEffectRef* Create(GrTexture* tex, const SkMatrix& matrix, bool bilerp) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix, bilerp)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix, bilerp)));
         return CreateEffectRef(effect);
     }
 
     static GrEffectRef* Create(GrTexture* tex, const SkMatrix& matrix, const GrTextureParams& p) {
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix, p)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix, p)));
         return CreateEffectRef(effect);
     }
 
@@ -54,8 +54,8 @@
     GrSimpleTextureEffect(GrTexture* texture, const SkMatrix& matrix, const GrTextureParams& params)
         : GrSingleTextureEffect(texture, matrix, params) {}
 
-    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
-        const GrSimpleTextureEffect& ste = static_cast<const GrSimpleTextureEffect&>(other);
+    virtual bool onIsEqual(const GrEffectRef& other) const SK_OVERRIDE {
+        const GrSimpleTextureEffect& ste = CastEffect<GrSimpleTextureEffect>(other);
         return this->hasSameTextureParamsAndMatrix(ste);
     }
 
diff --git a/src/gpu/effects/GrTextureDomainEffect.cpp b/src/gpu/effects/GrTextureDomainEffect.cpp
index c4a59d8..58c8b80 100644
--- a/src/gpu/effects/GrTextureDomainEffect.cpp
+++ b/src/gpu/effects/GrTextureDomainEffect.cpp
@@ -14,7 +14,7 @@
 
 class GrGLTextureDomainEffect : public GrGLEffect {
 public:
-    GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrEffect&);
+    GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrEffectRef&);
 
     virtual void emitCode(GrGLShaderBuilder*,
                           const GrEffectStage&,
@@ -37,7 +37,7 @@
 };
 
 GrGLTextureDomainEffect::GrGLTextureDomainEffect(const GrBackendEffectFactory& factory,
-                                                 const GrEffect&)
+                                                 const GrEffectRef&)
     : INHERITED(factory)
     , fNameUni(GrGLUniformManager::kInvalidUniformHandle) {
     fPrevDomain[0] = SK_FloatNaN;
@@ -50,8 +50,7 @@
                                        const char* outputColor,
                                        const char* inputColor,
                                        const TextureSamplerArray& samplers) {
-    const GrTextureDomainEffect& effect =
-        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
+    const GrTextureDomainEffect& effect = GetEffectFromStage<GrTextureDomainEffect>(stage);
 
     const char* coords;
     fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, vertexCoords, &coords);
@@ -81,8 +80,7 @@
 }
 
 void GrGLTextureDomainEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-    const GrTextureDomainEffect& effect =
-        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
+    const GrTextureDomainEffect& effect = GetEffectFromStage<GrTextureDomainEffect>(stage);
     const GrRect& domain = effect.domain();
 
     float values[4] = {
@@ -109,8 +107,7 @@
 }
 
 GrGLEffect::EffectKey GrGLTextureDomainEffect::GenKey(const GrEffectStage& stage, const GrGLCaps&) {
-    const GrTextureDomainEffect& effect =
-        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
+    const GrTextureDomainEffect& effect = GetEffectFromStage<GrTextureDomainEffect>(stage);
     EffectKey key = effect.wrapMode();
     key <<= GrGLEffectMatrix::kKeyBits;
     EffectKey matrixKey = GrGLEffectMatrix::GenKey(effect.getMatrix(),
@@ -144,11 +141,11 @@
         GrAssert(clippedDomain.fLeft <= clippedDomain.fRight);
         GrAssert(clippedDomain.fTop <= clippedDomain.fBottom);
 
-        SkAutoTUnref<GrEffect> effect(SkNEW_ARGS(GrTextureDomainEffect, (texture,
-                                                                         matrix,
-                                                                         clippedDomain,
-                                                                         wrapMode,
-                                                                         bilerp)));
+        AutoEffectUnref effect(SkNEW_ARGS(GrTextureDomainEffect, (texture,
+                                                                  matrix,
+                                                                  clippedDomain,
+                                                                  wrapMode,
+                                                                  bilerp)));
         return CreateEffectRef(effect);
 
     }
@@ -172,8 +169,8 @@
     return GrTBackendEffectFactory<GrTextureDomainEffect>::getInstance();
 }
 
-bool GrTextureDomainEffect::onIsEqual(const GrEffect& sBase) const {
-    const GrTextureDomainEffect& s = static_cast<const GrTextureDomainEffect&>(sBase);
+bool GrTextureDomainEffect::onIsEqual(const GrEffectRef& sBase) const {
+    const GrTextureDomainEffect& s = CastEffect<GrTextureDomainEffect>(sBase);
     return this->hasSameTextureParamsAndMatrix(s) && this->fTextureDomain == s.fTextureDomain;
 }
 
diff --git a/src/gpu/effects/GrTextureDomainEffect.h b/src/gpu/effects/GrTextureDomainEffect.h
index b7f665c..81b3da4 100644
--- a/src/gpu/effects/GrTextureDomainEffect.h
+++ b/src/gpu/effects/GrTextureDomainEffect.h
@@ -77,7 +77,7 @@
                           WrapMode,
                           bool bilerp);
 
-    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrEffectRef&) const SK_OVERRIDE;
 
     GR_DECLARE_EFFECT_TEST;
 
diff --git a/src/gpu/gl/GrGLEffect.cpp b/src/gpu/gl/GrGLEffect.cpp
index 0bbf1f7..ccea269 100644
--- a/src/gpu/gl/GrGLEffect.cpp
+++ b/src/gpu/gl/GrGLEffect.cpp
@@ -20,11 +20,11 @@
 void GrGLEffect::setData(const GrGLUniformManager&, const GrEffectStage&) {
 }
 
-GrGLEffect::EffectKey GrGLEffect::GenTextureKey(const GrEffect& effect,
+GrGLEffect::EffectKey GrGLEffect::GenTextureKey(const GrEffectRef* effect,
                                                 const GrGLCaps& caps) {
     EffectKey key = 0;
-    for (int index = 0; index < effect.numTextures(); ++index) {
-        const GrTextureAccess& access = effect.textureAccess(index);
+    for (int index = 0; index < (*effect)->numTextures(); ++index) {
+        const GrTextureAccess& access = (*effect)->textureAccess(index);
         EffectKey value = GrGLShaderBuilder::KeyForTextureAccess(access, caps) << index;
         GrAssert(0 == (value & key)); // keys for each access ought not to overlap
         key |= value;
diff --git a/src/gpu/gl/GrGLEffect.h b/src/gpu/gl/GrGLEffect.h
index f2142c5..32fc960 100644
--- a/src/gpu/gl/GrGLEffect.h
+++ b/src/gpu/gl/GrGLEffect.h
@@ -86,7 +86,28 @@
 
     const char* name() const { return fFactory.name(); }
 
-    static EffectKey GenTextureKey(const GrEffect&, const GrGLCaps&);
+    static EffectKey GenTextureKey(const GrEffectRef*, const GrGLCaps&);
+
+   /**
+    * GrGLEffect subclasses get passed a GrEffectStage in their emitCode and setData functions.
+    * The GrGLEffect usually needs to cast the stage's effect to the GrEffect subclass that
+    * generated the GrGLEffect. This helper does just that.
+    */
+    template <typename T>
+    static const T& GetEffectFromStage(const GrEffectStage& effectStage) {
+        GrAssert(NULL != effectStage.getEffect());
+        return CastEffect<T>(*effectStage.getEffect());
+    }
+
+   /**
+    * Extracts the GrEffect from a GrEffectRef and down-casts to a GrEffect subclass. Usually used
+    * in a GrGLEffect subclass's constructor (which takes const GrEffectRef&).
+    */
+    template <typename T>
+    static const T& CastEffect(const GrEffectRef& effectRef) {
+        GrAssert(NULL != effectRef.get());
+        return *static_cast<const T*>(effectRef.get());
+    }
 
 protected:
     const GrBackendEffectFactory& fFactory;
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 26127e4..e6daa9c 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -914,7 +914,7 @@
             for (int u = 0; u < numSamplers; ++u) {
                 UniformHandle handle = fUniformHandles.fSamplerUnis[s][u];
                 if (GrGLUniformManager::kInvalidUniformHandle != handle) {
-                    const GrTextureAccess& access = stage.getEffect()->textureAccess(u);
+                    const GrTextureAccess& access = (*stage.getEffect())->textureAccess(u);
                     GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture());
                     gpu->bindTexture(texUnitIdx, access.getParams(), texture);
                     ++texUnitIdx;
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 0845fdd..a8514ad 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -422,16 +422,16 @@
                                 SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles) {
     GrAssert(NULL != stage.getEffect());
 
-    const GrEffect& effect = *stage.getEffect();
-    int numTextures = effect.numTextures();
+    const GrEffectRef& effect = *stage.getEffect();
+    int numTextures = effect->numTextures();
     SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
     textureSamplers.push_back_n(numTextures);
     for (int i = 0; i < numTextures; ++i) {
-        textureSamplers[i].init(this, &effect.textureAccess(i), i);
+        textureSamplers[i].init(this, &effect->textureAccess(i), i);
         samplerHandles->push_back(textureSamplers[i].fSamplerUniform);
     }
 
-    GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect);
+    GrGLEffect* glEffect = effect->getFactory().createGLInstance(effect);
 
     // Enclose custom code in a block to avoid namespace conflicts
     this->fVSCode.appendf("\t{ // %s\n", glEffect->name());
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 3d9f0fe..7e0d0b0 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -563,7 +563,7 @@
         bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
         if (!skip && drawState.isStageEnabled(s)) {
             lastEnabledStage = s;
-            const GrEffect* effect = drawState.getStage(s).getEffect();
+            const GrEffectRef& effect = *drawState.getStage(s).getEffect();
             const GrBackendEffectFactory& factory = effect->getFactory();
             desc->fEffectKeys[s] = factory.glEffectKey(drawState.getStage(s), this->glCaps());
         } else {
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index aafde35..e83ddeb 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -128,7 +128,8 @@
                 stages[s].setEffect(effect.get());
                 if (NULL != stages[s].getEffect()) {
                     pdesc.fEffectKeys[s] =
-                        stages[s].getEffect()->getFactory().glEffectKey(stages[s], this->glCaps());
+                        (*stages[s].getEffect())->getFactory().glEffectKey(stages[s],
+                                                                           this->glCaps());
                 }
             }
         }