| Index: src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| index 16cc5d496404c33b34591975e3026fe1e2ee4ac2..64150a4fda96b8abcd77c1f97fff210c6b912bc9 100644
|
| --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
|
| @@ -52,37 +52,15 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
|
| GrGLSLExpr1 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.fUseNvpr &&
|
| - gpu->glPathRendering()->texturingMode() ==
|
| - GrGLPathRendering::FixedFunction_TexturingMode);
|
| -
|
| - if (hasVertexShader) {
|
| - pb->fVS.setupUniformViewMatrix();
|
| - pb->fVS.setupPositionAndLocalCoords();
|
| -
|
| - if (header.fEmitsPointSize) {
|
| - pb->fVS.codeAppend("gl_PointSize = 1.0;");
|
| - }
|
| - if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) {
|
| - pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor);
|
| - }
|
| - if (GrProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
|
| - pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage);
|
| - }
|
| - }
|
| -
|
| // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
|
| // remove this cast to a vec4.
|
| - GrGLSLExpr4 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage);
|
| + GrGLSLExpr4 inputCoverageVec4;
|
| + if (inputCoverage.isValid()) {
|
| + inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage);
|
| + }
|
|
|
| pb->emitAndInstallProcs(&inputColor, &inputCoverageVec4);
|
|
|
| - if (hasVertexShader) {
|
| - pb->fVS.transformToNormalizedDeviceSpace();
|
| - }
|
| -
|
| // write the secondary color output if necessary
|
| if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
|
| pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4);
|
| @@ -145,6 +123,15 @@ void GrGLProgramBuilder::addVarying(const char* name,
|
| }
|
| }
|
|
|
| +void GrGLProgramBuilder::addPassThroughAttribute(const GrGeometryProcessor::GrAttribute* input,
|
| + const char* output) {
|
| + GrSLType type = GrVertexAttribTypeToSLType(input->fType);
|
| + GrGLVertToFrag v(type);
|
| + this->addVarying(input->fName, &v);
|
| + fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName);
|
| + fFS.codeAppendf("%s = %s;", output, v.fsIn());
|
| +}
|
| +
|
| void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
|
| if ('\0' == prefix) {
|
| *out = name;
|
| @@ -242,50 +229,84 @@ void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input
|
| }
|
| }
|
|
|
| -void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
|
| - GrGLSLExpr4* inputCoverage) {
|
| - fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
|
| - int numProcs = fOptState.numFragmentStages();
|
| - this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor);
|
| +void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
|
| if (fOptState.hasGeometryProcessor()) {
|
| + fVS.setupUniformViewMatrix();
|
| +
|
| + const GrProgramDesc::KeyHeader& header = this->header();
|
| + if (header.fEmitsPointSize) {
|
| + fVS.codeAppend("gl_PointSize = 1.0;");
|
| + }
|
| +
|
| + // Setup position
|
| + // TODO it'd be possible to remove these from the vertexshader builder and have them
|
| + // be outputs from the emit call. We don't do this because emitargs is constant. It would
|
| + // be easy to change this though
|
| + fVS.codeAppendf("vec3 %s;", fVS.glPosition());
|
| + fVS.codeAppendf("vec2 %s;", fVS.positionCoords());
|
| + fVS.codeAppendf("vec2 %s;", fVS.localCoords());
|
| +
|
| const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor();
|
| fVS.emitAttributes(gp);
|
| - GrGLSLExpr4 output;
|
| - this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, *inputCoverage, &output);
|
| - *inputCoverage = output;
|
| + GrGLSLExpr4 outputColor;
|
| + GrGLSLExpr4 outputCoverage;
|
| + this->emitAndInstallProc(gp, &outputColor, &outputCoverage);
|
| +
|
| + // We may override color and coverage here if we have unform color or coverage. This is
|
| + // obviously not ideal.
|
| + // TODO lets the GP itself do the override
|
| + if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) {
|
| + *inputColor = outputColor;
|
| + }
|
| + if (GrProgramDesc::kUniform_ColorInput != header.fCoverageInput) {
|
| + *inputCoverage = outputCoverage;
|
| + }
|
| }
|
| +
|
| + fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
|
| + int numProcs = fOptState.numFragmentStages();
|
| + this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor);
|
| this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs, inputCoverage);
|
| +
|
| + if (fOptState.hasGeometryProcessor()) {
|
| + fVS.transformToNormalizedDeviceSpace();
|
| + }
|
| }
|
|
|
| -void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) {
|
| +void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
|
| + int numProcs,
|
| + GrGLSLExpr4* inOut) {
|
| for (int e = procOffset; e < numProcs; ++e) {
|
| GrGLSLExpr4 output;
|
| const GrPendingFragmentStage& stage = fOptState.getFragmentStage(e);
|
| - this->emitAndInstallProc<GrPendingFragmentStage>(stage, e, *inOut, &output);
|
| + this->emitAndInstallProc(stage, e, *inOut, &output);
|
| *inOut = output;
|
| }
|
| }
|
|
|
| +void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
|
| + // create var to hold stage result. If we already have a valid output name, just use that
|
| + // otherwise create a new mangled one. This name is only valid if we are reordering stages
|
| + // and have to tell stage exactly where to put its output.
|
| + SkString outName;
|
| + if (output->isValid()) {
|
| + outName = output->c_str();
|
| + } else {
|
| + this->nameVariable(&outName, '\0', baseName);
|
| + }
|
| + fFS.codeAppendf("vec4 %s;", outName.c_str());
|
| + *output = outName;
|
| +}
|
| +
|
| // TODO Processors cannot output zeros because an empty string is all 1s
|
| // the fix is to allow effects to take the GrGLSLExpr4 directly
|
| -template <class Proc>
|
| -void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc,
|
| +void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc,
|
| int index,
|
| const GrGLSLExpr4& input,
|
| GrGLSLExpr4* output) {
|
| // Program builders have a bit of state we need to clear with each effect
|
| AutoStageAdvance adv(this);
|
| -
|
| - // 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;
|
| - if (output->isValid()) {
|
| - outColorName = output->c_str();
|
| - } else {
|
| - this->nameVariable(&outColorName, '\0', "output");
|
| - }
|
| - fFS.codeAppendf("vec4 %s;", outColorName.c_str());
|
| - *output = outColorName;
|
| + this->nameExpression(output, "output");
|
|
|
| // Enclose custom code in a block to avoid namespace conflicts
|
| SkString openBrace;
|
| @@ -297,10 +318,28 @@ void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc,
|
| fFS.codeAppend("}");
|
| }
|
|
|
| +void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& proc,
|
| + GrGLSLExpr4* outputColor,
|
| + GrGLSLExpr4* outputCoverage) {
|
| + // Program builders have a bit of state we need to clear with each effect
|
| + AutoStageAdvance adv(this);
|
| + this->nameExpression(outputColor, "outputColor");
|
| + this->nameExpression(outputCoverage, "outputCoverage");
|
| +
|
| + // Enclose custom code in a block to avoid namespace conflicts
|
| + SkString openBrace;
|
| + openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
|
| + fFS.codeAppend(openBrace.c_str());
|
| +
|
| + this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str());
|
| +
|
| + fFS.codeAppend("}");
|
| +}
|
| +
|
| void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs,
|
| const char* outColor,
|
| const char* inColor) {
|
| - GrGLInstalledFragProc* ifp = SkNEW_ARGS(GrGLInstalledFragProc, (fVS.hasLocalCoords()));
|
| + GrGLInstalledFragProc* ifp = SkNEW(GrGLInstalledFragProc);
|
|
|
| const GrFragmentProcessor& fp = *fs.getProcessor();
|
| ifp->fGLProc.reset(fp.getFactory().createGLInstance(fp));
|
| @@ -321,8 +360,8 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs,
|
| }
|
|
|
| void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp,
|
| - const char* outCoverage,
|
| - const char* inCoverage) {
|
| + const char* outColor,
|
| + const char* outCoverage) {
|
| SkASSERT(!fGeometryProcessor);
|
| fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
|
|
|
| @@ -331,7 +370,7 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp,
|
| SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
|
| this->emitSamplers(gp, &samplers, fGeometryProcessor);
|
|
|
| - GrGLGeometryProcessor::EmitArgs args(this, gp, outCoverage, inCoverage, samplers);
|
| + GrGLGeometryProcessor::EmitArgs args(this, gp, outColor, outCoverage, samplers);
|
| fGeometryProcessor->fGLProc->emitCode(args);
|
|
|
| // We have to check that effects and the code they emit are consistent, ie if an effect
|
| @@ -377,9 +416,10 @@ void GrGLProgramBuilder::emitTransforms(const GrPendingFragmentStage& stage,
|
| suffixedVaryingName.appendf("_%i", t);
|
| varyingName = suffixedVaryingName.c_str();
|
| }
|
| - const char* coords = kPosition_GrCoordSet == processor->coordTransform(t).sourceCoords() ?
|
| - fVS.positionAttribute().c_str() :
|
| - fVS.localCoordsAttribute().c_str();
|
| +
|
| + bool useLocalCoords = kLocal_GrCoordSet == processor->coordTransform(t).sourceCoords();
|
| + const char* coords = useLocalCoords ? fVS.localCoords() : fVS.positionCoords();
|
| +
|
| GrGLVertToFrag v(varyingType);
|
| this->addCoordVarying(varyingName, &v, uniName, coords);
|
|
|
| @@ -419,6 +459,7 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
|
| this->cleanupProgram(programID, shadersToDelete);
|
| return NULL;
|
| }
|
| +
|
| if (!(GrGLProgramDescBuilder::GetHeader(fDesc).fUseNvpr &&
|
| fGpu->glPathRendering()->texturingMode() ==
|
| GrGLPathRendering::FixedFunction_TexturingMode)) {
|
| @@ -426,7 +467,11 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
|
| this->cleanupProgram(programID, shadersToDelete);
|
| return NULL;
|
| }
|
| - fVS.bindVertexAttributes(programID);
|
| +
|
| + // Non fixed function NVPR actually requires a vertex shader to compile
|
| + if (fOptState.hasGeometryProcessor()) {
|
| + fVS.bindVertexAttributes(programID);
|
| + }
|
| }
|
| bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
|
| if (usingBindUniform) {
|
|
|