|
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 GrCrash("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 GrCrash("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 |