Add helpers to add/modulate glsl vec4s.
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 29 Aug 2012 12:59:57 +0000 (12:59 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 29 Aug 2012 12:59:57 +0000 (12:59 +0000)
Review URL: https://codereview.appspot.com/6497046/

git-svn-id: http://skia.googlecode.com/svn/trunk@5332 2bbb7eff-a529-9590-31e7-b0007b416f81

src/gpu/gl/GrGLProgram.cpp
src/gpu/gl/GrGLSL.cpp
src/gpu/gl/GrGLSL.h

index 9613697..50e839b 100644 (file)
@@ -46,20 +46,6 @@ inline const char* vector_all_coords(int count) {
     return ALL[count];
 }
 
-inline const char* all_ones_vec(int count) {
-    static const char* ONESVEC[] = {"ERROR", "1.0", "vec2(1,1)",
-                                    "vec3(1,1,1)", "vec4(1,1,1,1)"};
-    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ONESVEC));
-    return ONESVEC[count];
-}
-
-inline const char* all_zeros_vec(int count) {
-    static const char* ZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)",
-                                    "vec3(0,0,0)", "vec4(0,0,0,0)"};
-    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ZEROSVEC));
-    return ZEROSVEC[count];
-}
-
 inline const char* declared_color_output_name() { return "fsColorOut"; }
 inline const char* dual_source_output_name() { return "dualSourceOut"; }
 
@@ -146,62 +132,6 @@ void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
     }
 }
 
-// assigns modulation of two vars to an output var
-// vars can be vec4s or floats (or one of each)
-// result is always vec4
-// if either var is "" then assign to the other var
-// if both are "" then assign all ones
-static inline void modulate_helper(const char* outputVar,
-                                   const char* var0,
-                                   const char* var1,
-                                   SkString* code) {
-    GrAssert(NULL != outputVar);
-    GrAssert(NULL != var0);
-    GrAssert(NULL != var1);
-    GrAssert(NULL != code);
-
-    bool has0 = '\0' != *var0;
-    bool has1 = '\0' != *var1;
-
-    if (!has0 && !has1) {
-        code->appendf("\t%s = %s;\n", outputVar, all_ones_vec(4));
-    } else if (!has0) {
-        code->appendf("\t%s = vec4(%s);\n", outputVar, var1);
-    } else if (!has1) {
-        code->appendf("\t%s = vec4(%s);\n", outputVar, var0);
-    } else {
-        code->appendf("\t%s = vec4(%s * %s);\n", outputVar, var0, var1);
-    }
-}
-
-// assigns addition of two vars to an output var
-// vars can be vec4s or floats (or one of each)
-// result is always vec4
-// if either var is "" then assign to the other var
-// if both are "" then assign all zeros
-static inline void add_helper(const char* outputVar,
-                              const char* var0,
-                              const char* var1,
-                              SkString* code) {
-    GrAssert(NULL != outputVar);
-    GrAssert(NULL != var0);
-    GrAssert(NULL != var1);
-    GrAssert(NULL != code);
-
-    bool has0 = '\0' != *var0;
-    bool has1 = '\0' != *var1;
-
-    if (!has0 && !has1) {
-        code->appendf("\t%s = %s;\n", outputVar, all_zeros_vec(4));
-    } else if (!has0) {
-        code->appendf("\t%s = vec4(%s);\n", outputVar, var1);
-    } else if (!has1) {
-        code->appendf("\t%s = vec4(%s);\n", outputVar, var0);
-    } else {
-        code->appendf("\t%s = vec4(%s + %s);\n", outputVar, var0, var1);
-    }
-}
-
 // given two blend coeffecients determine whether the src
 // and/or dst computation can be omitted.
 static inline void needBlendInputs(SkXfermode::Coeff srcCoeff,
@@ -260,13 +190,13 @@ static void blendTermString(SkString* str, SkXfermode::Coeff coeff,
         str->printf("(%s * %s)", src, value);
         break;
     case SkXfermode::kISC_Coeff:
-        str->printf("((%s - %s) * %s)", all_ones_vec(4), src, value);
+        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value);
         break;
     case SkXfermode::kDC_Coeff:
         str->printf("(%s * %s)", dst, value);
         break;
     case SkXfermode::kIDC_Coeff:
-        str->printf("((%s - %s) * %s)", all_ones_vec(4), dst, value);
+        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value);
         break;
     case SkXfermode::kSA_Coeff:      /** src alpha */
         str->printf("(%s.a * %s)", src, value);
@@ -298,7 +228,9 @@ static void addColorFilter(SkString* fsCode, const char * outputVar,
     blendTermString(&colorStr, colorCoeff, filterColor, inColor, inColor);
     blendTermString(&constStr, uniformCoeff, filterColor, inColor, filterColor);
 
-    add_helper(outputVar, colorStr.c_str(), constStr.c_str(), fsCode);
+    fsCode->appendf("\t%s = ", outputVar);
+    GrGLSLAdd4f(fsCode, colorStr.c_str(), constStr.c_str());
+    fsCode->append(";\n");
 }
 
 bool GrGLProgram::genEdgeCoverage(SkString* coverageVar,
@@ -458,9 +390,9 @@ const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
           return inColor.c_str();
     } else {
         if (Desc::kSolidWhite_ColorInput == fDesc.fColorInput) {
-            return all_ones_vec(4);
+            return GrGLSLOnesVecf(4);
         } else {
-            return all_zeros_vec(4);
+            return GrGLSLZerosVecf(4);
         }
     }
 }
