| 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));
|
| }
|
|
|