Resubmit 2289 with fix for glsl version

git-svn-id: http://skia.googlecode.com/svn/trunk@2291 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-09-20 19:06:12 +00:00
parent 1fac5ca505
commit 4fa6694c58
8 changed files with 630 additions and 207 deletions

View File

@ -46,7 +46,7 @@ public:
*
* @return pointer to the added item.
*/
void* push_back() {
void* push_back() {
int indexInBlock = fCount % fItemsPerBlock;
// we always have at least one block
if (0 == indexInBlock) {
@ -153,7 +153,7 @@ public:
* Must be at least size(T)*itemsPerBlock sized.
* Caller is responsible for freeing this memory.
*/
GrTAllocator(int itemsPerBlock, void* initialBlock)
explicit GrTAllocator(int itemsPerBlock, void* initialBlock = NULL)
: fAllocator(sizeof(T), itemsPerBlock, initialBlock) {}
/**
@ -163,7 +163,7 @@ public:
* and the size of subsequent blocks.
*/
template <int N>
GrTAllocator(SkAlignedSTStorage<N,T>* initialBlock)
explicit GrTAllocator(SkAlignedSTStorage<N,T>* initialBlock)
: fAllocator(sizeof(T), N, initialBlock->get()) {}
/**
@ -177,7 +177,14 @@ public:
new (item) T;
return *(T*)item;
}
T& push_back(const T& t) {
void* item = fAllocator.push_back();
GrAssert(NULL != item);
new (item) T(t);
return *(T*)item;
}
/**
* removes all added items
*/

View File

@ -9,8 +9,8 @@
#include "GrGLProgram.h"
#include "GrGLConfig.h"
#include "GrAllocator.h"
#include "GrGLShaderVar.h"
#include "SkTrace.h"
#include "SkXfermode.h"
@ -36,6 +36,32 @@ const char* GrShaderPrecision(const GrGLInterface* gl) {
#define PRINT_SHADERS 0
typedef GrTAllocator<GrGLShaderVar> VarArray;
// number of each input/output type in a single allocation block
static const int gVarsPerBlock = 8;
// except FS outputs where we expect 2 at most.
static const int gMaxFSOutputs = 2;
struct ShaderCodeSegments {
ShaderCodeSegments()
: fVSUnis(gVarsPerBlock)
, fVSAttrs(gVarsPerBlock)
, fVaryings(gVarsPerBlock)
, fFSUnis(gVarsPerBlock)
, fFSOutputs(gMaxFSOutputs) {}
GrStringBuilder fHeader; // VS+FS, GLSL version, etc
VarArray fVSUnis;
VarArray fVSAttrs;
VarArray fVaryings;
VarArray fFSUnis;
VarArray fFSOutputs;
GrStringBuilder fFSFunctions;
GrStringBuilder fVSCode;
GrStringBuilder fFSCode;
};
#if GR_GL_ATTRIBUTE_MATRICES
#define VIEW_MATRIX_NAME "aViewM"
#else
@ -49,53 +75,61 @@ const char* GrShaderPrecision(const GrGLInterface* gl) {
#define EDGES_UNI_NAME "uEdges"
#define COL_FILTER_UNI_NAME "uColorFilter"
static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
namespace {
inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
*s = "aTexCoord";
s->appendS32(coordIdx);
}
static inline const char* float_vector_type(int count) {
static const char* FLOAT_VECS[] = {"ERROR", "float", "vec2", "vec3", "vec4"};
GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(FLOAT_VECS));
return FLOAT_VECS[count];
inline GrGLShaderVar::Type float_vector_type(int count) {
GR_STATIC_ASSERT(GrGLShaderVar::kFloat_Type == 0);
GR_STATIC_ASSERT(GrGLShaderVar::kVec2f_Type == 1);
GR_STATIC_ASSERT(GrGLShaderVar::kVec3f_Type == 2);
GR_STATIC_ASSERT(GrGLShaderVar::kVec4f_Type == 3);
GrAssert(count > 0 && count <= 4);
return (GrGLShaderVar::Type)(count - 1);
}
static inline const char* vector_homog_coord(int count) {
inline const char* float_vector_type_str(int count) {
return GrGLShaderVar::TypeString(float_vector_type(count));
}
inline const char* vector_homog_coord(int count) {
static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
return HOMOGS[count];
}
static inline const char* vector_nonhomog_coords(int count) {
inline const char* vector_nonhomog_coords(int count) {
static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"};
GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS));
return NONHOMOGS[count];
}
static inline const char* vector_all_coords(int count) {
inline const char* vector_all_coords(int count) {
static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"};
GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL));
return ALL[count];
}
static inline const char* all_ones_vec(int count) {
inline const char* all_ones_vec(int count) {
static const char* ONESVEC[] = {"ERROR", "1.0", "vec2(1,1)",
"vec3(1,1,1)", "vec4(1,1,1,1)"};
GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ONESVEC));
return ONESVEC[count];
}
static inline const char* all_zeros_vec(int count) {
inline const char* all_zeros_vec(int count) {
static const char* ZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)",
"vec3(0,0,0)", "vec4(0,0,0,0)"};
GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ZEROSVEC));
return ZEROSVEC[count];
}
static inline const char* declared_color_output_name() { return "fsColorOut"; }
static inline const char* dual_source_output_name() { return "dualSourceOut"; }
inline const char* declared_color_output_name() { return "fsColorOut"; }
inline const char* dual_source_output_name() { return "dualSourceOut"; }
static void tex_matrix_name(int stage, GrStringBuilder* s) {
inline void tex_matrix_name(int stage, GrStringBuilder* s) {
#if GR_GL_ATTRIBUTE_MATRICES
*s = "aTexM";
#else
@ -104,42 +138,43 @@ static void tex_matrix_name(int stage, GrStringBuilder* s) {
s->appendS32(stage);
}
static void normalized_texel_size_name(int stage, GrStringBuilder* s) {
inline void normalized_texel_size_name(int stage, GrStringBuilder* s) {
*s = "uTexelSize";
s->appendS32(stage);
}
static void sampler_name(int stage, GrStringBuilder* s) {
inline void sampler_name(int stage, GrStringBuilder* s) {
*s = "uSampler";
s->appendS32(stage);
}
static void stage_varying_name(int stage, GrStringBuilder* s) {
inline void stage_varying_name(int stage, GrStringBuilder* s) {
*s = "vStage";
s->appendS32(stage);
}
static void radial2_param_name(int stage, GrStringBuilder* s) {
inline void radial2_param_name(int stage, GrStringBuilder* s) {
*s = "uRadial2Params";
s->appendS32(stage);
}
static void radial2_varying_name(int stage, GrStringBuilder* s) {
inline void radial2_varying_name(int stage, GrStringBuilder* s) {
*s = "vB";
s->appendS32(stage);
}
static void convolve_param_names(int stage, GrStringBuilder* k, GrStringBuilder* i) {
inline void convolve_param_names(int stage, GrStringBuilder* k, GrStringBuilder* i) {
*k = "uKernel";
k->appendS32(stage);
*i = "uImageIncrement";
i->appendS32(stage);
}
static void tex_domain_name(int stage, GrStringBuilder* s) {
inline void tex_domain_name(int stage, GrStringBuilder* s) {
*s = "uTexDom";
s->appendS32(stage);
}
}
GrGLProgram::GrGLProgram() {
}
@ -321,15 +356,39 @@ static void addColorFilter(GrStringBuilder* fsCode, const char * outputVar,
add_helper(outputVar, colorStr.c_str(), constStr.c_str(), fsCode);
}
namespace {
const char* glsl_version_string(const GrGLInterface* gl,
GrGLProgram::GLSLVersion v) {
switch (v) {
case GrGLProgram::k120_GLSLVersion:
if (gl->supportsES()) {
// ES2s shader language is based on version 1.20 but is version
// 1.00 of the ES language.
return "#version 100\n";
} else {
return "#version 120\n";
}
case GrGLProgram::k130_GLSLVersion:
GrAssert(!gl->supportsES());
return "#version 130\n";
default:
GrCrash("Unknown GL version.");
return ""; // suppress warning
}
}
}
void GrGLProgram::genEdgeCoverage(const GrGLInterface* gl,
GrVertexLayout layout,
CachedData* programData,
GrStringBuilder* coverageVar,
ShaderCodeSegments* segments) const {
if (fProgramDesc.fEdgeAANumEdges > 0) {
segments->fFSUnis.append("uniform vec3 " EDGES_UNI_NAME "[");
segments->fFSUnis.appendS32(fProgramDesc.fEdgeAANumEdges);
segments->fFSUnis.append("];\n");
segments->fFSUnis.push_back().set(GrGLShaderVar::kVec3f_Type,
EDGES_UNI_NAME,
fProgramDesc.fEdgeAANumEdges);
programData->fUniLocations.fEdgesUni = kUseUniform;
int count = fProgramDesc.fEdgeAANumEdges;
segments->fFSCode.append(
@ -376,8 +435,8 @@ void GrGLProgram::genEdgeCoverage(const GrGLInterface* gl,
}
*coverageVar = "edgeAlpha";
} else if (layout & GrDrawTarget::kEdge_VertexLayoutBit) {
segments->fVSAttrs.append("attribute vec4 " EDGE_ATTR_NAME ";\n");
segments->fVaryings.append("varying vec4 vEdge;\n");
segments->fVaryings.push_back().set(GrGLShaderVar::kVec4f_Type, "vEdge");
segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type, EDGE_ATTR_NAME);
segments->fVSCode.append("\tvEdge = " EDGE_ATTR_NAME ";\n");
if (GrDrawTarget::kHairLine_EdgeType == fProgramDesc.fVertexEdgeType) {
segments->fFSCode.append("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), vEdge.xyz));\n");
@ -402,7 +461,33 @@ void GrGLProgram::genEdgeCoverage(const GrGLInterface* gl,
}
}
bool GrGLProgram::genProgram(const GrGLInterface* gl,
namespace {
// returns true if the color output was explicitly declared or not.
bool decl_and_get_fs_color_output(GrGLProgram::GLSLVersion v,
VarArray* fsOutputs,
const char** name) {
switch (v) {
case GrGLProgram::k120_GLSLVersion:
*name = "gl_FragColor";
return false;
break;
case GrGLProgram::k130_GLSLVersion:
*name = declared_color_output_name();
fsOutputs->push_back().set(GrGLShaderVar::kVec4f_Type,
declared_color_output_name());
return true;
break;
default:
GrCrash("Unknown GLSL version.");
return false; // suppress warning
}
}
}
bool GrGLProgram::genProgram(const GrGLInterface* gl,
GLSLVersion glslVersion,
GrGLProgram::CachedData* programData) const {
ShaderCodeSegments segments;
@ -432,25 +517,19 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
// declare an output, which is incompatible with gl_FragColor/gl_FragData.
const char* fsColorOutput;
bool dualSourceOutputWritten = false;
bool usingDeclaredOutputs = ProgramDesc::kNone_DualSrcOutput !=
fProgramDesc.fDualSrcOutput;
if (usingDeclaredOutputs) {
GrAssert(0 == segments.fHeader.size());
segments.fHeader.printf("#version 150\n");
fsColorOutput = declared_color_output_name();
segments.fFSOutputs.appendf("out vec4 %s;\n", fsColorOutput);
} else {
fsColorOutput = "gl_FragColor";
}
segments.fHeader.printf(glsl_version_string(gl, glslVersion));
bool isColorDeclared = decl_and_get_fs_color_output(glslVersion,
&segments.fFSOutputs,
&fsColorOutput);
#if GR_GL_ATTRIBUTE_MATRICES
segments.fVSAttrs += "attribute mat3 " VIEW_MATRIX_NAME ";\n";
segments.fVSAttrs.push_back().set(GrGLShaderVar::kMat33f_Type, VIEW_MATRIX_NAME);
programData->fUniLocations.fViewMatrixUni = kSetAsAttribute;
#else
segments.fVSUnis += "uniform mat3 " VIEW_MATRIX_NAME ";\n";
segments.fVSUnis.push_back().set(GrGLShaderVar::kMat33f_Type, VIEW_MATRIX_NAME);
programData->fUniLocations.fViewMatrixUni = kUseUniform;
#endif
segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec2f_Type, POS_ATTR_NAME);
segments.fVSCode.append(
"void main() {\n"
@ -463,13 +542,16 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
if (needComputedColor) {
switch (fProgramDesc.fColorType) {
case ProgramDesc::kAttribute_ColorType:
segments.fVSAttrs.append( "attribute vec4 " COL_ATTR_NAME ";\n");
segments.fVaryings.append("varying vec4 vColor;\n");
segments.fVSCode.append( "\tvColor = " COL_ATTR_NAME ";\n");
segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
COL_ATTR_NAME);
segments.fVaryings.push_back().set(GrGLShaderVar::kVec4f_Type,
"vColor");
segments.fVSCode.append("\tvColor = " COL_ATTR_NAME ";\n");
inColor = "vColor";
break;
case ProgramDesc::kUniform_ColorType:
segments.fFSUnis.append( "uniform vec4 " COL_UNI_NAME ";\n");
segments.fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
COL_UNI_NAME);
programData->fUniLocations.fColorUni = kUseUniform;
inColor = COL_UNI_NAME;
break;
@ -490,7 +572,8 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) {
if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) {
tex_attr_name(t, texCoordAttrs + t);
segments.fVSAttrs.appendf("attribute vec2 %s;\n", texCoordAttrs[t].c_str());
segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec2f_Type,
texCoordAttrs[t].c_str());
}
}
@ -521,7 +604,8 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
inCoords = texCoordAttrs[tcIdx].c_str();
}
genStageCode(gl, s,
genStageCode(gl,
s,
fProgramDesc.fStages[s],
inColor.size() ? inColor.c_str() : NULL,
outColor.c_str(),
@ -544,7 +628,8 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
&needColorFilterUniform, &bogus);
}
if (needColorFilterUniform) {
segments.fFSUnis.append( "uniform vec4 " COL_FILTER_UNI_NAME ";\n");
segments.fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
COL_FILTER_UNI_NAME);
programData->fUniLocations.fColorFilterUni = kUseUniform;
}
@ -608,8 +693,8 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
}
}
if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
segments.fFSOutputs.appendf("out vec4 %s;\n",
dual_source_output_name());
segments.fFSOutputs.push_back().set(GrGLShaderVar::kVec4f_Type,
dual_source_output_name());
bool outputIsZero = false;
GrStringBuilder coeff;
if (ProgramDesc::kCoverage_DualSrcOutput !=
@ -644,9 +729,9 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
if (!wroteFragColorZero) {
modulate_helper(fsColorOutput,
inColor.c_str(),
inCoverage.c_str(),
&segments.fFSCode);
inColor.c_str(),
inCoverage.c_str(),
&segments.fFSCode);
}
segments.fVSCode.append("}\n");
@ -655,12 +740,12 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
///////////////////////////////////////////////////////////////////////////
// compile and setup attribs and unis
if (!CompileFSAndVS(gl, segments, programData)) {
if (!CompileFSAndVS(gl, glslVersion, segments, programData)) {
return false;
}
if (!this->bindOutputsAttribsAndLinkProgram(gl, texCoordAttrs,
usingDeclaredOutputs,
isColorDeclared,
dualSourceOutputWritten,
programData)) {
return false;
@ -671,7 +756,36 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
return true;
}
namespace {
void expand_decls(const VarArray& unis,
const GrGLInterface* gl,
const char* prefix,
GrStringBuilder* string) {
const int count = unis.count();
for (int i = 0; i < count; ++i) {
string->append(prefix);
string->append(" ");
unis[i].appendDecl(gl, string);
string->append(";\n");
}
}
void print_shader(int stringCnt,
const char** strings,
int* stringLengths) {
for (int i = 0; i < stringCnt; ++i) {
if (NULL == stringLengths || stringLengths[i] < 0) {
GrPrintf(strings[i]);
} else {
GrPrintf("%.*s", stringLengths[i], strings[i]);
}
}
}
}
bool GrGLProgram::CompileFSAndVS(const GrGLInterface* gl,
GLSLVersion glslVersion,
const ShaderCodeSegments& segments,
CachedData* programData) {
@ -679,25 +793,41 @@ bool GrGLProgram::CompileFSAndVS(const GrGLInterface* gl,
const char* strings[MAX_STRINGS];
int lengths[MAX_STRINGS];
int stringCnt = 0;
GrStringBuilder attrs;
GrStringBuilder varyings;
GrStringBuilder unis;
GrStringBuilder fsOutputs;
static const char* gVaryingPrefixes[2][2] = {{"varying", "varying"},
{"out", "in"}};
const char** varyingPrefixes = glslVersion == k120_GLSLVersion ?
gVaryingPrefixes[0] :
gVaryingPrefixes[1];
const char* attributePrefix = glslVersion == k120_GLSLVersion ?
"attribute" :
"in";
if (segments.fHeader.size()) {
strings[stringCnt] = segments.fHeader.c_str();
lengths[stringCnt] = segments.fHeader.size();
++stringCnt;
}
if (segments.fVSUnis.size()) {
strings[stringCnt] = segments.fVSUnis.c_str();
lengths[stringCnt] = segments.fVSUnis.size();
expand_decls(segments.fVSUnis, gl, "uniform", &unis);
if (unis.size()) {
strings[stringCnt] = unis.c_str();
lengths[stringCnt] = unis.size();
++stringCnt;
}
if (segments.fVSAttrs.size()) {
strings[stringCnt] = segments.fVSAttrs.c_str();
lengths[stringCnt] = segments.fVSAttrs.size();
expand_decls(segments.fVSAttrs, gl, attributePrefix, &attrs);
if (attrs.size()) {
strings[stringCnt] = attrs.c_str();
lengths[stringCnt] = attrs.size();
++stringCnt;
}
if (segments.fVaryings.size()) {
strings[stringCnt] = segments.fVaryings.c_str();
lengths[stringCnt] = segments.fVaryings.size();
expand_decls(segments.fVaryings, gl, varyingPrefixes[0], &varyings);
if (varyings.size()) {
strings[stringCnt] = varyings.c_str();
lengths[stringCnt] = varyings.size();
++stringCnt;
}
@ -707,13 +837,10 @@ bool GrGLProgram::CompileFSAndVS(const GrGLInterface* gl,
++stringCnt;
#if PRINT_SHADERS
GrPrintf(segments.fHeader.c_str());
GrPrintf(segments.fVSUnis.c_str());
GrPrintf(segments.fVSAttrs.c_str());
GrPrintf(segments.fVaryings.c_str());
GrPrintf(segments.fVSCode.c_str());
print_shader(stringCnt, strings, lengths);
GrPrintf("\n");
#endif
GrAssert(stringCnt <= MAX_STRINGS);
programData->fVShaderID = CompileShader(gl, GR_GL_VERTEX_SHADER,
stringCnt, strings, lengths);
@ -734,19 +861,26 @@ bool GrGLProgram::CompileFSAndVS(const GrGLInterface* gl,
lengths[stringCnt] = strlen(GrShaderPrecision(gl));
++stringCnt;
}
if (segments.fFSUnis.size()) {
strings[stringCnt] = segments.fFSUnis.c_str();
lengths[stringCnt] = segments.fFSUnis.size();
unis.reset();
expand_decls(segments.fFSUnis, gl, "uniform", &unis);
if (unis.size()) {
strings[stringCnt] = unis.c_str();
lengths[stringCnt] = unis.size();
++stringCnt;
}
if (segments.fVaryings.size()) {
strings[stringCnt] = segments.fVaryings.c_str();
lengths[stringCnt] = segments.fVaryings.size();
varyings.reset();
expand_decls(segments.fVaryings, gl, varyingPrefixes[1], &varyings);
if (varyings.size()) {
strings[stringCnt] = varyings.c_str();
lengths[stringCnt] = varyings.size();
++stringCnt;
}
if (segments.fFSOutputs.size()) {
strings[stringCnt] = segments.fFSOutputs.c_str();
lengths[stringCnt] = segments.fFSOutputs.size();
expand_decls(segments.fFSOutputs, gl, "out", &fsOutputs);
if (fsOutputs.size()) {
// We shouldn't have declared outputs on 1.2
GrAssert(k120_GLSLVersion != glslVersion);
strings[stringCnt] = fsOutputs.c_str();
lengths[stringCnt] = fsOutputs.size();
++stringCnt;
}
if (segments.fFSFunctions.size()) {
@ -761,15 +895,10 @@ bool GrGLProgram::CompileFSAndVS(const GrGLInterface* gl,
++stringCnt;
#if PRINT_SHADERS
GrPrintf(segments.fHeader.c_str());
GrPrintf(GrShaderPrecision(gl));
GrPrintf(segments.fFSUnis.c_str());
GrPrintf(segments.fVaryings.c_str());
GrPrintf(segments.fFSOutputs.c_str());
GrPrintf(segments.fFSFunctions.c_str());
GrPrintf(segments.fFSCode.c_str());
print_shader(stringCnt, strings, lengths);
GrPrintf("\n");
#endif
GrAssert(stringCnt <= MAX_STRINGS);
programData->fFShaderID = CompileShader(gl, GR_GL_FRAGMENT_SHADER,
stringCnt, strings, lengths);
@ -810,13 +939,7 @@ GrGLuint GrGLProgram::CompileShader(const GrGLInterface* gl,
GrGLsizei length = GR_GL_INIT_ZERO;
GR_GL_CALL(gl, GetShaderInfoLog(shader, infoLen+1,
&length, (char*)log.get()));
for (int i = 0; i < stringCnt; ++i) {
if (NULL == stringLengths || stringLengths[i] < 0) {
GrPrintf(strings[i]);
} else {
GrPrintf("%.*s", stringLengths[i], strings[i]);
}
}
print_shader(stringCnt, strings, stringLengths);
GrPrintf("\n%s", log.get());
}
GrAssert(!"Shader compilation failed!");
@ -1027,9 +1150,6 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
GrAssert(stageNum >= 0 && stageNum <= 9);
GrStringBuilder varyingName;
stage_varying_name(stageNum, &varyingName);
// First decide how many coords are needed to access the texture
// Right now it's always 2 but we could start using 1D textures for
// gradients.
@ -1039,18 +1159,22 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
// decide whether we need a matrix to transform texture coords
// and whether the varying needs a perspective coord.
GrStringBuilder texMName;
tex_matrix_name(stageNum, &texMName);
const char* matName = NULL;
if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
varyingDims = coordDims;
} else {
GrGLShaderVar* mat;
#if GR_GL_ATTRIBUTE_MATRICES
segments->fVSAttrs.appendf("attribute mat3 %s;\n", texMName.c_str());
mat = &segments->fVSAttrs.push_back();
locations->fTextureMatrixUni = kSetAsAttribute;
#else
segments->fVSUnis.appendf("uniform mat3 %s;\n", texMName.c_str());
mat = &segments->fVSUnis.push_back();
locations->fTextureMatrixUni = kUseUniform;
#endif
tex_matrix_name(stageNum, mat->accessName());
mat->setType(GrGLShaderVar::kMat33f_Type);
matName = mat->getName().c_str();
if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
varyingDims = coordDims;
} else {
@ -1058,75 +1182,93 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
}
}
GrStringBuilder samplerName;
sampler_name(stageNum, &samplerName);
segments->fFSUnis.appendf("uniform sampler2D %s;\n", samplerName.c_str());
segments->fFSUnis.push_back().setType(GrGLShaderVar::kSampler2D_Type);
sampler_name(stageNum, segments->fFSUnis.back().accessName());
locations->fSamplerUni = kUseUniform;
const char* samplerName = segments->fFSUnis.back().getName().c_str();
GrStringBuilder texelSizeName;
const char* texelSizeName = NULL;
if (StageDesc::k2x2_FetchMode == desc.fFetchMode) {
normalized_texel_size_name(stageNum, &texelSizeName);
segments->fFSUnis.appendf("uniform vec2 %s;\n", texelSizeName.c_str());
segments->fFSUnis.push_back().setType(GrGLShaderVar::kVec2f_Type);
normalized_texel_size_name(stageNum, segments->fFSUnis.back().accessName());
texelSizeName = segments->fFSUnis.back().getName().c_str();
}
segments->fVaryings.appendf("varying %s %s;\n",
float_vector_type(varyingDims), varyingName.c_str());
const char* varyingName;
GrGLShaderVar* varying = &segments->fVaryings.push_back();
stage_varying_name(stageNum, varying->accessName());
varying->setType(float_vector_type(varyingDims));
varyingName = varying->getName().c_str();
if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
if (!matName) {
GrAssert(varyingDims == coordDims);
segments->fVSCode.appendf("\t%s = %s;\n", varyingName.c_str(), vsInCoord);
segments->fVSCode.appendf("\t%s = %s;\n", varyingName, vsInCoord);
} else {
// varying = texMatrix * texCoord
segments->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n",
varyingName.c_str(), texMName.c_str(),
vsInCoord, vector_all_coords(varyingDims));
varyingName, matName, vsInCoord,
vector_all_coords(varyingDims));
}
GrStringBuilder radial2ParamsName;
radial2_param_name(stageNum, &radial2ParamsName);
// for radial grads without perspective we can pass the linear
// part of the quadratic as a varying.
GrStringBuilder radial2VaryingName;
radial2_varying_name(stageNum, &radial2VaryingName);
const char* radial2ParamsName = NULL;
const char* radial2VaryingName = NULL;
if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping ||
if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping ||
StageDesc::kRadial2GradientDegenerate_CoordMapping == desc.fCoordMapping) {
segments->fVSUnis.appendf("uniform %s float %s[6];\n",
GrPrecision(gl), radial2ParamsName.c_str());
segments->fFSUnis.appendf("uniform float %s[6];\n",
radial2ParamsName.c_str());
GrGLShaderVar* radial2FSParams = &segments->fFSUnis.push_back();
radial2FSParams->setType(GrGLShaderVar::kFloat_Type);
radial2FSParams->setArrayCount(6);
radial2_param_name(stageNum, radial2FSParams->accessName());
segments->fVSUnis.push_back(*radial2FSParams).setEmitPrecision(true);
radial2ParamsName = radial2FSParams->getName().c_str();
locations->fRadial2Uni = kUseUniform;
// if there is perspective we don't interpolate this
// for radial grads without perspective we can pass the linear
// part of the quadratic as a varying.
if (varyingDims == coordDims) {
GrAssert(2 == coordDims);
segments->fVaryings.appendf("varying float %s;\n", radial2VaryingName.c_str());
GrGLShaderVar* radial2Varying = &segments->fVaryings.push_back();
radial2Varying->setType(GrGLShaderVar::kFloat_Type);
radial2_varying_name(stageNum, radial2Varying->accessName());
radial2VaryingName = radial2Varying->getName().c_str();
// r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
const char* r2ParamName = radial2FSParams->getName().c_str();
const char* r2VarName = radial2Varying->getName().c_str();
segments->fVSCode.appendf("\t%s = 2.0 *(%s[2] * %s.x - %s[3]);\n",
radial2VaryingName.c_str(), radial2ParamsName.c_str(),
varyingName.c_str(), radial2ParamsName.c_str());
r2VarName, r2ParamName, varyingName,
r2ParamName);
}
}
GrStringBuilder kernelName, kernelWidthName, imageIncrementName;
convolve_param_names(stageNum, &kernelName, &imageIncrementName);
const char* kernelName = NULL;
const char* imageIncrementName = NULL;
if (ProgramDesc::StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
segments->fFSUnis.appendf("uniform float %s[%d];\n",
kernelName.c_str(), desc.fKernelWidth);
segments->fFSUnis.appendf("uniform vec2 %s;\n",
imageIncrementName.c_str());
segments->fVSUnis.appendf("uniform %s vec2 %s;\n",
GrPrecision(gl),
imageIncrementName.c_str());
GrGLShaderVar* kernel = &segments->fFSUnis.push_back();
kernel->setType(GrGLShaderVar::kFloat_Type);
kernel->setArrayCount(desc.fKernelWidth);
GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
imgInc->setType(GrGLShaderVar::kVec2f_Type);
convolve_param_names(stageNum,
kernel->accessName(),
imgInc->accessName());
kernelName = kernel->getName().c_str();
imageIncrementName = imgInc->getName().c_str();
// need image increment in both VS and FS
segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true);
locations->fKernelUni = kUseUniform;
locations->fImageIncrementUni = kUseUniform;
float scale = (desc.fKernelWidth - 1) * 0.5f;
segments->fVSCode.appendf("\t%s -= vec2(%g, %g) * %s;\n",
varyingName.c_str(), scale, scale,
imageIncrementName.c_str());
varyingName, scale, scale,
imageIncrementName);
}
/// Fragment Shader Stuff
@ -1149,12 +1291,12 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
fsCoordName = "inCoord";
fsCoordName.appendS32(stageNum);
segments->fFSCode.appendf("\t%s %s = %s%s / %s%s;\n",
float_vector_type(coordDims),
fsCoordName.c_str(),
varyingName.c_str(),
vector_nonhomog_coords(varyingDims),
varyingName.c_str(),
vector_homog_coord(varyingDims));
GrGLShaderVar::TypeString(float_vector_type(coordDims)),
fsCoordName.c_str(),
varyingName,
vector_nonhomog_coords(varyingDims),
varyingName,
vector_homog_coord(varyingDims));
}
}
@ -1192,18 +1334,18 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
bVar = "b";
bVar.appendS32(stageNum);
segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
bVar.c_str(), radial2ParamsName.c_str(),
fsCoordName.c_str(), radial2ParamsName.c_str());
bVar.c_str(), radial2ParamsName,
fsCoordName.c_str(), radial2ParamsName);
}
// c = (x^2)+(y^2) - params[4]
segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
cName.c_str(), fsCoordName.c_str(),
fsCoordName.c_str(),
radial2ParamsName.c_str());
radial2ParamsName);
// ac4 = 4.0 * params[0] * c
segments->fFSCode.appendf("\tfloat %s = %s[0] * 4.0 * %s;\n",
ac4Name.c_str(), radial2ParamsName.c_str(),
ac4Name.c_str(), radial2ParamsName,
cName.c_str());
// root = sqrt(b^2-4ac)
@ -1215,8 +1357,8 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
// x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1]
// y coord is 0.5 (texture is effectively 1D)
sampleCoords.printf("vec2((-%s + %s[5] * %s) * %s[1], 0.5)",
bVar.c_str(), radial2ParamsName.c_str(),
rootName.c_str(), radial2ParamsName.c_str());
bVar.c_str(), radial2ParamsName,
rootName.c_str(), radial2ParamsName);
complexCoord = true;
break;}
case StageDesc::kRadial2GradientDegenerate_CoordMapping: {
@ -1235,15 +1377,15 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
bVar = "b";
bVar.appendS32(stageNum);
segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
bVar.c_str(), radial2ParamsName.c_str(),
fsCoordName.c_str(), radial2ParamsName.c_str());
bVar.c_str(), radial2ParamsName,
fsCoordName.c_str(), radial2ParamsName);
}
// c = (x^2)+(y^2) - params[4]
segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
cName.c_str(), fsCoordName.c_str(),
fsCoordName.c_str(),
radial2ParamsName.c_str());
radial2ParamsName);
// x coord is: -c/b
// y coord is 0.5 (texture is effectively 1D)
@ -1267,12 +1409,10 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
StageDesc::kCustomTextureDomain_OptFlagBit) {
GrStringBuilder texDomainName;
tex_domain_name(stageNum, &texDomainName);
segments->fFSUnis.appendf("uniform %s %s;\n",
float_vector_type(4),
texDomainName.c_str());
segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type, texDomainName);
GrStringBuilder coordVar("clampCoord");
segments->fFSCode.appendf("\t%s %s = clamp(%s, %s.xy, %s.zw);\n",
float_vector_type(coordDims),
float_vector_type_str(coordDims),
coordVar.c_str(),
sampleCoords.c_str(),
texDomainName.c_str(),
@ -1288,17 +1428,17 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
GrStringBuilder coordVar("tCoord");
coordVar.appendS32(stageNum);
segments->fFSCode.appendf("\t%s %s = %s;\n",
float_vector_type(coordDims),
coordVar.c_str(), sampleCoords.c_str());
float_vector_type_str(coordDims),
coordVar.c_str(), sampleCoords.c_str());
sampleCoords = coordVar;
}
GrAssert(2 == coordDims);
GrStringBuilder accumVar("accum");
accumVar.appendS32(stageNum);
segments->fFSCode.appendf("\tvec4 %s = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
segments->fFSCode.appendf("\tvec4 %s = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords.c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords.c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords.c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords.c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s = .25 * %s%s;\n", fsOutColor, accumVar.c_str(), modulate.c_str());
} else if (ProgramDesc::StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
GrStringBuilder sumVar("sum");
@ -1315,18 +1455,18 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
desc.fKernelWidth);
segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s[i];\n",
sumVar.c_str(), texFunc.c_str(),
samplerName.c_str(), coordVar.c_str(), smear,
kernelName.c_str());
samplerName, coordVar.c_str(), smear,
kernelName);
segments->fFSCode.appendf("\t\t%s += %s;\n",
coordVar.c_str(),
imageIncrementName.c_str());
imageIncrementName);
segments->fFSCode.appendf("\t}\n");
segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor,
sumVar.c_str(), modulate.c_str());
} else {
segments->fFSCode.appendf("\t%s = %s(%s, %s)%s%s;\n",
fsOutColor, texFunc.c_str(),
samplerName.c_str(), sampleCoords.c_str(),
samplerName, sampleCoords.c_str(),
smear, modulate.c_str());
}
}

