blob: acbcef3c45d384e3783e38ca70abe132a467e89a [file] [log] [blame]
bsalomon@google.com4fa66942011-09-20 19:06:12 +00001/*
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
robertphillips@google.com6177e692013-02-28 20:16:25 +000011#include "GrGLContext.h"
tomhudson@google.com086e5352011-12-08 14:44:10 +000012#include "GrGLSL.h"
bsalomon@google.comf0a104e2012-07-10 17:51:07 +000013#include "SkString.h"
bsalomon@google.com4fa66942011-09-20 19:06:12 +000014
tomhudson@google.comda668982011-12-07 15:06:29 +000015#define USE_UNIFORM_FLOAT_ARRAYS true
16
bsalomon@google.com4fa66942011-09-20 19:06:12 +000017/**
18 * Represents a variable in a shader
19 */
20class GrGLShaderVar {
21public:
22
bsalomon@google.com4fa66942011-09-20 19:06:12 +000023 /**
tomhudson@google.com086e5352011-12-08 14:44:10 +000024 * 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,
bsalomon@google.com77cf4602013-04-22 21:05:48 +000032 kInOut_TypeModifier,
tomhudson@google.com086e5352011-12-08 14:44:10 +000033 kUniform_TypeModifier,
bsalomon@google.com77cf4602013-04-22 21:05:48 +000034 kAttribute_TypeModifier,
35 kVaryingIn_TypeModifier,
36 kVaryingOut_TypeModifier
tomhudson@google.com086e5352011-12-08 14:44:10 +000037 };
38
bsalomon@google.comd7727ce2012-07-12 16:40:03 +000039 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
tomhudson@google.com086e5352011-12-08 14:44:10 +000050 /**
bsalomon@google.com5fa21072012-10-25 14:57:46 +000051 * 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 /**
bsalomon@google.com4fa66942011-09-20 19:06:12 +000059 * Defaults to a float with no precision specifier
60 */
61 GrGLShaderVar() {
tomhudson@google.com168e6342012-04-18 17:49:20 +000062 fType = kFloat_GrSLType;
tomhudson@google.com086e5352011-12-08 14:44:10 +000063 fTypeModifier = kNone_TypeModifier;
bsalomon@google.com4fa66942011-09-20 19:06:12 +000064 fCount = kNonArray;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +000065 fPrecision = kDefault_Precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +000066 fOrigin = kDefault_Origin;
tomhudson@google.comda668982011-12-07 15:06:29 +000067 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
bsalomon@google.com4fa66942011-09-20 19:06:12 +000068 }
69
commit-bot@chromium.org344cf452013-06-17 14:19:01 +000070 GrGLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray,
71 Precision precision = kDefault_Precision) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000072 SkASSERT(kVoid_GrSLType != type);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +000073 fType = type;
74 fTypeModifier = kNone_TypeModifier;
75 fCount = arrayCount;
commit-bot@chromium.org344cf452013-06-17 14:19:01 +000076 fPrecision = precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +000077 fOrigin = kDefault_Origin;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +000078 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
79 fName = name;
80 }
81
bsalomon@google.com4fa66942011-09-20 19:06:12 +000082 GrGLShaderVar(const GrGLShaderVar& var)
83 : fType(var.fType)
tomhudson@google.com086e5352011-12-08 14:44:10 +000084 , fTypeModifier(var.fTypeModifier)
bsalomon@google.com4fa66942011-09-20 19:06:12 +000085 , fName(var.fName)
86 , fCount(var.fCount)
bsalomon@google.comd7727ce2012-07-12 16:40:03 +000087 , fPrecision(var.fPrecision)
bsalomon@google.comb7f9a862012-10-25 19:35:05 +000088 , fOrigin(var.fOrigin)
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +000089 , fUseUniformFloatArrays(var.fUseUniformFloatArrays) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000090 SkASSERT(kVoid_GrSLType != var.fType);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +000091 }
bsalomon@google.com4fa66942011-09-20 19:06:12 +000092
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 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000104 void set(GrSLType type,
tomhudson@google.com086e5352011-12-08 14:44:10 +0000105 TypeModifier typeModifier,
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000106 const SkString& name,
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000107 Precision precision = kDefault_Precision,
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000108 Origin origin = kDefault_Origin,
tomhudson@google.comda668982011-12-07 15:06:29 +0000109 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000110 SkASSERT(kVoid_GrSLType != type);
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000111 fType = type;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000112 fTypeModifier = typeModifier;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000113 fName = name;
114 fCount = kNonArray;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000115 fPrecision = precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000116 fOrigin = origin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000117 fUseUniformFloatArrays = useUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000118 }
119
120 /**
121 * Sets as a non-array.
122 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000123 void set(GrSLType type,
tomhudson@google.com086e5352011-12-08 14:44:10 +0000124 TypeModifier typeModifier,
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000125 const char* name,
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000126 Precision precision = kDefault_Precision,
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000127 Origin origin = kDefault_Origin,
tomhudson@google.comda668982011-12-07 15:06:29 +0000128 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000129 SkASSERT(kVoid_GrSLType != type);
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000130 fType = type;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000131 fTypeModifier = typeModifier;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000132 fName = name;
133 fCount = kNonArray;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000134 fPrecision = precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000135 fOrigin = origin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000136 fUseUniformFloatArrays = useUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000137 }
138
139 /**
140 * Set all var options
141 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000142 void set(GrSLType type,
tomhudson@google.com086e5352011-12-08 14:44:10 +0000143 TypeModifier typeModifier,
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000144 const SkString& name,
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000145 int count,
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000146 Precision precision = kDefault_Precision,
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000147 Origin origin = kDefault_Origin,
tomhudson@google.comda668982011-12-07 15:06:29 +0000148 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000149 SkASSERT(kVoid_GrSLType != type);
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000150 fType = type;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000151 fTypeModifier = typeModifier;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000152 fName = name;
153 fCount = count;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000154 fPrecision = precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000155 fOrigin = origin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000156 fUseUniformFloatArrays = useUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000157 }
158
159 /**
160 * Set all var options
161 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000162 void set(GrSLType type,
tomhudson@google.com086e5352011-12-08 14:44:10 +0000163 TypeModifier typeModifier,
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000164 const char* name,
165 int count,
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000166 Precision precision = kDefault_Precision,
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000167 Origin origin = kDefault_Origin,
tomhudson@google.comda668982011-12-07 15:06:29 +0000168 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000169 SkASSERT(kVoid_GrSLType != type);
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000170 fType = type;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000171 fTypeModifier = typeModifier;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000172 fName = name;
173 fCount = count;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000174 fPrecision = precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000175 fOrigin = origin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000176 fUseUniformFloatArrays = useUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000177 }
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 */
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000207 SkString* accessName() { return &fName; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000208 /**
209 * Set the var name
210 */
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000211 void setName(const SkString& n) { fName = n; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000212 void setName(const char* n) { fName = n; }
bsalomon@google.com032b2212012-07-16 13:36:18 +0000213
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000214 /**
215 * Get the var name.
216 */
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000217 const SkString& getName() const { return fName; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000218
219 /**
bsalomon@google.com032b2212012-07-16 13:36:18 +0000220 * Shortcut for this->getName().c_str();
221 */
222 const char* c_str() const { return this->getName().c_str(); }
223
224 /**
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000225 * Get the type of the var
226 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000227 GrSLType getType() const { return fType; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000228 /**
229 * Set the type of the var
230 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000231 void setType(GrSLType type) { fType = type; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000232
tomhudson@google.com086e5352011-12-08 14:44:10 +0000233 TypeModifier getTypeModifier() const { return fTypeModifier; }
234 void setTypeModifier(TypeModifier type) { fTypeModifier = type; }
235
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000236 /**
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000237 * Get the precision of the var
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000238 */
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000239 Precision getPrecision() const { return fPrecision; }
240
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000241 /**
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000242 * Set the precision of the var
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000243 */
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000244 void setPrecision(Precision p) { fPrecision = p; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000245
246 /**
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000247 * 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 /**
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000257 * Write a declaration of this variable to out.
258 */
robertphillips@google.com6177e692013-02-28 20:16:25 +0000259 void appendDecl(const GrGLContextInfo& ctxInfo, SkString* out) const {
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000260 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 }
tomhudson@google.com086e5352011-12-08 14:44:10 +0000265 if (this->getTypeModifier() != kNone_TypeModifier) {
bsalomon@google.com96399942012-02-13 14:39:16 +0000266 out->append(TypeModifierString(this->getTypeModifier(),
robertphillips@google.com6177e692013-02-28 20:16:25 +0000267 ctxInfo.glslGeneration()));
tomhudson@google.com086e5352011-12-08 14:44:10 +0000268 out->append(" ");
269 }
robertphillips@google.com6177e692013-02-28 20:16:25 +0000270 out->append(PrecisionString(fPrecision, ctxInfo.binding()));
tomhudson@google.com168e6342012-04-18 17:49:20 +0000271 GrSLType effectiveType = this->getType();
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000272 if (this->isArray()) {
273 if (this->isUnsizedArray()) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000274 out->appendf("%s %s[]",
bsalomon@google.com018f1792013-04-18 19:36:09 +0000275 GrGLSLTypeString(effectiveType),
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000276 this->getName().c_str());
277 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000278 SkASSERT(this->getArrayCount() > 0);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000279 out->appendf("%s %s[%d]",
bsalomon@google.com018f1792013-04-18 19:36:09 +0000280 GrGLSLTypeString(effectiveType),
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000281 this->getName().c_str(),
282 this->getArrayCount());
283 }
284 } else {
285 out->appendf("%s %s",
bsalomon@google.com018f1792013-04-18 19:36:09 +0000286 GrGLSLTypeString(effectiveType),
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000287 this->getName().c_str());
288 }
289 }
290
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000291 void appendArrayAccess(int index, SkString* out) const {
tomhudson@google.comda668982011-12-07 15:06:29 +0000292 out->appendf("%s[%d]%s",
293 this->getName().c_str(),
294 index,
295 fUseUniformFloatArrays ? "" : ".x");
296 }
297
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000298 void appendArrayAccess(const char* indexName, SkString* out) const {
tomhudson@google.comda668982011-12-07 15:06:29 +0000299 out->appendf("%s[%s]%s",
300 this->getName().c_str(),
301 indexName,
302 fUseUniformFloatArrays ? "" : ".x");
303 }
304
commit-bot@chromium.org344cf452013-06-17 14:19:01 +0000305 static const char* PrecisionString(Precision p, GrGLBinding binding) {
306 // Desktop GLSL has added precision qualifiers but they don't do anything.
bsalomon@google.com791816a2013-08-15 18:54:39 +0000307 if (kES_GrGLBinding == binding) {
commit-bot@chromium.org344cf452013-06-17 14:19:01 +0000308 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
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000324private:
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000325 static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) {
tomhudson@google.com086e5352011-12-08 14:44:10 +0000326 switch (t) {
327 case kNone_TypeModifier:
328 return "";
tomhudson@google.com086e5352011-12-08 14:44:10 +0000329 case kIn_TypeModifier:
bsalomon@google.com77cf4602013-04-22 21:05:48 +0000330 return "in";
331 case kInOut_TypeModifier:
332 return "inout";
333 case kOut_TypeModifier:
334 return "out";
tomhudson@google.com086e5352011-12-08 14:44:10 +0000335 case kUniform_TypeModifier:
336 return "uniform";
337 case kAttribute_TypeModifier:
bsalomon@google.come55fd0f2012-02-10 15:56:06 +0000338 return k110_GrGLSLGeneration == gen ? "attribute" : "in";
bsalomon@google.com77cf4602013-04-22 21:05:48 +0000339 case kVaryingIn_TypeModifier:
340 return k110_GrGLSLGeneration == gen ? "varying" : "in";
341 case kVaryingOut_TypeModifier:
342 return k110_GrGLSLGeneration == gen ? "varying" : "out";
tomhudson@google.com086e5352011-12-08 14:44:10 +0000343 default:
344 GrCrash("Unknown shader variable type modifier.");
345 return ""; // suppress warning
346 }
347 }
348
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000349 GrSLType fType;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000350 TypeModifier fTypeModifier;
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000351 SkString fName;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000352 int fCount;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000353 Precision fPrecision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000354 Origin fOrigin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000355 /// Work around driver bugs on some hardware that don't correctly
356 /// support uniform float []
357 bool fUseUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000358};
359
360#endif