Index: src/gpu/gl/builders/GrGLProgramBuilder.cpp |
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp |
index 28d15174238d8ad198cc6a3dee39866cb2ef4a8a..6fe2208ae8d5978732cc0803b4a95e35117672ca 100644 |
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp |
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp |
@@ -37,72 +37,25 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, |
SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc, |
optState, |
drawType, |
- optState.hasGeometryProcessor(), |
gpu)); |
- |
- GrGLProgramBuilder* pb = builder.get(); |
- const GrGLProgramDesc::KeyHeader& header = pb->header(); |
- |
- // emit code to read the dst copy texture, if necessary |
- if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey |
- && !gpu->glCaps().fbFetchSupport()) { |
- pb->fFS.emitCodeToReadDstTexture(); |
- } |
- |
- // get the initial color and coverage to feed into the first effect in each effect chain |
- GrGLSLExpr4 inputColor, inputCoverage; |
- pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); |
- |
- // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have |
- // to setup a few more things like builtin vertex attributes |
- bool hasVertexShader = !header.fUseFragShaderOnly; |
- if (hasVertexShader) { |
- pb->fVS.setupLocalCoords(); |
- pb->fVS.transformGLToSkiaCoords(); |
- if (header.fEmitsPointSize) { |
- pb->fVS.codeAppend("gl_PointSize = 1.0;"); |
- } |
- if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { |
- pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor); |
- } |
- if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { |
- pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); |
- } |
- } |
- |
- pb->emitAndInstallProcs(optState, &inputColor, &inputCoverage); |
- |
- if (hasVertexShader) { |
- pb->fVS.transformSkiaToGLCoords(); |
- } |
- |
- // write the secondary color output if necessary |
- if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) { |
- pb->fFS.enableSecondaryOutput(inputColor, inputCoverage); |
- } |
- |
- pb->fFS.combineColorAndCoverage(inputColor, inputCoverage); |
- |
- return pb->finalize(); |
+ return builder->create(); |
} |
GrGLProgramBuilder* |
GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc, |
const GrOptDrawState& optState, |
GrGpu::DrawType drawType, |
- bool hasGeometryProcessor, |
GrGpuGL* gpu) { |
+ // We always have a GP but it gets ignored for nvpr |
if (desc.getHeader().fUseFragShaderOnly) { |
SkASSERT(gpu->glCaps().pathRenderingSupport()); |
SkASSERT(gpu->glPathRendering()->texturingMode() == |
GrGLPathRendering::FixedFunction_TexturingMode); |
- SkASSERT(!hasGeometryProcessor); |
return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc)); |
} else if (GrGpu::IsPathRenderingDrawType(drawType)) { |
SkASSERT(gpu->glCaps().pathRenderingSupport()); |
SkASSERT(gpu->glPathRendering()->texturingMode() == |
GrGLPathRendering::SeparableShaders_TexturingMode); |
- SkASSERT(!hasGeometryProcessor); |
return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc)); |
} else { |
return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc)); |
@@ -126,6 +79,49 @@ GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, |
, fUniforms(kVarsPerBlock) { |
} |
+GrGLProgram* GrGLProgramBuilder::create() { |
+ const GrGLProgramDesc::KeyHeader& header = this->header(); |
+ |
+ // emit code to read the dst copy texture, if necessary |
+ if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey |
+ && !fGpu->glCaps().fbFetchSupport()) { |
+ this->fFS.emitCodeToReadDstTexture(); |
+ } |
+ |
+ // get the initial color and coverage to feed into the first effect in each effect chain |
+ GrGLSLExpr4 inputColor, inputCoverage; |
+ this->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); |
+ |
+ // We always have a vertex shader in our default program |
+ fVS.setupLocalCoords(); |
+ |
+ // Setup default view matrix |
+ this->fUniformHandles.fViewMatrixUni = |
+ this->addUniform(GrGLProgramBuilder::kVertex_Visibility, |
+ kMat33f_GrSLType, |
+ fOptState.getGeometryProcessor()->uViewM()); |
+ if (header.fEmitsPointSize) { |
+ this->fVS.codeAppend("gl_PointSize = 1.0;"); |
+ } |
+ if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { |
+ this->fVS.setupBuiltinVertexAttribute("Color", &inputColor); |
+ } |
+ if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { |
+ this->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); |
+ } |
+ |
+ this->emitAndInstallProcs(&inputColor, &inputCoverage); |
+ |
+ // write the secondary color output if necessary |
+ if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) { |
+ fFS.enableSecondaryOutput(inputColor, inputCoverage); |
+ } |
+ |
+ fFS.combineColorAndCoverage(inputColor, inputCoverage); |
+ |
+ return this->finalize(); |
+} |
+ |
void GrGLProgramBuilder::addVarying(const char* name, |
GrGLVarying* varying, |
GrGLShaderVar::Precision fsPrecision) { |
@@ -169,7 +165,17 @@ GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32 |
UniformInfo& uni = fUniforms.push_back(); |
uni.fVariable.setType(type); |
uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); |
- this->nameVariable(uni.fVariable.accessName(), 'u', name); |
+ // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use |
+ // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB |
+ // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then |
+ // the names will mismatch. I think the correct solution is to have all GPs which need the |
+ // uniform view matrix, they should upload the view matrix in their setData along with regular |
+ // uniforms. |
+ char prefix = 'u'; |
+ if ('u' == name[0]) { |
+ prefix = '\0'; |
+ } |
+ this->nameVariable(uni.fVariable.accessName(), prefix, name); |
uni.fVariable.setArrayCount(count); |
uni.fVisibility = visibility; |
@@ -228,21 +234,32 @@ void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input |
} |
} |
-void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState, |
- GrGLSLExpr4* inputColor, |
- GrGLSLExpr4* inputCoverage) { |
+void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { |
+ // We need to collect all of the transforms to thread them through the GP in the case of GPs |
+ // which use additional shader stages between the VS and the FS. To do this we emit a dummy |
+ // input coverage |
+ AutoStageAdvance adv(this); |
+ SkString outColorName; |
+ this->nameVariable(&outColorName, '\0', "gpOutput"); |
+ GrGLSLExpr4 coverageInput = outColorName; |
+ GrGLSLExpr4 gpOutput = coverageInput; |
+ |
+ // Emit fragment processors |
fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); |
- int numProcs = optState.numFragmentStages(); |
- this->emitAndInstallFragProcs(0, optState.numColorStages(), inputColor); |
- if (optState.hasGeometryProcessor()) { |
- const GrGeometryProcessor& gp = *optState.getGeometryProcessor(); |
- fVS.emitAttributes(gp); |
- ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kGeometry_ProcessorType); |
- GrGLSLExpr4 output; |
- this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &output); |
- *inputCoverage = output; |
- } |
- this->emitAndInstallFragProcs(optState.numColorStages(), numProcs, inputCoverage); |
+ int numProcs = fOptState.numFragmentStages(); |
+ this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor); |
+ this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs, &coverageInput); |
+ |
+ // We have to save the existing code stack, and then append it to the fragment shader code |
+ // after emiting the GP |
+ SkString existingCode(fFS.fCode); |
+ fFS.fCode.reset(); |
+ const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor(); |
+ fVS.emitAttributes(gp); |
+ ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kGeometry_ProcessorType); |
+ this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &gpOutput); |
+ fFS.fCode.append(existingCode); |
+ *inputCoverage = coverageInput; |
} |
void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) { |
@@ -266,9 +283,14 @@ void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, |
// Program builders have a bit of state we need to clear with each effect |
AutoStageAdvance adv(this); |
- // create var to hold stage result |
+ // create var to hold stage result. If we already have a valid output name, just use that |
+ // otherwise create a new mangled one. |
SkString outColorName; |
- this->nameVariable(&outColorName, '\0', "output"); |
+ if (output->isValid()) { |
+ outColorName = output->c_str(); |
+ } else { |
+ this->nameVariable(&outColorName, '\0', "output"); |
+ } |
fFS.codeAppendf("vec4 %s;", outColorName.c_str()); |
*output = outColorName; |
@@ -368,23 +390,13 @@ void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage, |
suffixedVaryingName.appendf("_%i", t); |
varyingName = suffixedVaryingName.c_str(); |
} |
+ const char* coords = kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ? |
+ fVS.positionAttribute().c_str() : |
+ fVS.localCoordsAttribute().c_str(); |
GrGLVertToFrag v(varyingType); |
- this->addVarying(varyingName, &v); |
- |
- const GrGLShaderVar& coords = |
- kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ? |
- fVS.positionAttribute() : |
- fVS.localCoordsAttribute(); |
+ this->addCoordVarying(varyingName, &v, uniName, coords); |
- // varying = matrix * coords (logically) |
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); |
- if (kVec2f_GrSLType == varyingType) { |
- fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;", |
- v.vsOut(), uniName, coords.c_str()); |
- } else { |
- fVS.codeAppendf("%s = %s * vec3(%s, 1);", |
- v.vsOut(), uniName, coords.c_str()); |
- } |
SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, |
(SkString(v.fsIn()), varyingType)); |
} |