View File

@ -18,17 +18,7 @@
class GrBinHashKeyBuilder;
struct ShaderCodeSegments {
GrStringBuilder fHeader; // VS+FS, GLSL version, etc
GrStringBuilder fVSUnis;
GrStringBuilder fVSAttrs;
GrStringBuilder fVaryings;
GrStringBuilder fFSUnis;
GrStringBuilder fFSOutputs;
GrStringBuilder fFSFunctions;
GrStringBuilder fVSCode;
GrStringBuilder fFSCode;
};
struct ShaderCodeSegments;
/**
* This class manages a GPU program and records per-program information.
@ -41,6 +31,11 @@ struct ShaderCodeSegments {
*/
class GrGLProgram {
public:
enum GLSLVersion {
k120_GLSLVersion, // Desktop GLSL 1.2 and ES2 shading lang
k130_GLSLVersion // Desktop GLSL 1.3
};
class CachedData;
GrGLProgram();
@ -52,6 +47,7 @@ public:
* but in a separate cacheable container.
*/
bool genProgram(const GrGLInterface* gl,
GLSLVersion glslVersion,
CachedData* programData) const;
/**
@ -286,7 +282,7 @@ private:
const char* vsInCoord,
ShaderCodeSegments* segments,
StageUniLocations* locations) const;
// generates code to compute coverage based on edge AA.
void genEdgeCoverage(const GrGLInterface* gl,
GrVertexLayout layout,
@ -295,6 +291,7 @@ private:
ShaderCodeSegments* segments) const;
static bool CompileFSAndVS(const GrGLInterface* gl,
GLSLVersion glslVersion,
const ShaderCodeSegments& segments,
CachedData* programData);

217
gpu/src/GrGLShaderVar.h Normal file
View File

@ -0,0 +1,217 @@
/*
* 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 "GrGLInterface.h"
/**
* Represents a variable in a shader
*/
class GrGLShaderVar {
public:
enum Type {
kFloat_Type,
kVec2f_Type,
kVec3f_Type,
kVec4f_Type,
kMat33f_Type,
kSampler2D_Type,
};
/**
* Defaults to a float with no precision specifier
*/
GrGLShaderVar() {
fType = kFloat_Type;
fCount = kNonArray;
fEmitPrecision = false;
}
GrGLShaderVar(const GrGLShaderVar& var)
: fType(var.fType)
, fName(var.fName)
, fCount(var.fCount)
, fEmitPrecision(var.fEmitPrecision) {}
/**
* 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(Type type,
const GrStringBuilder& name,
bool emitPrecision = false) {
fType = type;
fName = name;
fCount = kNonArray;
fEmitPrecision = emitPrecision;
}
/**
* Sets as a non-array.
*/
void set(Type type,
const char* name,
bool specifyPrecision = false) {
fType = type;
fName = name;
fCount = kNonArray;
fEmitPrecision = specifyPrecision;
}
/**
* Set all var options
*/
void set(Type type,
const GrStringBuilder& name,
int count,
bool specifyPrecision = false) {
fType = type;
fName = name;
fCount = count;
fEmitPrecision = specifyPrecision;
}
/**
* Set all var options
*/
void set(Type type,
const char* name,
int count,
bool specifyPrecision = false) {
fType = type;
fName = name;
fCount = count;
fEmitPrecision = specifyPrecision;
}
/**
* Is the var an array.
*/
bool isArray() const { return kNonArray != fCount; }
/**
* Is this an unsized array, (i.e. declared with []).
*/
bool isUnsizedArray() const { return kUnsizedArray == fCount; }
/**
* Get the array length of the var.
*/
int getArrayCount() const { return fCount; }
/**
* Set the array length of the var
*/
void setArrayCount(int count) { fCount = count; }
/**
* Set to be a non-array.
*/
void setNonArray() { fCount = kNonArray; }
/**
* Set to be an unsized array.
*/
void setUnsizedArray() { fCount = kUnsizedArray; }
/**
* Access the var name as a writable string
*/
GrStringBuilder* accessName() { return &fName; }
/**
* Set the var name
*/
void setName(const GrStringBuilder& n) { fName = n; }
void setName(const char* n) { fName = n; }
/**
* Get the var name.
*/
const GrStringBuilder& getName() const { return fName; }
/**
* Get the type of the var
*/
Type getType() const { return fType; }
/**
* Set the type of the var
*/
void setType(Type type) { fType = type; }
/**
* Must the variable declaration emit a precision specifier
*/
bool emitsPrecision() const { return fEmitPrecision; }
/**
* Specify whether the declaration should specify precision
*/
void setEmitPrecision(bool p) { fEmitPrecision = p; }
/**
* Write a declaration of this variable to out.
*/
void appendDecl(const GrGLInterface* gl, GrStringBuilder* out) const {
if (this->emitsPrecision()) {
out->append(PrecisionString(gl));
out->append(" ");
}
if (this->isArray()) {
if (this->isUnsizedArray()) {
out->appendf("%s %s[]",
TypeString(this->getType()),
this->getName().c_str());
} else {
GrAssert(this->getArrayCount() > 0);
out->appendf("%s %s[%d]",
TypeString(this->getType()),
this->getName().c_str(),
this->getArrayCount());
}
} else {
out->appendf("%s %s",
TypeString(this->getType()),
this->getName().c_str());
}
}
static const char* TypeString(Type t) {
switch (t) {
case kFloat_Type:
return "float";
case kVec2f_Type:
return "vec2";
case kVec3f_Type:
return "vec3";
case kVec4f_Type:
return "vec4";
case kMat33f_Type:
return "mat3";
case kSampler2D_Type:
return "sampler2D";
default:
GrCrash("Unknown shader var type.");
return ""; // suppress warning
}
}
private:
static const char* PrecisionString(const GrGLInterface* gl) {
return gl->supportsDesktop() ? "" : "mediump";
}
Type fType;
GrStringBuilder fName;
int fCount;
bool fEmitPrecision;
};
#endif

View File

@ -26,6 +26,7 @@ public:
const GrGLInterface* glInterface() const { return fGL; }
GrGLBinding glBinding() const { return fGLBinding; }
float glVersion() const { return fGLVersion; }
protected:
GrGpuGL(const GrGLInterface* glInterface, GrGLBinding glBinding);
@ -46,10 +47,6 @@ protected:
DrState fHWDrawState;
bool fHWStencilClip;
// read these once at begining and then never again
SkString fExtensionString;
float fGLVersion;
// As flush of GL state proceeds it updates fHDrawState
// to reflect the new state. Later parts of the state flush
// may perform cascaded changes but cannot refer to fHWDrawState.
@ -193,13 +190,16 @@ private:
friend class GrGLTexture;
friend class GrGLRenderTarget;
// read these once at begining and then never again
SkString fExtensionString;
float fGLVersion;
SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
// we want to clear stencil buffers when they are created. We want to clear
// the entire buffer even if it is larger than the color attachment. We
// attach it to this fbo with no color attachment to do the initial clear.
GrGLuint fStencilClearFBO;
bool fHWBlendDisabled;
GrGLuint fAASamples[4];

View File

@ -51,15 +51,19 @@ private:
enum {
kMaxEntries = 32
};
Entry fEntries[kMaxEntries];
int fCount;
unsigned int fCurrLRUStamp;
const GrGLInterface* fGL;
Entry fEntries[kMaxEntries];
int fCount;
unsigned int fCurrLRUStamp;
const GrGLInterface* fGL;
GrGLProgram::GLSLVersion fGLSLVersion;
public:
ProgramCache(const GrGLInterface* gl)
ProgramCache(const GrGLInterface* gl,
GrGLProgram::GLSLVersion glslVersion)
: fCount(0)
, fCurrLRUStamp(0)
, fGL(gl) {
, fGL(gl)
, fGLSLVersion(glslVersion) {
}
~ProgramCache() {
@ -85,7 +89,7 @@ public:
Entry* entry = fHashCache.find(newEntry.fKey);
if (NULL == entry) {
if (!desc.genProgram(fGL, &newEntry.fProgramData)) {
if (!desc.genProgram(fGL, fGLSLVersion, &newEntry.fProgramData)) {
return NULL;
}
if (fCount < kMaxEntries) {
@ -136,14 +140,33 @@ void GrGpuGLShaders::DeleteProgram(const GrGLInterface* gl,
#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
namespace {
template <typename T>
T random_val(GrRandom* r, T count) {
return (T)(int)(r->nextF() * count);
GrGLProgram::GLSLVersion get_glsl_version(GrGLBinding binding, float glVersion) {
switch (binding) {
case kDesktop_GrGLBinding:
// TODO: proper check of the glsl version string
return (glVersion >= 3.0) ? GrGLProgram::k130_GLSLVersion :
GrGLProgram::k120_GLSLVersion;
case kES2_GrGLBinding:
return GrGLProgram::k120_GLSLVersion;
default:
GrCrash("Attempting to get GLSL version in unknown or fixed-"
"function GL binding.");
return GrGLProgram::k120_GLSLVersion; // suppress warning
}
};
}
template <typename T>
T random_val(GrRandom* r, T count) {
return (T)(int)(r->nextF() * count);
}
}
bool GrGpuGLShaders::programUnitTest() {
GrGLProgram::GLSLVersion glslVersion =
get_glsl_version(this->glBinding(), this->glVersion());
static const int STAGE_OPTS[] = {
0,
StageDesc::kNoPerspective_OptFlagBit,
@ -242,15 +265,12 @@ bool GrGpuGLShaders::programUnitTest() {
stage.fKernelWidth = 4 * random.nextF() + 2;
}
CachedData cachedData;
if (!program.genProgram(this->glInterface(), &cachedData)) {
if (!program.genProgram(this->glInterface(),
glslVersion,
&cachedData)) {
return false;
}
DeleteProgram(this->glInterface(), &cachedData);
bool again = false;
if (again) {
program.genProgram(this->glInterface(), &cachedData);
DeleteProgram(this->glInterface(), &cachedData);
}
}
return true;
}
@ -272,7 +292,8 @@ GrGpuGLShaders::GrGpuGLShaders(const GrGLInterface* gl)
fShaderSupport = true;
if (kDesktop_GrGLBinding == this->glBinding()) {
fDualSourceBlendingSupport =
fGLVersion >= 3.3f ||
this->glVersion() >= 3.25f || // TODO: when resolving Issue 387 change
// this back to 3.3
this->hasExtension("GL_ARB_blend_func_extended");
fShaderDerivativeSupport = true;
} else {
@ -282,7 +303,9 @@ GrGpuGLShaders::GrGpuGLShaders(const GrGLInterface* gl)
}
fProgramData = NULL;
fProgramCache = new ProgramCache(gl);
GrGLProgram::GLSLVersion glslVersion =
get_glsl_version(this->glBinding(), this->glVersion());
fProgramCache = new ProgramCache(gl, glslVersion);
#if 0
this->programUnitTest();

View File

@ -149,6 +149,7 @@
'../gpu/src/GrGLProgram.h',
'../gpu/src/GrGLRenderTarget.cpp',
'../gpu/src/GrGLRenderTarget.h',
'../gpu/src/GrGLShaderVar.h',
'../gpu/src/GrGLStencilBuffer.cpp',
'../gpu/src/GrGLStencilBuffer.h',
'../gpu/src/GrGLTexture.cpp',

View File

@ -245,6 +245,16 @@ public:
return fItemArray[fCount-1];
}
/**
* Version of above that uses a copy constructor to initialize the new item
*/
T& push_back(const T& t) {
checkRealloc(1);
new ((char*)fMemArray+sizeof(T)*fCount) T(t);
++fCount;
return fItemArray[fCount-1];
}
/**
* Allocates n more default T values, and returns the address of the start
* of that new range. Note: this address is only valid until the next API
@ -260,6 +270,34 @@ public:
return fItemArray + fCount - n;
}
/**
* Version of above that uses a copy constructor to initialize all n items
* to the same T.
*/
T* push_back_n(int n, const T& t) {
SkASSERT(n >= 0);
checkRealloc(n);
for (int i = 0; i < n; ++i) {
new (fItemArray + fCount + i) T(t);
}
fCount += n;
return fItemArray + fCount - n;
}
/**
* Version of above that uses a copy constructor to initialize the n items
* to separate T values.
*/
T* push_back_n(int n, const T t[]) {
SkASSERT(n >= 0);
checkRealloc(n);
for (int i = 0; i < n; ++i) {
new (fItemArray + fCount + i) T(t[i]);
}
fCount += n;
return fItemArray + fCount - n;
}
/**
* Removes the last element. Not safe to call when count() == 0.
*/