• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
GrGLShaderVar()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 
GrGLShaderVar(const GrGLShaderVar & var)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      */
isArray()178     bool isArray() const { return kNonArray != fCount; }
179     /**
180      * Is this an unsized array, (i.e. declared with []).
181      */
isUnsizedArray()182     bool isUnsizedArray() const { return kUnsizedArray == fCount; }
183     /**
184      * Get the array length of the var.
185      */
getArrayCount()186     int getArrayCount() const { return fCount; }
187     /**
188      * Set the array length of the var
189      */
setArrayCount(int count)190     void setArrayCount(int count) { fCount = count; }
191     /**
192      * Set to be a non-array.
193      */
setNonArray()194     void setNonArray() { fCount = kNonArray; }
195     /**
196      * Set to be an unsized array.
197      */
setUnsizedArray()198     void setUnsizedArray() { fCount = kUnsizedArray; }
199 
200     /**
201      * Access the var name as a writable string
202      */
accessName()203     SkString* accessName() { return &fName; }
204     /**
205      * Set the var name
206      */
setName(const SkString & n)207     void setName(const SkString& n) { fName = n; }
setName(const char * n)208     void setName(const char* n) { fName = n; }
209 
210     /**
211      * Get the var name.
212      */
getName()213     const SkString& getName() const { return fName; }
214 
215     /**
216      * Shortcut for this->getName().c_str();
217      */
c_str()218     const char* c_str() const { return this->getName().c_str(); }
219 
220     /**
221      * Get the type of the var
222      */
getType()223     GrSLType getType() const { return fType; }
224     /**
225      * Set the type of the var
226      */
setType(GrSLType type)227     void setType(GrSLType type) { fType = type; }
228 
getTypeModifier()229     TypeModifier getTypeModifier() const { return fTypeModifier; }
setTypeModifier(TypeModifier type)230     void setTypeModifier(TypeModifier type) { fTypeModifier = type; }
231 
232     /**
233      * Get the precision of the var
234      */
getPrecision()235     Precision getPrecision() const { return fPrecision; }
236 
237     /**
238      * Set the precision of the var
239      */
setPrecision(Precision p)240     void setPrecision(Precision p) { fPrecision = p; }
241 
242     /**
243      * Get the origin of the var
244      */
getOrigin()245     Origin getOrigin() const { return fOrigin; }
246 
247     /**
248      * Set the origin of the var
249      */
setOrigin(Origin origin)250     void setOrigin(Origin origin) { fOrigin = origin; }
251 
252     /**
253      * Write a declaration of this variable to out.
254      */
appendDecl(const GrGLContextInfo & gl,SkString * out)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 
TypeString(GrSLType t)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 
appendArrayAccess(int index,SkString * out)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 
appendArrayAccess(const char * indexName,SkString * out)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:
TypeModifierString(TypeModifier t,GrGLSLGeneration gen)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 
PrecisionString(Precision p,GrGLBinding binding)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