Recommit r5350 with fix for image failures (which affected GLs that don't support ARB_texture_swizzle).



git-svn-id: http://skia.googlecode.com/svn/trunk@5353 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index fbf5a40..318c03e 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -23,37 +23,39 @@
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE {
-        builder->fFSCode.append("\tvec4 tempColor;\n");
-        builder->emitTextureLookupAndModulate("tempColor", samplerName);
+        builder->fFSCode.appendf("\t\t%s = ", outputColor);
+        builder->appendTextureLookup(&builder->fFSCode, samplerName);
+        builder->fFSCode.appendf("%s;\n", builder->fSwizzle.c_str());
         if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
             GrAssert(fSwapRedAndBlue);
-            builder->fFSCode.appendf("\t%s = tempColor.bgra;\n", outputColor);
+            builder->fFSCode.appendf("\t%s = %s.bgra;\n", outputColor, outputColor);
         } else {
             const char* swiz = fSwapRedAndBlue ? "bgr" : "rgb";
             switch (fPMConversion) {
                 case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion:
                     builder->fFSCode.appendf(
-                        "\t%s = vec4(ceil(tempColor.%s*tempColor.a*255.0)/255.0, tempColor.a);\n",
-                         outputColor, swiz);
+                        "\t\t%s = vec4(ceil(%s.%s * %s.a * 255.0) / 255.0, %s.a);\n",
+                        outputColor, outputColor, swiz, outputColor, outputColor);
                     break;
                 case GrConfigConversionEffect::kMulByAlpha_RoundDown_PMConversion:
                     builder->fFSCode.appendf(
-                        "\t%s = vec4(floor(tempColor.%s*tempColor.a*255.0)/255.0, tempColor.a);\n",
-                         outputColor, swiz);
+                        "\t\t%s = vec4(floor(%s.%s * %s.a * 255.0) / 255.0, %s.a);\n",
+                        outputColor, outputColor, swiz, outputColor, outputColor);
                     break;
                 case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion:
-                    builder->fFSCode.appendf("\t%s = tempColor.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(tempColor.%s / tempColor.a * 255.0)/255.0, tempColor.a);\n",
-                        outputColor, swiz);
+                    builder->fFSCode.appendf("\t\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.%s / %s.a * 255.0) / 255.0, %s.a);\n",
+                        outputColor, outputColor, outputColor, swiz, outputColor, outputColor);
                     break;
                 case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion:
-                    builder->fFSCode.appendf("\t%s = tempColor.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(tempColor.%s / tempColor.a * 255.0)/255.0, tempColor.a);\n",
-                        outputColor, swiz);
+                    builder->fFSCode.appendf("\t\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.%s / %s.a * 255.0) / 255.0, %s.a);\n",
+                        outputColor, outputColor, outputColor, swiz, outputColor, outputColor);
                     break;
                 default:
                     GrCrash("Unknown conversion op.");
                     break;
             }
         }
+        GrGLSLMulVarBy4f(&builder->fFSCode, 2, outputColor, inputColor);
     }
 
     static inline StageKey GenKey(const GrCustomStage& s, const GrGLCaps&) {
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 162a0cc..635064f 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -84,15 +84,11 @@
         index.appendS32(i);
         kernel.appendArrayAccess(index.c_str(), &kernelIndex);
         code->appendf("\t\t%s += ", outputColor);
-        builder->emitTextureLookup(samplerName, "coord");
+        builder->appendTextureLookup(&builder->fFSCode, samplerName, "coord");
         code->appendf(" * %s;\n", kernelIndex.c_str());
         code->appendf("\t\tcoord += %s;\n", imgInc);
     }
-
-    if (builder->fModulate.size()) {
-        code->appendf("\t\t%s = %s%s;\n", outputColor, outputColor,
-                      builder->fModulate.c_str());
-    }
+    GrGLSLMulVarBy4f(&builder->fFSCode, 2, outputColor, inputColor);
 }
 
 void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman,
diff --git a/src/gpu/effects/GrSingleTextureEffect.cpp b/src/gpu/effects/GrSingleTextureEffect.cpp
index 42a8bf9..dc91a68 100644
--- a/src/gpu/effects/GrSingleTextureEffect.cpp
+++ b/src/gpu/effects/GrSingleTextureEffect.cpp
@@ -23,7 +23,9 @@
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE {
-        builder->emitTextureLookupAndModulate(outputColor, samplerName);
+        builder->fFSCode.appendf("\t%s = ", outputColor);
+        builder->appendTextureLookupAndModulate(&builder->fFSCode, inputColor, samplerName);
+        builder->fFSCode.append(";\n");
     }
 
     static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&) { return 0; }
