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 */ GrGLShaderVar()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 GrSLPrecision precision = kDefault_GrSLPrecision) GrShaderVar(name,type,arrayCount,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, GrSLPrecision precision = kDefault_GrSLPrecision) GrShaderVar(name,type,typeModifier,arrayCount,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 GrGLShaderVar(const GrShaderVar & var)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 GrGLShaderVar(const GrGLShaderVar & var)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 GrSLPrecision precision = kDefault_GrSLPrecision, 87 Origin origin = kDefault_Origin, 88 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 89 SkASSERT(kVoid_GrSLType != type); 90 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type)); 91 INHERITED::set(type, name, typeModifier, precision); 92 fOrigin = origin; 93 fUseUniformFloatArrays = useUniformFloatArrays; 94 } 95 96 /** 97 * Sets as a non-array. 98 */ 99 void set(GrSLType type, 100 TypeModifier typeModifier, 101 const char* name, 102 GrSLPrecision precision = kDefault_GrSLPrecision, 103 Origin origin = kDefault_Origin, 104 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 105 SkASSERT(kVoid_GrSLType != type); 106 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type)); 107 INHERITED::set(type, name, typeModifier, precision); 108 fOrigin = origin; 109 fUseUniformFloatArrays = useUniformFloatArrays; 110 } 111 112 /** 113 * Set all var options 114 */ 115 void set(GrSLType type, 116 TypeModifier typeModifier, 117 const SkString& name, 118 int count, 119 GrSLPrecision precision = kDefault_GrSLPrecision, 120 Origin origin = kDefault_Origin, 121 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 122 SkASSERT(kVoid_GrSLType != type); 123 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type)); 124 INHERITED::set(type, name, typeModifier, precision, count); 125 fOrigin = origin; 126 fUseUniformFloatArrays = useUniformFloatArrays; 127 } 128 129 /** 130 * Set all var options 131 */ 132 void set(GrSLType type, 133 TypeModifier typeModifier, 134 const char* name, 135 int count, 136 GrSLPrecision precision = kDefault_GrSLPrecision, 137 Origin origin = kDefault_Origin, 138 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 139 SkASSERT(kVoid_GrSLType != type); 140 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type)); 141 INHERITED::set(type, name, typeModifier, precision, count); 142 fOrigin = origin; 143 fUseUniformFloatArrays = useUniformFloatArrays; 144 } 145 146 /** 147 * Get the origin of the var 148 */ getOrigin()149 Origin getOrigin() const { return fOrigin; } 150 151 /** 152 * Set the origin of the var 153 */ setOrigin(Origin origin)154 void setOrigin(Origin origin) { fOrigin = origin; } 155 156 /** 157 * Write a declaration of this variable to out. 158 */ appendDecl(const GrGLContextInfo & ctxInfo,SkString * out)159 void appendDecl(const GrGLContextInfo& ctxInfo, SkString* out) const { 160 SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeIsFloatType(fType)); 161 if (kUpperLeft_Origin == fOrigin) { 162 // this is the only place where we specify a layout modifier. If we use other layout 163 // modifiers in the future then they should be placed in a list. 164 out->append("layout(origin_upper_left) "); 165 } 166 if (this->getTypeModifier() != kNone_TypeModifier) { 167 out->append(TypeModifierString(this->getTypeModifier(), ctxInfo.glslGeneration())); 168 out->append(" "); 169 } 170 out->append(PrecisionString(fPrecision, ctxInfo.standard())); 171 GrSLType effectiveType = this->getType(); 172 if (this->isArray()) { 173 if (this->isUnsizedArray()) { 174 out->appendf("%s %s[]", 175 GrGLSLTypeString(effectiveType), 176 this->getName().c_str()); 177 } else { 178 SkASSERT(this->getArrayCount() > 0); 179 out->appendf("%s %s[%d]", 180 GrGLSLTypeString(effectiveType), 181 this->getName().c_str(), 182 this->getArrayCount()); 183 } 184 } else { 185 out->appendf("%s %s", 186 GrGLSLTypeString(effectiveType), 187 this->getName().c_str()); 188 } 189 } 190 appendArrayAccess(int index,SkString * out)191 void appendArrayAccess(int index, SkString* out) const { 192 out->appendf("%s[%d]%s", 193 this->getName().c_str(), 194 index, 195 fUseUniformFloatArrays ? "" : ".x"); 196 } 197 appendArrayAccess(const char * indexName,SkString * out)198 void appendArrayAccess(const char* indexName, SkString* out) const { 199 out->appendf("%s[%s]%s", 200 this->getName().c_str(), 201 indexName, 202 fUseUniformFloatArrays ? "" : ".x"); 203 } 204 PrecisionString(GrSLPrecision p,GrGLStandard standard)205 static const char* PrecisionString(GrSLPrecision p, GrGLStandard standard) { 206 // Desktop GLSL has added precision qualifiers but they don't do anything. 207 if (kGLES_GrGLStandard == standard) { 208 switch (p) { 209 case kLow_GrSLPrecision: 210 return "lowp "; 211 case kMedium_GrSLPrecision: 212 return "mediump "; 213 case kHigh_GrSLPrecision: 214 return "highp "; 215 default: 216 SkFAIL("Unexpected precision type."); 217 } 218 } 219 return ""; 220 } 221 222 private: TypeModifierString(TypeModifier t,GrGLSLGeneration gen)223 static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) { 224 switch (t) { 225 case kNone_TypeModifier: 226 return ""; 227 case kIn_TypeModifier: 228 return "in"; 229 case kInOut_TypeModifier: 230 return "inout"; 231 case kOut_TypeModifier: 232 return "out"; 233 case kUniform_TypeModifier: 234 return "uniform"; 235 case kAttribute_TypeModifier: 236 return k110_GrGLSLGeneration == gen ? "attribute" : "in"; 237 case kVaryingIn_TypeModifier: 238 return k110_GrGLSLGeneration == gen ? "varying" : "in"; 239 case kVaryingOut_TypeModifier: 240 return k110_GrGLSLGeneration == gen ? "varying" : "out"; 241 default: 242 SkFAIL("Unknown shader variable type modifier."); 243 return ""; // suppress warning 244 } 245 } 246 247 Origin fOrigin; 248 /// Work around driver bugs on some hardware that don't correctly 249 /// support uniform float [] 250 bool fUseUniformFloatArrays; 251 252 typedef GrShaderVar INHERITED; 253 }; 254 255 #endif 256