Attempt to reland 8264-5 with warning-as-error fixes.




git-svn-id: http://skia.googlecode.com/svn/trunk@8272 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/effects/GrCircleEdgeEffect.cpp b/src/gpu/effects/GrCircleEdgeEffect.cpp
index ba73502..4ecdedb 100644
--- a/src/gpu/effects/GrCircleEdgeEffect.cpp
+++ b/src/gpu/effects/GrCircleEdgeEffect.cpp
@@ -17,29 +17,27 @@
 
 class GrGLCircleEdgeEffect : public GrGLEffect {
 public:
-    GrGLCircleEdgeEffect(const GrBackendEffectFactory& factory, const GrEffectRef&)
+    GrGLCircleEdgeEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
     : INHERITED (factory) {}
 
     virtual void emitCode(GrGLShaderBuilder* builder,
-                          const GrEffectStage& stage,
+                          const GrDrawEffect& drawEffect,
                           EffectKey key,
-                          const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray& samplers) SK_OVERRIDE {
-        const GrCircleEdgeEffect& effect = GetEffectFromStage<GrCircleEdgeEffect>(stage);
-
+        const GrCircleEdgeEffect& circleEffect = drawEffect.castEffect<GrCircleEdgeEffect>();
         const char *vsName, *fsName;
         builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName);
 
         const SkString* attrName =
-            builder->getEffectAttributeName(stage.getVertexAttribIndices()[0]);
+            builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
         builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
 
         builder->fsCodeAppendf("\tfloat d = distance(%s.xy, %s.xy);\n",
                                builder->fragmentPosition(), fsName);
         builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName);
-        if (effect.isStroked()) {
+        if (circleEffect.isStroked()) {
             builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0, 1.0);\n", fsName);
             builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n");
         }
@@ -48,13 +46,13 @@
         builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
     }
 
-    static inline EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) {
-        const GrCircleEdgeEffect& effect = GetEffectFromStage<GrCircleEdgeEffect>(stage);
+    static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+        const GrCircleEdgeEffect& circleEffect = drawEffect.castEffect<GrCircleEdgeEffect>();
 
-        return effect.isStroked() ? 0x1 : 0x0;
+        return circleEffect.isStroked() ? 0x1 : 0x0;
     }
 
-    virtual void setData(const GrGLUniformManager& uman, const GrEffectStage& stage) SK_OVERRIDE {
+    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {
     }
 
 private:
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 5cc05e2..df8ab8d 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -16,21 +16,22 @@
 class GrGLConfigConversionEffect : public GrGLEffect {
 public:
     GrGLConfigConversionEffect(const GrBackendEffectFactory& factory,
-                               const GrEffectRef& s) : INHERITED (factory) {
-        const GrConfigConversionEffect& effect = CastEffect<GrConfigConversionEffect>(s);
+                               const GrDrawEffect& drawEffect)
+    : INHERITED (factory)
+    , fEffectMatrix(drawEffect.castEffect<GrConfigConversionEffect>().coordsType()) {
+        const GrConfigConversionEffect& effect = drawEffect.castEffect<GrConfigConversionEffect>();
         fSwapRedAndBlue = effect.swapsRedAndBlue();
         fPMConversion = effect.pmConversion();
     }
 
     virtual void emitCode(GrGLShaderBuilder* builder,
-                          const GrEffectStage&,
+                          const GrDrawEffect&,
                           EffectKey key,
-                          const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray& samplers) SK_OVERRIDE {
         const char* coords;
-        GrSLType coordsType = fEffectMatrix.emitCode(builder, key, vertexCoords, &coords);
+        GrSLType coordsType = fEffectMatrix.emitCode(builder, key, &coords);
         builder->fsCodeAppendf("\t\t%s = ", outputColor);
         builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
                                      samplers[0],
@@ -71,23 +72,19 @@
         builder->fsCodeAppend(modulate.c_str());
     }
 
-    void setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-        const GrConfigConversionEffect& effect =
-            GetEffectFromStage<GrConfigConversionEffect>(stage);
-        fEffectMatrix.setData(uman,
-                              effect.getMatrix(),
-                              stage.getCoordChangeMatrix(),
-                              effect.texture(0));
+    void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
+        const GrConfigConversionEffect& conv = drawEffect.castEffect<GrConfigConversionEffect>();
+        fEffectMatrix.setData(uman, conv.getMatrix(), drawEffect, conv.texture(0));
     }
 
-    static inline EffectKey GenKey(const GrEffectStage& s, const GrGLCaps&) {
-        const GrConfigConversionEffect& effect = GetEffectFromStage<GrConfigConversionEffect>(s);
-        EffectKey key = static_cast<EffectKey>(effect.swapsRedAndBlue()) |
-                        (effect.pmConversion() << 1);
+    static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+        const GrConfigConversionEffect& conv = drawEffect.castEffect<GrConfigConversionEffect>();
+        EffectKey key = static_cast<EffectKey>(conv.swapsRedAndBlue()) | (conv.pmConversion() << 1);
         key <<= GrGLEffectMatrix::kKeyBits;
-        EffectKey matrixKey =  GrGLEffectMatrix::GenKey(effect.getMatrix(),
-                                                        s.getCoordChangeMatrix(),
-                                                        effect.texture(0));
+        EffectKey matrixKey =  GrGLEffectMatrix::GenKey(conv.getMatrix(),
+                                                        drawEffect,
+                                                        conv.coordsType(),
+                                                        conv.texture(0));
         GrAssert(!(matrixKey & key));
         return matrixKey | key;
     }
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 794a936..924b03c 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -18,19 +18,18 @@
 
 class GrGLConvolutionEffect : public GrGLEffect {
 public:
-    GrGLConvolutionEffect(const GrBackendEffectFactory&, const GrEffectRef&);
+    GrGLConvolutionEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffectStage&,
+                          const GrDrawEffect&,
                           EffectKey,
-                          const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    virtual void setData(const GrGLUniformManager& uman, const GrEffectStage&) SK_OVERRIDE;
+    virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK_OVERRIDE;
 
-    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
+    static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
 
 private:
     int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
@@ -44,23 +43,23 @@
 };
 
 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrBackendEffectFactory& factory,
-                                             const GrEffectRef& effect)
+                                             const GrDrawEffect& drawEffect)
     : INHERITED(factory)
     , fKernelUni(kInvalidUniformHandle)
