| Index: src/gpu/gl/GrGLProgram.cpp | 
| diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp | 
| index 480e1b77352c99b59fbf33a84357d0b293e0153d..e0d4939323b0f2438944fcaad78712d7b6120d63 100644 | 
| --- a/src/gpu/gl/GrGLProgram.cpp | 
| +++ b/src/gpu/gl/GrGLProgram.cpp | 
| @@ -7,8 +7,6 @@ | 
|  | 
| #include "GrGLProgram.h" | 
|  | 
| -#include "builders/GrGLFullProgramBuilder.h" | 
| -#include "builders/GrGLFragmentOnlyProgramBuilder.h" | 
| #include "GrAllocator.h" | 
| #include "GrProcessor.h" | 
| #include "GrCoordTransform.h" | 
| @@ -23,45 +21,58 @@ | 
| #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) | 
| #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X) | 
|  | 
| -GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu, | 
| -                                 const GrOptDrawState& optState, | 
| -                                 const GrGLProgramDesc& desc, | 
| -                                 const GrGeometryStage* geometryProcessor, | 
| -                                 const GrFragmentStage* colorStages[], | 
| -                                 const GrFragmentStage* coverageStages[]) { | 
| -    SkAutoTDelete<GrGLProgramBuilder> builder; | 
| -    if (desc.getHeader().fUseFragShaderOnly) { | 
| -        SkASSERT(gpu->glCaps().pathRenderingSupport()); | 
| -        SkASSERT(gpu->glPathRendering()->texturingMode() == | 
| -                 GrGLPathRendering::FixedFunction_TexturingMode); | 
| -        SkASSERT(NULL == geometryProcessor); | 
| -        builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, optState, desc))); | 
| +/** | 
| + * Retrieves the final matrix that a transform needs to apply to its source coords. | 
| + */ | 
| +static SkMatrix get_transform_matrix(const GrProcessorStage& processorStage, | 
| +                                     bool useExplicitLocalCoords, | 
| +                                     int transformIdx) { | 
| +    const GrCoordTransform& coordTransform = | 
| +            processorStage.getProcessor()->coordTransform(transformIdx); | 
| +    SkMatrix combined; | 
| + | 
| +    if (kLocal_GrCoordSet == coordTransform.sourceCoords()) { | 
| +        // If we have explicit local coords then we shouldn't need a coord change. | 
| +        const SkMatrix& ccm = | 
| +                useExplicitLocalCoords ? SkMatrix::I() : processorStage.getCoordChangeMatrix(); | 
| +        combined.setConcat(coordTransform.getMatrix(), ccm); | 
| } else { | 
| -        builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, optState, desc))); | 
| +        combined = coordTransform.getMatrix(); | 
| } | 
| -    if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) { | 
| -        SkASSERT(0 != builder->getProgramID()); | 
| -        return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder)); | 
| +    if (coordTransform.reverseY()) { | 
| +        // combined.postScale(1,-1); | 
| +        // combined.postTranslate(0,1); | 
| +        combined.set(SkMatrix::kMSkewY, | 
| +            combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]); | 
| +        combined.set(SkMatrix::kMScaleY, | 
| +            combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]); | 
| +        combined.set(SkMatrix::kMTransY, | 
| +            combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]); | 
| } | 
| -    return NULL; | 
| +    return combined; | 
| } | 
|  | 
| +/////////////////////////////////////////////////////////////////////////////////////////////////// | 
| + | 
| GrGLProgram::GrGLProgram(GrGpuGL* gpu, | 
| const GrGLProgramDesc& desc, | 
| -                         const GrGLProgramBuilder& builder) | 
| +                         const BuiltinUniformHandles& builtinUniforms, | 
| +                         GrGLuint programID, | 
| +                         const UniformInfoArray& uniforms, | 
| +                         GrGLInstalledProcessors* geometryProcessor, | 
| +                         GrGLInstalledProcessors* colorProcessors, | 
| +                         GrGLInstalledProcessors* coverageProcessors) | 
| : fColor(GrColor_ILLEGAL) | 
| , fCoverage(GrColor_ILLEGAL) | 
| , fDstCopyTexUnit(-1) | 
| -    , fBuiltinUniformHandles(builder.getBuiltinUniformHandles()) | 
| -    , fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor())) | 
| -    , fColorEffects(SkRef(builder.getColorEffects())) | 
| -    , fCoverageEffects(SkRef(builder.getCoverageEffects())) | 
| -    , fProgramID(builder.getProgramID()) | 
| -    , fHasVertexShader(builder.hasVertexShader()) | 
| -    , fTexCoordSetCnt(builder.getTexCoordSetCount()) | 
| +    , fBuiltinUniformHandles(builtinUniforms) | 
| +    , fProgramID(programID) | 
| +    , fGeometryProcessor(SkSafeRef(geometryProcessor)) | 
| +    , fColorEffects(SkRef(colorProcessors)) | 
| +    , fCoverageEffects(SkRef(coverageProcessors)) | 
| , fDesc(desc) | 
| , fGpu(gpu) | 
| -    , fProgramDataManager(gpu, this, builder) { | 
| +    , fProgramDataManager(gpu, uniforms) { | 
| this->initSamplerUniforms(); | 
| } | 
|  | 
| @@ -83,12 +94,42 @@ void GrGLProgram::initSamplerUniforms() { | 
| fDstCopyTexUnit = texUnitIdx++; | 
| } | 
| if (fGeometryProcessor.get()) { | 
| -        fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx); | 
| +        this->initSamplers(fGeometryProcessor.get(), &texUnitIdx); | 
| +    } | 
| +    this->initSamplers(fColorEffects.get(), &texUnitIdx); | 
| +    this->initSamplers(fCoverageEffects.get(), &texUnitIdx); | 
| +} | 
| + | 
| +void GrGLProgram::initSamplers(GrGLInstalledProcessors* ip, int* texUnitIdx) { | 
| +    int numEffects = ip->fGLProcessors.count(); | 
| +    SkASSERT(numEffects == ip->fSamplers.count()); | 
| +    for (int e = 0; e < numEffects; ++e) { | 
| +        SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[e]; | 
| +        int numSamplers = samplers.count(); | 
| +        for (int s = 0; s < numSamplers; ++s) { | 
| +            SkASSERT(samplers[s].fUniform.isValid()); | 
| +            fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx); | 
| +            samplers[s].fTextureUnit = (*texUnitIdx)++; | 
| +        } | 
| +    } | 
| +} | 
| + | 
| +void GrGLProgram::bindTextures(const GrGLInstalledProcessors* ip, | 
| +                               const GrProcessor& processor, | 
| +                               int effectIdx) { | 
| +    const SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[effectIdx]; | 
| +    int numSamplers = samplers.count(); | 
| +    SkASSERT(numSamplers == processor.numTextures()); | 
| +    for (int s = 0; s < numSamplers; ++s) { | 
| +        SkASSERT(samplers[s].fTextureUnit >= 0); | 
| +        const GrTextureAccess& textureAccess = processor.textureAccess(s); | 
| +        fGpu->bindTexture(samplers[s].fTextureUnit, | 
| +                          textureAccess.getParams(), | 
| +                          static_cast<GrGLTexture*>(textureAccess.getTexture())); | 
| } | 
| -    fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx); | 
| -    fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx); | 
| } | 
|  | 
| + | 
| /////////////////////////////////////////////////////////////////////////////// | 
|  | 
| void GrGLProgram::setData(const GrOptDrawState& optState, | 
| @@ -126,21 +167,39 @@ void GrGLProgram::setData(const GrOptDrawState& optState, | 
| SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid()); | 
| } | 
|  | 
| +    // we set the textures, and uniforms for installed processors in a generic way, but subclasses | 
| +    // of GLProgram determine how to set coord transforms | 
| if (fGeometryProcessor.get()) { | 
| SkASSERT(geometryProcessor); | 
| -        fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor); | 
| +        this->setData<GrGeometryStage>(&geometryProcessor, fGeometryProcessor.get()); | 
| } | 
| -    fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages); | 
| -    fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages); | 
| +    this->setData<GrFragmentStage>(colorStages, fColorEffects.get()); | 
| +    this->setData<GrFragmentStage>(coverageStages, fCoverageEffects.get()); | 
| + | 
| +    // Some of GrGLProgram subclasses need to update state here | 
| +    this->didSetData(drawType); | 
| +} | 
|  | 
| -    // PathTexGen state applies to the the fixed function vertex shader. For | 
| -    // custom shaders, it's ignored, so we don't need to change the texgen | 
| -    // settings in that case. | 
| -    if (!fHasVertexShader) { | 
| -        fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt); | 
| +void GrGLProgram::setTransformData(const GrProcessorStage& processor, | 
| +                                   int effectIdx, | 
| +                                   GrGLInstalledProcessors* ip) { | 
| +    SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx]; | 
| +    int numTransforms = transforms.count(); | 
| +    SkASSERT(numTransforms == processor.getProcessor()->numTransforms()); | 
| +    for (int t = 0; t < numTransforms; ++t) { | 
| +        SkASSERT(transforms[t].fHandle.isValid()); | 
| +        const SkMatrix& matrix = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t); | 
| +        if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) { | 
| +            fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix); | 
| +            transforms[t].fCurrentValue = matrix; | 
| +        } | 
| } | 
| } | 
|  | 
| +void GrGLProgram::didSetData(GrGpu::DrawType drawType) { | 
| +    SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType)); | 
| +} | 
| + | 
| void GrGLProgram::setColor(const GrOptDrawState& optState, | 
| GrColor color, | 
| SharedGLState* sharedState) { | 
| @@ -220,22 +279,25 @@ void GrGLProgram::setCoverage(const GrOptDrawState& optState, | 
|  | 
| void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, | 
| const GrOptDrawState& optState) { | 
| -    const GrRenderTarget* rt = optState.getRenderTarget(); | 
| -    SkISize size; | 
| -    size.set(rt->width(), rt->height()); | 
| - | 
| // Load the RT height uniform if it is needed to y-flip gl_FragCoord. | 
| if (fBuiltinUniformHandles.fRTHeightUni.isValid() && | 
| -        fMatrixState.fRenderTargetSize.fHeight != size.fHeight) { | 
| +        fMatrixState.fRenderTargetSize.fHeight != optState.getRenderTarget()->height()) { | 
| fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, | 
| -                                   SkIntToScalar(size.fHeight)); | 
| +                                   SkIntToScalar(optState.getRenderTarget()->height())); | 
| } | 
|  | 
| -    if (GrGpu::IsPathRenderingDrawType(drawType)) { | 
| -        fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin()); | 
| -    } else if (fMatrixState.fRenderTargetOrigin != rt->origin() || | 
| -               fMatrixState.fRenderTargetSize != size || | 
| -               !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) { | 
| +    // call subclasses to set the actual view matrix | 
| +    this->onSetMatrixAndRenderTargetHeight(drawType, optState); | 
| +} | 
| + | 
| +void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, | 
| +                                                   const GrOptDrawState& optState) { | 
| +    const GrRenderTarget* rt = optState.getRenderTarget(); | 
| +    SkISize size; | 
| +    size.set(rt->width(), rt->height()); | 
| +    if (fMatrixState.fRenderTargetOrigin != rt->origin() || | 
| +        fMatrixState.fRenderTargetSize != size || | 
| +        !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) { | 
| SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid()); | 
|  | 
| fMatrixState.fViewMatrix = optState.getViewMatrix(); | 
| @@ -251,3 +313,115 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, | 
| fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); | 
| } | 
| } | 
| + | 
| +///////////////////////////////////////////////////////////////////////////////////////// | 
| + | 
| +GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu, | 
| +                                         const GrGLProgramDesc& desc, | 
| +                                         const BuiltinUniformHandles& builtinUniforms, | 
| +                                         GrGLuint programID, | 
| +                                         const UniformInfoArray& uniforms, | 
| +                                         GrGLInstalledProcessors* colorProcessors, | 
| +                                         GrGLInstalledProcessors* coverageProcessors) | 
| +    : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, colorProcessors, | 
| +                coverageProcessors) { | 
| +} | 
| + | 
| +void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, | 
| +                                                           const GrOptDrawState& optState) { | 
| +    SkASSERT(GrGpu::IsPathRenderingDrawType(drawType)); | 
| +    const GrRenderTarget* rt = optState.getRenderTarget(); | 
| +    SkISize size; | 
| +    size.set(rt->width(), rt->height()); | 
| +    fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin()); | 
| +} | 
| + | 
| +///////////////////////////////////////////////////////////////////////////////////////// | 
| + | 
| +GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu, | 
| +                                 const GrGLProgramDesc& desc, | 
| +                                 const BuiltinUniformHandles& builtinUniforms, | 
| +                                 GrGLuint programID, | 
| +                                 const UniformInfoArray& uniforms, | 
| +                                 GrGLInstalledProcessors* colorProcessors, | 
| +                                 GrGLInstalledProcessors* coverageProcessors, | 
| +                                 const SeparableVaryingInfoArray& separableVaryings) | 
| +    : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors, | 
| +                coverageProcessors) { | 
| +    int count = separableVaryings.count(); | 
| +    fVaryings.push_back_n(count); | 
| +    for (int i = 0; i < count; i++) { | 
| +        Varying& varying = fVaryings[i]; | 
| +        const SeparableVaryingInfo& builderVarying = separableVaryings[i]; | 
| +        SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount()); | 
| +        SkDEBUGCODE( | 
| +            varying.fType = builderVarying.fVariable.getType(); | 
| +        ); | 
| +        varying.fLocation = builderVarying.fLocation; | 
| +    } | 
| +} | 
| + | 
| +void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) { | 
| +    SkASSERT(GrGpu::IsPathRenderingDrawType(drawType)); | 
| +} | 
| + | 
| +void GrGLNvprProgram::setTransformData(const GrProcessorStage& processor, | 
| +                                       int effectIdx, | 
| +                                       GrGLInstalledProcessors* ip) { | 
| +    SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx]; | 
| +    int numTransforms = transforms.count(); | 
| +    SkASSERT(numTransforms == processor.getProcessor()->numTransforms()); | 
| +    for (int t = 0; t < numTransforms; ++t) { | 
| +        SkASSERT(transforms[t].fHandle.isValid()); | 
| +        const SkMatrix& transform = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t); | 
| +        if (transforms[t].fCurrentValue.cheapEqualTo(transform)) { | 
| +            continue; | 
| +        } | 
| +        transforms[t].fCurrentValue = transform; | 
| +        const Varying& fragmentInput = fVaryings[transforms[t].fHandle.handle()]; | 
| +        SkASSERT(transforms[t].fType == kVec2f_GrSLType || transforms[t].fType == kVec3f_GrSLType); | 
| +        unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3; | 
| +        fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID, | 
| +                                                                      fragmentInput.fLocation, | 
| +                                                                      GR_GL_OBJECT_LINEAR, | 
| +                                                                      components, | 
| +                                                                      transform); | 
| +    } | 
| +} | 
| + | 
| +////////////////////////////////////////////////////////////////////////////////////// | 
| + | 
| +GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu, | 
| +                                 const GrGLProgramDesc& desc, | 
| +                                 const BuiltinUniformHandles& builtinUniforms, | 
| +                                 GrGLuint programID, | 
| +                                 const UniformInfoArray& uniforms, | 
| +                                 GrGLInstalledProcessors* colorProcessors, | 
| +                                 GrGLInstalledProcessors* coverageProcessors, | 
| +                                 int texCoordSetCnt) | 
| +    : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors, | 
| +                coverageProcessors) | 
| +    , fTexCoordSetCnt(texCoordSetCnt) { | 
| +} | 
| + | 
| +void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) { | 
| +    SkASSERT(GrGpu::IsPathRenderingDrawType(drawType)); | 
| +    fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt); | 
| +} | 
| + | 
| +void GrGLLegacyNvprProgram::setTransformData(const GrProcessorStage& processorStage, | 
| +                                       int effectIdx, | 
| +                                       GrGLInstalledProcessors* ip) { | 
| +    // We've hidden the texcoord index in the first entry of the transforms array for each effect | 
| +    int texCoordIndex = ip->fTransforms[effectIdx][0].fHandle.handle(); | 
| +    int numTransforms = processorStage.getProcessor()->numTransforms(); | 
| +    for (int t = 0; t < numTransforms; ++t) { | 
| +        const SkMatrix& transform = get_transform_matrix(processorStage, false, t); | 
| +        GrGLPathRendering::PathTexGenComponents components = | 
| +                GrGLPathRendering::kST_PathTexGenComponents; | 
| +        if (processorStage.isPerspectiveCoordTransform(t, false)) { | 
| +            components = GrGLPathRendering::kSTR_PathTexGenComponents; | 
| +        } | 
| +        fGpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform); | 
| +    } | 
| +} | 
|  |