Re-re-land sksl fragment processor support

This reverts commit 5ce397205528f82084fc650c2ce27d246c01da33.

Bug: skia:
Change-Id: I88260c90004610a1cf8ad1a87c2b4b222525bbb6
Reviewed-on: https://skia-review.googlesource.com/21108
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp
index 1461bf9..3e3d747 100644
--- a/src/sksl/SkSLMain.cpp
+++ b/src/sksl/SkSLMain.cpp
@@ -5,11 +5,28 @@
  * found in the LICENSE file.
  */
 
-#include "stdio.h"
 #include <fstream>
 #include "SkSLCompiler.h"
 #include "SkSLFileOutputStream.h"
 
+// Given the path to a file (e.g. src/gpu/effects/GrFooFragmentProcessor.fp) and the expected
+// filename prefix and suffix (e.g. "Gr" and ".fp"), returns the "base name" of the
+// file (in this case, 'FooFragmentProcessor'). If no match, returns the empty string.
+static SkSL::String base_name(const char* fpPath, const char* prefix, const char* suffix) {
+    SkSL::String result;
+    const char* end = fpPath + strlen(fpPath);
+    const char* fileName = end;
+    // back up until we find a slash
+    while (fileName != fpPath && '/' != *(fileName - 1) && '\\' != *(fileName - 1)) {
+        --fileName;
+    }
+    if (!strncmp(fileName, prefix, strlen(prefix)) &&
+        !strncmp(end - strlen(suffix), suffix, strlen(suffix))) {
+        result.append(fileName + strlen(prefix), end - fileName - strlen(prefix) - strlen(suffix));
+    }
+    return result;
+}
+
 /**
  * Very simple standalone executable to facilitate testing.
  */
@@ -19,15 +36,17 @@
         exit(1);
     }
     SkSL::Program::Kind kind;
-    size_t len = strlen(argv[1]);
-    if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".vert")) {
+    SkSL::String input(argv[1]);
+    if (input.endsWith(".vert")) {
         kind = SkSL::Program::kVertex_Kind;
-    } else if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".frag")) {
+    } else if (input.endsWith(".frag")) {
         kind = SkSL::Program::kFragment_Kind;
-    } else if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".geom")) {
+    } else if (input.endsWith(".geom")) {
         kind = SkSL::Program::kGeometry_Kind;
+    } else if (input.endsWith(".fp")) {
+        kind = SkSL::Program::kFragmentProcessor_Kind;
     } else {
-        printf("input filename must end in '.vert', '.frag', or '.geom'\n");
+        printf("input filename must end in '.vert', '.frag', '.geom', or '.fp'\n");
         exit(1);
     }
 
@@ -40,6 +59,7 @@
         exit(2);
     }
     SkSL::Program::Settings settings;
+    settings.fArgs.insert(std::make_pair("gpImplementsDistanceVector", 1));
     SkSL::String name(argv[2]);
     if (name.endsWith(".spirv")) {
         SkSL::FileOutputStream out(argv[2]);
@@ -73,7 +93,41 @@
             printf("error writing '%s'\n", argv[2]);
             exit(4);
         }
+    } else if (name.endsWith(".h")) {
+        SkSL::FileOutputStream out(argv[2]);
+        SkSL::Compiler compiler;
+        if (!out.isValid()) {
+            printf("error writing '%s'\n", argv[2]);
+            exit(4);
+        }
+        settings.fReplaceSettings = false;
+        std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings);
+        if (!program || !compiler.toH(*program, base_name(argv[1], "Gr", ".fp"), out)) {
+            printf("%s", compiler.errorText().c_str());
+            exit(3);
+        }
+        if (!out.close()) {
+            printf("error writing '%s'\n", argv[2]);
+            exit(4);
+        }
+    } else if (name.endsWith(".cpp")) {
+        SkSL::FileOutputStream out(argv[2]);
+        SkSL::Compiler compiler;
+        if (!out.isValid()) {
+            printf("error writing '%s'\n", argv[2]);
+            exit(4);
+        }
+        settings.fReplaceSettings = false;
+        std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings);
+        if (!program || !compiler.toCPP(*program, base_name(argv[1], "Gr", ".fp"), out)) {
+            printf("%s", compiler.errorText().c_str());
+            exit(3);
+        }
+        if (!out.close()) {
+            printf("error writing '%s'\n", argv[2]);
+            exit(4);
+        }
     } else {
-        printf("expected output filename to end with '.spirv' or '.glsl'");
+        printf("expected output filename to end with '.spirv', '.glsl', '.cpp', or '.h'");
     }
 }