Index: src/gpu/gl/GrGLShaderBuilder.cpp |
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp |
index b379c784324176d7caea456b34d7efb133274942..c1732b20e766b3b32016b6efe57344f3eb9f5afa 100644 |
--- a/src/gpu/gl/GrGLShaderBuilder.cpp |
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp |
@@ -103,7 +103,6 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, |
, fFSOutputs(kMaxFSOutputs) |
, fCtxInfo(ctxInfo) |
, fUniformManager(uniformManager) |
- , fCurrentStageIdx(kNonStageIdx) |
, fFSFeaturesAddedMask(0) |
#if GR_GL_EXPERIMENTAL_GS |
, fUsesGS(desc.fExperimentalGS) |
@@ -215,6 +214,21 @@ void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionN |
} |
} |
+void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) { |
+ if ('\0' == prefix) { |
+ *out = name; |
+ } else { |
+ out->printf("%c%s", prefix, name); |
+ } |
+ if (fCodeStage.inStageCode()) { |
+ if (out->endsWith('_')) { |
+ // Names containing "__" are reserved. |
+ out->append("x"); |
+ } |
+ out->appendf("_Stage%d", fCodeStage.stageIndex()); |
+ } |
+} |
+ |
const char* GrGLShaderBuilder::dstColor() { |
static const char kFBFetchColorName[] = "gl_LastFragData[0]"; |
GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType(); |
@@ -364,12 +378,7 @@ GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t vi |
GrAssert(h2 == h); |
uni.fVariable.setType(type); |
uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); |
- SkString* uniName = uni.fVariable.accessName(); |
- if (kNonStageIdx == fCurrentStageIdx) { |
- uniName->printf("u%s", name); |
- } else { |
- uniName->printf("u%s%d", name, fCurrentStageIdx); |
- } |
+ this->nameVariable(uni.fVariable.accessName(), 'u', name); |
uni.fVariable.setArrayCount(count); |
uni.fVisibility = visibility; |
@@ -415,11 +424,8 @@ void GrGLShaderBuilder::addVarying(GrSLType type, |
fVSOutputs.push_back(); |
fVSOutputs.back().setType(type); |
fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); |
- if (kNonStageIdx == fCurrentStageIdx) { |
- fVSOutputs.back().accessName()->printf("v%s", name); |
- } else { |
- fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStageIdx); |
- } |
+ this->nameVariable(fVSOutputs.back().accessName(), 'v', name); |
+ |
if (vsOutName) { |
*vsOutName = fVSOutputs.back().getName().c_str(); |
} |
@@ -436,11 +442,7 @@ void GrGLShaderBuilder::addVarying(GrSLType type, |
fGSOutputs.push_back(); |
fGSOutputs.back().setType(type); |
fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); |
- if (kNonStageIdx == fCurrentStageIdx) { |
- fGSOutputs.back().accessName()->printf("g%s", name); |
- } else { |
- fGSOutputs.back().accessName()->printf("g%s%d", name, fCurrentStageIdx); |
- } |
+ this->nameVariable(fGSOutputs.back().accessName(), 'g', name); |
fsName = fGSOutputs.back().accessName(); |
} else { |
fsName = fVSOutputs.back().accessName(); |
@@ -470,18 +472,16 @@ const char* GrGLShaderBuilder::fragmentPosition() { |
} else { |
static const char* kCoordName = "fragCoordYDown"; |
if (!fSetupFragPosition) { |
+ // temporarily change the stage index because we're inserting non-stage code. |
+ CodeStage::AutoStageRestore csar(&fCodeStage, NULL); |
+ |
GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform); |
const char* rtHeightName; |
- // temporarily change the stage index because we're inserting a uniform whose name |
- // shouldn't be mangled to be stage-specific. |
- int oldStageIdx = fCurrentStageIdx; |
- fCurrentStageIdx = kNonStageIdx; |
fRTHeightUniform = this->addUniform(kFragment_ShaderType, |
kFloat_GrSLType, |
"RTHeight", |
&rtHeightName); |
- fCurrentStageIdx = oldStageIdx; |
this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n", |
kCoordName, rtHeightName); |
@@ -514,11 +514,7 @@ void GrGLShaderBuilder::emitFunction(ShaderType shader, |
SkString* outName) { |
GrAssert(kFragment_ShaderType == shader); |
fFSFunctions.append(GrGLSLTypeString(returnType)); |
- if (kNonStageIdx != fCurrentStageIdx) { |
- outName->printf("%s_%d", name, fCurrentStageIdx); |
- } else { |
- *outName = name; |
- } |
+ this->nameVariable(outName, '\0', name); |
fFSFunctions.appendf(" %s", outName->c_str()); |
fFSFunctions.append("("); |
for (int i = 0; i < argCnt; ++i) { |
@@ -623,52 +619,86 @@ void GrGLShaderBuilder::finished(GrGLuint programID) { |
fUniformManager.getUniformLocations(programID, fUniforms); |
} |
-GrGLEffect* GrGLShaderBuilder::createAndEmitGLEffect( |
- const GrEffectStage& stage, |
- GrGLEffect::EffectKey key, |
- const char* fsInColor, |
- const char* fsOutColor, |
- SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles) { |
- GrAssert(NULL != stage.getEffect()); |
- |
- const GrEffectRef& effect = *stage.getEffect(); |
- int numTextures = effect->numTextures(); |
- SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; |
- textureSamplers.push_back_n(numTextures); |
- for (int i = 0; i < numTextures; ++i) { |
- textureSamplers[i].init(this, &effect->textureAccess(i), i); |
- samplerHandles->push_back(textureSamplers[i].fSamplerUniform); |
- } |
- GrDrawEffect drawEffect(stage, this->hasExplicitLocalCoords()); |
- |
- int numAttributes = stage.getVertexAttribIndexCount(); |
- const int* attributeIndices = stage.getVertexAttribIndices(); |
- SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames; |
- for (int i = 0; i < numAttributes; ++i) { |
- SkString attributeName("aAttr"); |
- attributeName.appendS32(attributeIndices[i]); |
- |
- if (this->addAttribute(effect->vertexAttribType(i), attributeName.c_str())) { |
- fEffectAttributes.push_back().set(attributeIndices[i], attributeName); |
+void GrGLShaderBuilder::emitEffects( |
+ const GrEffectStage* effectStages[], |
+ const GrBackendEffectFactory::EffectKey effectKeys[], |
+ int effectCnt, |
+ SkString* fsInOutColor, |
+ GrSLConstantVec* fsInOutColorKnownValue, |
+ SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[], |
+ GrGLEffect* glEffects[]) { |
+ bool effectEmitted = false; |
+ |
+ SkString inColor = *fsInOutColor; |
+ SkString outColor; |
+ |
+ for (int e = 0; e < effectCnt; ++e) { |
+ if (NULL == effectStages[e] || GrGLEffect::kNoEffectKey == effectKeys[e]) { |
+ continue; |
+ } |
+ |
+ GrAssert(NULL != effectStages[e]->getEffect()); |
+ const GrEffectStage& stage = *effectStages[e]; |
+ const GrEffectRef& effect = *stage.getEffect(); |
+ |
+ CodeStage::AutoStageRestore csar(&fCodeStage, &stage); |
+ |
+ int numTextures = effect->numTextures(); |
+ SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; |
+ textureSamplers.push_back_n(numTextures); |
+ for (int t = 0; t < numTextures; ++t) { |
+ textureSamplers[t].init(this, &effect->textureAccess(t), t); |
+ effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform); |
+ } |
+ GrDrawEffect drawEffect(stage, this->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. |
+ SkString attributeName("aAttr"); |
+ attributeName.appendS32(attributeIndices[a]); |
+ if (this->addAttribute(effect->vertexAttribType(a), attributeName.c_str())) { |
+ fEffectAttributes.push_back().set(attributeIndices[a], attributeName); |
+ } |
+ } |
+ |
+ glEffects[e] = effect->getFactory().createGLInstance(drawEffect); |
+ |
+ if (kZeros_GrSLConstantVec == *fsInOutColorKnownValue) { |
+ // Effects have no way to communicate zeros, they treat an empty string as ones. |
+ this->nameVariable(&inColor, '\0', "input"); |
+ this->fsCodeAppendf("\tvec4 %s = %s;\n", inColor.c_str(), GrGLSLZerosVecf(4)); |
} |
- } |
- GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); |
+ // create var to hold stage result |
+ this->nameVariable(&outColor, '\0', "output"); |
+ this->fsCodeAppendf("\tvec4 %s;\n", outColor.c_str()); |
- // Enclose custom code in a block to avoid namespace conflicts |
- this->fVSCode.appendf("\t{ // %s\n", glEffect->name()); |
- this->fFSCode.appendf("\t{ // %s \n", glEffect->name()); |
+ // 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); |
- glEffect->emitCode(this, |
- drawEffect, |
- key, |
- fsOutColor, |
- fsInColor, |
- textureSamplers); |
- this->fVSCode.appendf("\t}\n"); |
- this->fFSCode.appendf("\t}\n"); |
+ glEffects[e]->emitCode(this, |
+ drawEffect, |
+ effectKeys[e], |
+ outColor.c_str(), |
+ inColor.isEmpty() ? NULL : inColor.c_str(), |
+ textureSamplers); |
+ this->fVSCode.append("\t}\n"); |
+ this->fFSCode.append("\t}\n"); |
- return glEffect; |
+ inColor = outColor; |
+ *fsInOutColorKnownValue = kNone_GrSLConstantVec; |
+ effectEmitted = true; |
+ } |
+ |
+ if (effectEmitted) { |
+ *fsInOutColor = outColor; |
+ } |
} |
const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const { |