@@ -736,7 +668,7 @@ bool GrGLProgram::genProgram(const GrCustomStage** customStages) {
         !applyColorMatrix) {
         builder.fFSCode.appendf("\t%s = %s;\n",
                                 colorOutput.getName().c_str(),
-                                all_zeros_vec(4));
+                                GrGLSLZerosVecf(4));
         wroteFragColorZero = true;
     } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
         builder.fFSCode.append("\tvec4 filteredColor;\n");
@@ -854,12 +786,11 @@ bool GrGLProgram::genProgram(const GrCustomStage** customStages) {
             if (outputIsZero) {
                 builder.fFSCode.appendf("\t%s = %s;\n",
                                         dual_source_output_name(),
-                                         all_zeros_vec(4));
+                                        GrGLSLZerosVecf(4));
             } else {
-                modulate_helper(dual_source_output_name(),
-                                coeff.c_str(),
-                                inCoverage.c_str(),
-                                &builder.fFSCode);
+                builder.fFSCode.appendf("\t%s =", dual_source_output_name());
+                GrGLSLModulate4f(&builder.fFSCode, coeff.c_str(), inCoverage.c_str());
+                builder.fFSCode.append(";\n");
             }
             dualSourceOutputWritten = true;
         }
@@ -872,12 +803,11 @@ bool GrGLProgram::genProgram(const GrCustomStage** customStages) {
         if (coverageIsZero) {
             builder.fFSCode.appendf("\t%s = %s;\n",
                                     colorOutput.getName().c_str(),
-                                    all_zeros_vec(4));
+                                    GrGLSLZerosVecf(4));
         } else {
-            modulate_helper(colorOutput.getName().c_str(),
-                            inColor.c_str(),
-                            inCoverage.c_str(),
-                            &builder.fFSCode);
+            builder.fFSCode.appendf("\t%s = ", colorOutput.getName().c_str());
+            GrGLSLModulate4f(&builder.fFSCode, inColor.c_str(), inCoverage.c_str());
+            builder.fFSCode.append(";\n");
         }
     }
 
index f1f7d92..21e9183 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "GrGLSL.h"
 #include "GrGLShaderVar.h"
