Merge GrGLSLShaderVar and GrShaderVar

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=5087

Change-Id: Ib8943a1da1ea495554feaf5b0992b94fbb9539ab
Reviewed-on: https://skia-review.googlesource.com/5087
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/include/gpu/GrShaderVar.h b/include/gpu/GrShaderVar.h
index 60e951c..81a7566 100644
--- a/include/gpu/GrShaderVar.h
+++ b/include/gpu/GrShaderVar.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Google Inc.
+ * Copyright 2016 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
@@ -8,20 +8,18 @@
 #ifndef GrShaderVar_DEFINED
 #define GrShaderVar_DEFINED
 
-#include "GrTypesPriv.h"
 #include "SkString.h"
+#include "GrTypesPriv.h"
 
+class GrGLSLCaps;
+
+#define USE_UNIFORM_FLOAT_ARRAYS true
+
+/**
+ * Represents a variable in a shader
+ */
 class GrShaderVar {
 public:
-    /**
-     * Early versions of GLSL have Varying and Attribute; those are later
-     * deprecated, but we still need to know whether a Varying variable
-     * should be treated as In or Out.
-     *
-     * TODO This really shouldn't live here, but until we have c++11, there is really no good way
-     * to write extensible enums.  In reality, only none, out, in, inout, and uniform really
-     * make sense on this base class
-     */
     enum TypeModifier {
         kNone_TypeModifier,
         kOut_TypeModifier,
@@ -31,77 +29,178 @@
     };
 
     /**
-     * Defaults to a float with no precision specifier
-     */
-    GrShaderVar()
-        : fType(kFloat_GrSLType)
-        , fTypeModifier(kNone_TypeModifier)
-        , fCount(kNonArray)
-        , fPrecision(kDefault_GrSLPrecision) {
-    }
-
-    GrShaderVar(const SkString& name, GrSLType type, int arrayCount = kNonArray,
-                GrSLPrecision precision = kDefault_GrSLPrecision)
-        : fType(type)
-        , fTypeModifier(kNone_TypeModifier)
-        , fName(name)
-        , fCount(arrayCount)
-        , fPrecision(precision) {
-        SkASSERT(kVoid_GrSLType != type);
-    }
-
-    GrShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray,
-                GrSLPrecision precision = kDefault_GrSLPrecision)
-        : fType(type)
-        , fTypeModifier(kNone_TypeModifier)
-        , fName(name)
-        , fCount(arrayCount)
-        , fPrecision(precision) {
-        SkASSERT(kVoid_GrSLType != type);
-    }
-
-    GrShaderVar(const char* name, GrSLType type, TypeModifier typeModifier,
-                int arrayCount = kNonArray, GrSLPrecision precision = kDefault_GrSLPrecision)
-        : fType(type)
-        , fTypeModifier(typeModifier)
-        , fName(name)
-        , fCount(arrayCount)
-        , fPrecision(precision) {
-        SkASSERT(kVoid_GrSLType != type);
-    }
-
-    /**
-     * Values for array count that have special meaning. We allow 1-sized arrays.
+     * Values for array count that have special meaning. We allow 1-sized arrays.git 
      */
     enum {
         kNonArray     =  0, // not an array
         kUnsizedArray = -1, // an unsized array (declared with [])
     };
 
+    /**
+     * Defaults to a non-arry float with no precision specifier, type modifier, or layout qualifier.
+     */
+    GrShaderVar()
+        : fType(kFloat_GrSLType)
+        , fTypeModifier(kNone_TypeModifier)
+        , fCount(kNonArray)
+        , fPrecision(kDefault_GrSLPrecision)
+        , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
+    }
+
+    GrShaderVar(const SkString& name, GrSLType type, int arrayCount = kNonArray,
+                GrSLPrecision precision = kDefault_GrSLPrecision)
+        : fType(type)
+        , fTypeModifier(kNone_TypeModifier)
+        , fCount(arrayCount)
+        , fPrecision(precision)
+        , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
+        , fName(name) {
+        SkASSERT(kVoid_GrSLType != type);
+        fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
+    }
+
+    GrShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray,
+                GrSLPrecision precision = kDefault_GrSLPrecision)
+        : fType(type)
+        , fTypeModifier(kNone_TypeModifier)
+        , fCount(arrayCount)
+        , fPrecision(precision)
+        , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
+        , fName(name) {
+        SkASSERT(kVoid_GrSLType != type);
+        fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
+    }
+
+    GrShaderVar(const char* name, GrSLType type, TypeModifier typeModifier,
+                GrSLPrecision precision = kDefault_GrSLPrecision)
+        : fType(type)
+        , fTypeModifier(typeModifier)
+        , fCount(kNonArray)
+        , fPrecision(precision)
+        , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
+        , fName(name) {
+        SkASSERT(kVoid_GrSLType != type);
+    }
+
+    GrShaderVar(const char* name, GrSLType type, TypeModifier typeModifier,
+                int arrayCount, GrSLPrecision precision = kDefault_GrSLPrecision)
+        : fType(type)
+        , fTypeModifier(typeModifier)
+        , fCount(arrayCount)
+        , fPrecision(precision)
+        , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
+        , fName(name) {
+        SkASSERT(kVoid_GrSLType != type);
+    }
+
+    GrShaderVar(const GrShaderVar& that)
+        : fType(that.fType)
+        , fTypeModifier(that.fTypeModifier)
+        , fCount(that.fCount)
+        , fPrecision(that.fPrecision)
+        , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
+        , fName(that.fName)
+        , fLayoutQualifier(that.fLayoutQualifier)
+        , fExtraModifiers(that.fExtraModifiers) {
+        SkASSERT(kVoid_GrSLType != that.getType());
+    }
+
+    /**
+     * Sets as a non-array.
+     */
     void set(GrSLType type,
              const SkString& name,
              TypeModifier typeModifier = kNone_TypeModifier,
              GrSLPrecision precision = kDefault_GrSLPrecision,
-             int count = kNonArray) {
+             const char* layoutQualifier = nullptr,
+             const char* extraModifiers = nullptr,
+             bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
         SkASSERT(kVoid_GrSLType != type);
+        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
         fType = type;
         fTypeModifier = typeModifier;
         fName = name;
-        fCount = count;
+        fCount = kNonArray;
         fPrecision = precision;
+        fLayoutQualifier = layoutQualifier;
+        if (extraModifiers) {
+            fExtraModifiers.printf("%s ", extraModifiers);
+        }
+        fUseUniformFloatArrays = useUniformFloatArrays;
     }
 