-    , fImageIncrementUni(kInvalidUniformHandle) {
-    const GrConvolutionEffect& c = CastEffect<GrConvolutionEffect>(effect);
+    , fImageIncrementUni(kInvalidUniformHandle)
+    , fEffectMatrix(drawEffect.castEffect<GrConvolutionEffect>().coordsType()) {
+    const GrConvolutionEffect& c = drawEffect.castEffect<GrConvolutionEffect>();
     fRadius = c.radius();
 }
 
 void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
-                                     const GrEffectStage&,
+                                     const GrDrawEffect&,
                                      EffectKey key,
-                                     const char* vertexCoords,
                                      const char* outputColor,
                                      const char* inputColor,
                                      const TextureSamplerArray& samplers) {
     const char* coords;
-    fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, vertexCoords, &coords);
+    fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords);
     fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
                                              kVec2f_GrSLType, "ImageIncrement");
     fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_ShaderType,
@@ -90,8 +89,9 @@
     builder->fsCodeAppend(modulate.c_str());
 }
 
-void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-    const GrConvolutionEffect& conv = GetEffectFromStage<GrConvolutionEffect>(stage);
+void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman,
+                                    const GrDrawEffect& drawEffect) {
+    const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect>();
     GrTexture& texture = *conv.texture(0);
     // the code we generated was for a specific kernel radius
     GrAssert(conv.radius() == fRadius);
@@ -108,15 +108,17 @@
     }
     uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement);
     uman.set1fv(fKernelUni, 0, this->width(), conv.kernel());
-    fEffectMatrix.setData(uman, conv.getMatrix(), stage.getCoordChangeMatrix(), conv.texture(0));
+    fEffectMatrix.setData(uman, conv.getMatrix(), drawEffect, conv.texture(0));
 }
 
-GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrEffectStage& s, const GrGLCaps&) {
-    const GrConvolutionEffect& conv = GetEffectFromStage<GrConvolutionEffect>(s);
+GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrDrawEffect& drawEffect,
+                                                    const GrGLCaps&) {
+    const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect>();
     EffectKey key = conv.radius();
     key <<= GrGLEffectMatrix::kKeyBits;
     EffectKey matrixKey = GrGLEffectMatrix::GenKey(conv.getMatrix(),
-                                                   s.getCoordChangeMatrix(),
+                                                   drawEffect,
+                                                   conv.coordsType(),
                                                    conv.texture(0));
     return key | matrixKey;
 }
