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 "GrShaderVar.h" 14 15 #define USE_UNIFORM_FLOAT_ARRAYS true 16 17 /** 18 * Represents a variable in a shader 19 */ 20 class GrGLShaderVar : public GrShaderVar { 21 public: 22 /** 23 * See GL_ARB_fragment_coord_conventions. 24 */ 25 enum Origin { 26 kDefault_Origin, // when set to kDefault the origin field is ignored. 27 kUpperLeft_Origin, // only used to declare vec4 in gl_FragCoord. 28 }; 29 30 /** 31 * Defaults to a float with no precision specifier 32 */ 33 GrGLShaderVar() 34 : GrShaderVar() 35 , fOrigin(kDefault_Origin) 36 , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { 37 } 38 39 GrGLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray, 40 Precision precision = kDefault_Precision) 41 : GrShaderVar(name, type, arrayCount, precision) 42 , fOrigin(kDefault_Origin) 43 , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { 44 SkASSERT(kVoid_GrSLType != type); 45 fOrigin = kDefault_Origin; 46 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; 47 } 48 49 GrGLShaderVar(const char* name, GrSLType type, TypeModifier typeModifier, 50 int arrayCount = kNonArray, Precision precision = kDefault_Precision) 51 : GrShaderVar(name, type, typeModifier, arrayCount, precision) 52 , fOrigin(kDefault_Origin) 53 , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { 54 SkASSERT(kVoid_GrSLType != type); 55 } 56 57 GrGLShaderVar(const GrShaderVar& var) 58 : GrShaderVar(var) 59 , fOrigin(kDefault_Origin) 60 , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { 61 SkASSERT(kVoid_GrSLType != var.getType()); 62 } 63 64 GrGLShaderVar(const GrGLShaderVar& var) 65 : GrShaderVar(var.c_str(), var.getType(), var.getTypeModifier(), 66 var.getArrayCount(), var.getPrecision()) 67 , fOrigin(var.fOrigin) 68 , fUseUniformFloatArrays(var.fUseUniformFloatArrays) { 69 SkASSERT(kVoid_GrSLType != var.getType()); 70 } 71 72 /** 73 * Values for array count that have special meaning. We allow 1-sized arrays. 74 */ 75 enum { 76 kNonArray = 0, // not an array 77 kUnsizedArray = -1, // an unsized array (declared with []) 78 }; 79 80 /** 81 * Sets as a non-array. 82 */ 83 void set(GrSLType type, 84 TypeModifier typeModifier, 85 const SkString& name, 86 Precision precision = kDefault_Precision, 87 Origin origin = kDefault_Origin, 88 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 89 SkASSERT(kVoid_GrSLType != type); 90 INHERITED::set(type, typeModifier, name, precision); 91 fOrigin = origin; 92 fUseUniformFloatArrays = useUniformFloatArrays; 93 } 94 95 /** 96 * Sets as a non-array. 97 */ 98 void set(GrSLType type, 99 TypeModifier typeModifier, 100 const char* name, 101 Precision precision = kDefault_Precision, 102 Origin origin = kDefault_Origin, 103 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 104 SkASSERT(kVoid_GrSLType != type); 105 INHERITED::set(type, typeModifier, name, precision); 106 fOrigin = origin; 107 fUseUniformFloatArrays = useUniformFloatArrays; 108 } 109 110 /** 111 * Set all var options 112 */ 113 void set(GrSLType type, 114 TypeModifier typeModifier, 115 const SkString& name, 116 int count, 117 Precision precision = kDefault_Precision, 118 Origin origin = kDefault_Origin, 119 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 120 SkASSERT(kVoid_GrSLType != type); 121 INHERITED::set(type, typeModifier, name, count, precision); 122 fOrigin = origin; 123 fUseUniformFloatArrays = useUniformFloatArrays; 124 } 125 126 /** 127 * Set all var options 128 */ 129 void set(GrSLType type, 130 TypeModifier typeModifier, 131 const char* name, 132 int count, 133 Precision precision = kDefault_Precision, 134 Origin origin = kDefault_Origin, 135 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 136 SkASSERT(kVoid_GrSLType != type); 137 INHERITED::set(type, typeModifier, name, count, precision); 138 fOrigin = origin; 139 fUseUniformFloatArrays = useUniformFloatArrays; 140 } 141 142 /** 143 * Get the origin of the var 144 */ 145 Origin getOrigin() const { return fOrigin; } 146 147 /** 148 * Set the origin of the var 149 */ 150 void setOrigin(Origin origin) { fOrigin = origin; } 151 152 /** 153 * Write a declaration of this variable to out. 154 */ 155 void appendDecl(const GrGLContextInfo& ctxInfo, SkString* out) const { 156 if (kUpperLeft_Origin == fOrigin) { 157 // this is the only place where we specify a layout modifier. If we use other layout 158 // modifiers in the future then they should be placed in a list. 159 out->append("layout(origin_upper_left) "); 160 } 161 if (this->getTypeModifier() != kNone_TypeModifier) { 162 out->append(TypeModifierString(this->getTypeModifier(), 163 ctxInfo.glslGeneration())); 164 out->append(" "); 165 } 166 out->append(PrecisionString(fPrecision, ctxInfo.standard())); 167 GrSLType effectiveType = this->getType(); 168 if (this->isArray()) { 169 if (this->isUnsizedArray()) { 170 out->appendf("%s %s[]", 171 GrGLSLTypeString(effectiveType), 172 this->getName().c_str()); 173 } else { 174 SkASSERT(this->getArrayCount() > 0); 175 out->appendf("%s %s[%d]", 176 GrGLSLTypeString(effectiveType), 177 this->getName().c_str(), 178 this->getArrayCount()); 179 } 180 } else { 181 out->appendf("%s %s", 182 GrGLSLTypeString(effectiveType), 183 this->getName().c_str()); 184 } 185 } 186 187 void appendArrayAccess(int index, SkString* out) const { 188 out->appendf("%s[%d]%s", 189 this->getName().c_str(), 190 index, 191 fUseUniformFloatArrays ? "" : ".x"); 192 } 193 194 void appendArrayAccess(const char* indexName, SkString* out) const { 195 out->appendf("%s[%s]%s", 196 this->getName().c_str(), 197 indexName, 198 fUseUniformFloatArrays ? "" : ".x"); 199 } 200 201 static const char* PrecisionString(Precision p, GrGLStandard standard) { 202 // Desktop GLSL has added precision qualifiers but they don't do anything. 203 if (kGLES_GrGLStandard == standard) { 204 switch (p) { 205 case kLow_Precision: 206 return "lowp "; 207 case kMedium_Precision: 208 return "mediump "; 209 case kHigh_Precision: 210 return "highp "; 211 case kDefault_Precision: 212 return ""; 213 default: 214 SkFAIL("Unexpected precision type."); 215 } 216 } 217 return ""; 218 } 219 220 private: 221 static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) { 222 switch (t) { 223 case kNone_TypeModifier: 224 return ""; 225 case kIn_TypeModifier: 226 return "in"; 227 case kInOut_TypeModifier: 228 return "inout"; 229 case kOut_TypeModifier: 230 return "out"; 231 case kUniform_TypeModifier: 232 return "uniform"; 233 case kAttribute_TypeModifier: 234 return k110_GrGLSLGeneration == gen ? "attribute" : "in"; 235 case kVaryingIn_TypeModifier: 236 return k110_GrGLSLGeneration == gen ? "varying" : "in"; 237 case kVaryingOut_TypeModifier: 238 return k110_GrGLSLGeneration == gen ? "varying" : "out"; 239 default: 240 SkFAIL("Unknown shader variable type modifier."); 241 return ""; // suppress warning 242 } 243 } 244 245 Origin fOrigin; 246 /// Work around driver bugs on some hardware that don't correctly 247 /// support uniform float [] 248 bool fUseUniformFloatArrays; 249 250 typedef GrShaderVar INHERITED; 251 }; 252 253 #endif 254