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