Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef GrGLShaderVar_DEFINED
      9 #define GrGLShaderVar_DEFINED
     10 
     11 #include "GrGLContextInfo.h"
     12 #include "GrGLSL.h"
     13 #include "SkString.h"
     14 
     15 #define USE_UNIFORM_FLOAT_ARRAYS true
     16 
     17 /**
     18  * Represents a variable in a shader
     19  */
     20 class GrGLShaderVar {
     21 public:
     22 
     23     /**
     24      * Early versions of GLSL have Varying and Attribute; those are later
     25      * deprecated, but we still need to know whether a Varying variable
     26      * should be treated as In or Out.
     27      */
     28     enum TypeModifier {
     29         kNone_TypeModifier,
     30         kOut_TypeModifier,
     31         kIn_TypeModifier,
     32         kUniform_TypeModifier,
     33         kAttribute_TypeModifier
     34     };
     35 
     36     enum Precision {
     37         kLow_Precision,         // lowp
     38         kMedium_Precision,      // mediump
     39         kHigh_Precision,        // highp
     40         kDefault_Precision,     // Default for the current context. We make
     41                                 // fragment shaders default to mediump on ES2
     42                                 // because highp support is not guaranteed (and
     43                                 // we haven't been motivated to test for it).
     44                                 // Otherwise, highp.
     45     };
     46 
     47     /**
     48      * See GL_ARB_fragment_coord_conventions.
     49      */
     50     enum Origin {
     51         kDefault_Origin,        // when set to kDefault the origin field is ignored.
     52         kUpperLeft_Origin,      // only used to declare vec4 in gl_FragCoord.
     53     };
     54 
     55     /**
     56      * Defaults to a float with no precision specifier
     57      */
     58     GrGLShaderVar() {
     59         fType = kFloat_GrSLType;
     60         fTypeModifier = kNone_TypeModifier;
     61         fCount = kNonArray;
     62         fPrecision = kDefault_Precision;
     63         fOrigin = kDefault_Origin;
     64         fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
     65     }
     66 
     67     GrGLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray) {
     68         GrAssert(kVoid_GrSLType != type);
     69         fType = type;
     70         fTypeModifier = kNone_TypeModifier;
     71         fCount = arrayCount;
     72         fPrecision = kDefault_Precision;
     73         fOrigin = kDefault_Origin;
     74         fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
     75         fName = name;
     76     }
     77 
     78     GrGLShaderVar(const GrGLShaderVar& var)
     79         : fType(var.fType)
     80         , fTypeModifier(var.fTypeModifier)
     81         , fName(var.fName)
     82         , fCount(var.fCount)
     83         , fPrecision(var.fPrecision)
     84         , fOrigin(var.fOrigin)
     85         , fUseUniformFloatArrays(var.fUseUniformFloatArrays) {
     86         GrAssert(kVoid_GrSLType != var.fType);
     87     }
     88 
     89     /**
     90      * Values for array count that have special meaning. We allow 1-sized arrays.
     91      */
     92     enum {
     93         kNonArray     =  0, // not an array
     94         kUnsizedArray = -1, // an unsized array (declared with [])
     95     };
     96 
     97     /**
     98      * Sets as a non-array.
     99      */
    100     void set(GrSLType type,
    101              TypeModifier typeModifier,
    102              const SkString& name,
    103              Precision precision = kDefault_Precision,
    104              Origin origin = kDefault_Origin,
    105              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
    106         GrAssert(kVoid_GrSLType != type);
    107         fType = type;
    108         fTypeModifier = typeModifier;
    109         fName = name;
    110         fCount = kNonArray;
    111         fPrecision = precision;
    112         fOrigin = origin;
    113         fUseUniformFloatArrays = useUniformFloatArrays;
    114     }
    115 
    116     /**
    117      * Sets as a non-array.
    118      */
    119     void set(GrSLType type,
    120              TypeModifier typeModifier,
    121              const char* name,
    122              Precision precision = kDefault_Precision,
    123              Origin origin = kDefault_Origin,
    124              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
    125         GrAssert(kVoid_GrSLType != type);
    126         fType = type;
    127         fTypeModifier = typeModifier;
    128         fName = name;
    129         fCount = kNonArray;
    130         fPrecision = precision;
    131         fOrigin = origin;
    132         fUseUniformFloatArrays = useUniformFloatArrays;
    133     }
    134 
    135     /**
    136      * Set all var options
    137      */
    138     void set(GrSLType type,
    139              TypeModifier typeModifier,
    140              const SkString& name,
    141              int count,
    142              Precision precision = kDefault_Precision,
    143              Origin origin = kDefault_Origin,
    144              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
    145         GrAssert(kVoid_GrSLType != type);
    146         fType = type;
    147         fTypeModifier = typeModifier;
    148         fName = name;
    149         fCount = count;
    150         fPrecision = precision;
    151         fOrigin = origin;
    152         fUseUniformFloatArrays = useUniformFloatArrays;
    153     }
    154 
    155     /**
    156      * Set all var options
    157      */
    158     void set(GrSLType type,
    159              TypeModifier typeModifier,
    160              const char* name,
    161              int count,
    162              Precision precision = kDefault_Precision,
    163              Origin origin = kDefault_Origin,
    164              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
    165         GrAssert(kVoid_GrSLType != type);
    166         fType = type;
    167         fTypeModifier = typeModifier;
    168         fName = name;
    169         fCount = count;
    170         fPrecision = precision;
    171         fOrigin = origin;
    172         fUseUniformFloatArrays = useUniformFloatArrays;
    173     }
    174 
    175     /**
    176      * Is the var an array.
    177      */
    178     bool isArray() const { return kNonArray != fCount; }
    179     /**
    180      * Is this an unsized array, (i.e. declared with []).
    181      */
    182     bool isUnsizedArray() const { return kUnsizedArray == fCount; }
    183     /**
    184      * Get the array length of the var.
    185      */
    186     int getArrayCount() const { return fCount; }
    187     /**
    188      * Set the array length of the var
    189      */
    190     void setArrayCount(int count) { fCount = count; }
    191     /**
    192      * Set to be a non-array.
    193      */
    194     void setNonArray() { fCount = kNonArray; }
    195     /**
    196      * Set to be an unsized array.
    197      */
    198     void setUnsizedArray() { fCount = kUnsizedArray; }
    199 
    200     /**
    201      * Access the var name as a writable string
    202      */
    203     SkString* accessName() { return &fName; }
    204     /**
    205      * Set the var name
    206      */
    207     void setName(const SkString& n) { fName = n; }
    208     void setName(const char* n) { fName = n; }
    209 
    210     /**
    211      * Get the var name.
    212      */
    213     const SkString& getName() const { return fName; }
    214 
    215     /**
    216      * Shortcut for this->getName().c_str();
    217      */
    218     const char* c_str() const { return this->getName().c_str(); }
    219 
    220     /**
    221      * Get the type of the var
    222      */
    223     GrSLType getType() const { return fType; }
    224     /**
    225      * Set the type of the var
    226      */
    227     void setType(GrSLType type) { fType = type; }
    228 
    229     TypeModifier getTypeModifier() const { return fTypeModifier; }
    230     void setTypeModifier(TypeModifier type) { fTypeModifier = type; }
    231 
    232     /**
    233      * Get the precision of the var
    234      */
    235     Precision getPrecision() const { return fPrecision; }
    236 
    237     /**
    238      * Set the precision of the var
    239      */
    240     void setPrecision(Precision p) { fPrecision = p; }
    241 
    242     /**
    243      * Get the origin of the var
    244      */
    245     Origin getOrigin() const { return fOrigin; }
    246 
    247     /**
    248      * Set the origin of the var
    249      */
    250     void setOrigin(Origin origin) { fOrigin = origin; }
    251 
    252     /**
    253      * Write a declaration of this variable to out.
    254      */
    255     void appendDecl(const GrGLContextInfo& gl, SkString* out) const {
    256         if (kUpperLeft_Origin == fOrigin) {
    257             // this is the only place where we specify a layout modifier. If we use other layout
    258             // modifiers in the future then they should be placed in a list.
    259             out->append("layout(origin_upper_left) ");
    260         }
    261         if (this->getTypeModifier() != kNone_TypeModifier) {
    262            out->append(TypeModifierString(this->getTypeModifier(),
    263                                           gl.glslGeneration()));
    264            out->append(" ");
    265         }
    266         out->append(PrecisionString(fPrecision, gl.binding()));
    267         GrSLType effectiveType = this->getType();
    268         if (this->isArray()) {
    269             if (this->isUnsizedArray()) {
    270                 out->appendf("%s %s[]",
    271                              TypeString(effectiveType),
    272                              this->getName().c_str());
    273             } else {
    274                 GrAssert(this->getArrayCount() > 0);
    275                 out->appendf("%s %s[%d]",
    276                              TypeString(effectiveType),
    277                              this->getName().c_str(),
    278                              this->getArrayCount());
    279             }
    280         } else {
    281             out->appendf("%s %s",
    282                          TypeString(effectiveType),
    283                          this->getName().c_str());
    284         }
    285     }
    286 
    287     static const char* TypeString(GrSLType t) {
    288         switch (t) {
    289             case kVoid_GrSLType:
    290                 return "void";
    291             case kFloat_GrSLType:
    292                 return "float";
    293             case kVec2f_GrSLType:
    294                 return "vec2";
    295             case kVec3f_GrSLType:
    296                 return "vec3";
    297             case kVec4f_GrSLType:
    298                 return "vec4";
    299             case kMat33f_GrSLType:
    300                 return "mat3";
    301             case kMat44f_GrSLType:
    302                 return "mat4";
    303             case kSampler2D_GrSLType:
    304                 return "sampler2D";
    305             default:
    306                 GrCrash("Unknown shader var type.");
    307                 return ""; // suppress warning
    308         }
    309     }
    310 
    311     void appendArrayAccess(int index, SkString* out) const {
    312         out->appendf("%s[%d]%s",
    313                      this->getName().c_str(),
    314                      index,
    315                      fUseUniformFloatArrays ? "" : ".x");
    316     }
    317 
    318     void appendArrayAccess(const char* indexName, SkString* out) const {
    319         out->appendf("%s[%s]%s",
    320                      this->getName().c_str(),
    321                      indexName,
    322                      fUseUniformFloatArrays ? "" : ".x");
    323     }
    324 
    325 private:
    326     static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) {
    327         switch (t) {
    328             case kNone_TypeModifier:
    329                 return "";
    330             case kOut_TypeModifier:
    331                 return k110_GrGLSLGeneration == gen ? "varying" : "out";
    332             case kIn_TypeModifier:
    333                 return k110_GrGLSLGeneration == gen ? "varying" : "in";
    334             case kUniform_TypeModifier:
    335                 return "uniform";
    336             case kAttribute_TypeModifier:
    337                 return k110_GrGLSLGeneration == gen ? "attribute" : "in";
    338             default:
    339                 GrCrash("Unknown shader variable type modifier.");
    340                 return ""; // suppress warning
    341         }
    342     }
    343 
    344     static const char* PrecisionString(Precision p, GrGLBinding binding) {
    345         // Desktop GLSL has added precision qualifiers but they don't do anything.
    346         if (kES2_GrGLBinding == binding) {
    347             switch (p) {
    348                 case kLow_Precision:
    349                     return "lowp ";
    350                 case kMedium_Precision:
    351                     return "mediump ";
    352                 case kHigh_Precision:
    353                     return "highp ";
    354                 case kDefault_Precision:
    355                     return "";
    356                 default:
    357                     GrCrash("Unexpected precision type.");
    358             }
    359         }
    360         return "";
    361     }
    362 
    363     GrSLType        fType;
    364     TypeModifier    fTypeModifier;
    365     SkString        fName;
    366     int             fCount;
    367     Precision       fPrecision;
    368     Origin          fOrigin;
    369     /// Work around driver bugs on some hardware that don't correctly
    370     /// support uniform float []
    371     bool            fUseUniformFloatArrays;
    372 };
    373 
    374 #endif
    375