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
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 2554142..e62bfde 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -93,37 +93,23 @@
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 @@
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::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 @@
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 @@
// 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 @@
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 @@
}
}
-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;