Mangle function names as a separate step before emitting func-bodies.

This is necessary to support function calls in FP files properly; in
some cases, functions can be referenced before they have been emitted,
and we need to be able to name them.

This CL resolves the remaining errors in GrRecursion.cpp. There are
still additional errors in GrNestedCall.cpp that will be fixed in
followup CLs.

Change-Id: Iec98ef02ea6a98a9945a4e0e3cfa3537dff01305
Bug: skia:10684, skia:10872
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/329676
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index d554f0f..fb6f20c 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -197,12 +197,12 @@
         this->codeAppendf("return %s;\n", args.fOutputColor);
     }
 
-    SkString result;
-    this->emitFunction(kHalf4_GrSLType, args.fFp.name(), paramCount, params,
-                       this->code().c_str(), &result, args.fForceInline);
+    SkString funcName = this->getMangledFunctionName(args.fFp.name());
+    this->emitFunction(kHalf4_GrSLType, funcName.c_str(), paramCount, params,
+                       this->code().c_str(), args.fForceInline);
     this->deleteStage();
     this->onAfterChildProcEmitCode();
-    return result;
+    return funcName;
 }
 
 const char* GrGLSLFragmentShaderBuilder::dstColor() {
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
index 8a5b071..c54fcea 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
@@ -41,23 +41,24 @@
     this->definitions().append(";");
 }
 
+SkString GrGLSLShaderBuilder::getMangledFunctionName(const char* baseName) {
+    return fProgramBuilder->nameVariable(/*prefix=*/'\0', baseName);
+}
+
 void GrGLSLShaderBuilder::emitFunction(GrSLType returnType,
-                                       const char* name,
+                                       const char* mangledName,
                                        int argCnt,
                                        const GrShaderVar* args,
                                        const char* body,
-                                       SkString* outName,
                                        bool forceInline) {
-    *outName = fProgramBuilder->nameVariable(/*prefix=*/'\0', name);
-    this->functions().appendf("%s%s %s(",
-                              forceInline ? "inline " : "",
-                              GrGLSLTypeString(returnType),
-                              outName->c_str());
+    this->functions().appendf("%s%s %s(", forceInline ? "inline " : "",
+                                          GrGLSLTypeString(returnType),
+                                          mangledName);
     for (int i = 0; i < argCnt; ++i) {
-        args[i].appendDecl(fProgramBuilder->shaderCaps(), &this->functions());
-        if (i < argCnt - 1) {
+        if (i > 0) {
             this->functions().append(", ");
         }
+        args[i].appendDecl(fProgramBuilder->shaderCaps(), &this->functions());
     }
     this->functions().appendf(") {\n"
                               "%s"
@@ -168,9 +169,9 @@
                 break;
         }
         body.append("return s * x;");
-        SkString funcName;
-        this->emitFunction(kHalf_GrSLType, name, SK_ARRAY_COUNT(gTFArgs), gTFArgs, body.c_str(),
-                           &funcName);
+        SkString funcName = this->getMangledFunctionName(name);
+        this->emitFunction(kHalf_GrSLType, funcName.c_str(), SK_ARRAY_COUNT(gTFArgs), gTFArgs,
+                           body.c_str());
         return funcName;
     };
 
@@ -193,8 +194,9 @@
         SkString body;
         body.appendf("color.rgb = (%s * color.rgb);", xform);
         body.append("return color;");
-        this->emitFunction(kHalf4_GrSLType, "gamut_xform", SK_ARRAY_COUNT(gGamutXformArgs),
-                           gGamutXformArgs, body.c_str(), &gamutXformFuncName);
+        gamutXformFuncName = this->getMangledFunctionName("gamut_xform");
+        this->emitFunction(kHalf4_GrSLType, gamutXformFuncName.c_str(),
+                           SK_ARRAY_COUNT(gGamutXformArgs), gGamutXformArgs, body.c_str());
     }
 
     // Now define a wrapper function that applies all the intermediate steps
@@ -228,9 +230,9 @@
             body.append("color.rgb *= color.a;");
         }
         body.append("return half4(color);");
-        SkString colorXformFuncName;
-        this->emitFunction(kHalf4_GrSLType, "color_xform", SK_ARRAY_COUNT(gColorXformArgs),
-                           gColorXformArgs, body.c_str(), &colorXformFuncName);
+        SkString colorXformFuncName = this->getMangledFunctionName("color_xform");
+        this->emitFunction(kHalf4_GrSLType, colorXformFuncName.c_str(),
+                           SK_ARRAY_COUNT(gColorXformArgs), gColorXformArgs, body.c_str());
         out->appendf("%s(%s)", colorXformFuncName.c_str(), srcColor);
     }
 }
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index b7f44b5..14dc021 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -95,8 +95,8 @@
     }
 
     /**
-    * Called by GrGLSLProcessors to add code to one of the shaders.
-    */
+     * Called by GrGLSLProcessors to add code to one of the shaders.
+     */
     void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
        va_list args;
        va_start(args, format);
@@ -120,22 +120,27 @@
      */
     void declAppend(const GrShaderVar& var);
 
+    /**
+     * Generates a mangled name for a helper function in the fragment shader. Will give consistent
+     * results if called more than once.
+     */
+    SkString getMangledFunctionName(const char* baseName);
+
     /** Emits a helper function outside of main() in the fragment shader. */
     void emitFunction(GrSLType returnType,
-                      const char* name,
+                      const char* mangledName,
                       int argCnt,
                       const GrShaderVar* args,
                       const char* body,
-                      SkString* outName,
                       bool forceInline = false);
 
-    /*
+    /**
      * Combines the various parts of the shader to create a single finalized shader string.
      */
     void finalize(uint32_t visibility);
 
-    /*
-     * Get parent builder for adding uniforms
+    /**
+     * Get parent builder for adding uniforms.
      */
     GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }