1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #ifndef GrGLShaderVar_DEFINED 10 #define GrGLShaderVar_DEFINED 11 12 #include "GrGLContextInfo.h" 13 #include "GrGLSL.h" 14 #include "../GrStringBuilder.h" 15 16 #define USE_UNIFORM_FLOAT_ARRAYS true 17 18 /** 19 * Represents a variable in a shader 20 */ 21 class GrGLShaderVar { 22 public: 23 24 enum Type { 25 kFloat_Type, 26 kVec2f_Type, 27 kVec3f_Type, 28 kVec4f_Type, 29 kMat33f_Type, 30 kMat44f_Type, 31 kSampler2D_Type, 32 }; 33 34 /** 35 * Early versions of GLSL have Varying and Attribute; those are later 36 * deprecated, but we still need to know whether a Varying variable 37 * should be treated as In or Out. 38 */ 39 enum TypeModifier { 40 kNone_TypeModifier, 41 kOut_TypeModifier, 42 kIn_TypeModifier, 43 kUniform_TypeModifier, 44 kAttribute_TypeModifier 45 }; 46 47 /** 48 * Defaults to a float with no precision specifier 49 */ GrGLShaderVar()50 GrGLShaderVar() { 51 fType = kFloat_Type; 52 fTypeModifier = kNone_TypeModifier; 53 fCount = kNonArray; 54 fEmitPrecision = false; 55 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; 56 } 57 GrGLShaderVar(const GrGLShaderVar & var)58 GrGLShaderVar(const GrGLShaderVar& var) 59 : fType(var.fType) 60 , fTypeModifier(var.fTypeModifier) 61 , fName(var.fName) 62 , fCount(var.fCount) 63 , fEmitPrecision(var.fEmitPrecision) 64 , fUseUniformFloatArrays(var.fUseUniformFloatArrays) {} 65 66 /** 67 * Values for array count that have special meaning. We allow 1-sized arrays. 68 */ 69 enum { 70 kNonArray = 0, // not an array 71 kUnsizedArray = -1, // an unsized array (declared with []) 72 }; 73 74 /** 75 * Sets as a non-array. 76 */ 77 void set(Type type, 78 TypeModifier typeModifier, 79 const GrStringBuilder& name, 80 bool emitPrecision = false, 81 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 82 fType = type; 83 fTypeModifier = typeModifier; 84 fName = name; 85 fCount = kNonArray; 86 fEmitPrecision = emitPrecision; 87 fUseUniformFloatArrays = useUniformFloatArrays; 88 } 89 90 /** 91 * Sets as a non-array. 92 */ 93 void set(Type type, 94 TypeModifier typeModifier, 95 const char* name, 96 bool specifyPrecision = false, 97 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 98 fType = type; 99 fTypeModifier = typeModifier; 100 fName = name; 101 fCount = kNonArray; 102 fEmitPrecision = specifyPrecision; 103 fUseUniformFloatArrays = useUniformFloatArrays; 104 } 105 106 /** 107 * Set all var options 108 */ 109 void set(Type type, 110 TypeModifier typeModifier, 111 const GrStringBuilder& name, 112 int count, 113 bool specifyPrecision = false, 114 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 115 fType = type; 116 fTypeModifier = typeModifier; 117 fName = name; 118 fCount = count; 119 fEmitPrecision = specifyPrecision; 120 fUseUniformFloatArrays = useUniformFloatArrays; 121 } 122 123 /** 124 * Set all var options 125 */ 126 void set(Type type, 127 TypeModifier typeModifier, 128 const char* name, 129 int count, 130 bool specifyPrecision = false, 131 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 132 fType = type; 133 fTypeModifier = typeModifier; 134 fName = name; 135 fCount = count; 136 fEmitPrecision = specifyPrecision; 137 fUseUniformFloatArrays = useUniformFloatArrays; 138 } 139 140 /** 141 * Is the var an array. 142 */ isArray()143 bool isArray() const { return kNonArray != fCount; } 144 /** 145 * Is this an unsized array, (i.e. declared with []). 146 */ isUnsizedArray()147 bool isUnsizedArray() const { return kUnsizedArray == fCount; } 148 /** 149 * Get the array length of the var. 150 */ getArrayCount()151 int getArrayCount() const { return fCount; } 152 /** 153 * Set the array length of the var 154 */ setArrayCount(int count)155 void setArrayCount(int count) { fCount = count; } 156 /** 157 * Set to be a non-array. 158 */ setNonArray()159 void setNonArray() { fCount = kNonArray; } 160 /** 161 * Set to be an unsized array. 162 */ setUnsizedArray()163 void setUnsizedArray() { fCount = kUnsizedArray; } 164 165 /** 166 * Access the var name as a writable string 167 */ accessName()168 GrStringBuilder* accessName() { return &fName; } 169 /** 170 * Set the var name 171 */ setName(const GrStringBuilder & n)172 void setName(const GrStringBuilder& n) { fName = n; } setName(const char * n)173 void setName(const char* n) { fName = n; } 174 /** 175 * Get the var name. 176 */ getName()177 const GrStringBuilder& getName() const { return fName; } 178 179 /** 180 * Get the type of the var 181 */ getType()182 Type getType() const { return fType; } 183 /** 184 * Set the type of the var 185 */ setType(Type type)186 void setType(Type type) { fType = type; } 187 getTypeModifier()188 TypeModifier getTypeModifier() const { return fTypeModifier; } setTypeModifier(TypeModifier type)189 void setTypeModifier(TypeModifier type) { fTypeModifier = type; } 190 191 /** 192 * Must the variable declaration emit a precision specifier 193 */ emitsPrecision()194 bool emitsPrecision() const { return fEmitPrecision; } 195 /** 196 * Specify whether the declaration should specify precision 197 */ setEmitPrecision(bool p)198 void setEmitPrecision(bool p) { fEmitPrecision = p; } 199 200 /** 201 * Write a declaration of this variable to out. 202 */ appendDecl(const GrGLContextInfo & gl,GrStringBuilder * out)203 void appendDecl(const GrGLContextInfo& gl, GrStringBuilder* out) const { 204 if (this->getTypeModifier() != kNone_TypeModifier) { 205 out->append(TypeModifierString(this->getTypeModifier(), 206 gl.glslGeneration())); 207 out->append(" "); 208 } 209 if (this->emitsPrecision()) { 210 out->append(GrGetGLSLVarPrecisionDeclType(gl.binding())); 211 out->append(" "); 212 } 213 Type effectiveType = this->getType(); 214 if (this->isArray()) { 215 if (this->isUnsizedArray()) { 216 out->appendf("%s %s[]", 217 TypeString(effectiveType), 218 this->getName().c_str()); 219 } else { 220 GrAssert(this->getArrayCount() > 0); 221 out->appendf("%s %s[%d]", 222 TypeString(effectiveType), 223 this->getName().c_str(), 224 this->getArrayCount()); 225 } 226 } else { 227 out->appendf("%s %s", 228 TypeString(effectiveType), 229 this->getName().c_str()); 230 } 231 out->append(";\n"); 232 } 233 TypeString(Type t)234 static const char* TypeString(Type t) { 235 switch (t) { 236 case kFloat_Type: 237 return "float"; 238 case kVec2f_Type: 239 return "vec2"; 240 case kVec3f_Type: 241 return "vec3"; 242 case kVec4f_Type: 243 return "vec4"; 244 case kMat33f_Type: 245 return "mat3"; 246 case kMat44f_Type: 247 return "mat4"; 248 case kSampler2D_Type: 249 return "sampler2D"; 250 default: 251 GrCrash("Unknown shader var type."); 252 return ""; // suppress warning 253 } 254 } 255 appendArrayAccess(int index,GrStringBuilder * out)256 void appendArrayAccess(int index, GrStringBuilder* out) { 257 out->appendf("%s[%d]%s", 258 this->getName().c_str(), 259 index, 260 fUseUniformFloatArrays ? "" : ".x"); 261 } 262 appendArrayAccess(const char * indexName,GrStringBuilder * out)263 void appendArrayAccess(const char* indexName, GrStringBuilder* out) { 264 out->appendf("%s[%s]%s", 265 this->getName().c_str(), 266 indexName, 267 fUseUniformFloatArrays ? "" : ".x"); 268 } 269 270 private: TypeModifierString(TypeModifier t,GrGLSLGeneration gen)271 static const char* TypeModifierString(TypeModifier t, 272 GrGLSLGeneration gen) { 273 switch (t) { 274 case kNone_TypeModifier: 275 return ""; 276 case kOut_TypeModifier: 277 return k110_GrGLSLGeneration == gen ? "varying" : "out"; 278 case kIn_TypeModifier: 279 return k110_GrGLSLGeneration == gen ? "varying" : "in"; 280 case kUniform_TypeModifier: 281 return "uniform"; 282 case kAttribute_TypeModifier: 283 return k110_GrGLSLGeneration == gen ? "attribute" : "in"; 284 default: 285 GrCrash("Unknown shader variable type modifier."); 286 return ""; // suppress warning 287 } 288 } 289 290 Type fType; 291 TypeModifier fTypeModifier; 292 GrStringBuilder fName; 293 int fCount; 294 bool fEmitPrecision; 295 /// Work around driver bugs on some hardware that don't correctly 296 /// support uniform float [] 297 bool fUseUniformFloatArrays; 298 }; 299 300 #endif 301