Switch atlas clients over to using absolute texture coordinates (take 2)

This is a prerequisite for being able to resize the atlas with impunity.

Change-Id: Iccc9c7ced43f38a7d8483a7bd12a458d59a3453a
Reviewed-on: https://skia-review.googlesource.com/38362
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 8dd2fa6..87b47e4 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -23,11 +23,12 @@
 class GrGLDistanceFieldA8TextGeoProc : public GrGLSLGeometryProcessor {
 public:
     GrGLDistanceFieldA8TextGeoProc()
-        : fViewMatrix(SkMatrix::InvalidMatrix())
-#ifdef SK_GAMMA_APPLY_TO_A8
-        , fDistanceAdjust(-1.0f)
-#endif
-        {}
+            : fViewMatrix(SkMatrix::InvalidMatrix())
+    #ifdef SK_GAMMA_APPLY_TO_A8
+            , fDistanceAdjust(-1.0f)
+    #endif
+            , fAtlasSize({0,0}) {
+    }
 
     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
         const GrDistanceFieldA8TextGeoProc& dfTexEffect =
@@ -41,6 +42,12 @@
         // emit attributes
         varyingHandler->emitAttributes(dfTexEffect);
 
+        const char* atlasSizeInvName;
+        fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
+                                                          kVec2f_GrSLType,
+                                                          kHigh_GrSLPrecision,
+                                                          "AtlasSizeInv",
+                                                          &atlasSizeInvName);
 #ifdef SK_GAMMA_APPLY_TO_A8
         // adjust based on gamma
         const char* distanceAdjustUniName = nullptr;
@@ -70,8 +77,17 @@
                              args.fFPCoordTransformHandler);
 
         // add varyings
-        GrGLSLVertToFrag recipScale(kFloat_GrSLType);
         GrGLSLVertToFrag uv(kVec2f_GrSLType);
+        varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = %s * %s;", uv.vsOut(),
+                                 dfTexEffect.inTextureCoords()->fName,
+                                 atlasSizeInvName);
+
+        GrGLSLVertToFrag st(kVec2f_GrSLType);
+        varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = %s;", st.vsOut(),
+                                 dfTexEffect.inTextureCoords()->fName);
+
         bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
                               kUniformScale_DistanceFieldEffectMask;
         bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
@@ -79,29 +95,14 @@
             SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
         bool isAliased =
             SkToBool(dfTexEffect.getFlags() & kAliased_DistanceFieldEffectFlag);
-        varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
-        vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName);
-
-        // compute numbers to be hardcoded to convert texture coordinates from float to int
-        SkASSERT(dfTexEffect.numTextureSamplers() == 1);
-        GrTexture* atlas = dfTexEffect.textureSampler(0).peekTexture();
-        SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
-
-        GrGLSLVertToFrag st(kVec2f_GrSLType);
-        varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
-        vertBuilder->codeAppendf("%s = float2(%d, %d) * %s;", st.vsOut(),
-                                 atlas->width(), atlas->height(),
-                                 dfTexEffect.inTextureCoords()->fName);
 
         // Use highp to work around aliasing issues
         fragBuilder->codeAppendf("highp float2 uv = %s;\n", uv.fsIn());
 