diff --git a/src/gpu/effects/GrEllipseEdgeEffect.cpp b/src/gpu/effects/GrEllipseEdgeEffect.cpp
index 37432f0..12f3197 100644
--- a/src/gpu/effects/GrEllipseEdgeEffect.cpp
+++ b/src/gpu/effects/GrEllipseEdgeEffect.cpp
@@ -15,29 +15,28 @@
 
 class GrGLEllipseEdgeEffect : public GrGLEffect {
 public:
-    GrGLEllipseEdgeEffect(const GrBackendEffectFactory& factory, const GrEffectRef&)
+    GrGLEllipseEdgeEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
     : INHERITED (factory) {}
 
     virtual void emitCode(GrGLShaderBuilder* builder,
-                          const GrEffectStage& stage,
+                          const GrDrawEffect& drawEffect,
                           EffectKey key,
-                          const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray& samplers) SK_OVERRIDE {
-        const GrEllipseEdgeEffect& effect = GetEffectFromStage<GrEllipseEdgeEffect>(stage);
+        const GrEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<GrEllipseEdgeEffect>();
 
         const char *vsCenterName, *fsCenterName;
         const char *vsEdgeName, *fsEdgeName;
 
         builder->addVarying(kVec2f_GrSLType, "EllipseCenter", &vsCenterName, &fsCenterName);
         const SkString* attr0Name =
-            builder->getEffectAttributeName(stage.getVertexAttribIndices()[0]);
+            builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
         builder->vsCodeAppendf("\t%s = %s;\n", vsCenterName, attr0Name->c_str());
 
         builder->addVarying(kVec4f_GrSLType, "EllipseEdge", &vsEdgeName, &fsEdgeName);
         const SkString* attr1Name =
-            builder->getEffectAttributeName(stage.getVertexAttribIndices()[1]);
+            builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]);
         builder->vsCodeAppendf("\t%s = %s;\n", vsEdgeName, attr1Name->c_str());
 
         // translate to origin
@@ -50,7 +49,7 @@
         // compare outer lengths against xOuterRadius
         builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.x-dOuter, 0.0, 1.0);\n", fsEdgeName);
 
-        if (effect.isStroked()) {
+        if (ellipseEffect.isStroked()) {
             builder->fsCodeAppendf("\tinnerOffset.y *= %s.w;\n", fsEdgeName);
             builder->fsCodeAppend("\tfloat dInner = length(innerOffset);\n");
 
@@ -64,13 +63,13 @@
         builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
     }
 
-    static inline EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) {
-        const GrEllipseEdgeEffect& effect = GetEffectFromStage<GrEllipseEdgeEffect>(stage);
+    static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+        const GrEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<GrEllipseEdgeEffect>();
 
-        return effect.isStroked() ? 0x1 : 0x0;
+        return ellipseEffect.isStroked() ? 0x1 : 0x0;
     }
 
-    virtual void setData(const GrGLUniformManager& uman, const GrEffectStage& stage) SK_OVERRIDE {
+    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {
     }
 
 private:
diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp
index 37e6eb4..80627aa 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/GrSimpleTextureEffect.cpp
@@ -15,41 +15,69 @@
 
 class GrGLSimpleTextureEffect : public GrGLEffect {
 public:
-    GrGLSimpleTextureEffect(const GrBackendEffectFactory& factory, const GrEffectRef&)
-    : INHERITED (factory) {}
+    GrGLSimpleTextureEffect(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect)
+    : INHERITED (factory) {
+        GrEffect::CoordsType coordsType =
+            drawEffect.castEffect<GrSimpleTextureEffect>().coordsType();
+        if (GrEffect::kCustom_CoordsType != coordsType) {
+            SkNEW_IN_TLAZY(&fEffectMatrix, GrGLEffectMatrix, (coordsType));
+        }
+    }
 
     virtual void emitCode(GrGLShaderBuilder* builder,
-                          const GrEffectStage&,
+                          const GrDrawEffect& drawEffect,
                           EffectKey key,
-                          const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray& samplers) SK_OVERRIDE {
-        const char* coordName;
-        GrSLType coordType = fEffectMatrix.emitCode(builder, key, vertexCoords, &coordName);
+        const GrSimpleTextureEffect& ste = drawEffect.castEffect<GrSimpleTextureEffect>();
+        const char* fsCoordName;
+        GrSLType fsCoordSLType;
+        if (GrEffect::kCustom_CoordsType == ste.coordsType()) {
+            GrAssert(ste.getMatrix().isIdentity());
+            GrAssert(1 == ste.numVertexAttribs());
+            fsCoordSLType = kVec2f_GrSLType;
+            const char* vsVaryingName;
+            builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsCoordName);
+            const char* attrName =
+                builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str();
+            builder->vsCodeAppendf("\t%s = %s;", vsVaryingName, attrName);
+        } else {
+            fsCoordSLType = fEffectMatrix.get()->emitCode(builder, key, &fsCoordName);
+        }
         builder->fsCodeAppendf("\t%s = ", outputColor);
         builder->appendTextureLookupAndModulate(GrGLShaderBuilder::kFragment_ShaderType,
                                                 inputColor,
                                                 samplers[0],
-                                                coordName,
-                                                coordType);
+                                                fsCoordName,
+                                                fsCoordSLType);
         builder->fsCodeAppend(";\n");
     }
 
