Refactor 'in uniform' CPP code generation

Easily supports mapping ctypes to sksl types with templates that
specify how to send data to the GPU and how to track state changes.
The template logic and type mappings are defined in
SkSLCPPUniformCTypes.* while SkSLCPPCodeGenerator is updated to
utilize it.

It also updates the supported ctypes to properly generate code for
SkPoint, SkIPoint, SkIRect, and GrColor4f. The code generated for
'in uniforms' now also correctly supports conditional uniforms.


Bug: skia:
Change-Id: Ib7c0a873bdd68a966b6a00871f33102dfa2c432d
Reviewed-on: https://skia-review.googlesource.com/150129
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp
index 532ebef..90d96f7 100644
--- a/src/sksl/SkSLHCodeGenerator.cpp
+++ b/src/sksl/SkSLHCodeGenerator.cpp
@@ -15,6 +15,8 @@
 #include "ir/SkSLSection.h"
 #include "ir/SkSLVarDeclarations.h"
 
+#include <set>
+
 namespace SkSL {
 
 HCodeGenerator::HCodeGenerator(const Context* context, const Program* program,
@@ -31,14 +33,24 @@
         return layout.fCType;
     } else if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
         return "float";
+    } else if (type == *context.fInt_Type ||
+               type == *context.fShort_Type ||
+               type == *context.fByte_Type) {
+        return "int32_t";
     } else if (type == *context.fFloat2_Type || type == *context.fHalf2_Type) {
         return "SkPoint";
+    } else if (type == *context.fInt2_Type ||
+               type == *context.fShort2_Type ||
+               type == *context.fByte2_Type) {
+        return "SkIPoint";
     } else if (type == *context.fInt4_Type ||
                type == *context.fShort4_Type ||
                type == *context.fByte4_Type) {
         return "SkIRect";
     } else if (type == *context.fFloat4_Type || type == *context.fHalf4_Type) {
         return "SkRect";
+    } else if (type == *context.fFloat3x3_Type || type == *context.fHalf3x3_Type) {
+        return "SkMatrix";
     } else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) {
         return "SkMatrix44";
     } else if (type.kind() == Type::kSampler_Kind) {
@@ -62,6 +74,19 @@
     return ParameterType(context, type, layout);
 }
 
+String HCodeGenerator::AccessType(const Context& context, const Type& type,
+                                  const Layout& layout) {
+    static const std::set<String> primitiveTypes = { "int32_t", "float", "SkPMColor" };
+
+    String fieldType = FieldType(context, type, layout);
+    bool isPrimitive = primitiveTypes.find(fieldType) != primitiveTypes.end();
+    if (isPrimitive) {
+        return fieldType;
+    } else {
+        return String::printf("const %s&", fieldType.c_str());
+    }
+}
+
 void HCodeGenerator::writef(const char* s, va_list va) {
     static constexpr int BUFFER_SIZE = 1024;
     va_list copy;
@@ -312,7 +337,7 @@
         String nameString(param->fName);
         const char* name = nameString.c_str();
         this->writef("    %s %s() const { return %s; }\n",
-                     FieldType(fContext, param->fType, param->fModifiers.fLayout).c_str(), name,
+                     AccessType(fContext, param->fType, param->fModifiers.fLayout).c_str(), name,
                      FieldName(name).c_str());
     }
     this->writeMake();