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 GrGLSLShaderVar_DEFINED 9#define GrGLSLShaderVar_DEFINED 10 11#include "GrShaderVar.h" 12#include "../glsl/GrGLSL.h" 13#include "../glsl/GrGLSLCaps.h" 14 15#define USE_UNIFORM_FLOAT_ARRAYS true 16 17/** 18 * Represents a variable in a shader 19 */ 20class GrGLSLShaderVar : public GrShaderVar { 21public: 22 /** 23 * Defaults to a float with no precision specifier 24 */ 25 GrGLSLShaderVar() 26 : GrShaderVar() 27 , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { 28 } 29 30 GrGLSLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray, 31 GrSLPrecision precision = kDefault_GrSLPrecision) 32 : GrShaderVar(name, type, arrayCount, precision) 33 , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { 34 SkASSERT(kVoid_GrSLType != type); 35 fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; 36 } 37 38 GrGLSLShaderVar(const char* name, GrSLType type, TypeModifier typeModifier, 39 int arrayCount = kNonArray, GrSLPrecision precision = kDefault_GrSLPrecision) 40 : GrShaderVar(name, type, typeModifier, arrayCount, precision) 41 , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { 42 SkASSERT(kVoid_GrSLType != type); 43 } 44 45 GrGLSLShaderVar(const GrShaderVar& var) 46 : GrShaderVar(var) 47 , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { 48 SkASSERT(kVoid_GrSLType != var.getType()); 49 } 50 51 GrGLSLShaderVar(const GrGLSLShaderVar& var) 52 : GrShaderVar(var.c_str(), var.getType(), var.getTypeModifier(), 53 var.getArrayCount(), var.getPrecision()) 54 , fUseUniformFloatArrays(var.fUseUniformFloatArrays) 55 , fLayoutQualifier(var.fLayoutQualifier) 56 , fExtraModifiers(var.fExtraModifiers) { 57 SkASSERT(kVoid_GrSLType != var.getType()); 58 } 59 60 /** 61 * Values for array count that have special meaning. We allow 1-sized arrays. 62 */ 63 enum { 64 kNonArray = 0, // not an array 65 kUnsizedArray = -1, // an unsized array (declared with []) 66 }; 67 68 /** 69 * Sets as a non-array. 70 */ 71 void set(GrSLType type, 72 TypeModifier typeModifier, 73 const SkString& name, 74 GrSLPrecision precision = kDefault_GrSLPrecision, 75 const char* layoutQualifier = nullptr, 76 const char* extraModifiers = nullptr, 77 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 78 SkASSERT(kVoid_GrSLType != type); 79 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type)); 80 INHERITED::set(type, name, typeModifier, precision); 81 fLayoutQualifier = layoutQualifier; 82 if (extraModifiers) { 83 fExtraModifiers.printf("%s ", extraModifiers); 84 } 85 fUseUniformFloatArrays = useUniformFloatArrays; 86 } 87 88 /** 89 * Sets as a non-array. 90 */ 91 void set(GrSLType type, 92 TypeModifier typeModifier, 93 const char* name, 94 GrSLPrecision precision = kDefault_GrSLPrecision, 95 const char* layoutQualifier = nullptr, 96 const char* extraModifiers = nullptr, 97 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 98 SkASSERT(kVoid_GrSLType != type); 99 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type)); 100 INHERITED::set(type, name, typeModifier, precision); 101 fLayoutQualifier = layoutQualifier; 102 if (extraModifiers) { 103 fExtraModifiers.printf("%s ", extraModifiers); 104 } 105 fUseUniformFloatArrays = useUniformFloatArrays; 106 } 107 108 /** 109 * Set all var options 110 */ 111 void set(GrSLType type, 112 TypeModifier typeModifier, 113 const SkString& name, 114 int count, 115 GrSLPrecision precision = kDefault_GrSLPrecision, 116 const char* layoutQualifier = nullptr, 117 const char* extraModifiers = nullptr, 118 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 119 SkASSERT(kVoid_GrSLType != type); 120 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type)); 121 INHERITED::set(type, name, typeModifier, precision, count); 122 fLayoutQualifier = layoutQualifier; 123 if (extraModifiers) { 124 fExtraModifiers.printf("%s ", extraModifiers); 125 } 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 const char* layoutQualifier = nullptr, 138 const char* extraModifiers = nullptr, 139 bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { 140 SkASSERT(kVoid_GrSLType != type); 141 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type)); 142 INHERITED::set(type, name, typeModifier, precision, count); 143 fLayoutQualifier = layoutQualifier; 144 if (extraModifiers) { 145 fExtraModifiers.printf("%s ", extraModifiers); 146 } 147 fUseUniformFloatArrays = useUniformFloatArrays; 148 } 149 150 /** 151 * Set the layout qualifier 152 */ 153 void setLayoutQualifier(const char* layoutQualifier) { 154 fLayoutQualifier = layoutQualifier; 155 } 156 157 void addModifier(const char* modifier) { 158 if (modifier) { 159 fExtraModifiers.appendf("%s ", modifier); 160 } 161 } 162 163 /** 164 * Write a declaration of this variable to out. 165 */ 166 void appendDecl(const GrGLSLCaps* glslCaps, SkString* out) const { 167 SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeIsNumeric(fType)); 168 if (!fLayoutQualifier.isEmpty()) { 169 out->appendf("layout(%s) ", fLayoutQualifier.c_str()); 170 } 171 out->append(fExtraModifiers); 172 if (this->getTypeModifier() != kNone_TypeModifier) { 173 out->append(TypeModifierString(glslCaps, this->getTypeModifier())); 174 out->append(" "); 175 } 176 GrSLType effectiveType = this->getType(); 177 if (effectiveType != kBool_GrSLType) { 178 out->append(PrecisionString(glslCaps, fPrecision)); 179 } 180 if (this->isArray()) { 181 if (this->isUnsizedArray()) { 182 out->appendf("%s %s[]", 183 GrGLSLTypeString(effectiveType), 184 this->getName().c_str()); 185 } else { 186 SkASSERT(this->getArrayCount() > 0); 187 out->appendf("%s %s[%d]", 188 GrGLSLTypeString(effectiveType), 189 this->getName().c_str(), 190 this->getArrayCount()); 191 } 192 } else { 193 out->appendf("%s %s", 194 GrGLSLTypeString(effectiveType), 195 this->getName().c_str()); 196 } 197 } 198 199 void appendArrayAccess(int index, SkString* out) const { 200 out->appendf("%s[%d]%s", 201 this->getName().c_str(), 202 index, 203 fUseUniformFloatArrays ? "" : ".x"); 204 } 205 206 void appendArrayAccess(const char* indexName, SkString* out) const { 207 out->appendf("%s[%s]%s", 208 this->getName().c_str(), 209 indexName, 210 fUseUniformFloatArrays ? "" : ".x"); 211 } 212 213 static const char* PrecisionString(const GrGLSLCaps* glslCaps, GrSLPrecision p) { 214 // Desktop GLSL has added precision qualifiers but they don't do anything. 215 if (glslCaps->usesPrecisionModifiers()) { 216 switch (p) { 217 case kLow_GrSLPrecision: 218 return "lowp "; 219 case kMedium_GrSLPrecision: 220 return "mediump "; 221 case kHigh_GrSLPrecision: 222 return "highp "; 223 default: 224 SkFAIL("Unexpected precision type."); 225 } 226 } 227 return ""; 228 } 229 230private: 231 static const char* TypeModifierString(const GrGLSLCaps* glslCaps, TypeModifier t) { 232 GrGLSLGeneration gen = glslCaps->generation(); 233 switch (t) { 234 case kNone_TypeModifier: 235 return ""; 236 case kIn_TypeModifier: 237 return "in"; 238 case kInOut_TypeModifier: 239 return "inout"; 240 case kOut_TypeModifier: 241 return "out"; 242 case kUniform_TypeModifier: 243 return "uniform"; 244 case kAttribute_TypeModifier: 245 return k110_GrGLSLGeneration == gen ? "attribute" : "in"; 246 case kVaryingIn_TypeModifier: 247 return k110_GrGLSLGeneration == gen ? "varying" : "in"; 248 case kVaryingOut_TypeModifier: 249 return k110_GrGLSLGeneration == gen ? "varying" : "out"; 250 default: 251 SkFAIL("Unknown shader variable type modifier."); 252 return ""; // suppress warning 253 } 254 } 255 256 /// Work around driver bugs on some hardware that don't correctly 257 /// support uniform float [] 258 bool fUseUniformFloatArrays; 259 260 SkString fLayoutQualifier; 261 SkString fExtraModifiers; 262 263 typedef GrShaderVar INHERITED; 264}; 265 266#endif 267