aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-30 20:17:31 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-30 20:17:31 +0000
commit5a02cb48fdff04dc274d4cb1af8c4dc65a503438 (patch)
treec4c7c3bf5d8d86d0f6274f4abb2d95e281f552ac /src/gpu/gl
parent74a3a2135ca82ab9324b7e499caa3280348a4fda (diff)
Isolate VertexBuilder from GrGLShaderBuilder
Adds a nested class to GrGLShaderBuilder called VertexBuilder. Now GrGLShaderBuilder can only modify the fragment shader directly. In order to modify the vertex shader, the client code needs to call getVertexShader, which will return null for vertex-less shaders. R=bsalomon@google.com Author: cdalton@nvidia.com Review URL: https://chromiumcodereview.appspot.com/23754003 git-svn-id: http://skia.googlecode.com/svn/trunk@11046 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/gl')
-rw-r--r--src/gpu/gl/GrGLEffectMatrix.cpp25
-rw-r--r--src/gpu/gl/GrGLProgram.cpp176
-rw-r--r--src/gpu/gl/GrGLProgram.h3
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp253
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.h191
5 files changed, 367 insertions, 281 deletions
diff --git a/src/gpu/gl/GrGLEffectMatrix.cpp b/src/gpu/gl/GrGLEffectMatrix.cpp
index 19f99c0673..7530b5911a 100644
--- a/src/gpu/gl/GrGLEffectMatrix.cpp
+++ b/src/gpu/gl/GrGLEffectMatrix.cpp
@@ -48,6 +48,9 @@ GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder,
SkString* fsCoordName,
SkString* vsCoordName,
const char* suffix) {
+ GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder();
+ SkASSERT(NULL != vertexBuilder);
+
GrSLType varyingType = kVoid_GrSLType;
const char* uniName;
key &= kKeyMask;
@@ -96,17 +99,17 @@ GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder,
}
const char* vsVaryingName;
const char* fsVaryingName;
- builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+ vertexBuilder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
const GrGLShaderVar* coords;
switch (fCoordsType) {
case GrEffect::kLocal_CoordsType:
SkASSERT(!(kPositionCoords_Flag & key));
- coords = &builder->localCoordsAttribute();
+ coords = &vertexBuilder->localCoordsAttribute();
break;
case GrEffect::kPosition_CoordsType:
- SkASSERT((kPositionCoords_Flag & key) || !builder->hasExplicitLocalCoords());
- coords = &builder->positionAttribute();
+ SkASSERT((kPositionCoords_Flag & key) || !vertexBuilder->hasExplicitLocalCoords());
+ coords = &vertexBuilder->positionAttribute();
break;
default:
coords = NULL; // prevents warning
@@ -116,21 +119,21 @@ GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder,
switch (fUniType) {
case kVoid_GrSLType:
SkASSERT(kVec2f_GrSLType == varyingType);
- builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords->c_str());
+ vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords->c_str());
break;
case kVec2f_GrSLType:
SkASSERT(kVec2f_GrSLType == varyingType);
- builder->vsCodeAppendf("\t%s = %s + %s;\n",
- vsVaryingName, uniName, coords->c_str());
+ vertexBuilder->vsCodeAppendf("\t%s = %s + %s;\n",
+ vsVaryingName, uniName, coords->c_str());
break;
case kMat33f_GrSLType: {
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
if (kVec2f_GrSLType == varyingType) {
- builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
- vsVaryingName, uniName, coords->c_str());
+ vertexBuilder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
+ vsVaryingName, uniName, coords->c_str());
} else {
- builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
- vsVaryingName, uniName, coords->c_str());
+ vertexBuilder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
+ vsVaryingName, uniName, coords->c_str());
}
break;
}
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index a1c4fd5d76..540ebcaeb3 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -222,10 +222,12 @@ void add_color_filter(GrGLShaderBuilder* builder,
GrSLConstantVec GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
switch (fDesc.getHeader().fColorInput) {
case GrGLProgramDesc::kAttribute_ColorInput: {
- builder->addAttribute(kVec4f_GrSLType, COL_ATTR_NAME);
+ GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder();
+ SkASSERT(NULL != vertexBuilder);
+ vertexBuilder->addAttribute(kVec4f_GrSLType, COL_ATTR_NAME);
const char *vsName, *fsName;
- builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
- builder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
+ vertexBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
+ vertexBuilder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
*inColor = fsName;
return kNone_GrSLConstantVec;
}
@@ -251,10 +253,12 @@ GrSLConstantVec GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString*
GrSLConstantVec GrGLProgram::genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage) {
switch (fDesc.getHeader().fCoverageInput) {
case GrGLProgramDesc::kAttribute_ColorInput: {
- builder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME);
+ GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder();
+ SkASSERT(NULL != vertexBuilder);
+ vertexBuilder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME);
const char *vsName, *fsName;
- builder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
- builder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
+ vertexBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
+ vertexBuilder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
*inCoverage = fsName;
return kNone_GrSLConstantVec;
}
@@ -278,28 +282,28 @@ GrSLConstantVec GrGLProgram::genInputCoverage(GrGLShaderBuilder* builder, SkStri
}
}
-void GrGLProgram::genGeometryShader(GrGLShaderBuilder* builder) const {
+void GrGLProgram::genGeometryShader(GrGLShaderBuilder::VertexBuilder* vertexBuilder) const {
#if GR_GL_EXPERIMENTAL_GS
// TODO: The builder should add all this glue code.
if (fDesc.getHeader().fExperimentalGS) {
SkASSERT(fContext.info().glslGeneration() >= k150_GrGLSLGeneration);
- builder->fGSHeader.append("layout(triangles) in;\n"
- "layout(triangle_strip, max_vertices = 6) out;\n");
- builder->gsCodeAppend("\tfor (int i = 0; i < 3; ++i) {\n"
- "\t\tgl_Position = gl_in[i].gl_Position;\n");
+ vertexBuilder->fGSHeader.append("layout(triangles) in;\n"
+ "layout(triangle_strip, max_vertices = 6) out;\n");
+ vertexBuilder->gsCodeAppend("\tfor (int i = 0; i < 3; ++i) {\n"
+ "\t\tgl_Position = gl_in[i].gl_Position;\n");
if (fDesc.getHeader().fEmitsPointSize) {
- builder->gsCodeAppend("\t\tgl_PointSize = 1.0;\n");
+ vertexBuilder->gsCodeAppend("\t\tgl_PointSize = 1.0;\n");
}
- SkASSERT(builder->fGSInputs.count() == builder->fGSOutputs.count());
- int count = builder->fGSInputs.count();
+ SkASSERT(vertexBuilder->fGSInputs.count() == vertexBuilder->fGSOutputs.count());
+ int count = vertexBuilder->fGSInputs.count();
for (int i = 0; i < count; ++i) {
- builder->gsCodeAppendf("\t\t%s = %s[i];\n",
- builder->fGSOutputs[i].getName().c_str(),
- builder->fGSInputs[i].getName().c_str());
+ vertexBuilder->gsCodeAppendf("\t\t%s = %s[i];\n",
+ vertexBuilder->fGSOutputs[i].getName().c_str(),
+ vertexBuilder->fGSInputs[i].getName().c_str());
}
- builder->gsCodeAppend("\t\tEmitVertex();\n"
- "\t}\n"
- "\tEndPrimitive();\n");
+ vertexBuilder->gsCodeAppend("\t\tEmitVertex();\n"
+ "\t}\n"
+ "\tEndPrimitive();\n");
}
#endif
}
@@ -397,31 +401,34 @@ void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
// compiles all the shaders from builder and stores the shader IDs
bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) {
- SkString shader;
-
- builder.vsGetShader(&shader);
- if (c_PrintShaders) {
- GrPrintf(shader.c_str());
- GrPrintf("\n");
- }
+ SkASSERT(!fVShaderID);
+ SkASSERT(!fGShaderID);
+ SkASSERT(!fFShaderID);
- if (!(fVShaderID = compile_shader(fContext, GR_GL_VERTEX_SHADER, shader))) {
- return false;
- }
-
- fGShaderID = 0;
-#if GR_GL_EXPERIMENTAL_GS
- if (fDesc.getHeader().fExperimentalGS) {
- builder.gsGetShader(&shader);
+ SkString shader;
+ if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
+ vertexBuilder->vsGetShader(&shader);
if (c_PrintShaders) {
GrPrintf(shader.c_str());
GrPrintf("\n");
}
- if (!(fGShaderID = compile_shader(fContext, GR_GL_GEOMETRY_SHADER, shader))) {
+ if (!(fVShaderID = compile_shader(fContext, GR_GL_VERTEX_SHADER, shader))) {
return false;
}
- }
+
+#if GR_GL_EXPERIMENTAL_GS
+ if (fDesc.getHeader().fExperimentalGS) {
+ vertexBuilder->gsGetShader(&shader);
+ if (c_PrintShaders) {
+ GrPrintf(shader.c_str());
+ GrPrintf("\n");
+ }
+ if (!(fGShaderID = compile_shader(fContext, GR_GL_GEOMETRY_SHADER, shader))) {
+ return false;
+ }
+ }
#endif
+ }
builder.fsGetShader(&shader);
if (c_PrintShaders) {
@@ -441,7 +448,28 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
- GrGLShaderBuilder builder(fContext.info(), fUniformManager, fDesc);
+ bool needsVertexShader = true;
+
+ GrGLShaderBuilder builder(fContext.info(), fUniformManager, fDesc, needsVertexShader);
+
+ if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
+ const char* viewMName;
+ fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_Visibility,
+ kMat33f_GrSLType, "ViewM", &viewMName);
+
+ vertexBuilder->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
+ "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
+ viewMName, vertexBuilder->positionAttribute().c_str());
+
+ // we output point size in the GS if present
+ if (header.fEmitsPointSize
+#if GR_GL_EXPERIMENTAL_GS
+ && !header.fExperimentalGS
+#endif
+ ) {
+ vertexBuilder->vsCodeAppend("\tgl_PointSize = 1.0;\n");
+ }
+ }
// the dual source output has no canonical var name, have to
// declare an output, which is incompatible with gl_FragColor/gl_FragData.
@@ -452,31 +480,13 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
declared_color_output_name(),
&colorOutput);
if (isColorDeclared) {
- builder.fFSOutputs.push_back(colorOutput);
+ builder.fsOutputAppend(colorOutput);
}
- const char* viewMName;
- fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_Visibility,
- kMat33f_GrSLType, "ViewM", &viewMName);
-
-
- builder.vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
- "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
- viewMName, builder.positionAttribute().getName().c_str());
-
// incoming color to current stage being processed.
SkString inColor;
GrSLConstantVec knownColorValue = this->genInputColor(&builder, &inColor);
- // we output point size in the GS if present
- if (header.fEmitsPointSize
-#if GR_GL_EXPERIMENTAL_GS
- && !header.fExperimentalGS
-#endif
- ) {
- builder.vsCodeAppend("\tgl_PointSize = 1.0;\n");
- }
-
// Get the coeffs for the Mode-based color filter, determine if color is needed.
SkXfermode::Coeff colorCoeff;
SkXfermode::Coeff filterColorCoeff;
@@ -567,9 +577,9 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
GrGLProgramDesc::CoverageOutput coverageOutput =
static_cast<GrGLProgramDesc::CoverageOutput>(header.fCoverageOutput);
if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(coverageOutput)) {
- builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
- GrGLShaderVar::kOut_TypeModifier,
- dual_source_output_name());
+ builder.fsOutputAppend().set(kVec4f_GrSLType,
+ GrGLShaderVar::kOut_TypeModifier,
+ dual_source_output_name());
// default coeff to ones for kCoverage_DualSrcOutput
SkString coeff;
GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec;
@@ -651,7 +661,9 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
///////////////////////////////////////////////////////////////////////////
// insert GS
#ifdef SK_DEBUG
- this->genGeometryShader(&builder);
+ if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
+ this->genGeometryShader(vertexBuilder);
+ }
#endif
///////////////////////////////////////////////////////////////////////////
@@ -686,7 +698,9 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil
return false;
}
- GL_CALL(AttachShader(fProgramID, fVShaderID));
+ if (fVShaderID) {
+ GL_CALL(AttachShader(fProgramID, fVShaderID));
+ }
if (fGShaderID) {
GL_CALL(AttachShader(fProgramID, fGShaderID));
}
@@ -702,26 +716,28 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
// Bind the attrib locations to same values for all shaders
- GL_CALL(BindAttribLocation(fProgramID,
- header.fPositionAttributeIndex,
- builder.positionAttribute().c_str()));
- if (-1 != header.fLocalCoordAttributeIndex) {
+ if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
GL_CALL(BindAttribLocation(fProgramID,
- header.fLocalCoordAttributeIndex,
- builder.localCoordsAttribute().c_str()));
- }
- if (-1 != header.fColorAttributeIndex) {
- GL_CALL(BindAttribLocation(fProgramID, header.fColorAttributeIndex, COL_ATTR_NAME));
- }
- if (-1 != header.fCoverageAttributeIndex) {
- GL_CALL(BindAttribLocation(fProgramID, header.fCoverageAttributeIndex, COV_ATTR_NAME));
- }
+ header.fPositionAttributeIndex,
+ vertexBuilder->positionAttribute().c_str()));
+ if (-1 != header.fLocalCoordAttributeIndex) {
+ GL_CALL(BindAttribLocation(fProgramID,
+ header.fLocalCoordAttributeIndex,
+ vertexBuilder->localCoordsAttribute().c_str()));
+ }
+ if (-1 != header.fColorAttributeIndex) {
+ GL_CALL(BindAttribLocation(fProgramID, header.fColorAttributeIndex, COL_ATTR_NAME));
+ }
+ if (-1 != header.fCoverageAttributeIndex) {
+ GL_CALL(BindAttribLocation(fProgramID, header.fCoverageAttributeIndex, COV_ATTR_NAME));
+ }
- const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end();
- for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin();
- attrib != attribEnd;
- ++attrib) {
- GL_CALL(BindAttribLocation(fProgramID, attrib->fIndex, attrib->fName.c_str()));
+ const GrGLShaderBuilder::VertexBuilder::AttributePair* attribEnd = vertexBuilder->getEffectAttributes().end();
+ for (const GrGLShaderBuilder::VertexBuilder::AttributePair* attrib = vertexBuilder->getEffectAttributes().begin();
+ attrib != attribEnd;
+ ++attrib) {
+ GL_CALL(BindAttribLocation(fProgramID, attrib->fIndex, attrib->fName.c_str()));
+ }
}
GL_CALL(LinkProgram(fProgramID));
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 279890f5d4..e39e9bf076 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -12,6 +12,7 @@
#include "GrDrawState.h"
#include "GrGLContext.h"
#include "GrGLProgramDesc.h"
+#include "GrGLShaderBuilder.h"
#include "GrGLSL.h"
#include "GrGLTexture.h"
#include "GrGLUniformManager.h"
@@ -162,7 +163,7 @@ private:
GrSLConstantVec genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage);
- void genGeometryShader(GrGLShaderBuilder* segments) const;
+ void genGeometryShader(GrGLShaderBuilder::VertexBuilder* vertexBuilder) const;
// Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 2554142583..e62bfdebe8 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -93,37 +93,23 @@ static const char kDstCopyColorName[] = "_dstColor";
GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
GrGLUniformManager& uniformManager,
- const GrGLProgramDesc& desc)
+ const GrGLProgramDesc& desc,
+ bool needsVertexShader)
: fUniforms(kVarsPerBlock)
- , fVSAttrs(kVarsPerBlock)
- , fVSOutputs(kVarsPerBlock)
- , fGSInputs(kVarsPerBlock)
- , fGSOutputs(kVarsPerBlock)
- , fFSInputs(kVarsPerBlock)
- , fFSOutputs(kMaxFSOutputs)
, fCtxInfo(ctxInfo)
, fUniformManager(uniformManager)
, fFSFeaturesAddedMask(0)
-#if GR_GL_EXPERIMENTAL_GS
- , fUsesGS(SkToBool(desc.getHeader().fExperimentalGS))
-#else
- , fUsesGS(false)
-#endif
+ , fFSInputs(kVarsPerBlock)
+ , fFSOutputs(kMaxFSOutputs)
, fSetupFragPosition(false)
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) {
const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
- fPositionVar = &fVSAttrs.push_back();
- fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
- if (-1 != header.fLocalCoordAttributeIndex) {
- fLocalCoordsVar = &fVSAttrs.push_back();
- fLocalCoordsVar->set(kVec2f_GrSLType,
- GrGLShaderVar::kAttribute_TypeModifier,
- "aLocalCoords");
- } else {
- fLocalCoordsVar = fPositionVar;
+ if (needsVertexShader) {
+ fVertexBuilder.reset(SkNEW_ARGS(VertexBuilder, (this, desc)));
}
+
// Emit code to read the dst copy textue if necessary.
if (kNoDstRead_DstReadKey != header.fDstReadKey &&
GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) {
@@ -375,61 +361,6 @@ GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t vi
return h;
}
-bool GrGLShaderBuilder::addAttribute(GrSLType type,
- const char* name) {
- for (int i = 0; i < fVSAttrs.count(); ++i) {
- const GrGLShaderVar& attr = fVSAttrs[i];
- // if attribute already added, don't add it again
- if (attr.getName().equals(name)) {
- SkASSERT(attr.getType() == type);
- return false;
- }
- }
- fVSAttrs.push_back().set(type,
- GrGLShaderVar::kAttribute_TypeModifier,
- name);
- return true;
-}
-
-void GrGLShaderBuilder::addVarying(GrSLType type,
- const char* name,
- const char** vsOutName,
- const char** fsInName) {
- fVSOutputs.push_back();
- fVSOutputs.back().setType(type);
- fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
- this->nameVariable(fVSOutputs.back().accessName(), 'v', name);
-
- if (vsOutName) {
- *vsOutName = fVSOutputs.back().getName().c_str();
- }
- // input to FS comes either from VS or GS
- const SkString* fsName;
- if (fUsesGS) {
- // if we have a GS take each varying in as an array
- // and output as non-array.
- fGSInputs.push_back();
- fGSInputs.back().setType(type);
- fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
- fGSInputs.back().setUnsizedArray();
- *fGSInputs.back().accessName() = fVSOutputs.back().getName();
- fGSOutputs.push_back();
- fGSOutputs.back().setType(type);
- fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
- this->nameVariable(fGSOutputs.back().accessName(), 'g', name);
- fsName = fGSOutputs.back().accessName();
- } else {
- fsName = fVSOutputs.back().accessName();
- }
- fFSInputs.push_back();
- fFSInputs.back().setType(type);
- fFSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
- fFSInputs.back().setName(*fsName);
- if (fsInName) {
- *fsInName = fsName->c_str();
- }
-}
-
const char* GrGLShaderBuilder::fragmentPosition() {
if (fCodeStage.inStageCode()) {
const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
@@ -547,31 +478,6 @@ void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility,
}
}
-void GrGLShaderBuilder::vsGetShader(SkString* shaderStr) const {
- *shaderStr = GrGetGLSLVersionDecl(fCtxInfo);
- this->appendUniformDecls(kVertex_Visibility, shaderStr);
- this->appendDecls(fVSAttrs, shaderStr);
- this->appendDecls(fVSOutputs, shaderStr);
- shaderStr->append("void main() {\n");
- shaderStr->append(fVSCode);
- shaderStr->append("}\n");
-}
-
-void GrGLShaderBuilder::gsGetShader(SkString* shaderStr) const {
- if (!fUsesGS) {
- shaderStr->reset();
- return;
- }
-
- *shaderStr = GrGetGLSLVersionDecl(fCtxInfo);
- shaderStr->append(fGSHeader);
- this->appendDecls(fGSInputs, shaderStr);
- this->appendDecls(fGSOutputs, shaderStr);
- shaderStr->append("void main() {\n");
- shaderStr->append(fGSCode);
- shaderStr->append("}\n");
-}
-
void GrGLShaderBuilder::fsGetShader(SkString* shaderStr) const {
*shaderStr = GrGetGLSLVersionDecl(fCtxInfo);
shaderStr->append(fFSExtensions);
@@ -620,18 +526,20 @@ void GrGLShaderBuilder::emitEffects(
textureSamplers[t].init(this, &effect->textureAccess(t), t);
effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform);
}
- GrDrawEffect drawEffect(stage, this->hasExplicitLocalCoords());
+ GrDrawEffect drawEffect(stage, fVertexBuilder.get()
+ && fVertexBuilder->hasExplicitLocalCoords());
int numAttributes = stage.getVertexAttribIndexCount();
const int* attributeIndices = stage.getVertexAttribIndices();
SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames;
for (int a = 0; a < numAttributes; ++a) {
// TODO: Make addAttribute mangle the name.
+ SkASSERT(fVertexBuilder.get());
SkString attributeName("aAttr");
attributeName.appendS32(attributeIndices[a]);
- if (this->addAttribute(effect->vertexAttribType(a), attributeName.c_str())) {
- fEffectAttributes.push_back().set(attributeIndices[a], attributeName);
- }
+ fVertexBuilder->addEffectAttribute(attributeIndices[a],
+ effect->vertexAttribType(a),
+ attributeName);
}
glEffects[e] = effect->getFactory().createGLInstance(drawEffect);
@@ -649,8 +557,10 @@ void GrGLShaderBuilder::emitEffects(
// Enclose custom code in a block to avoid namespace conflicts
SkString openBrace;
openBrace.printf("\t{ // Stage %d: %s\n", fCodeStage.stageIndex(), glEffects[e]->name());
- this->fVSCode.append(openBrace);
- this->fFSCode.append(openBrace);
+ if (fVertexBuilder.get()) {
+ fVertexBuilder->vsCodeAppend(openBrace.c_str());
+ }
+ this->fsCodeAppend(openBrace.c_str());
glEffects[e]->emitCode(this,
drawEffect,
@@ -658,8 +568,11 @@ void GrGLShaderBuilder::emitEffects(
outColor.c_str(),
inColor.isEmpty() ? NULL : inColor.c_str(),
textureSamplers);
- this->fVSCode.append("\t}\n");
- this->fFSCode.append("\t}\n");
+
+ if (fVertexBuilder.get()) {
+ fVertexBuilder->vsCodeAppend("\t}\n");
+ }
+ this->fsCodeAppend("\t}\n");
inColor = outColor;
*fsInOutColorKnownValue = kNone_GrSLConstantVec;
@@ -671,7 +584,127 @@ void GrGLShaderBuilder::emitEffects(
}
}
-const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const {
+////////////////////////////////////////////////////////////////////////////
+
+GrGLShaderBuilder::VertexBuilder::VertexBuilder(GrGLShaderBuilder* parent,
+ const GrGLProgramDesc& desc)
+ : fVSAttrs(kVarsPerBlock)
+ , fVSOutputs(kVarsPerBlock)
+ , fGSInputs(kVarsPerBlock)
+ , fGSOutputs(kVarsPerBlock)
+ , fParent(parent)
+#if GR_GL_EXPERIMENTAL_GS
+ , fUsesGS(SkToBool(desc.getHeader().fExperimentalGS))
+#else
+ , fUsesGS(false)
+#endif
+{
+ const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
+
+ fPositionVar = &fVSAttrs.push_back();
+ fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
+ if (-1 != header.fLocalCoordAttributeIndex) {
+ fLocalCoordsVar = &fVSAttrs.push_back();
+ fLocalCoordsVar->set(kVec2f_GrSLType,
+ GrGLShaderVar::kAttribute_TypeModifier,
+ "aLocalCoords");
+ } else {
+ fLocalCoordsVar = fPositionVar;
+ }
+}
+
+bool GrGLShaderBuilder::VertexBuilder::addAttribute(GrSLType type,
+ const char* name) {
+ for (int i = 0; i < fVSAttrs.count(); ++i) {
+ const GrGLShaderVar& attr = fVSAttrs[i];
+ // if attribute already added, don't add it again
+ if (attr.getName().equals(name)) {
+ SkASSERT(attr.getType() == type);
+ return false;
+ }
+ }
+ fVSAttrs.push_back().set(type,
+ GrGLShaderVar::kAttribute_TypeModifier,
+ name);
+ return true;
+}
+
+bool GrGLShaderBuilder::VertexBuilder::addEffectAttribute(int attributeIndex,
+ GrSLType type,
+ const SkString& name) {
+ if (!this->addAttribute(type, name.c_str())) {
+ return false;
+ }
+
+ fEffectAttributes.push_back().set(attributeIndex, name);
+ return true;
+}
+
+void GrGLShaderBuilder::VertexBuilder::addVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName,
+ const char** fsInName) {
+ fVSOutputs.push_back();
+ fVSOutputs.back().setType(type);
+ fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
+ fParent->nameVariable(fVSOutputs.back().accessName(), 'v', name);
+
+ if (vsOutName) {
+ *vsOutName = fVSOutputs.back().getName().c_str();
+ }
+ // input to FS comes either from VS or GS
+ const SkString* fsName;
+ if (fUsesGS) {
+ // if we have a GS take each varying in as an array
+ // and output as non-array.
+ fGSInputs.push_back();
+ fGSInputs.back().setType(type);
+ fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
+ fGSInputs.back().setUnsizedArray();
+ *fGSInputs.back().accessName() = fVSOutputs.back().getName();
+ fGSOutputs.push_back();
+ fGSOutputs.back().setType(type);
+ fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
+ fParent->nameVariable(fGSOutputs.back().accessName(), 'g', name);
+ fsName = fGSOutputs.back().accessName();
+ } else {
+ fsName = fVSOutputs.back().accessName();
+ }
+ fParent->fsInputAppend().set(type,
+ GrGLShaderVar::kVaryingIn_TypeModifier,
+ *fsName);
+ if (fsInName) {
+ *fsInName = fsName->c_str();
+ }
+}
+
+void GrGLShaderBuilder::VertexBuilder::vsGetShader(SkString* shaderStr) const {
+ *shaderStr = GrGetGLSLVersionDecl(fParent->ctxInfo());
+ fParent->appendUniformDecls(kVertex_Visibility, shaderStr);
+ fParent->appendDecls(fVSAttrs, shaderStr);
+ fParent->appendDecls(fVSOutputs, shaderStr);
+ shaderStr->append("void main() {\n");
+ shaderStr->append(fVSCode);
+ shaderStr->append("}\n");
+}
+
+void GrGLShaderBuilder::VertexBuilder::gsGetShader(SkString* shaderStr) const {
+ if (!fUsesGS) {
+ shaderStr->reset();
+ return;
+ }
+
+ *shaderStr = GrGetGLSLVersionDecl(fParent->ctxInfo());
+ shaderStr->append(fGSHeader);
+ fParent->appendDecls(fGSInputs, shaderStr);
+ fParent->appendDecls(fGSOutputs, shaderStr);
+ shaderStr->append("void main() {\n");
+ shaderStr->append(fGSCode);
+ shaderStr->append("}\n");
+}
+
+
+const SkString* GrGLShaderBuilder::VertexBuilder::getEffectAttributeName(int attributeIndex) const {
const AttributePair* attribEnd = this->getEffectAttributes().end();
for (const AttributePair* attrib = this->getEffectAttributes().begin();
attrib != attribEnd;
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index ad0d87ef31..28f1b3822a 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -96,6 +96,7 @@ public:
};
typedef SkTArray<TextureSampler> TextureSamplerArray;
+ typedef GrTAllocator<GrGLShaderVar> VarArray;
enum ShaderVisibility {
kVertex_Visibility = 0x1,
@@ -103,7 +104,10 @@ public:
kFragment_Visibility = 0x4,
};
- GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&, const GrGLProgramDesc&);
+ GrGLShaderBuilder(const GrGLContextInfo&,
+ GrGLUniformManager&,
+ const GrGLProgramDesc&,
+ bool needsVertexShader);
/**
* Use of these features may require a GLSL extension to be enabled. Shaders may not compile
@@ -122,22 +126,8 @@ public:
bool enableFeature(GLSLFeature);
/**
- * Called by GrGLEffects to add code to one of the shaders.
+ * Called by GrGLEffects to add code the fragment shader.
*/
- void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
- va_list args;
- va_start(args, format);
- fVSCode.appendf(format, args);
- va_end(args);
- }
-
- void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
- va_list args;
- va_start(args, format);
- fGSCode.appendf(format, args);
- va_end(args);
- }
-
void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
va_list args;
va_start(args, format);
@@ -145,8 +135,6 @@ public:
va_end(args);
}
- void vsCodeAppend(const char* str) { fVSCode.append(str); }
- void gsCodeAppend(const char* str) { fGSCode.append(str); }
void fsCodeAppend(const char* str) { fFSCode.append(str); }
/** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
@@ -180,6 +168,12 @@ public:
const char* body,
SkString* outName);
+ /** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
+ GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
+ GrGLShaderVar& fsOutputAppend() { return fFSOutputs.push_back(); }
+ GrGLShaderVar& fsInputAppend(const GrGLShaderVar& var) { return fFSInputs.push_back(var); }
+ GrGLShaderVar& fsOutputAppend(const GrGLShaderVar& var) { return fFSOutputs.push_back(var); }
+
/** Generates a EffectKey for the shader code based on the texture access parameters and the
capabilities of the GL context. This is useful for keying the shader programs that may
have multiple representations, based on the type/format of textures used. */
@@ -233,50 +227,22 @@ public:
return this->getUniformVariable(u).c_str();
}
- /** Add a vertex attribute to the current program that is passed in from the vertex data.
- Returns false if the attribute was already there, true otherwise. */
- bool addAttribute(GrSLType type, const char* name);
-
- /** Add a varying variable to the current program to pass values between vertex and fragment
- shaders. If the last two parameters are non-NULL, they are filled in with the name
- generated. */
- void addVarying(GrSLType type,
- const char* name,
- const char** vsOutName = NULL,
- const char** fsInName = NULL);
-
/** Returns a variable name that represents the position of the fragment in the FS. The position
is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
const char* fragmentPosition();
- /** Returns a vertex attribute that represents the vertex position in the VS. This is the
- pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
- */
- const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
-
- /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
- as positionAttribute() or it may not be. It depends upon whether the rendering code
- specified explicit local coords or not in the GrDrawState. */
- const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }
-
/** Returns the color of the destination pixel. This may be NULL if no effect advertised
that it will read the destination. */
const char* dstColor();
/**
- * Are explicit local coordinates provided as input to the vertex shader.
- */
- bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
-
- /**
* Interfaces used by GrGLProgram.
* TODO: Hide these from the GrEffects using friend or splitting this into two related classes.
* Also, GrGLProgram's shader string construction should be moved to this class.
*/
- /** Called after building is complete to get the final shader string. */
- void vsGetShader(SkString*) const;
- void gsGetShader(SkString*) const;
+ /** Called after building is complete to get the final shader string. To acces the vertex
+ and geometry shaders, use the VertexBuilder. */
void fsGetShader(SkString*) const;
/**
@@ -309,17 +275,103 @@ public:
return fDstCopySampler.fSamplerUniform;
}
- struct AttributePair {
- void set(int index, const SkString& name) {
- fIndex = index; fName = name;
+ /** Helper class used to build the vertex and geometry shaders. This functionality
+ is kept separate from the rest of GrGLShaderBuilder to allow for shaders programs
+ that only use the fragment shader. */
+ class VertexBuilder {
+ public:
+ VertexBuilder(GrGLShaderBuilder* parent, const GrGLProgramDesc&);
+
+ /**
+ * Called by GrGLEffects to add code to one of the shaders.
+ */
+ void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
+ va_list args;
+ va_start(args, format);
+ fVSCode.appendf(format, args);
+ va_end(args);
+ }
+
+ void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
+ va_list args;
+ va_start(args, format);
+ fGSCode.appendf(format, args);
+ va_end(args);
+ }
+
+ void vsCodeAppend(const char* str) { fVSCode.append(str); }
+ void gsCodeAppend(const char* str) { fGSCode.append(str); }
+
+ /** Add a vertex attribute to the current program that is passed in from the vertex data.
+ Returns false if the attribute was already there, true otherwise. */
+ bool addAttribute(GrSLType type, const char* name);
+
+ /** Add a varying variable to the current program to pass values between vertex and fragment
+ shaders. If the last two parameters are non-NULL, they are filled in with the name
+ generated. */
+ void addVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName = NULL,
+ const char** fsInName = NULL);
+
+ /** Returns a vertex attribute that represents the vertex position in the VS. This is the
+ pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
+ */
+ const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
+
+ /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
+ as positionAttribute() or it may not be. It depends upon whether the rendering code
+ specified explicit local coords or not in the GrDrawState. */
+ const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }
+
+ /**
+ * Are explicit local coordinates provided as input to the vertex shader.
+ */
+ bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
+
+ /** Called after building is complete to get the final shader string. */
+ void vsGetShader(SkString*) const;
+ void gsGetShader(SkString*) const;
+
+ struct AttributePair {
+ void set(int index, const SkString& name) {
+ fIndex = index; fName = name;
+ }
+ int fIndex;
+ SkString fName;
+ };
+ const SkTArray<AttributePair, true>& getEffectAttributes() const {
+ return fEffectAttributes;
}
- int fIndex;
- SkString fName;
+ bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name);
+ const SkString* getEffectAttributeName(int attributeIndex) const;
+
+ // TODO: Everything below here private.
+ public:
+
+ VarArray fVSAttrs;
+ VarArray fVSOutputs;
+ VarArray fGSInputs;
+ VarArray fGSOutputs;
+ SkString fGSHeader; // layout qualifiers specific to GS
+
+ private:
+ GrGLShaderBuilder* fParent;
+
+ bool fUsesGS;
+
+ SkString fVSCode;
+ SkString fGSCode;
+
+ SkSTArray<10, AttributePair, true> fEffectAttributes;
+
+ GrGLShaderVar* fPositionVar;
+ GrGLShaderVar* fLocalCoordsVar;
};
- const SkTArray<AttributePair, true>& getEffectAttributes() const {
- return fEffectAttributes;
- }
- const SkString* getEffectAttributeName(int attributeIndex) const;
+
+ /** Gets the vertex builder that is used to construct the vertex and geometry shaders.
+ It may be NULL if this shader program is only meant to have a fragment shader. */
+ VertexBuilder* getVertexBuilder() const { return fVertexBuilder.get(); }
// TODO: Make this do all the compiling, linking, etc.
void finished(GrGLuint programID);
@@ -327,25 +379,12 @@ public:
const GrGLContextInfo& ctxInfo() const { return fCtxInfo; }
private:
- typedef GrTAllocator<GrGLShaderVar> VarArray;
-
void appendDecls(const VarArray&, SkString*) const;
void appendUniformDecls(ShaderVisibility, SkString*) const;
typedef GrGLUniformManager::BuilderUniform BuilderUniform;
GrGLUniformManager::BuilderUniformArray fUniforms;
- // TODO: Everything below here private.
-public:
-
- VarArray fVSAttrs;
- VarArray fVSOutputs;
- VarArray fGSInputs;
- VarArray fGSOutputs;
- VarArray fFSInputs;
- SkString fGSHeader; // layout qualifiers specific to GS
- VarArray fFSOutputs;
-
private:
class CodeStage : GrNoncopyable {
public:
@@ -436,12 +475,10 @@ private:
uint32_t fFSFeaturesAddedMask;
SkString fFSFunctions;
SkString fFSExtensions;
-
- bool fUsesGS;
+ VarArray fFSInputs;
+ VarArray fFSOutputs;
SkString fFSCode;
- SkString fVSCode;
- SkString fGSCode;
bool fSetupFragPosition;
TextureSampler fDstCopySampler;
@@ -452,11 +489,7 @@ private:
bool fTopLeftFragPosRead;
- SkSTArray<10, AttributePair, true> fEffectAttributes;
-
- GrGLShaderVar* fPositionVar;
- GrGLShaderVar* fLocalCoordsVar;
-
+ SkAutoTDelete<VertexBuilder> fVertexBuilder;
};
#endif