-        fragBuilder->codeAppend("\tfloat texColor = ");
-        fragBuilder->appendTextureLookup(args.fTexSamplers[0],
-                                         "uv",
-                                         kVec2f_GrSLType);
-        fragBuilder->codeAppend(".r;\n");
-        fragBuilder->codeAppend("\tfloat distance = "
+        fragBuilder->codeAppend("float texColor = ");
+        fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv", kVec2f_GrSLType);
+        fragBuilder->codeAppend(".r;");
+        fragBuilder->codeAppend("float distance = "
                        SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
 #ifdef SK_GAMMA_APPLY_TO_A8
         // adjust width based on gamma
@@ -177,15 +178,15 @@
 
     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
                  FPCoordTransformIter&& transformIter) override {
+        const GrDistanceFieldA8TextGeoProc& dfa8gp = proc.cast<GrDistanceFieldA8TextGeoProc>();
+
 #ifdef SK_GAMMA_APPLY_TO_A8
-        const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>();
-        float distanceAdjust = dfTexEffect.getDistanceAdjust();
+        float distanceAdjust = dfa8gp.getDistanceAdjust();
         if (distanceAdjust != fDistanceAdjust) {
-            pdman.set1f(fDistanceAdjustUni, distanceAdjust);
             fDistanceAdjust = distanceAdjust;
+            pdman.set1f(fDistanceAdjustUni, distanceAdjust);
         }
 #endif
-        const GrDistanceFieldA8TextGeoProc& dfa8gp = proc.cast<GrDistanceFieldA8TextGeoProc>();
 
         if (!dfa8gp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfa8gp.viewMatrix())) {
             fViewMatrix = dfa8gp.viewMatrix();
@@ -193,6 +194,16 @@
             GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
             pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
         }
+
+        SkASSERT(dfa8gp.numTextureSamplers() == 1);
+        GrTexture* atlas = dfa8gp.textureSampler(0).peekTexture();
+        SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
+
+        if (fAtlasSize.fWidth != atlas->width() || fAtlasSize.fHeight != atlas->height()) {
+            fAtlasSize.set(atlas->width(), atlas->height());
+            pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
+        }
+
         this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
     }
 
@@ -203,14 +214,6 @@
         uint32_t key = dfTexEffect.getFlags();
         key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
         b->add32(key);
-
-        // Currently we hardcode numbers to convert atlas coordinates to normalized floating point
-        SkASSERT(gp.numTextureSamplers() == 1);
-        GrTextureProxy* atlas = gp.textureSampler(0).proxy();
-        if (atlas) {
-            b->add32(atlas->width());
-            b->add32(atlas->height());
-        }
     }
 
 private:
@@ -220,6 +223,8 @@
     float         fDistanceAdjust;
     UniformHandle fDistanceAdjustUni;
 #endif
+    SkISize       fAtlasSize;
+    UniformHandle fAtlasSizeInvUniform;
 
     typedef GrGLSLGeometryProcessor INHERITED;
 };
@@ -249,7 +254,7 @@
     fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
                                          kHigh_GrSLPrecision);
     fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
-    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType,
+    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_uint_GrVertexAttribType,
                                               kHigh_GrSLPrecision);
     this->addTextureSampler(&fTextureSampler);
 }
@@ -308,8 +313,9 @@
 class GrGLDistanceFieldPathGeoProc : public GrGLSLGeometryProcessor {
 public:
     GrGLDistanceFieldPathGeoProc()
-        : fViewMatrix(SkMatrix::InvalidMatrix())
-        , fTextureSize(SkISize::Make(-1, -1)) {}
+            : fViewMatrix(SkMatrix::InvalidMatrix())
+            , fAtlasSize({0,0}) {
+    }
 
     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
         const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>();
@@ -323,12 +329,26 @@
         // emit attributes
         varyingHandler->emitAttributes(dfTexEffect);
 
-        GrGLSLVertToFrag v(kVec2f_GrSLType);
-        varyingHandler->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
+        const char* atlasSizeInvName;
+        fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
+                                                          kVec2f_GrSLType,
+                                                          kHigh_GrSLPrecision,
+                                                          "AtlasSizeInv",
+                                                          &atlasSizeInvName);
+
+        GrGLSLVertToFrag uv(kVec2f_GrSLType);
+        varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = %s * %s;", uv.vsOut(),
+                                 dfTexEffect.inTextureCoords()->fName,
+                                 atlasSizeInvName);
+
+        GrGLSLVertToFrag st(kVec2f_GrSLType);
+        varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = %s;", st.vsOut(),
+                                 dfTexEffect.inTextureCoords()->fName);
 
         // setup pass through color
         varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
-        vertBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
 
         // Setup position
         this->writeOutputPosition(vertBuilder,
@@ -346,23 +366,15 @@
                              dfTexEffect.inPosition()->fName,
                              args.fFPCoordTransformHandler);
 
