blob: 8e7e36e232045426b54030c26e4ccc1715b1c1ab [file] [log] [blame]
/*
* 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