-    static inline EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) {
-        const GrSimpleTextureEffect& ste = GetEffectFromStage<GrSimpleTextureEffect>(stage);
-        return GrGLEffectMatrix::GenKey(ste.getMatrix(),
-                                        stage.getCoordChangeMatrix(),
-                                        ste.texture(0));
+    static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+        const GrSimpleTextureEffect& ste = drawEffect.castEffect<GrSimpleTextureEffect>();
+        if (GrEffect::kCustom_CoordsType == ste.coordsType()) {
+            return 1 << GrGLEffectMatrix::kKeyBits;
+        } else {
+            return GrGLEffectMatrix::GenKey(ste.getMatrix(),
+                                            drawEffect,
+                                            ste.coordsType(),
+                                            ste.texture(0));
+        }
     }
 
-    virtual void setData(const GrGLUniformManager& uman, const GrEffectStage& stage) SK_OVERRIDE {
-        const GrSimpleTextureEffect& ste = GetEffectFromStage<GrSimpleTextureEffect>(stage);
-        fEffectMatrix.setData(uman, ste.getMatrix(), stage.getCoordChangeMatrix(), ste.texture(0));
+    virtual void setData(const GrGLUniformManager& uman,
+                         const GrDrawEffect& drawEffect) SK_OVERRIDE {
+        const GrSimpleTextureEffect& ste = drawEffect.castEffect<GrSimpleTextureEffect>();
+        if (GrEffect::kCustom_CoordsType == ste.coordsType()) {
+            GrAssert(ste.getMatrix().isIdentity());
+        } else {
+            fEffectMatrix.get()->setData(uman, ste.getMatrix(), drawEffect, ste.texture(0));
+        }
     }
 
 private:
-    GrGLEffectMatrix fEffectMatrix;
+    SkTLazy<GrGLEffectMatrix> fEffectMatrix;
     typedef GrGLEffect INHERITED;
 };
 
@@ -72,6 +100,28 @@
                                                GrTexture* textures[]) {
     int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
                                       GrEffectUnitTest::kAlphaTextureIdx;
-    const SkMatrix& matrix = GrEffectUnitTest::TestMatrix(random);
-    return GrSimpleTextureEffect::Create(textures[texIdx], matrix);
+    static const SkShader::TileMode kTileModes[] = {
+        SkShader::kClamp_TileMode,
+        SkShader::kRepeat_TileMode,
+        SkShader::kMirror_TileMode,
+    };
+    SkShader::TileMode tileModes[] = {
+        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
+        kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
+    };
+    GrTextureParams params(tileModes, random->nextBool());
+
+    static const CoordsType kCoordsTypes[] = {
+        kLocal_CoordsType,
+        kPosition_CoordsType,
+        kCustom_CoordsType
+    };
+    CoordsType coordsType = kCoordsTypes[random->nextULessThan(GR_ARRAY_COUNT(kCoordsTypes))];
+
+    if (kCustom_CoordsType == coordsType) {
+        return GrSimpleTextureEffect::CreateWithCustomCoords(textures[texIdx], params);
+    } else {
+        const SkMatrix& matrix = GrEffectUnitTest::TestMatrix(random);
+        return GrSimpleTextureEffect::Create(textures[texIdx], matrix);
+    }
 }
