blob: c79589772ae704a48f81b35938a30777f9b5e82e [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
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +000070 GrGLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray) {
71 GrAssert(kVoid_GrSLType != type);
72 fType = type;
73 fTypeModifier = kNone_TypeModifier;
74 fCount = arrayCount;
75 fPrecision = kDefault_Precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +000076 fOrigin = kDefault_Origin;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +000077 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
78 fName = name;
79 }
80
bsalomon@google.com4fa66942011-09-20 19:06:12 +000081 GrGLShaderVar(const GrGLShaderVar& var)
82 : fType(var.fType)
tomhudson@google.com086e5352011-12-08 14:44:10 +000083 , fTypeModifier(var.fTypeModifier)
bsalomon@google.com4fa66942011-09-20 19:06:12 +000084 , fName(var.fName)
85 , fCount(var.fCount)
bsalomon@google.comd7727ce2012-07-12 16:40:03 +000086 , fPrecision(var.fPrecision)
bsalomon@google.comb7f9a862012-10-25 19:35:05 +000087 , fOrigin(var.fOrigin)
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +000088 , fUseUniformFloatArrays(var.fUseUniformFloatArrays) {
89 GrAssert(kVoid_GrSLType != var.fType);
90 }
bsalomon@google.com4fa66942011-09-20 19:06:12 +000091
92 /**
93 * Values for array count that have special meaning. We allow 1-sized arrays.
94 */
95 enum {
96 kNonArray = 0, // not an array
97 kUnsizedArray = -1, // an unsized array (declared with [])
98 };
99
100 /**
101 * Sets as a non-array.
102 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000103 void set(GrSLType type,
tomhudson@google.com086e5352011-12-08 14:44:10 +0000104 TypeModifier typeModifier,
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000105 const SkString& name,
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000106 Precision precision = kDefault_Precision,
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000107 Origin origin = kDefault_Origin,
tomhudson@google.comda668982011-12-07 15:06:29 +0000108 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000109 GrAssert(kVoid_GrSLType != type);
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000110 fType = type;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000111 fTypeModifier = typeModifier;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000112 fName = name;
113 fCount = kNonArray;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000114 fPrecision = precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000115 fOrigin = origin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000116 fUseUniformFloatArrays = useUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000117 }
118
119 /**
120 * Sets as a non-array.
121 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000122 void set(GrSLType type,
tomhudson@google.com086e5352011-12-08 14:44:10 +0000123 TypeModifier typeModifier,
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000124 const char* name,
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000125 Precision precision = kDefault_Precision,
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000126 Origin origin = kDefault_Origin,
tomhudson@google.comda668982011-12-07 15:06:29 +0000127 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000128 GrAssert(kVoid_GrSLType != type);
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000129 fType = type;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000130 fTypeModifier = typeModifier;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000131 fName = name;
132 fCount = kNonArray;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000133 fPrecision = precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000134 fOrigin = origin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000135 fUseUniformFloatArrays = useUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000136 }
137
138 /**
139 * Set all var options
140 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000141 void set(GrSLType type,
tomhudson@google.com086e5352011-12-08 14:44:10 +0000142 TypeModifier typeModifier,
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000143 const SkString& name,
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000144 int count,
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000145 Precision precision = kDefault_Precision,
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000146 Origin origin = kDefault_Origin,
tomhudson@google.comda668982011-12-07 15:06:29 +0000147 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000148 GrAssert(kVoid_GrSLType != type);
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000149 fType = type;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000150 fTypeModifier = typeModifier;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000151 fName = name;
152 fCount = count;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000153 fPrecision = precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000154 fOrigin = origin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000155 fUseUniformFloatArrays = useUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000156 }
157
158 /**
159 * Set all var options
160 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000161 void set(GrSLType type,
tomhudson@google.com086e5352011-12-08 14:44:10 +0000162 TypeModifier typeModifier,
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000163 const char* name,
164 int count,
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000165 Precision precision = kDefault_Precision,
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000166 Origin origin = kDefault_Origin,
tomhudson@google.comda668982011-12-07 15:06:29 +0000167 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000168 GrAssert(kVoid_GrSLType != type);
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000169 fType = type;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000170 fTypeModifier = typeModifier;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000171 fName = name;
172 fCount = count;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000173 fPrecision = precision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000174 fOrigin = origin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000175 fUseUniformFloatArrays = useUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000176 }
177
178 /**
179 * Is the var an array.
180 */
181 bool isArray() const { return kNonArray != fCount; }
182 /**
183 * Is this an unsized array, (i.e. declared with []).
184 */
185 bool isUnsizedArray() const { return kUnsizedArray == fCount; }
186 /**
187 * Get the array length of the var.
188 */
189 int getArrayCount() const { return fCount; }
190 /**
191 * Set the array length of the var
192 */
193 void setArrayCount(int count) { fCount = count; }
194 /**
195 * Set to be a non-array.
196 */
197 void setNonArray() { fCount = kNonArray; }
198 /**
199 * Set to be an unsized array.
200 */
201 void setUnsizedArray() { fCount = kUnsizedArray; }
202
203 /**
204 * Access the var name as a writable string
205 */
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000206 SkString* accessName() { return &fName; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000207 /**
208 * Set the var name
209 */
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000210 void setName(const SkString& n) { fName = n; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000211 void setName(const char* n) { fName = n; }
bsalomon@google.com032b2212012-07-16 13:36:18 +0000212
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000213 /**
214 * Get the var name.
215 */
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000216 const SkString& getName() const { return fName; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000217
218 /**
bsalomon@google.com032b2212012-07-16 13:36:18 +0000219 * Shortcut for this->getName().c_str();
220 */
221 const char* c_str() const { return this->getName().c_str(); }
222
223 /**
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000224 * Get the type of the var
225 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000226 GrSLType getType() const { return fType; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000227 /**
228 * Set the type of the var
229 */
tomhudson@google.com168e6342012-04-18 17:49:20 +0000230 void setType(GrSLType type) { fType = type; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000231
tomhudson@google.com086e5352011-12-08 14:44:10 +0000232 TypeModifier getTypeModifier() const { return fTypeModifier; }
233 void setTypeModifier(TypeModifier type) { fTypeModifier = type; }
234
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000235 /**
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000236 * Get the precision of the var
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000237 */
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000238 Precision getPrecision() const { return fPrecision; }
239
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000240 /**
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000241 * Set the precision of the var
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000242 */
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000243 void setPrecision(Precision p) { fPrecision = p; }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000244
245 /**
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000246 * Get the origin of the var
247 */
248 Origin getOrigin() const { return fOrigin; }
249
250 /**
251 * Set the origin of the var
252 */
253 void setOrigin(Origin origin) { fOrigin = origin; }
254
255 /**
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000256 * Write a declaration of this variable to out.
257 */
robertphillips@google.com6177e692013-02-28 20:16:25 +0000258 void appendDecl(const GrGLContextInfo& ctxInfo, SkString* out) const {
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000259 if (kUpperLeft_Origin == fOrigin) {
260 // this is the only place where we specify a layout modifier. If we use other layout
261 // modifiers in the future then they should be placed in a list.
262 out->append("layout(origin_upper_left) ");
263 }
tomhudson@google.com086e5352011-12-08 14:44:10 +0000264 if (this->getTypeModifier() != kNone_TypeModifier) {
bsalomon@google.com96399942012-02-13 14:39:16 +0000265 out->append(TypeModifierString(this->getTypeModifier(),
robertphillips@google.com6177e692013-02-28 20:16:25 +0000266 ctxInfo.glslGeneration()));
tomhudson@google.com086e5352011-12-08 14:44:10 +0000267 out->append(" ");
268 }
robertphillips@google.com6177e692013-02-28 20:16:25 +0000269 out->append(PrecisionString(fPrecision, ctxInfo.binding()));
tomhudson@google.com168e6342012-04-18 17:49:20 +0000270 GrSLType effectiveType = this->getType();
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000271 if (this->isArray()) {
272 if (this->isUnsizedArray()) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000273 out->appendf("%s %s[]",
bsalomon@google.com018f1792013-04-18 19:36:09 +0000274 GrGLSLTypeString(effectiveType),
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000275 this->getName().c_str());
276 } else {
277 GrAssert(this->getArrayCount() > 0);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000278 out->appendf("%s %s[%d]",
bsalomon@google.com018f1792013-04-18 19:36:09 +0000279 GrGLSLTypeString(effectiveType),
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000280 this->getName().c_str(),
281 this->getArrayCount());
282 }
283 } else {
284 out->appendf("%s %s",
bsalomon@google.com018f1792013-04-18 19:36:09 +0000285 GrGLSLTypeString(effectiveType),
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000286 this->getName().c_str());
287 }
288 }
289
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000290 void appendArrayAccess(int index, SkString* out) const {
tomhudson@google.comda668982011-12-07 15:06:29 +0000291 out->appendf("%s[%d]%s",
292 this->getName().c_str(),
293 index,
294 fUseUniformFloatArrays ? "" : ".x");
295 }
296
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000297 void appendArrayAccess(const char* indexName, SkString* out) const {
tomhudson@google.comda668982011-12-07 15:06:29 +0000298 out->appendf("%s[%s]%s",
299 this->getName().c_str(),
300 indexName,
301 fUseUniformFloatArrays ? "" : ".x");
302 }
303
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000304private:
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000305 static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) {
tomhudson@google.com086e5352011-12-08 14:44:10 +0000306 switch (t) {
307 case kNone_TypeModifier:
308 return "";
tomhudson@google.com086e5352011-12-08 14:44:10 +0000309 case kIn_TypeModifier:
bsalomon@google.com77cf4602013-04-22 21:05:48 +0000310 return "in";
311 case kInOut_TypeModifier:
312 return "inout";
313 case kOut_TypeModifier:
314 return "out";
tomhudson@google.com086e5352011-12-08 14:44:10 +0000315 case kUniform_TypeModifier:
316 return "uniform";
317 case kAttribute_TypeModifier:
bsalomon@google.come55fd0f2012-02-10 15:56:06 +0000318 return k110_GrGLSLGeneration == gen ? "attribute" : "in";
bsalomon@google.com77cf4602013-04-22 21:05:48 +0000319 case kVaryingIn_TypeModifier:
320 return k110_GrGLSLGeneration == gen ? "varying" : "in";
321 case kVaryingOut_TypeModifier:
322 return k110_GrGLSLGeneration == gen ? "varying" : "out";
tomhudson@google.com086e5352011-12-08 14:44:10 +0000323 default:
324 GrCrash("Unknown shader variable type modifier.");
325 return ""; // suppress warning
326 }
327 }
328
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000329 static const char* PrecisionString(Precision p, GrGLBinding binding) {
330 // Desktop GLSL has added precision qualifiers but they don't do anything.
331 if (kES2_GrGLBinding == binding) {
332 switch (p) {
333 case kLow_Precision:
334 return "lowp ";
335 case kMedium_Precision:
336 return "mediump ";
337 case kHigh_Precision:
338 return "highp ";
339 case kDefault_Precision:
340 return "";
341 default:
342 GrCrash("Unexpected precision type.");
343 }
344 }
345 return "";
346 }
347
348 GrSLType fType;
tomhudson@google.com086e5352011-12-08 14:44:10 +0000349 TypeModifier fTypeModifier;
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000350 SkString fName;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000351 int fCount;
bsalomon@google.comd7727ce2012-07-12 16:40:03 +0000352 Precision fPrecision;
bsalomon@google.com5fa21072012-10-25 14:57:46 +0000353 Origin fOrigin;
tomhudson@google.comda668982011-12-07 15:06:29 +0000354 /// Work around driver bugs on some hardware that don't correctly
355 /// support uniform float []
356 bool fUseUniformFloatArrays;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000357};
358
359#endif