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 GrGLSLShaderVar_DEFINED
9 #define GrGLSLShaderVar_DEFINED
10 
11 #include "GrShaderVar.h"
12 #include "../glsl/GrGLSL.h"
13 #include "../glsl/GrGLSLCaps.h"
14 
15 #define USE_UNIFORM_FLOAT_ARRAYS true
16 
17 /**
18  * Represents a variable in a shader
19  */
20 class GrGLSLShaderVar : public GrShaderVar {
21 public:
22     /**
23      * Defaults to a float with no precision specifier
24      */
GrGLSLShaderVar()25     GrGLSLShaderVar()
26         : GrShaderVar()
27         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
28     }
29 
30     GrGLSLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray,
31                     GrSLPrecision precision = kDefault_GrSLPrecision)
GrShaderVar(name,type,arrayCount,precision)32         : GrShaderVar(name, type, arrayCount, precision)
33         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
34         SkASSERT(kVoid_GrSLType != type);
35         fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
36     }
37 
38     GrGLSLShaderVar(const char* name, GrSLType type, TypeModifier typeModifier,
39                     int arrayCount = kNonArray, GrSLPrecision precision = kDefault_GrSLPrecision)
GrShaderVar(name,type,typeModifier,arrayCount,precision)40         : GrShaderVar(name, type, typeModifier, arrayCount, precision)
41         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
42         SkASSERT(kVoid_GrSLType != type);
43     }
44 
GrGLSLShaderVar(const GrShaderVar & var)45     GrGLSLShaderVar(const GrShaderVar& var)
46         : GrShaderVar(var)
47         , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
48         SkASSERT(kVoid_GrSLType != var.getType());
49     }
50 
GrGLSLShaderVar(const GrGLSLShaderVar & var)51     GrGLSLShaderVar(const GrGLSLShaderVar& var)
52         : GrShaderVar(var.c_str(), var.getType(), var.getTypeModifier(),
53                       var.getArrayCount(), var.getPrecision())
54         , fUseUniformFloatArrays(var.fUseUniformFloatArrays)
55         , fLayoutQualifier(var.fLayoutQualifier)
56         , fExtraModifiers(var.fExtraModifiers) {
57         SkASSERT(kVoid_GrSLType != var.getType());
58     }
59 
60     /**
61      * Values for array count that have special meaning. We allow 1-sized arrays.
62      */
63     enum {
64         kNonArray     =  0, // not an array
65         kUnsizedArray = -1, // an unsized array (declared with [])
66     };
67 
68     /**
69      * Sets as a non-array.
70      */
71     void set(GrSLType type,
72              TypeModifier typeModifier,
73              const SkString& name,
74              GrSLPrecision precision = kDefault_GrSLPrecision,
75              const char* layoutQualifier = nullptr,
76              const char* extraModifiers = nullptr,
77              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
78         SkASSERT(kVoid_GrSLType != type);
79         SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type));
80         INHERITED::set(type, name, typeModifier, precision);
81         fLayoutQualifier = layoutQualifier;
82         if (extraModifiers) {
83             fExtraModifiers.printf("%s ", extraModifiers);
84         }
85         fUseUniformFloatArrays = useUniformFloatArrays;
86     }
87 
88     /**
89      * Sets as a non-array.
90      */
91     void set(GrSLType type,
92              TypeModifier typeModifier,
93              const char* name,
94              GrSLPrecision precision = kDefault_GrSLPrecision,
95              const char* layoutQualifier = nullptr,
96              const char* extraModifiers = nullptr,
97              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
98         SkASSERT(kVoid_GrSLType != type);
99         SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type));
100         INHERITED::set(type, name, typeModifier, precision);
101         fLayoutQualifier = layoutQualifier;
102         if (extraModifiers) {
103             fExtraModifiers.printf("%s ", extraModifiers);
104         }
105         fUseUniformFloatArrays = useUniformFloatArrays;
106     }
107 
108     /**
109      * Set all var options
110      */
111     void set(GrSLType type,
112              TypeModifier typeModifier,
113              const SkString& name,
114              int count,
115              GrSLPrecision precision = kDefault_GrSLPrecision,
116              const char* layoutQualifier = nullptr,
117              const char* extraModifiers = nullptr,
118              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
119         SkASSERT(kVoid_GrSLType != type);
120         SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type));
121         INHERITED::set(type, name, typeModifier, precision, count);
122         fLayoutQualifier = layoutQualifier;
123         if (extraModifiers) {
124             fExtraModifiers.printf("%s ", extraModifiers);
125         }
126         fUseUniformFloatArrays = useUniformFloatArrays;
127     }
128 
129     /**
130      * Set all var options
131      */
132     void set(GrSLType type,
133              TypeModifier typeModifier,
134              const char* name,
135              int count,
136              GrSLPrecision precision = kDefault_GrSLPrecision,
137              const char* layoutQualifier = nullptr,
138              const char* extraModifiers = nullptr,
139              bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
140         SkASSERT(kVoid_GrSLType != type);
141         SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type));
142         INHERITED::set(type, name, typeModifier, precision, count);
143         fLayoutQualifier = layoutQualifier;
144         if (extraModifiers) {
145             fExtraModifiers.printf("%s ", extraModifiers);
146         }
147         fUseUniformFloatArrays = useUniformFloatArrays;
148     }
149 
150     /**
151      * Set the layout qualifier
152      */
setLayoutQualifier(const char * layoutQualifier)153     void setLayoutQualifier(const char* layoutQualifier) {
154         fLayoutQualifier = layoutQualifier;
155     }
156 
addModifier(const char * modifier)157     void addModifier(const char* modifier) {
158         if (modifier) {
159             fExtraModifiers.appendf("%s ", modifier);
160         }
161     }
162 
163     /**
164      * Write a declaration of this variable to out.
165      */
appendDecl(const GrGLSLCaps * glslCaps,SkString * out)166     void appendDecl(const GrGLSLCaps* glslCaps, SkString* out) const {
167         SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeIsNumeric(fType));
168         if (!fLayoutQualifier.isEmpty()) {
169             out->appendf("layout(%s) ", fLayoutQualifier.c_str());
170         }
171         out->append(fExtraModifiers);
172         if (this->getTypeModifier() != kNone_TypeModifier) {
173             out->append(TypeModifierString(glslCaps, this->getTypeModifier()));
174             out->append(" ");
175         }
176         GrSLType effectiveType = this->getType();
177         if (effectiveType != kBool_GrSLType) {
178             out->append(PrecisionString(glslCaps, fPrecision));
179         }
180         if (this->isArray()) {
181             if (this->isUnsizedArray()) {
182                 out->appendf("%s %s[]",
183                              GrGLSLTypeString(effectiveType),
184                              this->getName().c_str());
185             } else {
186                 SkASSERT(this->getArrayCount() > 0);
187                 out->appendf("%s %s[%d]",
188                              GrGLSLTypeString(effectiveType),
189                              this->getName().c_str(),
190                              this->getArrayCount());
191             }
192         } else {
193             out->appendf("%s %s",
194                          GrGLSLTypeString(effectiveType),
195                          this->getName().c_str());
196         }
197     }
198 
appendArrayAccess(int index,SkString * out)199     void appendArrayAccess(int index, SkString* out) const {
200         out->appendf("%s[%d]%s",
201                      this->getName().c_str(),
202                      index,
203                      fUseUniformFloatArrays ? "" : ".x");
204     }
205 
appendArrayAccess(const char * indexName,SkString * out)206     void appendArrayAccess(const char* indexName, SkString* out) const {
207         out->appendf("%s[%s]%s",
208                      this->getName().c_str(),
209                      indexName,
210                      fUseUniformFloatArrays ? "" : ".x");
211     }
212 
PrecisionString(const GrGLSLCaps * glslCaps,GrSLPrecision p)213     static const char* PrecisionString(const GrGLSLCaps* glslCaps, GrSLPrecision p) {
214         // Desktop GLSL has added precision qualifiers but they don't do anything.
215         if (glslCaps->usesPrecisionModifiers()) {
216             switch (p) {
217                 case kLow_GrSLPrecision:
218                     return "lowp ";
219                 case kMedium_GrSLPrecision:
220                     return "mediump ";
221                 case kHigh_GrSLPrecision:
222                     return "highp ";
223                 default:
224                     SkFAIL("Unexpected precision type.");
225             }
226         }
227         return "";
228     }
229 
230 private:
TypeModifierString(const GrGLSLCaps * glslCaps,TypeModifier t)231     static const char* TypeModifierString(const GrGLSLCaps* glslCaps, TypeModifier t) {
232         GrGLSLGeneration gen = glslCaps->generation();
233         switch (t) {
234             case kNone_TypeModifier:
235                 return "";
236             case kIn_TypeModifier:
237                 return "in";
238             case kInOut_TypeModifier:
239                 return "inout";
240             case kOut_TypeModifier:
241                 return "out";
242             case kUniform_TypeModifier:
243                 return "uniform";
244             case kAttribute_TypeModifier:
245                 return k110_GrGLSLGeneration == gen ? "attribute" : "in";
246             case kVaryingIn_TypeModifier:
247                 return k110_GrGLSLGeneration == gen ? "varying" : "in";
248             case kVaryingOut_TypeModifier:
249                 return k110_GrGLSLGeneration == gen ? "varying" : "out";
250             default:
251                 SkFAIL("Unknown shader variable type modifier.");
252                 return ""; // suppress warning
253         }
254     }
255 
256     /// Work around driver bugs on some hardware that don't correctly
257     /// support uniform float []
258     bool        fUseUniformFloatArrays;
259 
260     SkString    fLayoutQualifier;
261     SkString    fExtraModifiers;
262 
263     typedef GrShaderVar INHERITED;
264 };
265 
266 #endif
267