diff --git a/src/gpu/effects/GrTextureDomainEffect.cpp b/src/gpu/effects/GrTextureDomainEffect.cpp
index a67dd49..f5306c7 100644
--- a/src/gpu/effects/GrTextureDomainEffect.cpp
+++ b/src/gpu/effects/GrTextureDomainEffect.cpp
@@ -55,7 +55,9 @@
                            builder->getUniformCStr(fNameUni),
                            builder->getUniformCStr(fNameUni));
 
-    builder->emitTextureLookupAndModulate(outputColor, samplerName, "clampCoord");
+    builder->fFSCode.appendf("\t%s = ", outputColor);
+    builder->appendTextureLookupAndModulate(&builder->fFSCode, inputColor, samplerName, "clampCoord");
+    builder->fFSCode.append(";\n");
 }
 
 void GrGLTextureDomainEffect::setData(const GrGLUniformManager& uman,
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 50e839b..ff29bd4 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -987,7 +987,6 @@
     builder->fVSCode.appendf("\t}\n");
 
     builder->computeSwizzle(desc.fInConfigFlags);
-    builder->computeModulate(fsInColor);
 
     // Enclose custom code in a block to avoid namespace conflicts
     builder->fFSCode.appendf("\t{ // stage %d %s \n",
diff --git a/src/gpu/gl/GrGLSL.cpp b/src/gpu/gl/GrGLSL.cpp
index c995a34..079c082 100644
--- a/src/gpu/gl/GrGLSL.cpp
+++ b/src/gpu/gl/GrGLSL.cpp
@@ -115,6 +115,7 @@
             outAppend->append(GrGLSLZerosVecf(4));
             return kZeros_GrSLConstantVec;
         } else {
+            // both inputs are ones vectors
             outAppend->append(GrGLSLOnesVecf(4));
             return kOnes_GrSLConstantVec;
         }
@@ -142,6 +143,43 @@
     }
 }
 
+namespace {
+void append_tabs(SkString* outAppend, int tabCnt) {
+    static const char kTabs[] = "\t\t\t\t\t\t\t\t";
+    while (tabCnt) {
+        int cnt = GrMin((int)GR_ARRAY_COUNT(kTabs), tabCnt);
+        outAppend->append(kTabs, cnt);
+        tabCnt -= cnt;
+    }
+}
+}
+
+GrSLConstantVec GrGLSLMulVarBy4f(SkString* outAppend,
+                                 int tabCnt,
+                                 const char* vec4VarName,
+                                 const char* mulFactor,
+                                 GrSLConstantVec mulFactorDefault) {
+    bool haveFactor = NULL != mulFactor && '\0' != *mulFactor;
+
+    GrAssert(NULL != outAppend);
+    GrAssert(NULL != vec4VarName);
+    GrAssert(kNone_GrSLConstantVec != mulFactorDefault || haveFactor);
+
+    if (!haveFactor) {
+        if (kOnes_GrSLConstantVec == mulFactorDefault) {
+            return kNone_GrSLConstantVec;
+        } else {
+            GrAssert(kZeros_GrSLConstantVec == mulFactorDefault);
+            append_tabs(outAppend, tabCnt);
+            outAppend->appendf("%s = vec4(0, 0, 0, 0);\n", vec4VarName);
+            return kZeros_GrSLConstantVec;
+        }
+    }
+    append_tabs(outAppend, tabCnt);
+    outAppend->appendf("%s *= %s;\n", vec4VarName, mulFactor);
+    return kNone_GrSLConstantVec;
+}
+
 GrSLConstantVec GrGLSLAdd4f(SkString* outAppend,
                             const char* in0,
                             const char* in1,
diff --git a/src/gpu/gl/GrGLSL.h b/src/gpu/gl/GrGLSL.h
index 6595608..cbff273 100644
--- a/src/gpu/gl/GrGLSL.h
+++ b/src/gpu/gl/GrGLSL.h
@@ -144,6 +144,19 @@
                                  GrSLConstantVec default0 = kOnes_GrSLConstantVec,
                                  GrSLConstantVec default1 = kOnes_GrSLConstantVec);
 
