Some improvements to reduce the number of pixels touched in generating alpha clip masks
Review URL: https://codereview.appspot.com/6828043

git-svn-id: http://skia.googlecode.com/svn/trunk@6329 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/effects/GrTextureDomainEffect.cpp b/src/gpu/effects/GrTextureDomainEffect.cpp
index 823b072..e500fad 100644
--- a/src/gpu/effects/GrTextureDomainEffect.cpp
+++ b/src/gpu/effects/GrTextureDomainEffect.cpp
@@ -43,28 +43,40 @@
 }
 
 void GrGLTextureDomainEffect::emitCode(GrGLShaderBuilder* builder,
-                                       const GrEffectStage&,
+                                       const GrEffectStage& stage,
                                        EffectKey key,
                                        const char* vertexCoords,
                                        const char* outputColor,
                                        const char* inputColor,
                                        const TextureSamplerArray& samplers) {
+    const GrTextureDomainEffect& effect =
+        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
+
     const char* coords;
     fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, vertexCoords, &coords);
+    const char* domain;
     fNameUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
-                                   kVec4f_GrSLType, "TexDom");
+                                    kVec4f_GrSLType, "TexDom", &domain);
+    if (GrTextureDomainEffect::kClamp_WrapMode == effect.wrapMode()) {
 
-    builder->fFSCode.appendf("\tvec2 clampCoord = clamp(%s, %s.xy, %s.zw);\n",
-                           coords,
-                           builder->getUniformCStr(fNameUni),
-                           builder->getUniformCStr(fNameUni));
+        builder->fFSCode.appendf("\tvec2 clampCoord = clamp(%s, %s.xy, %s.zw);\n",
+                               coords, domain, domain);
 
-    builder->fFSCode.appendf("\t%s = ", outputColor);
-    builder->appendTextureLookupAndModulate(&builder->fFSCode,
-                                            inputColor,
-                                            samplers[0],
-                                            "clampCoord");
-    builder->fFSCode.append(";\n");
+        builder->fFSCode.appendf("\t%s = ", outputColor);
+        builder->appendTextureLookupAndModulate(&builder->fFSCode,
+                                                inputColor,
+                                                samplers[0],
+                                                "clampCoord");
+        builder->fFSCode.append(";\n");
+    } else {
+        GrAssert(GrTextureDomainEffect::kDecal_WrapMode == effect.wrapMode());
+        builder->fFSCode.append("\tbvec4 outside;\n");
+        builder->fFSCode.appendf("\toutside.xy = lessThan(%s, %s.xy);\n", coords, domain);
+        builder->fFSCode.appendf("\toutside.zw = greaterThan(%s, %s.zw);\n", coords, domain);
+        builder->fFSCode.appendf("\t%s = any(outside) ? vec4(0.0, 0.0, 0.0, 0.0) : ", outputColor);
+        builder->appendTextureLookupAndModulate(&builder->fFSCode, inputColor, samplers[0], coords);
+        builder->fFSCode.append(";\n");
+    }
 }
 
 void GrGLTextureDomainEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
@@ -98,21 +110,41 @@
 GrGLEffect::EffectKey GrGLTextureDomainEffect::GenKey(const GrEffectStage& stage, const GrGLCaps&) {
     const GrTextureDomainEffect& effect =
         static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
-    return GrGLEffectMatrix::GenKey(effect.getMatrix(), stage.getCoordChangeMatrix(), effect.texture(0));
+    EffectKey key = effect.wrapMode();
+    key <<= GrGLEffectMatrix::kKeyBits;
+    EffectKey matrixKey = GrGLEffectMatrix::GenKey(effect.getMatrix(),
+                                                   stage.getCoordChangeMatrix(),
+                                                   effect.texture(0));
+    return key | matrixKey;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture, const GrRect& domain)
-    : GrSingleTextureEffect(texture)
-    , fTextureDomain(domain) {
+GrEffect* GrTextureDomainEffect::Create(GrTexture* texture,
+                                        const SkMatrix& matrix,
+                                        const GrRect& domain,
+                                        WrapMode wrapMode,
+                                        bool bilerp) {
+    static const SkRect kFullRect = {0, 0, SK_Scalar1, SK_Scalar1};
+    if (kClamp_WrapMode == wrapMode && domain.contains(kFullRect)) {
+        return SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix, bilerp));
+    } else {
+        SkRect clippedDomain;
+        // We don't currently handle domains that are empty or don't intersect the texture.
+        SkAssertResult(clippedDomain.intersect(kFullRect, domain));
+        return SkNEW_ARGS(GrTextureDomainEffect,
+                          (texture, matrix, clippedDomain, wrapMode, bilerp));
+    }
 }
 
 GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture,
+                                             const SkMatrix& matrix,
                                              const GrRect& domain,
-                                             const GrTextureParams& params)
-    : GrSingleTextureEffect(texture, params)
+                                             WrapMode wrapMode,
+                                             bool bilerp)
+    : GrSingleTextureEffect(texture, matrix, bilerp)
+    , fWrapMode(wrapMode)
     , fTextureDomain(domain) {
 }
 
@@ -143,5 +175,7 @@
     domain.fRight = random->nextRangeScalar(domain.fLeft, SK_Scalar1);
     domain.fTop = random->nextUScalar1();
     domain.fBottom = random->nextRangeScalar(domain.fTop, SK_Scalar1);
-    return SkNEW_ARGS(GrTextureDomainEffect, (textures[texIdx], domain));
+    WrapMode wrapMode = random->nextBool() ? kClamp_WrapMode : kDecal_WrapMode;
+    const SkMatrix& matrix = GrEffectUnitTest::TestMatrix(random);
+    return GrTextureDomainEffect::Create(textures[texIdx], matrix, domain, wrapMode);
 }