1 /*
2  * Copyright 2016 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 GrShaderVar_DEFINED
9 #define GrShaderVar_DEFINED
10 
11 #include "SkString.h"
12 #include "GrTypesPriv.h"
13 
14 class GrShaderCaps;
15 
16 #define USE_UNIFORM_FLOAT_ARRAYS true
17 
18 /**
19  * Represents a variable in a shader
20  */
21 class GrShaderVar {
22 public:
23     enum TypeModifier {
24         kNone_TypeModifier,
25         kOut_TypeModifier,
26         kIn_TypeModifier,
27         kInOut_TypeModifier,
28         kUniform_TypeModifier,
29     };
30 
31     /**
32      * Values for array count that have special meaning. We allow 1-sized arrays.git
33      */
34     enum {
35         kNonArray     =  0, // not an array
36         kUnsizedArray = -1, // an unsized array (declared with [])
37     };
38 
39     /**
40      * Defaults to a non-arry half with no type modifier or layout qualifier.
41      */
42     GrShaderVar()
43         : fType(kHalf_GrSLType)
44         , fTypeModifier(kNone_TypeModifier)
45         , fCount(kNonArray)
46         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
47     }
48 
49     GrShaderVar(const SkString& name, GrSLType type, int arrayCount = kNonArray,
50                 GrSLPrecision precision = kDefault_GrSLPrecision)
51         : fType(type)
52         , fTypeModifier(kNone_TypeModifier)
53         , fCount(arrayCount)
54         , fPrecision(precision)
55         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
56         , fName(name) {
57         SkASSERT(kVoid_GrSLType != type);
58         fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
59     }
60 
61     GrShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray,
62                 GrSLPrecision precision = kDefault_GrSLPrecision)
63         : fType(type)
64         , fTypeModifier(kNone_TypeModifier)
65         , fCount(arrayCount)
66         , fPrecision(precision)
67         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
68         , fName(name) {
69         SkASSERT(kVoid_GrSLType != type);
70         fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
71     }
72 
73     GrShaderVar(const char* name, GrSLType type, TypeModifier typeModifier,
74                 GrSLPrecision precision = kDefault_GrSLPrecision)
75         : fType(type)
76         , fTypeModifier(typeModifier)
77         , fCount(kNonArray)
78         , fPrecision(precision)
79         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
80         , fName(name) {
81         SkASSERT(kVoid_GrSLType != type);
82     }
83 
84     GrShaderVar(const char* name, GrSLType type, TypeModifier typeModifier,
85                 int arrayCount, GrSLPrecision precision = kDefault_GrSLPrecision)
86         : fType(type)
87         , fTypeModifier(typeModifier)
88         , fCount(arrayCount)
89         , fPrecision(precision)
90         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
91         , fName(name) {
92         SkASSERT(kVoid_GrSLType != type);
93     }
94 
95     GrShaderVar(const GrShaderVar& that)
96         : fType(that.fType)
97         , fTypeModifier(that.fTypeModifier)
98         , fCount(that.fCount)
99         , fPrecision(that.fPrecision)
100         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
101         , fName(that.fName)
102         , fLayoutQualifier(that.fLayoutQualifier)
103         , fExtraModifiers(that.fExtraModifiers) {
104         SkASSERT(kVoid_GrSLType != that.getType());
105     }
106 
107     /**
108      * Sets as a non-array.
109      */
110     void set(GrSLType type,
111              const SkString& name,
112              TypeModifier typeModifier = kNone_TypeModifier,
113              GrSLPrecision precision = kDefault_GrSLPrecision,
114              const char* layoutQualifier = nullptr,
115              const char* extraModifiers = nullptr,
116              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
117         SkASSERT(kVoid_GrSLType != type);
118         SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
119         fType = type;
120         fTypeModifier = typeModifier;
121         fName = name;
122         fCount = kNonArray;
123         fPrecision = precision;
124         fLayoutQualifier = layoutQualifier;
125         if (extraModifiers) {
126             fExtraModifiers.printf("%s ", extraModifiers);
127         }
128         fUseUniformFloatArrays = useUniformFloatArrays;
129     }
130 
131     /**
132      * Sets as a non-array.
133      */
134     void set(GrSLType type,
135              const char* name,
136              TypeModifier typeModifier = kNone_TypeModifier,
137              GrSLPrecision precision = kDefault_GrSLPrecision,
138              const char* layoutQualifier = nullptr,
139              const char* extraModifiers = nullptr,
140              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
141         SkASSERT(kVoid_GrSLType != type);
142         SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
143         fType = type;
144         fTypeModifier = typeModifier;
145         fName = name;
146         fCount = kNonArray;
147         fPrecision = precision;
148         fLayoutQualifier = layoutQualifier;
149         if (extraModifiers) {
150             fExtraModifiers.printf("%s ", extraModifiers);
151         }
152         fUseUniformFloatArrays = useUniformFloatArrays;
153     }
154 
155     /**
156      * Set all var options
157      */
158     void set(GrSLType type,
159              const SkString& name,
160              int count,
161              TypeModifier typeModifier,
162              GrSLPrecision precision = kDefault_GrSLPrecision,
163              const char* layoutQualifier = nullptr,
164              const char* extraModifiers = nullptr,
165              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
166         SkASSERT(kVoid_GrSLType != type);
167         SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
168         fType = type;
169         fTypeModifier = typeModifier;
170         fName = name;
171         fCount = count;
172         fPrecision = precision;
173         fLayoutQualifier = layoutQualifier;
174         if (extraModifiers) {
175             fExtraModifiers.printf("%s ", extraModifiers);
176         }
177         fUseUniformFloatArrays = useUniformFloatArrays;
178     }
179 
180     /**
181      * Set all var options
182      */
183     void set(GrSLType type,
184              const char* name,
185              int count,
186              TypeModifier typeModifier,
187              GrSLPrecision precision = kDefault_GrSLPrecision,
188              const char* layoutQualifier = nullptr,
189              const char* extraModifiers = nullptr,
190              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
191         SkASSERT(kVoid_GrSLType != type);
192         SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
193         fType = type;
194         fTypeModifier = typeModifier;
195         fName = name;
196         fCount = count;
197         fPrecision = precision;
198         fLayoutQualifier = layoutQualifier;
199         if (extraModifiers) {
200             fExtraModifiers.printf("%s ", extraModifiers);
201         }
202         fUseUniformFloatArrays = useUniformFloatArrays;
203     }
204 
205     /**
206      * Is the var an array.
207      */
208     bool isArray() const { return kNonArray != fCount; }
209     /**
210      * Is this an unsized array, (i.e. declared with []).
211      */
212     bool isUnsizedArray() const { return kUnsizedArray == fCount; }
213     /**
214      * Get the array length of the var.
215      */
216     int getArrayCount() const { return fCount; }
217     /**
218      * Set the array length of the var
219      */
220     void setArrayCount(int count) { fCount = count; }
221     /**
222      * Set to be a non-array.
223      */
224     void setNonArray() { fCount = kNonArray; }
225     /**
226      * Set to be an unsized array.
227      */
228     void setUnsizedArray() { fCount = kUnsizedArray; }
229 
230     /**
231      * Access the var name as a writable string
232      */
233     SkString* accessName() { return &fName; }
234     /**
235      * Set the var name
236      */
237     void setName(const SkString& n) { fName = n; }
238     void setName(const char* n) { fName = n; }
239 
240     /**
241      * Get the var name.
242      */
243     const SkString& getName() const { return fName; }
244 
245     /**
246      * Shortcut for this->getName().c_str();
247      */
248     const char* c_str() const { return this->getName().c_str(); }
249 
250     /**
251      * Get the type of the var
252      */
253     GrSLType getType() const { return fType; }
254     /**
255      * Set the type of the var
256      */
257     void setType(GrSLType type) { fType = type; }
258 
259     TypeModifier getTypeModifier() const { return fTypeModifier; }
260     void setTypeModifier(TypeModifier type) { fTypeModifier = type; }
261 
262     /**
263      * Get the precision of the var
264      */
265     GrSLPrecision getPrecision() const { return fPrecision; }
266 
267     /**
268      * Set the precision of the var
269      */
270     void setPrecision(GrSLPrecision p) { fPrecision = p; }
271 
272     /**
273      * Appends to the layout qualifier
274      */
275     void addLayoutQualifier(const char* layoutQualifier) {
276         if (!layoutQualifier || !strlen(layoutQualifier)) {
277             return;
278         }
279         if (fLayoutQualifier.isEmpty()) {
280             fLayoutQualifier = layoutQualifier;
281         } else {
282             fLayoutQualifier.appendf(", %s", layoutQualifier);
283         }
284     }
285 
286     void setIOType(GrIOType);
287 
288     void addModifier(const char* modifier) {
289         if (modifier) {
290             fExtraModifiers.appendf("%s ", modifier);
291         }
292     }
293 
294     /**
295      * Write a declaration of this variable to out.
296      */
297     void appendDecl(const GrShaderCaps*, SkString* out) const;
298 
299     void appendArrayAccess(int index, SkString* out) const {
300         out->appendf("%s[%d]%s",
301                      this->getName().c_str(),
302                      index,
303                      fUseUniformFloatArrays ? "" : ".x");
304     }
305 
306     void appendArrayAccess(const char* indexName, SkString* out) const {
307         out->appendf("%s[%s]%s",
308                      this->getName().c_str(),
309                      indexName,
310                      fUseUniformFloatArrays ? "" : ".x");
311     }
312 
313 private:
314     GrSLType        fType;
315     TypeModifier    fTypeModifier;
316     int             fCount;
317     GrSLPrecision   fPrecision;
318     /// Work around driver bugs on some hardware that don't correctly
319     /// support uniform float []
320     bool            fUseUniformFloatArrays;
321 
322     SkString        fName;
323     SkString        fLayoutQualifier;
324     SkString        fExtraModifiers;
325 };
326 
327 #endif
328