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