| Index: src/gpu/gl/builders/GrGLProgramBuilder.cpp | 
| diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp | 
| index 0c4178197913d1c741a33713bac2f335a4e10130..147723b9d3bb4cf8656ca030493cacd5005d3bb9 100644 | 
| --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp | 
| +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp | 
| @@ -12,8 +12,6 @@ | 
| #include "../GrGLXferProcessor.h" | 
| #include "../GrGLGpu.h" | 
| #include "GrCoordTransform.h" | 
| -#include "GrGLLegacyNvprProgramBuilder.h" | 
| -#include "GrGLNvprProgramBuilder.h" | 
| #include "GrGLProgramBuilder.h" | 
| #include "GrTexture.h" | 
| #include "SkRTConf.h" | 
| @@ -22,6 +20,30 @@ | 
| #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) | 
| #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) | 
|  | 
| +/////////////////////////////////////////////////////////////////////////////////////////////////// | 
| + | 
| +class GrGLNvprProgramBuilder : public GrGLProgramBuilder { | 
| +public: | 
| +    GrGLNvprProgramBuilder(GrGLGpu* gpu, const GrOptDrawState& optState) | 
| +        : INHERITED(gpu, optState) {} | 
| + | 
| +    GrGLProgram* createProgram(GrGLuint programID) SK_OVERRIDE { | 
| +        // this is just for nvpr es, which has separable varyings that are plugged in after | 
| +        // building | 
| +        GrGLPathProcessor* pathProc = | 
| +                static_cast<GrGLPathProcessor*>(fGeometryProcessor->fGLProc.get()); | 
| +        pathProc->resolveSeparableVaryings(fGpu, programID); | 
| +        return SkNEW_ARGS(GrGLNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms, | 
| +                                            fGeometryProcessor, | 
| +                                            fXferProcessor, fFragmentProcessors.get())); | 
| +    } | 
| + | 
| +private: | 
| +    typedef GrGLProgramBuilder INHERITED; | 
| +}; | 
| + | 
| + | 
| + | 
| ////////////////////////////////////////////////////////////////////////////// | 
|  | 
| const int GrGLProgramBuilder::kVarsPerBlock = 8; | 
| @@ -29,12 +51,11 @@ const int GrGLProgramBuilder::kVarsPerBlock = 8; | 
| GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, GrGLGpu* gpu) { | 
| // create a builder.  This will be handed off to effects so they can use it to add | 
| // uniforms, varyings, textures, etc | 
| -    SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(optState, | 
| -                                                                   optState.hasGeometryProcessor(), | 
| -                                                                   gpu)); | 
| +    SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(optState, gpu)); | 
|  | 
| GrGLProgramBuilder* pb = builder.get(); | 
| -    const GrGLProgramDescBuilder::GLKeyHeader& header = GrGLProgramDescBuilder::GetHeader(pb->desc()); | 
| +    const GrGLProgramDescBuilder::GLKeyHeader& header = | 
| +            GrGLProgramDescBuilder::GetHeader(pb->desc()); | 
|  | 
| // emit code to read the dst copy texture, if necessary | 
| if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey && | 
| @@ -53,18 +74,12 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, G | 
| } | 
|  | 
| GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const GrOptDrawState& optState, | 
| -                                                             bool hasGeometryProcessor, | 
| GrGLGpu* gpu) { | 
| const GrProgramDesc& desc = optState.programDesc(); | 
| if (GrGLProgramDescBuilder::GetHeader(desc).fUseNvpr) { | 
| SkASSERT(gpu->glCaps().pathRenderingSupport()); | 
| -        SkASSERT(!hasGeometryProcessor); | 
| -        if (gpu->glPathRendering()->texturingMode() == | 
| -            GrGLPathRendering::FixedFunction_TexturingMode) { | 
| -            return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState)); | 
| -        } else { | 
| -            return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState)); | 
| -        } | 
| +        SkASSERT(!optState.hasGeometryProcessor()); | 
| +        return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState)); | 
| } else { | 
| return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState)); | 
| } | 
| @@ -177,19 +192,15 @@ const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { | 
| } | 
|  | 
| void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { | 
| -    if (fOptState.hasGeometryProcessor()) { | 
| -        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); | 
| +    // First we loop over all of the installed processors and collect coord transforms.  These will | 
| +    // be sent to the GrGLPrimitiveProcessor in its emitCode function | 
| +    SkSTArray<8, GrGLProcessor::TransformedCoordsArray> outCoords; | 
| +    for (int i = 0; i < fOptState.numFragmentStages(); i++) { | 
| +        const GrFragmentProcessor* processor = fOptState.getFragmentStage(i).processor(); | 
| +        SkSTArray<2, const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back(); | 
| +        for (int t = 0; t < processor->numTransforms(); t++) { | 
| +            procCoords.push_back(&processor->coordTransform(t)); | 
| +        } | 
| } | 
|  | 
| const GrPrimitiveProcessor& primProc = *fOptState.getPrimitiveProcessor(); | 
| @@ -199,11 +210,6 @@ void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr | 
| int numProcs = fOptState.numFragmentStages(); | 
| this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor); | 
| this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs,  inputCoverage); | 
| - | 
| -    if (fOptState.hasGeometryProcessor()) { | 
| -        fVS.transformToNormalizedDeviceSpace(); | 
| -    } | 
| - | 
| this->emitAndInstallXferProc(*fOptState.getXferProcessor(), *inputColor, *inputCoverage); | 
| } | 
|  | 
| @@ -247,7 +253,7 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc, | 
| openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); | 
| fFS.codeAppend(openBrace.c_str()); | 
|  | 
| -    this->emitAndInstallProc(proc, output->c_str(), input.isOnes() ? NULL : input.c_str()); | 
| +    this->emitAndInstallProc(proc, index, output->c_str(), input.isOnes() ? NULL : input.c_str()); | 
|  | 
| fFS.codeAppend("}"); | 
| } | 
| @@ -271,6 +277,7 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc, | 
| } | 
|  | 
| void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs, | 
| +                                            int index, | 
| const char* outColor, | 
| const char* inColor) { | 
| GrGLInstalledFragProc* ifp = SkNEW(GrGLInstalledFragProc); | 
| @@ -281,11 +288,7 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs, | 
| SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures()); | 
| this->emitSamplers(fp, &samplers, ifp); | 
|  | 
| -    // Fragment processors can have coord transforms | 
| -    SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp.numTransforms()); | 
| -    this->emitTransforms(fs, &coords, ifp); | 
| - | 
| -    ifp->fGLProc->emitCode(this, fp, outColor, inColor, coords, samplers); | 
| +    ifp->fGLProc->emitCode(this, fp, outColor, inColor, fOutCoords[index], samplers); | 
|  | 
| // We have to check that effects and the code they emit are consistent, ie if an effect | 
| // asks for dst color, then the emit code needs to follow suit | 
| @@ -300,12 +303,13 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp, | 
| fGeometryProcessor = SkNEW(GrGLInstalledGeoProc); | 
|  | 
| const GrBatchTracker& bt = fOptState.getBatchTracker(); | 
| -    fGeometryProcessor->fGLProc.reset(gp.createGLInstance(bt)); | 
| +    fGeometryProcessor->fGLProc.reset(gp.createGLInstance(bt, fGpu->glCaps())); | 
|  | 
| SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures()); | 
| this->emitSamplers(gp, &samplers, fGeometryProcessor); | 
|  | 
| -    GrGLGeometryProcessor::EmitArgs args(this, gp, bt, outColor, outCoverage, samplers); | 
| +    GrGLGeometryProcessor::EmitArgs args(this, gp, bt, outColor, outCoverage, samplers, | 
| +                                         fCoordTransforms, &fOutCoords); | 
| fGeometryProcessor->fGLProc->emitCode(args); | 
|  | 
| // We have to check that effects and the code they emit are consistent, ie if an effect | 
| @@ -367,59 +371,10 @@ void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { | 
| SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor()); | 
| } | 
|  | 
| -void GrGLProgramBuilder::emitTransforms(const GrPendingFragmentStage& stage, | 
| -                                        GrGLProcessor::TransformedCoordsArray* outCoords, | 
| -                                        GrGLInstalledFragProc* ifp) { | 
| -    const GrFragmentProcessor* processor = stage.processor(); | 
| -    int numTransforms = processor->numTransforms(); | 
| -    ifp->fTransforms.push_back_n(numTransforms); | 
| - | 
| -    for (int t = 0; t < numTransforms; t++) { | 
| -        const char* uniName = "StageMatrix"; | 
| -        GrSLType varyingType; | 
| - | 
| -        GrCoordSet coordType = processor->coordTransform(t).sourceCoords(); | 
| -        const SkMatrix& localMatrix = fOptState.getPrimitiveProcessor()->localMatrix(); | 
| -        uint32_t type = processor->coordTransform(t).getMatrix().getType(); | 
| -        if (kLocal_GrCoordSet == coordType) { | 
| -            type |= localMatrix.getType(); | 
| -        } | 
| -        varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType : | 
| -                                                                     kVec2f_GrSLType; | 
| -        GrSLPrecision precision = processor->coordTransform(t).precision(); | 
| - | 
| -        SkString suffixedUniName; | 
| -        if (0 != t) { | 
| -            suffixedUniName.append(uniName); | 
| -            suffixedUniName.appendf("_%i", t); | 
| -            uniName = suffixedUniName.c_str(); | 
| -        } | 
| -        ifp->fTransforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility, | 
| -                                                       kMat33f_GrSLType, precision, | 
| -                                                       uniName, | 
| -                                                       &uniName).toShaderBuilderIndex(); | 
| - | 
| -        const char* varyingName = "MatrixCoord"; | 
| -        SkString suffixedVaryingName; | 
| -        if (0 != t) { | 
| -            suffixedVaryingName.append(varyingName); | 
| -            suffixedVaryingName.appendf("_%i", t); | 
| -            varyingName = suffixedVaryingName.c_str(); | 
| -        } | 
| - | 
| -        GrGLVertToFrag v(varyingType); | 
| -        this->addVarying(varyingName, &v, precision); | 
| -        fCoordVaryings.push_back(TransformVarying(v, uniName, coordType)); | 
| - | 
| -        SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); | 
| -        SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, | 
| -                               (SkString(v.fsIn()), varyingType)); | 
| -    } | 
| -} | 
| - | 
| +template <class Proc> | 
| void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, | 
| GrGLProcessor::TextureSamplerArray* outSamplers, | 
| -                                      GrGLInstalledProc* ip) { | 
| +                                      GrGLInstalledProc<Proc>* ip) { | 
| int numTextures = processor.numTextures(); | 
| ip->fSamplers.push_back_n(numTextures); | 
| SkString name; | 
|  |