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 "GrGLContext.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 kInOut_TypeModifier, 33 kUniform_TypeModifier, 34 kAttribute_TypeModifier, 35 kVaryingIn_TypeModifier, 36 kVaryingOut_TypeModifier 37 }; 38 39 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 50 /** 51 * 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 /** 59 * Defaults to a float with no precision specifier 60 */ GrGLShaderVar()61 GrGLShaderVar() { 62 fType = kFloat_GrSLType; 63 fTypeModifier = kNone_TypeModifier; 64 fCount = kNonArray; 65 fPrecision = kDefault_Precision; 66 fOrigin = kDefault_Origin; 67 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; 68 } 69 70 GrGLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray, 71 Precision precision = kDefault_Precision) { 72 SkASSERT(kVoid_GrSLType != type); 73 fType = type; 74 fTypeModifier = kNone_TypeModifier; 75 fCount = arrayCount; 76 fPrecision = precision; 77 fOrigin = kDefault_Origin; 78 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; 79 fName = name; 80 } 81 GrGLShaderVar(const GrGLShaderVar & var)82 GrGLShaderVar(const GrGLShaderVar& var) 83 : fType(var.fType) 84 , fTypeModifier(var.fTypeModifier) 85 , fName(var.fName) 86 , fCount(var.fCount) 87 , fPrecision(var.fPrecision) 88 , fOrigin(var.fOrigin) 89 , fUseUniformFloatArrays(var.fUseUniformFloatArrays) { 90 SkASSERT(kVoid_GrSLType != var.fType); 91 } 92 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 */ 104 void set(GrSLType type, 105 TypeModifier typeModifier, 106 const SkString& name, 107 Precision precision = kDefault_Precision, 108 Origin origin = kDefault_Origin, 109 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 110 SkASSERT(kVoid_GrSLType != type); 111 fType = type; 112 fTypeModifier = typeModifier; 113 fName = name; 114 fCount = kNonArray; 115 fPrecision = precision; 116 fOrigin = origin; 117 fUseUniformFloatArrays = useUniformFloatArrays; 118 } 119 120 /** 121 * Sets as a non-array. 122 */ 123 void set(GrSLType type, 124 TypeModifier typeModifier, 125 const char* name, 126 Precision precision = kDefault_Precision, 127 Origin origin = kDefault_Origin, 128 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 129 SkASSERT(kVoid_GrSLType != type); 130 fType = type; 131 fTypeModifier = typeModifier; 132 fName = name; 133 fCount = kNonArray; 134 fPrecision = precision; 135 fOrigin = origin; 136 fUseUniformFloatArrays = useUniformFloatArrays; 137 } 138 139 /** 140 * Set all var options 141 */ 142 void set(GrSLType type, 143 TypeModifier typeModifier, 144 const SkString& name, 145 int count, 146 Precision precision = kDefault_Precision, 147 Origin origin = kDefault_Origin, 148 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 149 SkASSERT(kVoid_GrSLType != type); 150 fType = type; 151 fTypeModifier = typeModifier; 152 fName = name; 153 fCount = count; 154 fPrecision = precision; 155 fOrigin = origin; 156 fUseUniformFloatArrays = useUniformFloatArrays; 157 } 158 159 /** 160 * Set all var options 161 */ 162 void set(GrSLType type, 163 TypeModifier typeModifier, 164 const char* name, 165 int count, 166 Precision precision = kDefault_Precision, 167 Origin origin = kDefault_Origin, 168 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 169 SkASSERT(kVoid_GrSLType != type); 170 fType = type; 171 fTypeModifier = typeModifier; 172 fName = name; 173 fCount = count; 174 fPrecision = precision; 175 fOrigin = origin; 176 fUseUniformFloatArrays = useUniformFloatArrays; 177 } 178 179 /** 180 * Is the var an array. 181 */ isArray()182 bool isArray() const { return kNonArray != fCount; } 183 /** 184 * Is this an unsized array, (i.e. declared with []). 185 */ isUnsizedArray()186 bool isUnsizedArray() const { return kUnsizedArray == fCount; } 187 /** 188 * Get the array length of the var. 189 */ getArrayCount()190 int getArrayCount() const { return fCount; } 191 /** 192 * Set the array length of the var 193 */ setArrayCount(int count)194 void setArrayCount(int count) { fCount = count; } 195 /** 196 * Set to be a non-array. 197 */ setNonArray()198 void setNonArray() { fCount = kNonArray; } 199 /** 200 * Set to be an unsized array. 201 */ setUnsizedArray()202 void setUnsizedArray() { fCount = kUnsizedArray; } 203 204 /** 205 * Access the var name as a writable string 206 */ accessName()207 SkString* accessName() { return &fName; } 208 /** 209 * Set the var name 210 */ setName(const SkString & n)211 void setName(const SkString& n) { fName = n; } setName(const char * n)212 void setName(const char* n) { fName = n; } 213 214 /** 215 * Get the var name. 216 */ getName()217 const SkString& getName() const { return fName; } 218 219 /** 220 * Shortcut for this->getName().c_str(); 221 */ c_str()222 const char* c_str() const { return this->getName().c_str(); } 223 224 /** 225 * Get the type of the var 226 */ getType()227 GrSLType getType() const { return fType; } 228 /** 229 * Set the type of the var 230 */ setType(GrSLType type)231 void setType(GrSLType type) { fType = type; } 232 getTypeModifier()233 TypeModifier getTypeModifier() const { return fTypeModifier; } setTypeModifier(TypeModifier type)234 void setTypeModifier(TypeModifier type) { fTypeModifier = type; } 235 236 /** 237 * Get the precision of the var 238 */ getPrecision()239 Precision getPrecision() const { return fPrecision; } 240 241 /** 242 * Set the precision of the var 243 */ setPrecision(Precision p)244 void setPrecision(Precision p) { fPrecision = p; } 245 246 /** 247 * Get the origin of the var 248 */ getOrigin()249 Origin getOrigin() const { return fOrigin; } 250 251 /** 252 * Set the origin of the var 253 */ setOrigin(Origin origin)254 void setOrigin(Origin origin) { fOrigin = origin; } 255 256 /** 257 * Write a declaration of this variable to out. 258 */ appendDecl(const GrGLContextInfo & ctxInfo,SkString * out)259 void appendDecl(const GrGLContextInfo& ctxInfo, SkString* out) const { 260 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 } 265 if (this->getTypeModifier() != kNone_TypeModifier) { 266 out->append(TypeModifierString(this->getTypeModifier(), 267 ctxInfo.glslGeneration())); 268 out->append(" "); 269 } 270 out->append(PrecisionString(fPrecision, ctxInfo.standard())); 271 GrSLType effectiveType = this->getType(); 272 if (this->isArray()) { 273 if (this->isUnsizedArray()) { 274 out->appendf("%s %s[]", 275 GrGLSLTypeString(effectiveType), 276 this->getName().c_str()); 277 } else { 278 SkASSERT(this->getArrayCount() > 0); 279 out->appendf("%s %s[%d]", 280 GrGLSLTypeString(effectiveType), 281 this->getName().c_str(), 282 this->getArrayCount()); 283 } 284 } else { 285 out->appendf("%s %s", 286 GrGLSLTypeString(effectiveType), 287 this->getName().c_str()); 288 } 289 } 290 appendArrayAccess(int index,SkString * out)291 void appendArrayAccess(int index, SkString* out) const { 292 out->appendf("%s[%d]%s", 293 this->getName().c_str(), 294 index, 295 fUseUniformFloatArrays ? "" : ".x"); 296 } 297 appendArrayAccess(const char * indexName,SkString * out)298 void appendArrayAccess(const char* indexName, SkString* out) const { 299 out->appendf("%s[%s]%s", 300 this->getName().c_str(), 301 indexName, 302 fUseUniformFloatArrays ? "" : ".x"); 303 } 304 PrecisionString(Precision p,GrGLStandard standard)305 static const char* PrecisionString(Precision p, GrGLStandard standard) { 306 // Desktop GLSL has added precision qualifiers but they don't do anything. 307 if (kGLES_GrGLStandard == standard) { 308 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 SkFAIL("Unexpected precision type."); 319 } 320 } 321 return ""; 322 } 323 324 private: TypeModifierString(TypeModifier t,GrGLSLGeneration gen)325 static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) { 326 switch (t) { 327 case kNone_TypeModifier: 328 return ""; 329 case kIn_TypeModifier: 330 return "in"; 331 case kInOut_TypeModifier: 332 return "inout"; 333 case kOut_TypeModifier: 334 return "out"; 335 case kUniform_TypeModifier: 336 return "uniform"; 337 case kAttribute_TypeModifier: 338 return k110_GrGLSLGeneration == gen ? "attribute" : "in"; 339 case kVaryingIn_TypeModifier: 340 return k110_GrGLSLGeneration == gen ? "varying" : "in"; 341 case kVaryingOut_TypeModifier: 342 return k110_GrGLSLGeneration == gen ? "varying" : "out"; 343 default: 344 SkFAIL("Unknown shader variable type modifier."); 345 return ""; // suppress warning 346 } 347 } 348 349 GrSLType fType; 350 TypeModifier fTypeModifier; 351 SkString fName; 352 int fCount; 353 Precision fPrecision; 354 Origin fOrigin; 355 /// Work around driver bugs on some hardware that don't correctly 356 /// support uniform float [] 357 bool fUseUniformFloatArrays; 358 }; 359 360 #endif 361