+#include "SkString.h"
 
 GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding,
                                    const GrGLInterface* gl) {
@@ -93,3 +94,79 @@ const char* GrGLSLVectorNonhomogCoords(int count) {
 const char* GrGLSLVectorNonhomogCoord(GrSLType type) {
     return GrGLSLVectorNonhomogCoords(GrSLTypeToVecLength(type));
 }
+
+GrSLConstantVec GrGLSLModulate4f(SkString* outAppend,
+                                 const char* in0,
+                                 const char* in1,
+                                 GrSLConstantVec default0,
+                                 GrSLConstantVec default1) {
+    GrAssert(NULL != outAppend);
+
+    bool has0 = NULL != in0 && '\0' != *in0;
+    bool has1 = NULL != in1 && '\0' != *in1;
+
+    GrAssert(has0 || kNone_GrSLConstantVec != default0);
+    GrAssert(has1 || kNone_GrSLConstantVec != default1);
+
+    if (!has0 && !has1) {
+        GrAssert(kZeros_GrSLConstantVec == default0 || kOnes_GrSLConstantVec == default0);
+        GrAssert(kZeros_GrSLConstantVec == default1 || kOnes_GrSLConstantVec == default1);
+        if (kZeros_GrSLConstantVec == default0 || kZeros_GrSLConstantVec == default1) {
+            outAppend->append(GrGLSLZerosVecf(4));
+            return kZeros_GrSLConstantVec;
+        } else {
+            outAppend->appendf(GrGLSLOnesVecf(4));
+            return kOnes_GrSLConstantVec;
+        }
+    } else if (!has0) {
+        GrAssert(kZeros_GrSLConstantVec == default0 || kOnes_GrSLConstantVec == default0);
+        if (kZeros_GrSLConstantVec == default0) {
+            outAppend->append(GrGLSLZerosVecf(4));
+            return kZeros_GrSLConstantVec;
+        } else {
+            outAppend->appendf("vec4(%s)", in1);
+            return kNone_GrSLConstantVec;
+        }
+    } else if (!has1) {
+        GrAssert(kZeros_GrSLConstantVec == default1 || kOnes_GrSLConstantVec == default1);
+        if (kZeros_GrSLConstantVec == default1) {
+            outAppend->append(GrGLSLZerosVecf(4));
+            return kZeros_GrSLConstantVec;
+        } else {
+            outAppend->appendf("vec4(%s)", in0);
+            return kNone_GrSLConstantVec;
+        }
+    } else {
+        outAppend->appendf("vec4(%s * %s)", in0, in1);
+        return kNone_GrSLConstantVec;
+    }
+}
+
+GrSLConstantVec GrGLSLAdd4f(SkString* outAppend,
+                            const char* in0,
+                            const char* in1,
+                            GrSLConstantVec default0,
+                            GrSLConstantVec default1) {
+    GrAssert(NULL != outAppend);
+
+    bool has0 = NULL != in0 && '\0' != *in0;
+    bool has1 = NULL != in1 && '\0' != *in1;
+
+    if (!has0 && !has1) {
+        GrAssert(kZeros_GrSLConstantVec == default0);
+        GrAssert(kZeros_GrSLConstantVec == default1);
+        outAppend->append(GrGLSLZerosVecf(4));
+        return kZeros_GrSLConstantVec;
+    } else if (!has0) {
+        GrAssert(kZeros_GrSLConstantVec == default0);
+        outAppend->appendf("vec4(%s)", in1);
+        return kNone_GrSLConstantVec;
+    } else if (!has1) {
+        GrAssert(kZeros_GrSLConstantVec == default1);
+        outAppend->appendf("vec4(%s)", in0);
+        return kNone_GrSLConstantVec;
+    } else {
+        outAppend->appendf("(vec4(%s) + vec4(%s))", in0, in1);
+        return kNone_GrSLConstantVec;
+    }
+}
index f69385f..6595608 100644 (file)
@@ -11,6 +11,7 @@
 #include "gl/GrGLInterface.h"
 
 class GrGLShaderVar;
+class SkString;
 
 // Limited set of GLSL versions we build shaders for. Caller should round
 // down the GLSL version to one of these enums.
@@ -45,6 +46,12 @@ enum GrSLType {
     kSampler2D_GrSLType
 };
 
+enum GrSLConstantVec {
+    kZeros_GrSLConstantVec,
+    kOnes_GrSLConstantVec,
+    kNone_GrSLConstantVec,
+};
+
 namespace {
 inline int GrSLTypeToVecLength(GrSLType type) {
     static const int kVecLengths[] = {
@@ -60,6 +67,20 @@ inline int GrSLTypeToVecLength(GrSLType type) {
     GrAssert((size_t) type < GR_ARRAY_COUNT(kVecLengths));
     return kVecLengths[type];
 }
+
+const char* GrGLSLOnesVecf(int count) {
+    static const char* kONESVEC[] = {"ERROR", "1.0", "vec2(1,1)",
+                                     "vec3(1,1,1)", "vec4(1,1,1,1)"};
+    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(kONESVEC));
+    return kONESVEC[count];
+}
+
+const char* GrGLSLZerosVecf(int count) {
+    static const char* kZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)",
+                                      "vec3(0,0,0)", "vec4(0,0,0,0)"};
+    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(kZEROSVEC));
+    return kZEROSVEC[count];
+}
 }
 
 /**
@@ -107,4 +128,36 @@ const char* GrGLSLVectorHomogCoord(GrSLType type);
     with the given number of coordinates, e.g. 2 -> ".x", 3 -> ".xy" */
 const char* GrGLSLVectorNonhomogCoords(int count);
 const char* GrGLSLVectorNonhomogCoords(GrSLType type);
+
+/**
+  * Produces a string that is the result of modulating two inputs. The inputs must be vec4 or
+  * float. The result is always a vec4. The inputs may be expressions, not just identifier names.
+  * Either can be NULL or "" in which case the default params control whether vec4(1,1,1,1) or
+  * vec4(0,0,0,0) is assumed. It is an error to pass kNone for default<i> if in<i> is NULL or "".
+  * Note that when if function determines that the result is a zeros or ones vec then any expression
+  * represented by in0 or in1 will not be emitted. The return value indicates whether a zeros, ones
+  * or neither was appeneded.
+  */
+GrSLConstantVec GrGLSLModulate4f(SkString* outAppend,
+                                 const char* in0,
+                                 const char* in1,
+                                 GrSLConstantVec default0 = kOnes_GrSLConstantVec,
+                                 GrSLConstantVec default1 = kOnes_GrSLConstantVec);
+
+
+/**
+  * Produces a string that is the result of adding two inputs. The inputs must be vec4 or float.
+  * The result is always a vec4. The inputs may be expressions, not just identifier names. Either
+  * can be NULL or "" in which case if the default is kZeros then vec4(0,0,0,0) is assumed. It is an
+  * error to pass kOnes for either default or to pass kNone for default<i> if in<i> is NULL or "".
+  * Note that if the function determines that the result is a zeros vec any expression represented
+  * by in0 or in1 will not be emitted. The return value indicates whether a zeros vec was appended
+  * or not.
+  */
+GrSLConstantVec GrGLSLAdd4f(SkString* outAppend,
+                            const char* in0,
+                            const char* in1,
+                            GrSLConstantVec default0 = kZeros_GrSLConstantVec,
+                            GrSLConstantVec default1 = kZeros_GrSLConstantVec);
+
 #endif