diff --git a/src/gpu/effects/GrSimpleTextureEffect.h b/src/gpu/effects/GrSimpleTextureEffect.h
index ffc05e5..661f40f 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.h
+++ b/src/gpu/effects/GrSimpleTextureEffect.h
@@ -14,25 +14,50 @@
 
 /**
  * The output color of this effect is a modulation of the input color and a sample from a texture.
- * The coord to sample the texture is determine by a matrix. It allows explicit specification of
- * the filtering and wrap modes (GrTextureParams).
+ * It allows explicit specification of the filtering and wrap modes (GrTextureParams). It can use
+ * local coords, positions, or a custom vertex attribute as input texture coords. The input coords
+ * can have a matrix applied in the VS in both the local and position cases but not with a custom
+ * attribute coords at this time. It will add a varying to input interpolate texture coords to the
+ * FS.
  */
 class GrSimpleTextureEffect : public GrSingleTextureEffect {
 public:
     /* unfiltered, clamp mode */
-    static GrEffectRef* Create(GrTexture* tex, const SkMatrix& matrix) {
-        AutoEffectUnref effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix)));
+    static GrEffectRef* Create(GrTexture* tex,
+                               const SkMatrix& matrix,
+                               CoordsType coordsType = kLocal_CoordsType) {
+        GrAssert(kLocal_CoordsType == coordsType || kPosition_CoordsType == coordsType);
+        AutoEffectUnref effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix, false, coordsType)));
         return CreateEffectRef(effect);
     }
 
     /* clamp mode */
-    static GrEffectRef* Create(GrTexture* tex, const SkMatrix& matrix, bool bilerp) {
-        AutoEffectUnref effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix, bilerp)));
+    static GrEffectRef* Create(GrTexture* tex,
+                               const SkMatrix& matrix,
+                               bool bilerp,
+                               CoordsType coordsType = kLocal_CoordsType) {
+        GrAssert(kLocal_CoordsType == coordsType || kPosition_CoordsType == coordsType);
+        AutoEffectUnref effect(
+            SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix, bilerp, coordsType)));
         return CreateEffectRef(effect);
     }
 
-    static GrEffectRef* Create(GrTexture* tex, const SkMatrix& matrix, const GrTextureParams& p) {
-        AutoEffectUnref effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix, p)));
+    static GrEffectRef* Create(GrTexture* tex,
+                               const SkMatrix& matrix,
+                               const GrTextureParams& p,
+                               CoordsType coordsType = kLocal_CoordsType) {
+        GrAssert(kLocal_CoordsType == coordsType || kPosition_CoordsType == coordsType);
+        AutoEffectUnref effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex, matrix, p, coordsType)));
+        return CreateEffectRef(effect);
+    }
+
+    /** Variant that requires the client to install a custom kVec2 vertex attribute that will be
+        the source of the coords. No matrix is allowed in this mode. */
+    static GrEffectRef* CreateWithCustomCoords(GrTexture* tex, const GrTextureParams& p) {
+        AutoEffectUnref effect(SkNEW_ARGS(GrSimpleTextureEffect, (tex,
+                                                                  SkMatrix::I(),
+                                                                  p,
+                                                                  kCustom_CoordsType)));
         return CreateEffectRef(effect);
     }
 
@@ -47,16 +72,28 @@
     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
 
 private:
-    GrSimpleTextureEffect(GrTexture* texture, const SkMatrix& matrix)
-        : GrSingleTextureEffect(texture, matrix) {}
-    GrSimpleTextureEffect(GrTexture* texture, const SkMatrix& matrix, bool bilerp)
-        : GrSingleTextureEffect(texture, matrix, bilerp) {}
-    GrSimpleTextureEffect(GrTexture* texture, const SkMatrix& matrix, const GrTextureParams& params)
-        : GrSingleTextureEffect(texture, matrix, params) {}
+    GrSimpleTextureEffect(GrTexture* texture,
+                          const SkMatrix& matrix,
+                          bool bilerp,
+                          CoordsType coordsType)
+        : GrSingleTextureEffect(texture, matrix, bilerp, coordsType) {
+        GrAssert(kLocal_CoordsType == coordsType || kPosition_CoordsType == coordsType);
+    }
+
+    GrSimpleTextureEffect(GrTexture* texture,
+                          const SkMatrix& matrix,
+                          const GrTextureParams& params,
+                          CoordsType coordsType)
+        : GrSingleTextureEffect(texture, matrix, params, coordsType) {
+        if (kCustom_CoordsType == coordsType) {
+            GrAssert(matrix.isIdentity());
+            this->addVertexAttrib(kVec2f_GrSLType);
+        }
+    }
 
     virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
         const GrSimpleTextureEffect& ste = CastEffect<GrSimpleTextureEffect>(other);
-        return this->hasSameTextureParamsAndMatrix(ste);
+        return this->hasSameTextureParamsMatrixAndCoordsType(ste);
     }
 
     GR_DECLARE_EFFECT_TEST;