+/**
+ * Does an inplace mul, *=, of vec4VarName by mulFactor. If mulFactorDefault is not kNone then
+ * mulFactor may be either "" or NULL. In this case either nothing will be appened (kOnes) or an
+ * assignment of vec(0,0,0,0) will be appended (kZeros). The assignment is prepended by tabCnt tabs.
+ * A semicolon and newline are added after the assignment. (TODO: Remove tabCnt when we auto-insert
+ * tabs to custom stage-generated lines.) If a zeros vec is assigned then the return value is
+ * kZeros, otherwise kNone.
+ */
+GrSLConstantVec GrGLSLMulVarBy4f(SkString* outAppend,
+                                 int tabCnt,
+                                 const char* vec4VarName,
+                                 const char* mulFactor,
+                                 GrSLConstantVec mulFactorDefault = kOnes_GrSLConstantVec);
 
 /**
   * Produces a string that is the result of adding two inputs. The inputs must be vec4 or float.
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index c061468..5d870dd 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -96,14 +96,6 @@
     }
 }
 
-void GrGLShaderBuilder::computeModulate(const char* fsInColor) {
-    if (NULL != fsInColor) {
-        fModulate.printf(" * %s", fsInColor);
-    } else {
-        fModulate.reset();
-    }
-}
-
 void GrGLShaderBuilder::setupTextureAccess(const char* varyingFSName, GrSLType varyingType) {
     // FIXME: We don't know how the custom stage will manipulate the coords. So we give up on using
     // projective texturing and always give the stage 2D coords. This will be fixed when custom
@@ -130,23 +122,27 @@
     }
 }
 
-void GrGLShaderBuilder::emitTextureLookup(const char* samplerName,
-                                          const char* coordName,
-                                          GrSLType varyingType) {
+void GrGLShaderBuilder::appendTextureLookup(SkString* out,
+                                            const char* samplerName,
+                                            const char* coordName,
+                                            GrSLType varyingType) const {
     if (NULL == coordName) {
         coordName = fDefaultTexCoordsName.c_str();
         varyingType = kVec2f_GrSLType;
     }
-    fFSCode.appendf("%s(%s, %s)", sample_function_name(varyingType), samplerName, coordName);
+    out->appendf("%s(%s, %s)", sample_function_name(varyingType), samplerName, coordName);
 }
 
-void GrGLShaderBuilder::emitTextureLookupAndModulate(const char* outColor,
-                                                     const char* samplerName,
-                                                     const char* coordName,
-                                                     GrSLType varyingType) {
-    fFSCode.appendf("\t%s = ", outColor);
-    this->emitTextureLookup(samplerName, coordName, varyingType);
-    fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
+void GrGLShaderBuilder::appendTextureLookupAndModulate(SkString* out,
+                                                       const char* modulation,
+                                                       const char* samplerName,
+                                                       const char* coordName,
+                                                       GrSLType varyingType) const {
+    GrAssert(NULL != out);
+    SkString lookup;
+    this->appendTextureLookup(&lookup, samplerName, coordName, varyingType);
+    lookup.append(fSwizzle.c_str());
+    GrGLSLModulate4f(out, modulation, lookup.c_str());
 }
 
 void GrGLShaderBuilder::emitCustomTextureLookup(const GrTextureAccess& textureAccess,
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index 66de5ab..bc10892 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -32,7 +32,6 @@
     GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&);
 
     void computeSwizzle(uint32_t configFlags);
-    void computeModulate(const char* fsInColor);
 
     /** Determines whether we should use texture2D() or texture2Dproj(), and if an explicit divide
         is required for the sample coordinates, creates the new variable and emits the code to
@@ -42,17 +41,20 @@
     /** texture2D(samplerName, coordName), with projection if necessary; if coordName is not
         specified, uses fSampleCoords. coordType must either be Vec2f or Vec3f. The latter is
         interpreted as projective texture coords. */
-    void emitTextureLookup(const char* samplerName,
-                           const char* coordName = NULL,
-                           GrSLType coordType = kVec2f_GrSLType);
+    void appendTextureLookup(SkString* out,
+                             const char* samplerName,
+                             const char* coordName = NULL,
+                             GrSLType coordType = kVec2f_GrSLType) const;
 
-    /** sets outColor to results of texture lookup, with swizzle, and/or modulate as necessary. If
-    coordName is NULL then it as if defaultTexCoordsName() was passed. coordType must be either
-    kVec2f or kVec3f. */
-    void emitTextureLookupAndModulate(const char* outColor,
-                                      const char* samplerName,
-                                      const char* coordName = NULL,
-                                      GrSLType coordType = kVec2f_GrSLType);
+    /** appends a texture lookup, with swizzle as necessary. If coordName is NULL then it as if
+        defaultTexCoordsName() was passed. coordType must be either kVec2f or kVec3f. If modulateVar
+        is not NULL or "" then the texture lookup will be modulated by it. modulation must refer to
+        be expression that evaluates to a float or vec4. */
+    void appendTextureLookupAndModulate(SkString* out,
+                                        const char* modulation,
+                                        const char* samplerName,
+                                        const char* coordName = NULL,
+                                        GrSLType varyingType = kVec2f_GrSLType) const;
 
     /** Gets the name of the default texture coords which are always kVec2f */
     const char* defaultTexCoordsName() const { return fDefaultTexCoordsName.c_str(); }
@@ -171,7 +173,6 @@
     //@{
 
     SkString         fSwizzle;
-    SkString         fModulate;
 
     //@}