-        const char* textureSizeUniName = nullptr;
-        fTextureSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                     kVec2f_GrSLType, kDefault_GrSLPrecision,
-                                                     "TextureSize", &textureSizeUniName);
-
         // Use highp to work around aliasing issues
-        fragBuilder->codeAppendf("highp float2 uv = %s;", v.fsIn());
+        fragBuilder->codeAppendf("highp float2 uv = %s;", uv.fsIn());
 
         fragBuilder->codeAppend("float texColor = ");
-        fragBuilder->appendTextureLookup(args.fTexSamplers[0],
-                                         "uv",
-                                         kVec2f_GrSLType);
+        fragBuilder->appendTextureLookup(args.fTexSamplers[0], "uv", kVec2f_GrSLType);
         fragBuilder->codeAppend(".r;");
         fragBuilder->codeAppend("float distance = "
             SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
 
-        fragBuilder->codeAppendf("highp float2 st = uv*%s;", textureSizeUniName);
         fragBuilder->codeAppend("float afwidth;");
         bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
                                kUniformScale_DistanceFieldEffectMask;
@@ -376,10 +388,12 @@
 
             // this gives us a smooth step across approximately one fragment
 #ifdef SK_VULKAN
-            fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));");
+            fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(%s.x));",
+                                     st.fsIn());
 #else
             // We use the y gradient because there is a bug in the Mali 400 in the x direction.
-            fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(st.y));");
+            fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(%s.y));",
+                                     st.fsIn());
 #endif
         } else if (isSimilarity) {
             // For similarity transform, we adjust the effect of the transformation on the distance
@@ -388,10 +402,10 @@
 
             // this gives us a smooth step across approximately one fragment
 #ifdef SK_VULKAN
-            fragBuilder->codeAppend("float st_grad_len = length(dFdx(st));");
+            fragBuilder->codeAppendf("float st_grad_len = length(dFdx(%s));", st.fsIn());
 #else
             // We use the y gradient because there is a bug in the Mali 400 in the x direction.
-            fragBuilder->codeAppend("float st_grad_len = length(dFdy(st));");
+            fragBuilder->codeAppendf("float st_grad_len = length(dFdy(%s));", st.fsIn());
 #endif
             fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*st_grad_len);");
         } else {
@@ -408,8 +422,8 @@
             fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
             fragBuilder->codeAppend("}");
 
-            fragBuilder->codeAppend("float2 Jdx = dFdx(st);");
-            fragBuilder->codeAppend("float2 Jdy = dFdy(st);");
+            fragBuilder->codeAppendf("float2 Jdx = dFdx(%s);", st.fsIn());
+            fragBuilder->codeAppendf("float2 Jdy = dFdy(%s);", st.fsIn());
             fragBuilder->codeAppend("float2 grad = float2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
             fragBuilder->codeAppend("                 dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
 
@@ -431,17 +445,6 @@
 
     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
                  FPCoordTransformIter&& transformIter) override {
-        SkASSERT(fTextureSizeUni.isValid());
-
-        GrTexture* texture = proc.textureSampler(0).peekTexture();
-
-        if (texture->width() != fTextureSize.width() ||
-            texture->height() != fTextureSize.height()) {
-            fTextureSize = SkISize::Make(texture->width(), texture->height());
-            pdman.set2f(fTextureSizeUni,
-                        SkIntToScalar(fTextureSize.width()),
-                        SkIntToScalar(fTextureSize.height()));
-        }
 
         const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>();
 
@@ -451,6 +454,16 @@
             GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
             pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
         }
+
+        SkASSERT(dfpgp.numTextureSamplers() == 1);
+        GrTexture* atlas = dfpgp.textureSampler(0).peekTexture();
+        SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
+
+        if (fAtlasSize.fWidth != atlas->width() || fAtlasSize.fHeight != atlas->height()) {
+            fAtlasSize.set(atlas->width(), atlas->height());
+            pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
+        }
+
         this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
     }
 
@@ -465,10 +478,11 @@
     }
 
 private:
