Allow .fp files to return a color from main().

Existing .fp files that assign their output to sk_OutColor will continue
to work as before. An error will be generated if an .fp file tries to
mix-and-match return statements and sk_OutColor assignment; only one or
the other is allowed within a single .fp file.

Change-Id: I53bc0e8b79b2fdd64a020a7e5b35a905f9b05c94
Bug: skia:10549
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/313197
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index da8e3eb..2ae6db5 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -295,6 +295,15 @@
     }
 }
 
+void CPPCodeGenerator::setReturnType(int offset, ReturnType typeToSet) {
+    if (fReturnType == ReturnType::kNothing) {
+        fReturnType = typeToSet;
+    } else if (fReturnType != typeToSet) {
+        fErrors.error(offset,
+                      "Fragment processors must not mix sk_OutColor and return statements\n");
+    }
+}
+
 void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
     if (fCPPMode) {
         this->write(ref.fVariable.fName);
@@ -304,6 +313,7 @@
         case SK_OUTCOLOR_BUILTIN:
             this->write("%s");
             fFormatArgs.push_back(String("args.fOutputColor"));
+            this->setReturnType(ref.fOffset, ReturnType::kUsesSkOutColor);
             break;
         case SK_MAIN_COORDS_BUILTIN:
             this->write("%s");
@@ -357,7 +367,7 @@
 
 void CPPCodeGenerator::writeReturnStatement(const ReturnStatement& s) {
     if (fInMain) {
-        fErrors.error(s.fOffset, "fragmentProcessor main() may not contain return statements");
+        this->setReturnType(s.fOffset, ReturnType::kUsesExplicitReturn);
     }
     INHERITED::writeReturnStatement(s);
 }
@@ -1406,6 +1416,10 @@
     }
     this->write("    return true;\n"
                 "}\n");
+    this->writef("bool %s::usesExplicitReturn() const {\n"
+                 "    return %s;\n"
+                 "}\n",
+                 fullName, fReturnType == ReturnType::kUsesExplicitReturn ? "true" : "false");
     this->writeClone();
     this->writeDumpInfo();
     this->writeOnTextureSampler();