diff --git a/src/gpu/effects/GrSingleTextureEffect.cpp b/src/gpu/effects/GrSingleTextureEffect.cpp
index 7183ba3..0c671f1 100644
--- a/src/gpu/effects/GrSingleTextureEffect.cpp
+++ b/src/gpu/effects/GrSingleTextureEffect.cpp
@@ -7,23 +7,32 @@
 
 #include "effects/GrSingleTextureEffect.h"
 
-GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, const SkMatrix& m)
+GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
+                                             const SkMatrix& m,
+                                             CoordsType coordsType)
     : fTextureAccess(texture)
-    , fMatrix(m) {
-    this->addTextureAccess(&fTextureAccess);
-}
-
-GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture, const SkMatrix& m, bool bilerp)
-    : fTextureAccess(texture, bilerp)
-    , fMatrix(m) {
+    , fMatrix(m)
+    , fCoordsType(coordsType) {
     this->addTextureAccess(&fTextureAccess);
 }
 
 GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
                                              const SkMatrix& m,
-                                             const GrTextureParams& params)
+                                             bool bilerp,
+                                             CoordsType coordsType)
+    : fTextureAccess(texture, bilerp)
+    , fMatrix(m)
+    , fCoordsType(coordsType) {
+    this->addTextureAccess(&fTextureAccess);
+}
+
+GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
+                                             const SkMatrix& m,
+                                             const GrTextureParams& params,
+                                             CoordsType coordsType)
     : fTextureAccess(texture, params)
