| /* |
| * 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 GrGLSLShaderVar_DEFINED |
| #define GrGLSLShaderVar_DEFINED |
| |
| #include "GrShaderVar.h" |
| #include "../glsl/GrGLSL.h" |
| #include "../glsl/GrGLSLCaps.h" |
| |
| #define USE_UNIFORM_FLOAT_ARRAYS true |
| |
| /** |
| * Represents a variable in a shader |
| */ |
| class GrGLSLShaderVar : public GrShaderVar { |
| public: |
| /** |
| * Defaults to a float with no precision specifier |
| */ |
| GrGLSLShaderVar() |
| : GrShaderVar() |
| , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { |
| } |
| |
| GrGLSLShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray, |
| GrSLPrecision precision = kDefault_GrSLPrecision) |
| : GrShaderVar(name, type, arrayCount, precision) |
| , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; |
| } |
| |
| GrGLSLShaderVar(const char* name, GrSLType type, TypeModifier typeModifier, |
| int arrayCount = kNonArray, GrSLPrecision precision = kDefault_GrSLPrecision) |
| : GrShaderVar(name, type, typeModifier, arrayCount, precision) |
| , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| } |
| |
| GrGLSLShaderVar(const GrShaderVar& var) |
| : GrShaderVar(var) |
| , fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != var.getType()); |
| } |
| |
| GrGLSLShaderVar(const GrGLSLShaderVar& var) |
| : GrShaderVar(var.c_str(), var.getType(), var.getTypeModifier(), |
| var.getArrayCount(), var.getPrecision()) |
| , fUseUniformFloatArrays(var.fUseUniformFloatArrays) |
| , fLayoutQualifier(var.fLayoutQualifier) |
| , fExtraModifiers(var.fExtraModifiers) { |
| 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, |
| GrSLPrecision precision = kDefault_GrSLPrecision, |
| const char* layoutQualifier = nullptr, |
| const char* extraModifiers = nullptr, |
| bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); |
| INHERITED::set(type, name, typeModifier, precision); |
| fLayoutQualifier = layoutQualifier; |
| if (extraModifiers) { |
| fExtraModifiers.printf("%s ", extraModifiers); |
| } |
| fUseUniformFloatArrays = useUniformFloatArrays; |
| } |
| |
| /** |
| * Sets as a non-array. |
| */ |
| void set(GrSLType type, |
| TypeModifier typeModifier, |
| const char* name, |
| GrSLPrecision precision = kDefault_GrSLPrecision, |
| const char* layoutQualifier = nullptr, |
| const char* extraModifiers = nullptr, |
| bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); |
| INHERITED::set(type, name, typeModifier, precision); |
| fLayoutQualifier = layoutQualifier; |
| if (extraModifiers) { |
| fExtraModifiers.printf("%s ", extraModifiers); |
| } |
| fUseUniformFloatArrays = useUniformFloatArrays; |
| } |
| |
| /** |
| * Set all var options |
| */ |
| void set(GrSLType type, |
| TypeModifier typeModifier, |
| const SkString& name, |
| int count, |
| GrSLPrecision precision = kDefault_GrSLPrecision, |
| const char* layoutQualifier = nullptr, |
| const char* extraModifiers = nullptr, |
| bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); |
| INHERITED::set(type, name, typeModifier, precision, count); |
| fLayoutQualifier = layoutQualifier; |
| if (extraModifiers) { |
| fExtraModifiers.printf("%s ", extraModifiers); |
| } |
| fUseUniformFloatArrays = useUniformFloatArrays; |
| } |
| |
| /** |
| * Set all var options |
| */ |
| void set(GrSLType type, |
| TypeModifier typeModifier, |
| const char* name, |
| int count, |
| GrSLPrecision precision = kDefault_GrSLPrecision, |
| const char* layoutQualifier = nullptr, |
| const char* extraModifiers = nullptr, |
| bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { |
| SkASSERT(kVoid_GrSLType != type); |
| SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); |
| INHERITED::set(type, name, typeModifier, precision, count); |
| fLayoutQualifier = layoutQualifier; |
| if (extraModifiers) { |
| fExtraModifiers.printf("%s ", extraModifiers); |
| } |
| fUseUniformFloatArrays = useUniformFloatArrays; |
| } |
| |
| /** |
| * Set the layout qualifier |
| */ |
| void setLayoutQualifier(const char* layoutQualifier) { |
| fLayoutQualifier = layoutQualifier; |
| } |
| |
| void addModifier(const char* modifier) { |
| if (modifier) { |
| fExtraModifiers.appendf("%s ", modifier); |
| } |
| } |
| |
| /** |
| * Write a declaration of this variable to out. |
| */ |
| void appendDecl(const GrGLSLCaps* glslCaps, SkString* out) const { |
| SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeAcceptsPrecision(fType)); |
| if (!fLayoutQualifier.isEmpty()) { |
| out->appendf("layout(%s) ", fLayoutQualifier.c_str()); |
| } |
| out->append(fExtraModifiers); |
| if (this->getTypeModifier() != kNone_TypeModifier) { |
| out->append(TypeModifierString(glslCaps, this->getTypeModifier())); |
| out->append(" "); |
| } |
| GrSLType effectiveType = this->getType(); |
| if (glslCaps->usesPrecisionModifiers() && GrSLTypeAcceptsPrecision(effectiveType)) { |
| // Desktop GLSL has added precision qualifiers but they don't do anything. |
| out->appendf("%s ", GrGLSLPrecisionString(fPrecision)); |
| } |
| 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"); |
| } |
| |
| private: |
| static const char* TypeModifierString(const GrGLSLCaps* glslCaps, TypeModifier t) { |
| 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"; |
| } |
| SkFAIL("Unknown shader variable type modifier."); |
| return ""; // suppress warning |
| } |
| |
| /// Work around driver bugs on some hardware that don't correctly |
| /// support uniform float [] |
| bool fUseUniformFloatArrays; |
| |
| SkString fLayoutQualifier; |
| SkString fExtraModifiers; |
| |
| typedef GrShaderVar INHERITED; |
| }; |
| |
| #endif |