| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrGLShaderVar_DEFINED |
| #define GrGLShaderVar_DEFINED |
| |
| #include "GrGLContext.h" |
| #include "GrGLSL.h" |
| #include "GrShaderVar.h" |
| |
| #define USE_UNIFORM_FLOAT_ARRAYS true |
| |
| /** |
| * Represents a variable in a shader |
| */ |
| class GrGLShaderVar : public GrShaderVar { |
| public: |
| /** |
| * See GL_ARB_fragment_coord_conventions. |
| */ |
| enum Origin { |
| kDefault_Origin, // when set to kDefault the origin field is ignored. |
| kUpperLeft_Origin, // only used to declare vec4 in gl_FragCoord. |
| }; |
| |
| /** |
| * Defaults to a float with no precision specifier |
| */ |
| GrGLShaderVar() |
| : GrShaderVar() |
| , fOrigin(kDefault_Origin) |
| , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { |
| } |
| |
| GrGLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray, |
| Precision precision = kDefault_Precision) |
| : GrShaderVar(name, type, arrayCount, precision) |
| , fOrigin(kDefault_Origin) |
| , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| fOrigin = kDefault_Origin; |
| fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; |
| } |
| |
| GrGLShaderVar(const char* name, GrSLType type, TypeModifier typeModifier, |
| int arrayCount = kNonArray, Precision precision = kDefault_Precision) |
| : GrShaderVar(name, type, typeModifier, arrayCount, precision) |
| , fOrigin(kDefault_Origin) |
| , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| } |
| |
| GrGLShaderVar(const GrShaderVar& var) |
| : GrShaderVar(var) |
| , fOrigin(kDefault_Origin) |
| , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != var.getType()); |
| } |
| |
| GrGLShaderVar(const GrGLShaderVar& var) |
| : GrShaderVar(var.c_str(), var.getType(), var.getTypeModifier(), |
| var.getArrayCount(), var.getPrecision()) |
| , fOrigin(var.fOrigin) |
| , fUseUniformFloatArrays(var.fUseUniformFloatArrays) { |
| SkASSERT(kVoid_GrSLType != var.getType()); |
| } |
| |
| /** |
| * Values for array count that have special meaning. We allow 1-sized arrays. |
| */ |
| enum { |
| kNonArray = 0, // not an array |
| kUnsizedArray = -1, // an unsized array (declared with []) |
| }; |
| |
| /** |
| * Sets as a non-array. |
| */ |
| void set(GrSLType type, |
| TypeModifier typeModifier, |
| const SkString& name, |
| Precision precision = kDefault_Precision, |
| Origin origin = kDefault_Origin, |
| bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| INHERITED::set(type, typeModifier, name, precision); |
| fOrigin = origin; |
| fUseUniformFloatArrays = useUniformFloatArrays; |
| } |
| |
| /** |
| * Sets as a non-array. |
| */ |
| void set(GrSLType type, |
| TypeModifier typeModifier, |
| const char* name, |
| Precision precision = kDefault_Precision, |
| Origin origin = kDefault_Origin, |
| bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| INHERITED::set(type, typeModifier, name, precision); |
| fOrigin = origin; |
| fUseUniformFloatArrays = useUniformFloatArrays; |
| } |
| |
| /** |
| * Set all var options |
| */ |
| void set(GrSLType type, |
| TypeModifier typeModifier, |
| const SkString& name, |
| int count, |
| Precision precision = kDefault_Precision, |
| Origin origin = kDefault_Origin, |
| bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| INHERITED::set(type, typeModifier, name, count, precision); |
| fOrigin = origin; |
| fUseUniformFloatArrays = useUniformFloatArrays; |
| } |
| |
| /** |
| * Set all var options |
| */ |
| void set(GrSLType type, |
| TypeModifier typeModifier, |
| const char* name, |
| int count, |
| Precision precision = kDefault_Precision, |
| Origin origin = kDefault_Origin, |
| bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| INHERITED::set(type, typeModifier, name, count, precision); |
| fOrigin = origin; |
| fUseUniformFloatArrays = useUniformFloatArrays; |
| } |
| |
| /** |
| * Get the origin of the var |
| */ |
| Origin getOrigin() const { return fOrigin; } |
| |
| /** |
| * Set the origin of the var |
| */ |
| void setOrigin(Origin origin) { fOrigin = origin; } |
| |
| /** |
| * Write a declaration of this variable to out. |
| */ |
| void appendDecl(const GrGLContextInfo& ctxInfo, SkString* out) const { |
| if (kUpperLeft_Origin == fOrigin) { |
| // this is the only place where we specify a layout modifier. If we use other layout |
| // modifiers in the future then they should be placed in a list. |
| out->append("layout(origin_upper_left) "); |
| } |
| if (this->getTypeModifier() != kNone_TypeModifier) { |
| out->append(TypeModifierString(this->getTypeModifier(), ctxInfo.glslGeneration())); |
| out->append(" "); |
| } |
| out->append(PrecisionString(fPrecision, ctxInfo.standard())); |
| GrSLType effectiveType = this->getType(); |
| if (this->isArray()) { |
| if (this->isUnsizedArray()) { |
| out->appendf("%s %s[]", |
| GrGLSLTypeString(effectiveType), |
| this->getName().c_str()); |
| } else { |
| SkASSERT(this->getArrayCount() > 0); |
| out->appendf("%s %s[%d]", |
| GrGLSLTypeString(effectiveType), |
| this->getName().c_str(), |
| this->getArrayCount()); |
| } |
| } else { |
| out->appendf("%s %s", |
| GrGLSLTypeString(effectiveType), |
| this->getName().c_str()); |
| } |
| } |
| |
| void appendArrayAccess(int index, SkString* out) const { |
| out->appendf("%s[%d]%s", |
| this->getName().c_str(), |
| index, |
| fUseUniformFloatArrays ? "" : ".x"); |
| } |
| |
| void appendArrayAccess(const char* indexName, SkString* out) const { |
| out->appendf("%s[%s]%s", |
| this->getName().c_str(), |
| indexName, |
| fUseUniformFloatArrays ? "" : ".x"); |
| } |
| |
| static const char* PrecisionString(Precision p, GrGLStandard standard) { |
| // Desktop GLSL has added precision qualifiers but they don't do anything. |
| if (kGLES_GrGLStandard == standard) { |
| switch (p) { |
| case kLow_Precision: |
| return "lowp "; |
| case kMedium_Precision: |
| return "mediump "; |
| case kHigh_Precision: |
| return "highp "; |
| case kDefault_Precision: |
| return ""; |
| default: |
| SkFAIL("Unexpected precision type."); |
| } |
| } |
| return ""; |
| } |
| |
| private: |
| static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) { |
| switch (t) { |
| case kNone_TypeModifier: |
| return ""; |
| case kIn_TypeModifier: |
| return "in"; |
| case kInOut_TypeModifier: |
| return "inout"; |
| case kOut_TypeModifier: |
| return "out"; |
| case kUniform_TypeModifier: |
| return "uniform"; |
| case kAttribute_TypeModifier: |
| return k110_GrGLSLGeneration == gen ? "attribute" : "in"; |
| case kVaryingIn_TypeModifier: |
| return k110_GrGLSLGeneration == gen ? "varying" : "in"; |
| case kVaryingOut_TypeModifier: |
| return k110_GrGLSLGeneration == gen ? "varying" : "out"; |
| default: |
| SkFAIL("Unknown shader variable type modifier."); |
| return ""; // suppress warning |
| } |
| } |
| |
| Origin fOrigin; |
| /// Work around driver bugs on some hardware that don't correctly |
| /// support uniform float [] |
| bool fUseUniformFloatArrays; |
| |
| typedef GrShaderVar INHERITED; |
| }; |
| |
| #endif |