gfx/skia/trunk/src/gpu/gl/GrGLProgram.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/gpu/gl/GrGLProgram.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,345 @@
     1.4 +/*
     1.5 + * Copyright 2011 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#include "GrGLProgram.h"
    1.12 +
    1.13 +#include "GrAllocator.h"
    1.14 +#include "GrEffect.h"
    1.15 +#include "GrCoordTransform.h"
    1.16 +#include "GrDrawEffect.h"
    1.17 +#include "GrGLEffect.h"
    1.18 +#include "GrGpuGL.h"
    1.19 +#include "GrGLShaderVar.h"
    1.20 +#include "GrGLSL.h"
    1.21 +#include "SkXfermode.h"
    1.22 +
    1.23 +#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
    1.24 +#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
    1.25 +
    1.26 +GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
    1.27 +                                 const GrGLProgramDesc& desc,
    1.28 +                                 const GrEffectStage* colorStages[],
    1.29 +                                 const GrEffectStage* coverageStages[]) {
    1.30 +    GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gpu, desc, colorStages, coverageStages));
    1.31 +    if (!program->succeeded()) {
    1.32 +        delete program;
    1.33 +        program = NULL;
    1.34 +    }
    1.35 +    return program;
    1.36 +}
    1.37 +
    1.38 +GrGLProgram::GrGLProgram(GrGpuGL* gpu,
    1.39 +                         const GrGLProgramDesc& desc,
    1.40 +                         const GrEffectStage* colorStages[],
    1.41 +                         const GrEffectStage* coverageStages[])
    1.42 +: fGpu(gpu)
    1.43 +, fUniformManager(gpu)
    1.44 +, fHasVertexShader(false)
    1.45 +, fNumTexCoordSets(0) {
    1.46 +    fDesc = desc;
    1.47 +    fProgramID = 0;
    1.48 +
    1.49 +    fDstCopyTexUnit = -1;
    1.50 +
    1.51 +    fColor = GrColor_ILLEGAL;
    1.52 +
    1.53 +    if (fDesc.getHeader().fHasVertexCode ||
    1.54 +        !fGpu->shouldUseFixedFunctionTexturing()) {
    1.55 +        GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
    1.56 +        if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
    1.57 +            fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
    1.58 +            fHasVertexShader = true;
    1.59 +        }
    1.60 +    } else {
    1.61 +        GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc);
    1.62 +        if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) {
    1.63 +            fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
    1.64 +        }
    1.65 +    }
    1.66 +}
    1.67 +
    1.68 +GrGLProgram::~GrGLProgram() {
    1.69 +    if (fProgramID) {
    1.70 +        GL_CALL(DeleteProgram(fProgramID));
    1.71 +    }
    1.72 +}
    1.73 +
    1.74 +void GrGLProgram::abandon() {
    1.75 +    fProgramID = 0;
    1.76 +}
    1.77 +
    1.78 +void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
    1.79 +                                GrBlendCoeff* dstCoeff) const {
    1.80 +    switch (fDesc.getHeader().fCoverageOutput) {
    1.81 +        case GrGLProgramDesc::kModulate_CoverageOutput:
    1.82 +            break;
    1.83 +        // The prog will write a coverage value to the secondary
    1.84 +        // output and the dst is blended by one minus that value.
    1.85 +        case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
    1.86 +        case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
    1.87 +        case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
    1.88 +            *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
    1.89 +            break;
    1.90 +        case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
    1.91 +            // We should only have set this if the blend was specified as (1, 0)
    1.92 +            SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
    1.93 +            break;
    1.94 +        default:
    1.95 +            GrCrash("Unexpected coverage output");
    1.96 +            break;
    1.97 +    }
    1.98 +}
    1.99 +
   1.100 +bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
   1.101 +                             const GrEffectStage* colorStages[],
   1.102 +                             const GrEffectStage* coverageStages[]) {
   1.103 +    SkASSERT(0 == fProgramID);
   1.104 +
   1.105 +    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
   1.106 +
   1.107 +    // incoming color to current stage being processed.
   1.108 +    GrGLSLExpr4 inColor = builder->getInputColor();
   1.109 +
   1.110 +    fColorEffects.reset(
   1.111 +        builder->createAndEmitEffects(colorStages,
   1.112 +                                      fDesc.effectKeys(),
   1.113 +                                      fDesc.numColorEffects(),
   1.114 +                                      &inColor));
   1.115 +
   1.116 +    ///////////////////////////////////////////////////////////////////////////
   1.117 +    // compute the partial coverage
   1.118 +    GrGLSLExpr4 inCoverage = builder->getInputCoverage();
   1.119 +
   1.120 +    fCoverageEffects.reset(
   1.121 +        builder->createAndEmitEffects(coverageStages,
   1.122 +                                      fDesc.getEffectKeys() + fDesc.numColorEffects(),
   1.123 +                                      fDesc.numCoverageEffects(),
   1.124 +                                      &inCoverage));
   1.125 +
   1.126 +    if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
   1.127 +        const char* secondaryOutputName = builder->enableSecondaryOutput();
   1.128 +
   1.129 +        // default coeff to ones for kCoverage_DualSrcOutput
   1.130 +        GrGLSLExpr4 coeff(1);
   1.131 +        if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
   1.132 +            // Get (1-A) into coeff
   1.133 +            coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a());
   1.134 +        } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
   1.135 +            // Get (1-RGBA) into coeff
   1.136 +            coeff = GrGLSLExpr4(1) - inColor;
   1.137 +        }
   1.138 +        // Get coeff * coverage into modulate and then write that to the dual source output.
   1.139 +        builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
   1.140 +    }
   1.141 +
   1.142 +    ///////////////////////////////////////////////////////////////////////////
   1.143 +    // combine color and coverage as frag color
   1.144 +
   1.145 +    // Get "color * coverage" into fragColor
   1.146 +    GrGLSLExpr4 fragColor = inColor * inCoverage;
   1.147 +    // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
   1.148 +    if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
   1.149 +        GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage;
   1.150 +
   1.151 +        GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor());
   1.152 +
   1.153 +        fragColor = fragColor + dstContribution;
   1.154 +    }
   1.155 +    builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());
   1.156 +
   1.157 +    if (!builder->finish(&fProgramID)) {
   1.158 +        return false;
   1.159 +    }
   1.160 +
   1.161 +    fUniformHandles.fRTHeightUni = builder->getRTHeightUniform();
   1.162 +    fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform();
   1.163 +    fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform();
   1.164 +    fUniformHandles.fColorUni = builder->getColorUniform();
   1.165 +    fUniformHandles.fCoverageUni = builder->getCoverageUniform();
   1.166 +    fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform();
   1.167 +    // This must be called after we set fDstCopySamplerUni above.
   1.168 +    this->initSamplerUniforms();
   1.169 +
   1.170 +    return true;
   1.171 +}
   1.172 +
   1.173 +void GrGLProgram::initSamplerUniforms() {
   1.174 +    GL_CALL(UseProgram(fProgramID));
   1.175 +    GrGLint texUnitIdx = 0;
   1.176 +    if (fUniformHandles.fDstCopySamplerUni.isValid()) {
   1.177 +        fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx);
   1.178 +        fDstCopyTexUnit = texUnitIdx++;
   1.179 +    }
   1.180 +    fColorEffects->initSamplers(fUniformManager, &texUnitIdx);
   1.181 +    fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx);
   1.182 +}
   1.183 +
   1.184 +///////////////////////////////////////////////////////////////////////////////
   1.185 +
   1.186 +void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
   1.187 +                          const GrEffectStage* colorStages[],
   1.188 +                          const GrEffectStage* coverageStages[],
   1.189 +                          const GrDeviceCoordTexture* dstCopy,
   1.190 +                          SharedGLState* sharedState) {
   1.191 +    const GrDrawState& drawState = fGpu->getDrawState();
   1.192 +
   1.193 +    GrColor color;
   1.194 +    GrColor coverage;
   1.195 +    if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
   1.196 +        color = 0;
   1.197 +        coverage = 0;
   1.198 +    } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
   1.199 +        color = 0xffffffff;
   1.200 +        coverage = drawState.getCoverageColor();
   1.201 +    } else {
   1.202 +        color = drawState.getColor();
   1.203 +        coverage = drawState.getCoverageColor();
   1.204 +    }
   1.205 +
   1.206 +    this->setColor(drawState, color, sharedState);
   1.207 +    this->setCoverage(drawState, coverage, sharedState);
   1.208 +    this->setMatrixAndRenderTargetHeight(drawState);
   1.209 +
   1.210 +    if (NULL != dstCopy) {
   1.211 +        if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
   1.212 +            fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
   1.213 +                                  static_cast<GrGLfloat>(dstCopy->offset().fX),
   1.214 +                                  static_cast<GrGLfloat>(dstCopy->offset().fY));
   1.215 +            fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni,
   1.216 +                                  1.f / dstCopy->texture()->width(),
   1.217 +                                  1.f / dstCopy->texture()->height());
   1.218 +            GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
   1.219 +            static GrTextureParams kParams; // the default is clamp, nearest filtering.
   1.220 +            fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
   1.221 +        } else {
   1.222 +            SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
   1.223 +            SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
   1.224 +        }
   1.225 +    } else {
   1.226 +        SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid());
   1.227 +        SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
   1.228 +        SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
   1.229 +    }
   1.230 +
   1.231 +    fColorEffects->setData(fGpu, fUniformManager, colorStages);
   1.232 +    fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
   1.233 +
   1.234 +
   1.235 +    // TexGen state applies to the the fixed function vertex shader. For custom shaders, it's
   1.236 +    // ignored, so we don't need to change the texgen settings in that case.
   1.237 +    if (!fHasVertexShader) {
   1.238 +        fGpu->flushTexGenSettings(fNumTexCoordSets);
   1.239 +    }
   1.240 +}
   1.241 +
   1.242 +void GrGLProgram::setColor(const GrDrawState& drawState,
   1.243 +                           GrColor color,
   1.244 +                           SharedGLState* sharedState) {
   1.245 +    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
   1.246 +    if (!drawState.hasColorVertexAttribute()) {
   1.247 +        switch (header.fColorInput) {
   1.248 +            case GrGLProgramDesc::kAttribute_ColorInput:
   1.249 +                SkASSERT(-1 != header.fColorAttributeIndex);
   1.250 +                if (sharedState->fConstAttribColor != color ||
   1.251 +                    sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
   1.252 +                    // OpenGL ES only supports the float varieties of glVertexAttrib
   1.253 +                    GrGLfloat c[4];
   1.254 +                    GrColorToRGBAFloat(color, c);
   1.255 +                    GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
   1.256 +                    sharedState->fConstAttribColor = color;
   1.257 +                    sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
   1.258 +                }
   1.259 +                break;
   1.260 +            case GrGLProgramDesc::kUniform_ColorInput:
   1.261 +                if (fColor != color && fUniformHandles.fColorUni.isValid()) {
   1.262 +                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
   1.263 +                    GrGLfloat c[4];
   1.264 +                    GrColorToRGBAFloat(color, c);
   1.265 +                    fUniformManager.set4fv(fUniformHandles.fColorUni, 1, c);
   1.266 +                    fColor = color;
   1.267 +                }
   1.268 +                sharedState->fConstAttribColorIndex = -1;
   1.269 +                break;
   1.270 +            case GrGLProgramDesc::kSolidWhite_ColorInput:
   1.271 +            case GrGLProgramDesc::kTransBlack_ColorInput:
   1.272 +                sharedState->fConstAttribColorIndex = -1;
   1.273 +                break;
   1.274 +            default:
   1.275 +                GrCrash("Unknown color type.");
   1.276 +        }
   1.277 +    } else {
   1.278 +        sharedState->fConstAttribColorIndex = -1;
   1.279 +    }
   1.280 +}
   1.281 +
   1.282 +void GrGLProgram::setCoverage(const GrDrawState& drawState,
   1.283 +                              GrColor coverage,
   1.284 +                              SharedGLState* sharedState) {
   1.285 +    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
   1.286 +    if (!drawState.hasCoverageVertexAttribute()) {
   1.287 +        switch (header.fCoverageInput) {
   1.288 +            case GrGLProgramDesc::kAttribute_ColorInput:
   1.289 +                if (sharedState->fConstAttribCoverage != coverage ||
   1.290 +                    sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
   1.291 +                    // OpenGL ES only supports the float varieties of  glVertexAttrib
   1.292 +                    GrGLfloat c[4];
   1.293 +                    GrColorToRGBAFloat(coverage, c);
   1.294 +                    GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
   1.295 +                    sharedState->fConstAttribCoverage = coverage;
   1.296 +                    sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
   1.297 +                }
   1.298 +                break;
   1.299 +            case GrGLProgramDesc::kUniform_ColorInput:
   1.300 +                if (fCoverage != coverage) {
   1.301 +                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
   1.302 +                    GrGLfloat c[4];
   1.303 +                    GrColorToRGBAFloat(coverage, c);
   1.304 +                    fUniformManager.set4fv(fUniformHandles.fCoverageUni, 1, c);
   1.305 +                    fCoverage = coverage;
   1.306 +                }
   1.307 +                sharedState->fConstAttribCoverageIndex = -1;
   1.308 +                break;
   1.309 +            case GrGLProgramDesc::kSolidWhite_ColorInput:
   1.310 +            case GrGLProgramDesc::kTransBlack_ColorInput:
   1.311 +                sharedState->fConstAttribCoverageIndex = -1;
   1.312 +                break;
   1.313 +            default:
   1.314 +                GrCrash("Unknown coverage type.");
   1.315 +        }
   1.316 +    } else {
   1.317 +        sharedState->fConstAttribCoverageIndex = -1;
   1.318 +    }
   1.319 +}
   1.320 +
   1.321 +void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
   1.322 +    const GrRenderTarget* rt = drawState.getRenderTarget();
   1.323 +    SkISize size;
   1.324 +    size.set(rt->width(), rt->height());
   1.325 +
   1.326 +    // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
   1.327 +    if (fUniformHandles.fRTHeightUni.isValid() &&
   1.328 +        fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
   1.329 +        fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
   1.330 +    }
   1.331 +
   1.332 +    if (!fHasVertexShader) {
   1.333 +        SkASSERT(!fUniformHandles.fViewMatrixUni.isValid());
   1.334 +        fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
   1.335 +    } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
   1.336 +               fMatrixState.fRenderTargetSize != size ||
   1.337 +               !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
   1.338 +        SkASSERT(fUniformHandles.fViewMatrixUni.isValid());
   1.339 +
   1.340 +        fMatrixState.fViewMatrix = drawState.getViewMatrix();
   1.341 +        fMatrixState.fRenderTargetSize = size;
   1.342 +        fMatrixState.fRenderTargetOrigin = rt->origin();
   1.343 +
   1.344 +        GrGLfloat viewMatrix[3 * 3];
   1.345 +        fMatrixState.getGLMatrix<3>(viewMatrix);
   1.346 +        fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix);
   1.347 +    }
   1.348 +}

mercurial