+    /**
+     * Sets as a non-array.
+     */
     void set(GrSLType type,
              const char* name,
              TypeModifier typeModifier = kNone_TypeModifier,
              GrSLPrecision precision = kDefault_GrSLPrecision,
-             int count = kNonArray) {
+             const char* layoutQualifier = nullptr,
+             const char* extraModifiers = nullptr,
+             bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
         SkASSERT(kVoid_GrSLType != type);
+        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
+        fType = type;
+        fTypeModifier = typeModifier;
+        fName = name;
+        fCount = kNonArray;
+        fPrecision = precision;
+        fLayoutQualifier = layoutQualifier;
+        if (extraModifiers) {
+            fExtraModifiers.printf("%s ", extraModifiers);
+        }
+        fUseUniformFloatArrays = useUniformFloatArrays;
+    }
+
+    /**
+     * Set all var options
+     */
+    void set(GrSLType type,
+             const SkString& name,
+             int count,
+             TypeModifier typeModifier,
+             GrSLPrecision precision = kDefault_GrSLPrecision,
+             const char* layoutQualifier = nullptr,
+             const char* extraModifiers = nullptr,
+             bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
+        SkASSERT(kVoid_GrSLType != type);
+        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
         fType = type;
         fTypeModifier = typeModifier;
         fName = name;
         fCount = count;
         fPrecision = precision;
+        fLayoutQualifier = layoutQualifier;
+        if (extraModifiers) {
+            fExtraModifiers.printf("%s ", extraModifiers);
+        }
+        fUseUniformFloatArrays = useUniformFloatArrays;
+    }
+
+    /**
+     * Set all var options
+     */
+    void set(GrSLType type,
+             const char* name,
+             int count,
+             TypeModifier typeModifier,
+             GrSLPrecision precision = kDefault_GrSLPrecision,
+             const char* layoutQualifier = nullptr,
+             const char* extraModifiers = nullptr,
+             bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
+        SkASSERT(kVoid_GrSLType != type);
+        SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
+        fType = type;
+        fTypeModifier = typeModifier;
+        fName = name;
+        fCount = count;
+        fPrecision = precision;
+        fLayoutQualifier = layoutQualifier;
+        if (extraModifiers) {
+            fExtraModifiers.printf("%s ", extraModifiers);
+        }
+        fUseUniformFloatArrays = useUniformFloatArrays;
     }
 
     /**
@@ -171,12 +270,67 @@
      */
     void setPrecision(GrSLPrecision p) { fPrecision = p; }
 
-protected:
+    /**
+     * Set the layout qualifier
+     */
+    void setLayoutQualifier(const char* layoutQualifier) {
+        fLayoutQualifier = layoutQualifier;
+    }
+
+    void addModifier(const char* modifier) {
+        if (modifier) {
+            fExtraModifiers.appendf("%s ", modifier);
+        }
+    }
+
+    /**
+     * Write a declaration of this variable to out.
+     */
+    void appendDecl(const GrGLSLCaps* glslCaps, SkString* out) const;
+
+    void appendArrayAccess(int index, SkString* out) const {
+        out->appendf("%s[%d]%s",
+                     this->getName().c_str(),
+                     index,
+                     fUseUniformFloatArrays ? "" : ".x");
+    }
+
+    void appendArrayAccess(const char* indexName, SkString* out) const {
+        out->appendf("%s[%s]%s",
+                     this->getName().c_str(),
+                     indexName,
+                     fUseUniformFloatArrays ? "" : ".x");
+    }
+
+private:
+    static const char* TypeModifierString(TypeModifier t) {
+        switch (t) {
+            case kNone_TypeModifier:
+                return "";
+            case kIn_TypeModifier:
+                return "in";
+            case kInOut_TypeModifier:
+                return "inout";
+            case kOut_TypeModifier:
+                return "out";
+            case kUniform_TypeModifier:
+                return "uniform";
+        }
+        SkFAIL("Unknown shader variable type modifier.");
+        return ""; // suppress warning
+    }
+
     GrSLType        fType;
     TypeModifier    fTypeModifier;
-    SkString        fName;
     int             fCount;
     GrSLPrecision   fPrecision;
+    /// Work around driver bugs on some hardware that don't correctly
+    /// support uniform float []
+    bool            fUseUniformFloatArrays;
+
+    SkString        fName;
+    SkString        fLayoutQualifier;
+    SkString        fExtraModifiers;
 };
 
-#endif
+ #endif