-    UniformHandle fTextureSizeUni;
-    UniformHandle fViewMatrixUniform;
     SkMatrix      fViewMatrix;
-    SkISize       fTextureSize;
+    UniformHandle fViewMatrixUniform;
+
+    SkISize       fAtlasSize;
+    UniformHandle fAtlasSizeInvUniform;
 
     typedef GrGLSLGeometryProcessor INHERITED;
 };
@@ -491,7 +505,8 @@
     fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
                                          kHigh_GrSLPrecision);
     fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
-    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType);
+    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_uint_GrVertexAttribType,
+                                              kHigh_GrSLPrecision);
     this->addTextureSampler(&fTextureSampler);
 }
 
@@ -547,7 +562,8 @@
 class GrGLDistanceFieldLCDTextGeoProc : public GrGLSLGeometryProcessor {
 public:
     GrGLDistanceFieldLCDTextGeoProc()
-        : fViewMatrix(SkMatrix::InvalidMatrix()) {
+            : fViewMatrix(SkMatrix::InvalidMatrix())
+            , fAtlasSize({0,0}) {
         fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
     }
 
@@ -562,6 +578,13 @@
         // emit attributes
         varyingHandler->emitAttributes(dfTexEffect);
 
+        const char* atlasSizeInvName;
+        fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
+                                                          kVec2f_GrSLType,
+                                                          kHigh_GrSLPrecision,
+                                                          "AtlasSizeInv",
+                                                          &atlasSizeInvName);
+
         GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
 
         // setup pass through color
@@ -584,39 +607,36 @@
                              args.fFPCoordTransformHandler);
 
         // set up varyings
+        GrGLSLVertToFrag uv(kVec2f_GrSLType);
+        varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = %s * %s;", uv.vsOut(),
+                                 dfTexEffect.inTextureCoords()->fName,
+                                 atlasSizeInvName);
+
+        GrGLSLVertToFrag st(kVec2f_GrSLType);
+        varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = %s;", st.vsOut(),
+                                 dfTexEffect.inTextureCoords()->fName);
+
+        GrGLSLVertToFrag delta(kFloat_GrSLType);
+        varyingHandler->addVarying("Delta", &delta, kHigh_GrSLPrecision);
+        if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
+            vertBuilder->codeAppendf("%s = -%s.x/3.0;", delta.vsOut(), atlasSizeInvName);
+        } else {
+            vertBuilder->codeAppendf("%s = %s.x/3.0;", delta.vsOut(), atlasSizeInvName);
+        }
+
+        // add frag shader code
         bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
                               kUniformScale_DistanceFieldEffectMask;
         bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
         bool isGammaCorrect =
             SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag);
-        GrGLSLVertToFrag recipScale(kFloat_GrSLType);
-        GrGLSLVertToFrag uv(kVec2f_GrSLType);
-        varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
-        vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName);
-
-        // compute numbers to be hardcoded to convert texture coordinates from float to int
-        SkASSERT(dfTexEffect.numTextureSamplers() == 1);
-        GrTexture* atlas = dfTexEffect.textureSampler(0).peekTexture();
-        SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
-
-        GrGLSLVertToFrag st(kVec2f_GrSLType);
-        varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
-        vertBuilder->codeAppendf("%s = float2(%d, %d) * %s;", st.vsOut(),
-                                 atlas->width(), atlas->height(),
-                                 dfTexEffect.inTextureCoords()->fName);
-
-        // add frag shader code
 
         // create LCD offset adjusted by inverse of transform
         // Use highp to work around aliasing issues
         fragBuilder->codeAppendf("highp float2 uv = %s;\n", uv.fsIn());
 
