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 "GrGLContextInfo.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 kUniform_TypeModifier, 33 kAttribute_TypeModifier 34 }; 35 36 enum Precision { 37 kLow_Precision, // lowp 38 kMedium_Precision, // mediump 39 kHigh_Precision, // highp 40 kDefault_Precision, // Default for the current context. We make 41 // fragment shaders default to mediump on ES2 42 // because highp support is not guaranteed (and 43 // we haven't been motivated to test for it). 44 // Otherwise, highp. 45 }; 46 47 /** 48 * See GL_ARB_fragment_coord_conventions. 49 */ 50 enum Origin { 51 kDefault_Origin, // when set to kDefault the origin field is ignored. 52 kUpperLeft_Origin, // only used to declare vec4 in gl_FragCoord. 53 }; 54 55 /** 56 * Defaults to a float with no precision specifier 57 */ 58 GrGLShaderVar() { 59 fType = kFloat_GrSLType; 60 fTypeModifier = kNone_TypeModifier; 61 fCount = kNonArray; 62 fPrecision = kDefault_Precision; 63 fOrigin = kDefault_Origin; 64 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; 65 } 66 67 GrGLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray) { 68 GrAssert(kVoid_GrSLType != type); 69 fType = type; 70 fTypeModifier = kNone_TypeModifier; 71 fCount = arrayCount; 72 fPrecision = kDefault_Precision; 73 fOrigin = kDefault_Origin; 74 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; 75 fName = name; 76 } 77 78 GrGLShaderVar(const GrGLShaderVar& var) 79 : fType(var.fType) 80 , fTypeModifier(var.fTypeModifier) 81 , fName(var.fName) 82 , fCount(var.fCount) 83 , fPrecision(var.fPrecision) 84 , fOrigin(var.fOrigin) 85 , fUseUniformFloatArrays(var.fUseUniformFloatArrays) { 86 GrAssert(kVoid_GrSLType != var.fType); 87 } 88 89 /** 90 * Values for array count that have special meaning. We allow 1-sized arrays. 91 */ 92 enum { 93 kNonArray = 0, // not an array 94 kUnsizedArray = -1, // an unsized array (declared with []) 95 }; 96 97 /** 98 * Sets as a non-array. 99 */ 100 void set(GrSLType type, 101 TypeModifier typeModifier, 102 const SkString& name, 103 Precision precision = kDefault_Precision, 104 Origin origin = kDefault_Origin, 105 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 106 GrAssert(kVoid_GrSLType != type); 107 fType = type; 108 fTypeModifier = typeModifier; 109 fName = name; 110 fCount = kNonArray; 111 fPrecision = precision; 112 fOrigin = origin; 113 fUseUniformFloatArrays = useUniformFloatArrays; 114 } 115 116 /** 117 * Sets as a non-array. 118 */ 119 void set(GrSLType type, 120 TypeModifier typeModifier, 121 const char* name, 122 Precision precision = kDefault_Precision, 123 Origin origin = kDefault_Origin, 124 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 125 GrAssert(kVoid_GrSLType != type); 126 fType = type; 127 fTypeModifier = typeModifier; 128 fName = name; 129 fCount = kNonArray; 130 fPrecision = precision; 131 fOrigin = origin; 132 fUseUniformFloatArrays = useUniformFloatArrays; 133 } 134 135 /** 136 * Set all var options 137 */ 138 void set(GrSLType type, 139 TypeModifier typeModifier, 140 const SkString& name, 141 int count, 142 Precision precision = kDefault_Precision, 143 Origin origin = kDefault_Origin, 144 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 145 GrAssert(kVoid_GrSLType != type); 146 fType = type; 147 fTypeModifier = typeModifier; 148 fName = name; 149 fCount = count; 150 fPrecision = precision; 151 fOrigin = origin; 152 fUseUniformFloatArrays = useUniformFloatArrays; 153 } 154 155 /** 156 * Set all var options 157 */ 158 void set(GrSLType type, 159 TypeModifier typeModifier, 160 const char* name, 161 int count, 162 Precision precision = kDefault_Precision, 163 Origin origin = kDefault_Origin, 164 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 165 GrAssert(kVoid_GrSLType != type); 166 fType = type; 167 fTypeModifier = typeModifier; 168 fName = name; 169 fCount = count; 170 fPrecision = precision; 171 fOrigin = origin; 172 fUseUniformFloatArrays = useUniformFloatArrays; 173 } 174 175 /** 176 * Is the var an array. 177 */ 178 bool isArray() const { return kNonArray != fCount; } 179 /** 180 * Is this an unsized array, (i.e. declared with []). 181 */ 182 bool isUnsizedArray() const { return kUnsizedArray == fCount; } 183 /** 184 * Get the array length of the var. 185 */ 186 int getArrayCount() const { return fCount; } 187 /** 188 * Set the array length of the var 189 */ 190 void setArrayCount(int count) { fCount = count; } 191 /** 192 * Set to be a non-array. 193 */ 194 void setNonArray() { fCount = kNonArray; } 195 /** 196 * Set to be an unsized array. 197 */ 198 void setUnsizedArray() { fCount = kUnsizedArray; } 199 200 /** 201 * Access the var name as a writable string 202 */ 203 SkString* accessName() { return &fName; } 204 /** 205 * Set the var name 206 */ 207 void setName(const SkString& n) { fName = n; } 208 void setName(const char* n) { fName = n; } 209 210 /** 211 * Get the var name. 212 */ 213 const SkString& getName() const { return fName; } 214 215 /** 216 * Shortcut for this->getName().c_str(); 217 */ 218 const char* c_str() const { return this->getName().c_str(); } 219 220 /** 221 * Get the type of the var 222 */ 223 GrSLType getType() const { return fType; } 224 /** 225 * Set the type of the var 226 */ 227 void setType(GrSLType type) { fType = type; } 228 229 TypeModifier getTypeModifier() const { return fTypeModifier; } 230 void setTypeModifier(TypeModifier type) { fTypeModifier = type; } 231 232 /** 233 * Get the precision of the var 234 */ 235 Precision getPrecision() const { return fPrecision; } 236 237 /** 238 * Set the precision of the var 239 */ 240 void setPrecision(Precision p) { fPrecision = p; } 241 242 /** 243 * Get the origin of the var 244 */ 245 Origin getOrigin() const { return fOrigin; } 246 247 /** 248 * Set the origin of the var 249 */ 250 void setOrigin(Origin origin) { fOrigin = origin; } 251 252 /** 253 * Write a declaration of this variable to out. 254 */ 255 void appendDecl(const GrGLContextInfo& gl, SkString* out) const { 256 if (kUpperLeft_Origin == fOrigin) { 257 // this is the only place where we specify a layout modifier. If we use other layout 258 // modifiers in the future then they should be placed in a list. 259 out->append("layout(origin_upper_left) "); 260 } 261 if (this->getTypeModifier() != kNone_TypeModifier) { 262 out->append(TypeModifierString(this->getTypeModifier(), 263 gl.glslGeneration())); 264 out->append(" "); 265 } 266 out->append(PrecisionString(fPrecision, gl.binding())); 267 GrSLType effectiveType = this->getType(); 268 if (this->isArray()) { 269 if (this->isUnsizedArray()) { 270 out->appendf("%s %s[]", 271 TypeString(effectiveType), 272 this->getName().c_str()); 273 } else { 274 GrAssert(this->getArrayCount() > 0); 275 out->appendf("%s %s[%d]", 276 TypeString(effectiveType), 277 this->getName().c_str(), 278 this->getArrayCount()); 279 } 280 } else { 281 out->appendf("%s %s", 282 TypeString(effectiveType), 283 this->getName().c_str()); 284 } 285 } 286 287 static const char* TypeString(GrSLType t) { 288 switch (t) { 289 case kVoid_GrSLType: 290 return "void"; 291 case kFloat_GrSLType: 292 return "float"; 293 case kVec2f_GrSLType: 294 return "vec2"; 295 case kVec3f_GrSLType: 296 return "vec3"; 297 case kVec4f_GrSLType: 298 return "vec4"; 299 case kMat33f_GrSLType: 300 return "mat3"; 301 case kMat44f_GrSLType: 302 return "mat4"; 303 case kSampler2D_GrSLType: 304 return "sampler2D"; 305 default: 306 GrCrash("Unknown shader var type."); 307 return ""; // suppress warning 308 } 309 } 310 311 void appendArrayAccess(int index, SkString* out) const { 312 out->appendf("%s[%d]%s", 313 this->getName().c_str(), 314 index, 315 fUseUniformFloatArrays ? "" : ".x"); 316 } 317 318 void appendArrayAccess(const char* indexName, SkString* out) const { 319 out->appendf("%s[%s]%s", 320 this->getName().c_str(), 321 indexName, 322 fUseUniformFloatArrays ? "" : ".x"); 323 } 324 325 private: 326 static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) { 327 switch (t) { 328 case kNone_TypeModifier: 329 return ""; 330 case kOut_TypeModifier: 331 return k110_GrGLSLGeneration == gen ? "varying" : "out"; 332 case kIn_TypeModifier: 333 return k110_GrGLSLGeneration == gen ? "varying" : "in"; 334 case kUniform_TypeModifier: 335 return "uniform"; 336 case kAttribute_TypeModifier: 337 return k110_GrGLSLGeneration == gen ? "attribute" : "in"; 338 default: 339 GrCrash("Unknown shader variable type modifier."); 340 return ""; // suppress warning 341 } 342 } 343 344 static const char* PrecisionString(Precision p, GrGLBinding binding) { 345 // Desktop GLSL has added precision qualifiers but they don't do anything. 346 if (kES2_GrGLBinding == binding) { 347 switch (p) { 348 case kLow_Precision: 349 return "lowp "; 350 case kMedium_Precision: 351 return "mediump "; 352 case kHigh_Precision: 353 return "highp "; 354 case kDefault_Precision: 355 return ""; 356 default: 357 GrCrash("Unexpected precision type."); 358 } 359 } 360 return ""; 361 } 362 363 GrSLType fType; 364 TypeModifier fTypeModifier; 365 SkString fName; 366 int fCount; 367 Precision fPrecision; 368 Origin fOrigin; 369 /// Work around driver bugs on some hardware that don't correctly 370 /// support uniform float [] 371 bool fUseUniformFloatArrays; 372 }; 373 374 #endif 375