text: /*
   * Copyright 2016 Google Inc.
   *
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */
  
  #ifndef GrShaderVar_DEFINED
  #define GrShaderVar_DEFINED
  
  #include "SkString.h"
  #include "GrTypesPriv.h"
  
  class GrShaderCaps;
  
  #define USE_UNIFORM_FLOAT_ARRAYS true
  
  /**
   * Represents a variable in a shader
   */
  class GrShaderVar {
  public:
      enum TypeModifier {
          kNone_TypeModifier,
          kOut_TypeModifier,
          kIn_TypeModifier,
          kInOut_TypeModifier,
          kUniform_TypeModifier,
      };
  
      /**
       * 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 half with no type modifier or layout qualifier.
       */
      GrShaderVar()
          : fType(kHalf_GrSLType)
          , fTypeModifier(kNone_TypeModifier)
          , fCount(kNonArray)
          , 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,
               const char* layoutQualifier = nullptr,
               const char* extraModifiers = nullptr,
               bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
          SkASSERT(kVoid_GrSLType != type);
          SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
          fType = type;
          fTypeModifier = typeModifier;
          fName = name;
          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,
               const char* layoutQualifier = nullptr,
               const char* extraModifiers = nullptr,
               bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
          SkASSERT(kVoid_GrSLType != type);
          SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(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 || GrSLTypeTemporarilyAcceptsPrecision(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 || GrSLTypeTemporarilyAcceptsPrecision(type));
          fType = type;
          fTypeModifier = typeModifier;
          fName = name;
          fCount = count;
          fPrecision = precision;
          fLayoutQualifier = layoutQualifier;
          if (extraModifiers) {
              fExtraModifiers.printf("%s ", extraModifiers);
          }
          fUseUniformFloatArrays = useUniformFloatArrays;
      }
  
      /**
       * Is the var an array.
       */
      bool isArray() const { return kNonArray != fCount; }
      /**
       * Is this an unsized array, (i.e. declared with []).
       */
      bool isUnsizedArray() const { return kUnsizedArray == fCount; }
      /**
       * Get the array length of the var.
       */
      int getArrayCount() const { return fCount; }
      /**
       * Set the array length of the var
       */
      void setArrayCount(int count) { fCount = count; }
      /**
       * Set to be a non-array.
       */
      void setNonArray() { fCount = kNonArray; }
      /**
       * Set to be an unsized array.
       */
      void setUnsizedArray() { fCount = kUnsizedArray; }
  
      /**
       * Access the var name as a writable string
       */
      SkString* accessName() { return &fName; }
      /**
       * Set the var name
       */
      void setName(const SkString& n) { fName = n; }
      void setName(const char* n) { fName = n; }
  
      /**
       * Get the var name.
       */
      const SkString& getName() const { return fName; }
  
      /**
       * Shortcut for this->getName().c_str();
       */
      const char* c_str() const { return this->getName().c_str(); }
  
      /**
       * Get the type of the var
       */
      GrSLType getType() const { return fType; }
      /**
       * Set the type of the var
       */
      void setType(GrSLType type) { fType = type; }
  
      TypeModifier getTypeModifier() const { return fTypeModifier; }
      void setTypeModifier(TypeModifier type) { fTypeModifier = type; }
  
      /**
       * Get the precision of the var
       */
      GrSLPrecision getPrecision() const { return fPrecision; }
  
      /**
       * Set the precision of the var
       */
      void setPrecision(GrSLPrecision p) { fPrecision = p; }
  
      /**
       * Appends to the layout qualifier
       */
      void addLayoutQualifier(const char* layoutQualifier) {
          if (!layoutQualifier || !strlen(layoutQualifier)) {
              return;
          }
          if (fLayoutQualifier.isEmpty()) {
              fLayoutQualifier = layoutQualifier;
          } else {
              fLayoutQualifier.appendf(", %s", layoutQualifier);
          }
      }
  
      void setIOType(GrIOType);
  
      void addModifier(const char* modifier) {
          if (modifier) {
              fExtraModifiers.appendf("%s ", modifier);
          }
      }
  
      /**
       * Write a declaration of this variable to out.
       */
      void appendDecl(const GrShaderCaps*, 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:
      GrSLType        fType;
      TypeModifier    fTypeModifier;
      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
  