-        SkScalar lcdDelta = 1.0f / (3.0f * atlas->width());
-        if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) {
-            fragBuilder->codeAppendf("highp float delta = -%.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta);
-        } else {
-            fragBuilder->codeAppendf("highp float delta = %.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta);
-        }
         if (isUniformScale) {
 #ifdef SK_VULKAN
             fragBuilder->codeAppendf("float st_grad_len = abs(dFdx(%s.x));", st.fsIn());
@@ -624,18 +644,19 @@
             // We use the y gradient because there is a bug in the Mali 400 in the x direction.
             fragBuilder->codeAppendf("float st_grad_len = abs(dFdy(%s.y));", st.fsIn());
 #endif
-            fragBuilder->codeAppend("float2 offset = float2(st_grad_len*delta, 0.0);");
+            fragBuilder->codeAppendf("float2 offset = float2(st_grad_len*%s, 0.0);", delta.fsIn());
         } else if (isSimilarity) {
             // For a similarity matrix with rotation, the gradient will not be aligned
             // with the texel coordinate axes, so we need to calculate it.
 #ifdef SK_VULKAN
             fragBuilder->codeAppendf("float2 st_grad = dFdx(%s);", st.fsIn());
-            fragBuilder->codeAppend("float2 offset = delta*st_grad;");
+            fragBuilder->codeAppendf("float2 offset = %s*st_grad;", delta.fsIn());
 #else
             // We use dFdy because of a Mali 400 bug, and rotate -90 degrees to
             // get the gradient in the x direction.
             fragBuilder->codeAppendf("float2 st_grad = dFdy(%s);", st.fsIn());
-            fragBuilder->codeAppend("float2 offset = delta*float2(st_grad.y, -st_grad.x);");
+            fragBuilder->codeAppendf("float2 offset = %s*float2(st_grad.y, -st_grad.x);",
+                                     delta.fsIn());
 #endif
             fragBuilder->codeAppend("float st_grad_len = length(st_grad);");
         } else {
@@ -643,7 +664,7 @@
 
             fragBuilder->codeAppend("float2 Jdx = dFdx(st);");
             fragBuilder->codeAppend("float2 Jdy = dFdy(st);");
-            fragBuilder->codeAppend("float2 offset = delta*Jdx;");
+            fragBuilder->codeAppendf("float2 offset = %s*Jdx;", delta.fsIn());
         }
 
         // green is distance to uv center
@@ -742,6 +763,16 @@
             GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
             pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
         }
+
+        SkASSERT(dflcd.numTextureSamplers() == 1);
+        GrTexture* atlas = dflcd.textureSampler(0).peekTexture();
+        SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
+
+        if (fAtlasSize.fWidth != atlas->width() || fAtlasSize.fHeight != atlas->height()) {
+            fAtlasSize.set(atlas->width(), atlas->height());
+            pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlas->width(), 1.0f / atlas->height());
+        }
+
         this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
     }
 
@@ -753,22 +784,17 @@
         uint32_t key = dfTexEffect.getFlags();
         key |= ComputePosKey(dfTexEffect.viewMatrix()) << 16;
         b->add32(key);
-
-        // Currently we hardcode numbers to convert atlas coordinates to normalized floating point
-        SkASSERT(gp.numTextureSamplers() == 1);
-        GrTextureProxy* atlas = gp.textureSampler(0).proxy();
-        if (atlas) {
-            b->add32(atlas->width());
-            b->add32(atlas->height());
-        }
     }
 
 private:
-    SkMatrix                                     fViewMatrix;
-    UniformHandle                                fViewMatrixUniform;
-    UniformHandle                                fColorUniform;
+    SkMatrix                                      fViewMatrix;
+    UniformHandle                                 fViewMatrixUniform;
+
     GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust;
-    UniformHandle                                fDistanceAdjustUni;
+    UniformHandle                                 fDistanceAdjustUni;
+
+    SkISize                                       fAtlasSize;
+    UniformHandle                                 fAtlasSizeInvUniform;
 
     typedef GrGLSLGeometryProcessor INHERITED;
 };
@@ -791,7 +817,7 @@
     fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
                                          kHigh_GrSLPrecision);
     fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
-    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType,
+    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_uint_GrVertexAttribType,
                                               kHigh_GrSLPrecision);
     this->addTextureSampler(&fTextureSampler);
 }