-    , fMatrix(m) {
+    , fMatrix(m)
+    , fCoordsType(coordsType) {
     this->addTextureAccess(&fTextureAccess);
 }
 
diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h
index 4f25ddb..82037cf 100644
--- a/src/gpu/effects/GrSingleTextureEffect.h
+++ b/src/gpu/effects/GrSingleTextureEffect.h
@@ -14,7 +14,8 @@
 class GrTexture;
 
 /**
- * A base class for effects that draw a single texture with a texture matrix.
+ * A base class for effects that draw a single texture with a texture matrix. This effect has no
+ * backend implementations. One must be provided by the subclass.
  */
 class GrSingleTextureEffect : public GrEffect {
 public:
@@ -22,20 +23,29 @@
 
     const SkMatrix& getMatrix() const { return fMatrix; }
 
+    /** Indicates whether the matrix operates on local coords or positions */
+    CoordsType coordsType() const { return fCoordsType; }
+
 protected:
-    GrSingleTextureEffect(GrTexture*, const SkMatrix&); /* unfiltered, clamp mode */
-    GrSingleTextureEffect(GrTexture*, const SkMatrix&, bool bilerp); /* clamp mode */
-    GrSingleTextureEffect(GrTexture*, const SkMatrix&, const GrTextureParams&);
+    /** unfiltered, clamp mode */
+    GrSingleTextureEffect(GrTexture*, const SkMatrix&, CoordsType = kLocal_CoordsType);
+    /** clamp mode */
+    GrSingleTextureEffect(GrTexture*, const SkMatrix&, bool bilerp, CoordsType = kLocal_CoordsType);
+    GrSingleTextureEffect(GrTexture*,
+                          const SkMatrix&,
+                          const GrTextureParams&,
+                          CoordsType = kLocal_CoordsType);
 
     /**
      * Helper for subclass onIsEqual() functions.
      */
-    bool hasSameTextureParamsAndMatrix(const GrSingleTextureEffect& other) const {
+    bool hasSameTextureParamsMatrixAndCoordsType(const GrSingleTextureEffect& other) const {
         const GrTextureAccess& otherAccess = other.fTextureAccess;
         // We don't have to check the accesses' swizzles because they are inferred from the texture.
         return fTextureAccess.getTexture() == otherAccess.getTexture() &&
                fTextureAccess.getParams() == otherAccess.getParams() &&
-               this->getMatrix().cheapEqualTo(other.getMatrix());
+               this->getMatrix().cheapEqualTo(other.getMatrix()) &&
+               fCoordsType == other.fCoordsType;
     }
 
     /**
@@ -55,6 +65,7 @@
 private:
     GrTextureAccess fTextureAccess;
     SkMatrix        fMatrix;
+    CoordsType      fCoordsType;
 
     typedef GrEffect INHERITED;
 };
diff --git a/src/gpu/effects/GrTextureDomainEffect.cpp b/src/gpu/effects/GrTextureDomainEffect.cpp
index e54af25..b1fd3ed 100644
--- a/src/gpu/effects/GrTextureDomainEffect.cpp
+++ b/src/gpu/effects/GrTextureDomainEffect.cpp
@@ -14,19 +14,18 @@
 
 class GrGLTextureDomainEffect : public GrGLEffect {
 public:
-    GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrEffectRef&);
+    GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
     virtual void emitCode(GrGLShaderBuilder*,
-                          const GrEffectStage&,
+                          const GrDrawEffect&,
                           EffectKey,
-                          const char* vertexCoords,
                           const char* outputColor,
                           const char* inputColor,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
+    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
 
-    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
+    static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
 
 private:
     GrGLUniformManager::UniformHandle fNameUni;
@@ -37,27 +36,27 @@
 };
 
 GrGLTextureDomainEffect::GrGLTextureDomainEffect(const GrBackendEffectFactory& factory,
-                                                 const GrEffectRef&)
+                                                 const GrDrawEffect& drawEffect)
     : INHERITED(factory)
-    , fNameUni(GrGLUniformManager::kInvalidUniformHandle) {
+    , fNameUni(GrGLUniformManager::kInvalidUniformHandle)
+    , fEffectMatrix(drawEffect.castEffect<GrTextureDomainEffect>().coordsType()) {
     fPrevDomain[0] = SK_FloatNaN;
 }
 
 void GrGLTextureDomainEffect::emitCode(GrGLShaderBuilder* builder,
-                                       const GrEffectStage& stage,
+                                       const GrDrawEffect& drawEffect,
                                        EffectKey key,
-                                       const char* vertexCoords,
                                        const char* outputColor,
                                        const char* inputColor,
                                        const TextureSamplerArray& samplers) {
-    const GrTextureDomainEffect& effect = GetEffectFromStage<GrTextureDomainEffect>(stage);
+    const GrTextureDomainEffect& texDom = drawEffect.castEffect<GrTextureDomainEffect>();
 
     const char* coords;
-    fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, vertexCoords, &coords);
+    fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords);
     const char* domain;
     fNameUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
                                     kVec4f_GrSLType, "TexDom", &domain);
-    if (GrTextureDomainEffect::kClamp_WrapMode == effect.wrapMode()) {
+    if (GrTextureDomainEffect::kClamp_WrapMode == texDom.wrapMode()) {
 
         builder->fsCodeAppendf("\tvec2 clampCoord = clamp(%s, %s.xy, %s.zw);\n",
                                 coords, domain, domain);
@@ -69,7 +68,7 @@
                                                 "clampCoord");
         builder->fsCodeAppend(";\n");
     } else {
-        GrAssert(GrTextureDomainEffect::kDecal_WrapMode == effect.wrapMode());
+        GrAssert(GrTextureDomainEffect::kDecal_WrapMode == texDom.wrapMode());
 
         if (kImagination_GrGLVendor == builder->ctxInfo().vendor()) {
             // On the NexusS and GalaxyNexus, the other path (with the 'any'
@@ -106,9 +105,10 @@
     }
 }
 
-void GrGLTextureDomainEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
-    const GrTextureDomainEffect& effect = GetEffectFromStage<GrTextureDomainEffect>(stage);
-    const GrRect& domain = effect.domain();
+void GrGLTextureDomainEffect::setData(const GrGLUniformManager& uman,
+                                      const GrDrawEffect& drawEffect) {
+    const GrTextureDomainEffect& texDom = drawEffect.castEffect<GrTextureDomainEffect>();
+    const GrRect& domain = texDom.domain();
 
     float values[4] = {
         SkScalarToFloat(domain.left()),
@@ -117,7 +117,7 @@
         SkScalarToFloat(domain.bottom())
     };
     // vertical flip if necessary
-    if (kBottomLeft_GrSurfaceOrigin == effect.texture(0)->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == texDom.texture(0)->origin()) {
         values[1] = 1.0f - values[1];
         values[3] = 1.0f - values[3];
         // The top and bottom were just flipped, so correct the ordering
@@ -128,18 +128,20 @@
         uman.set4fv(fNameUni, 0, 1, values);
     }
     fEffectMatrix.setData(uman,
-                          effect.getMatrix(),
-                          stage.getCoordChangeMatrix(),
-                          effect.texture(0));
+                          texDom.getMatrix(),
+                          drawEffect,
+                          texDom.texture(0));
 }
 
-GrGLEffect::EffectKey GrGLTextureDomainEffect::GenKey(const GrEffectStage& stage, const GrGLCaps&) {
-    const GrTextureDomainEffect& effect = GetEffectFromStage<GrTextureDomainEffect>(stage);
-    EffectKey key = effect.wrapMode();
+GrGLEffect::EffectKey GrGLTextureDomainEffect::GenKey(const GrDrawEffect& drawEffect,
+                                                      const GrGLCaps&) {
+    const GrTextureDomainEffect& texDom = drawEffect.castEffect<GrTextureDomainEffect>();
+    EffectKey key = texDom.wrapMode();
     key <<= GrGLEffectMatrix::kKeyBits;
-    EffectKey matrixKey = GrGLEffectMatrix::GenKey(effect.getMatrix(),
-                                                   stage.getCoordChangeMatrix(),
-                                                   effect.texture(0));
+    EffectKey matrixKey = GrGLEffectMatrix::GenKey(texDom.getMatrix(),
+                                                   drawEffect,
+                                                   texDom.coordsType(),
+                                                   texDom.texture(0));
     return key | matrixKey;
 }
 
@@ -150,7 +152,8 @@
                                            const SkMatrix& matrix,
                                            const GrRect& domain,
                                            WrapMode wrapMode,
-                                           bool bilerp) {
+                                           bool bilerp,
+                                           CoordsType coordsType) {
     static const SkRect kFullRect = {0, 0, SK_Scalar1, SK_Scalar1};
     if (kClamp_WrapMode == wrapMode && domain.contains(kFullRect)) {
         return GrSimpleTextureEffect::Create(texture, matrix, bilerp);
@@ -172,7 +175,8 @@
                                                                   matrix,
                                                                   clippedDomain,
                                                                   wrapMode,
-                                                                  bilerp)));
+                                                                  bilerp,
+                                                                  coordsType)));
         return CreateEffectRef(effect);
 
     }
@@ -182,8 +186,9 @@
                                              const SkMatrix& matrix,
                                              const GrRect& domain,
                                              WrapMode wrapMode,
-                                             bool bilerp)
-    : GrSingleTextureEffect(texture, matrix, bilerp)
+                                             bool bilerp,
+                                             CoordsType coordsType)
+    : GrSingleTextureEffect(texture, matrix, bilerp, coordsType)
     , fWrapMode(wrapMode)
     , fTextureDomain(domain) {
 }
@@ -198,7 +203,8 @@
 
 bool GrTextureDomainEffect::onIsEqual(const GrEffect& sBase) const {
     const GrTextureDomainEffect& s = CastEffect<GrTextureDomainEffect>(sBase);
-    return this->hasSameTextureParamsAndMatrix(s) && this->fTextureDomain == s.fTextureDomain;
+    return this->hasSameTextureParamsMatrixAndCoordsType(s) &&
+           this->fTextureDomain == s.fTextureDomain;
 }
 
 void GrTextureDomainEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
@@ -225,5 +231,12 @@
     domain.fBottom = random->nextRangeScalar(domain.fTop, SK_Scalar1);
     WrapMode wrapMode = random->nextBool() ? kClamp_WrapMode : kDecal_WrapMode;
     const SkMatrix& matrix = GrEffectUnitTest::TestMatrix(random);
-    return GrTextureDomainEffect::Create(textures[texIdx], matrix, domain, wrapMode);
+    bool bilerp = random->nextBool();
+    CoordsType coords = random->nextBool() ? kLocal_CoordsType : kPosition_CoordsType;
+    return GrTextureDomainEffect::Create(textures[texIdx],
+                                         matrix,
+                                         domain,
+                                         wrapMode,
+                                         bilerp,
+                                         coords);
 }
diff --git a/src/gpu/effects/GrTextureDomainEffect.h b/src/gpu/effects/GrTextureDomainEffect.h
index b7f665c..8b1f2b6 100644
--- a/src/gpu/effects/GrTextureDomainEffect.h
+++ b/src/gpu/effects/GrTextureDomainEffect.h
@@ -38,7 +38,8 @@
                                const SkMatrix&,
                                const SkRect& domain,
                                WrapMode,
-                               bool bilerp = false);
+                               bool bilerp,
+                               CoordsType = kLocal_CoordsType);
 
     virtual ~GrTextureDomainEffect();
 
@@ -75,7 +76,8 @@
                           const SkMatrix&,
                           const GrRect& domain,
                           WrapMode,
-                          bool bilerp);
+                          bool bilerp,
+                          CoordsType type);
 
     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;