Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrGLProgram.h"
      9 
     10 #include "GrAllocator.h"
     11 #include "GrEffect.h"
     12 #include "GrCoordTransform.h"
     13 #include "GrDrawEffect.h"
     14 #include "GrGLEffect.h"
     15 #include "GrGpuGL.h"
     16 #include "GrGLShaderVar.h"
     17 #include "GrGLSL.h"
     18 #include "SkXfermode.h"
     19 
     20 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
     21 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
     22 
     23 GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
     24                                  const GrGLProgramDesc& desc,
     25                                  const GrEffectStage* colorStages[],
     26                                  const GrEffectStage* coverageStages[]) {
     27     GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gpu, desc, colorStages, coverageStages));
     28     if (!program->succeeded()) {
     29         delete program;
     30         program = NULL;
     31     }
     32     return program;
     33 }
     34 
     35 GrGLProgram::GrGLProgram(GrGpuGL* gpu,
     36                          const GrGLProgramDesc& desc,
     37                          const GrEffectStage* colorStages[],
     38                          const GrEffectStage* coverageStages[])
     39 : fGpu(gpu)
     40 , fUniformManager(gpu)
     41 , fHasVertexShader(false)
     42 , fNumTexCoordSets(0) {
     43     fDesc = desc;
     44     fProgramID = 0;
     45 
     46     fDstCopyTexUnit = -1;
     47 
     48     fColor = GrColor_ILLEGAL;
     49 
     50     if (fDesc.getHeader().fHasVertexCode ||
     51         !fGpu->shouldUseFixedFunctionTexturing()) {
     52         GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
     53         if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
     54             fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
     55             fHasVertexShader = true;
     56         }
     57     } else {
     58         GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc);
     59         if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) {
     60             fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
     61         }
     62     }
     63 }
     64 
     65 GrGLProgram::~GrGLProgram() {
     66     if (fProgramID) {
     67         GL_CALL(DeleteProgram(fProgramID));
     68     }
     69 }
     70 
     71 void GrGLProgram::abandon() {
     72     fProgramID = 0;
     73 }
     74 
     75 void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
     76                                 GrBlendCoeff* dstCoeff) const {
     77     switch (fDesc.getHeader().fCoverageOutput) {
     78         case GrGLProgramDesc::kModulate_CoverageOutput:
     79             break;
     80         // The prog will write a coverage value to the secondary
     81         // output and the dst is blended by one minus that value.
     82         case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
     83         case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
     84         case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
     85             *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
     86             break;
     87         case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
     88             // We should only have set this if the blend was specified as (1, 0)
     89             SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
     90             break;
     91         default:
     92             GrCrash("Unexpected coverage output");
     93             break;
     94     }
     95 }
     96 
     97 bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
     98                              const GrEffectStage* colorStages[],
     99                              const GrEffectStage* coverageStages[]) {
    100     SkASSERT(0 == fProgramID);
    101 
    102     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
    103 
    104     // incoming color to current stage being processed.
    105     GrGLSLExpr4 inColor = builder->getInputColor();
    106 
    107     fColorEffects.reset(
    108         builder->createAndEmitEffects(colorStages,
    109                                       fDesc.effectKeys(),
    110                                       fDesc.numColorEffects(),
    111                                       &inColor));
    112 
    113     ///////////////////////////////////////////////////////////////////////////
    114     // compute the partial coverage
    115     GrGLSLExpr4 inCoverage = builder->getInputCoverage();
    116 
    117     fCoverageEffects.reset(
    118         builder->createAndEmitEffects(coverageStages,
    119                                       fDesc.getEffectKeys() + fDesc.numColorEffects(),
    120                                       fDesc.numCoverageEffects(),
    121                                       &inCoverage));
    122 
    123     // discard if coverage is zero
    124     if (header.fDiscardIfZeroCoverage && !inCoverage.isOnes()) {
    125         if (inCoverage.isZeros()) {
    126             // This is unfortunate.
    127             builder->fsCodeAppend("\tdiscard;\n");
    128         } else {
    129             builder->fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
    130                                    inCoverage.c_str());
    131         }
    132     }
    133 
    134     if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
    135         const char* secondaryOutputName = builder->enableSecondaryOutput();
    136 
    137         // default coeff to ones for kCoverage_DualSrcOutput
    138         GrGLSLExpr4 coeff(1);
    139         if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
    140             // Get (1-A) into coeff
    141             coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a());
    142         } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
    143             // Get (1-RGBA) into coeff
    144             coeff = GrGLSLExpr4(1) - inColor;
    145         }
    146         // Get coeff * coverage into modulate and then write that to the dual source output.
    147         builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
    148     }
    149 
    150     ///////////////////////////////////////////////////////////////////////////
    151     // combine color and coverage as frag color
    152 
    153     // Get "color * coverage" into fragColor
    154     GrGLSLExpr4 fragColor = inColor * inCoverage;
    155     // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
    156     if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
    157         GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage;
    158 
    159         GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor());
    160 
    161         fragColor = fragColor + dstContribution;
    162     }
    163     builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());
    164 
    165     if (!builder->finish(&fProgramID)) {
    166         return false;
    167     }
    168 
    169     fUniformHandles.fRTHeightUni = builder->getRTHeightUniform();
    170     fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform();
    171     fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform();
    172     fUniformHandles.fColorUni = builder->getColorUniform();
    173     fUniformHandles.fCoverageUni = builder->getCoverageUniform();
    174     fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform();
    175     // This must be called after we set fDstCopySamplerUni above.
    176     this->initSamplerUniforms();
    177 
    178     return true;
    179 }
    180 
    181 void GrGLProgram::initSamplerUniforms() {
    182     GL_CALL(UseProgram(fProgramID));
    183     GrGLint texUnitIdx = 0;
    184     if (fUniformHandles.fDstCopySamplerUni.isValid()) {
    185         fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx);
    186         fDstCopyTexUnit = texUnitIdx++;
    187     }
    188     fColorEffects->initSamplers(fUniformManager, &texUnitIdx);
    189     fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx);
    190 }
    191 
    192 ///////////////////////////////////////////////////////////////////////////////
    193 
    194 void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
    195                           const GrEffectStage* colorStages[],
    196                           const GrEffectStage* coverageStages[],
    197                           const GrDeviceCoordTexture* dstCopy,
    198                           SharedGLState* sharedState) {
    199     const GrDrawState& drawState = fGpu->getDrawState();
    200 
    201     GrColor color;
    202     GrColor coverage;
    203     if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
    204         color = 0;
    205         coverage = 0;
    206     } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
    207         color = 0xffffffff;
    208         coverage = drawState.getCoverageColor();
    209     } else {
    210         color = drawState.getColor();
    211         coverage = drawState.getCoverageColor();
    212     }
    213 
    214     this->setColor(drawState, color, sharedState);
    215     this->setCoverage(drawState, coverage, sharedState);
    216     this->setMatrixAndRenderTargetHeight(drawState);
    217 
    218     if (NULL != dstCopy) {
    219         if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
    220             fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
    221                                   static_cast<GrGLfloat>(dstCopy->offset().fX),
    222                                   static_cast<GrGLfloat>(dstCopy->offset().fY));
    223             fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni,
    224                                   1.f / dstCopy->texture()->width(),
    225                                   1.f / dstCopy->texture()->height());
    226             GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
    227             static GrTextureParams kParams; // the default is clamp, nearest filtering.
    228             fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
    229         } else {
    230             SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
    231             SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
    232         }
    233     } else {
    234         SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid());
    235         SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
    236         SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
    237     }
    238 
    239     fColorEffects->setData(fGpu, fUniformManager, colorStages);
    240     fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
    241 
    242 
    243     // TexGen state applies to the the fixed function vertex shader. For custom shaders, it's
    244     // ignored, so we don't need to change the texgen settings in that case.
    245     if (!fHasVertexShader) {
    246         fGpu->flushTexGenSettings(fNumTexCoordSets);
    247     }
    248 }
    249 
    250 void GrGLProgram::setColor(const GrDrawState& drawState,
    251                            GrColor color,
    252                            SharedGLState* sharedState) {
    253     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
    254     if (!drawState.hasColorVertexAttribute()) {
    255         switch (header.fColorInput) {
    256             case GrGLProgramDesc::kAttribute_ColorInput:
    257                 SkASSERT(-1 != header.fColorAttributeIndex);
    258                 if (sharedState->fConstAttribColor != color ||
    259                     sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
    260                     // OpenGL ES only supports the float varieties of glVertexAttrib
    261                     GrGLfloat c[4];
    262                     GrColorToRGBAFloat(color, c);
    263                     GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
    264                     sharedState->fConstAttribColor = color;
    265                     sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
    266                 }
    267                 break;
    268             case GrGLProgramDesc::kUniform_ColorInput:
    269                 if (fColor != color && fUniformHandles.fColorUni.isValid()) {
    270                     // OpenGL ES doesn't support unsigned byte varieties of glUniform
    271                     GrGLfloat c[4];
    272                     GrColorToRGBAFloat(color, c);
    273                     fUniformManager.set4fv(fUniformHandles.fColorUni, 1, c);
    274                     fColor = color;
    275                 }
    276                 sharedState->fConstAttribColorIndex = -1;
    277                 break;
    278             case GrGLProgramDesc::kSolidWhite_ColorInput:
    279             case GrGLProgramDesc::kTransBlack_ColorInput:
    280                 sharedState->fConstAttribColorIndex = -1;
    281                 break;
    282             default:
    283                 GrCrash("Unknown color type.");
    284         }
    285     } else {
    286         sharedState->fConstAttribColorIndex = -1;
    287     }
    288 }
    289 
    290 void GrGLProgram::setCoverage(const GrDrawState& drawState,
    291                               GrColor coverage,
    292                               SharedGLState* sharedState) {
    293     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
    294     if (!drawState.hasCoverageVertexAttribute()) {
    295         switch (header.fCoverageInput) {
    296             case GrGLProgramDesc::kAttribute_ColorInput:
    297                 if (sharedState->fConstAttribCoverage != coverage ||
    298                     sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
    299                     // OpenGL ES only supports the float varieties of  glVertexAttrib
    300                     GrGLfloat c[4];
    301                     GrColorToRGBAFloat(coverage, c);
    302                     GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
    303                     sharedState->fConstAttribCoverage = coverage;
    304                     sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
    305                 }
    306                 break;
    307             case GrGLProgramDesc::kUniform_ColorInput:
    308                 if (fCoverage != coverage) {
    309                     // OpenGL ES doesn't support unsigned byte varieties of glUniform
    310                     GrGLfloat c[4];
    311                     GrColorToRGBAFloat(coverage, c);
    312                     fUniformManager.set4fv(fUniformHandles.fCoverageUni, 1, c);
    313                     fCoverage = coverage;
    314                 }
    315                 sharedState->fConstAttribCoverageIndex = -1;
    316                 break;
    317             case GrGLProgramDesc::kSolidWhite_ColorInput:
    318             case GrGLProgramDesc::kTransBlack_ColorInput:
    319                 sharedState->fConstAttribCoverageIndex = -1;
    320                 break;
    321             default:
    322                 GrCrash("Unknown coverage type.");
    323         }
    324     } else {
    325         sharedState->fConstAttribCoverageIndex = -1;
    326     }
    327 }
    328 
    329 void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
    330     const GrRenderTarget* rt = drawState.getRenderTarget();
    331     SkISize size;
    332     size.set(rt->width(), rt->height());
    333 
    334     // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
    335     if (fUniformHandles.fRTHeightUni.isValid() &&
    336         fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
    337         fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
    338     }
    339 
    340     if (!fHasVertexShader) {
    341         SkASSERT(!fUniformHandles.fViewMatrixUni.isValid());
    342         fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
    343     } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
    344                fMatrixState.fRenderTargetSize != size ||
    345                !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
    346         SkASSERT(fUniformHandles.fViewMatrixUni.isValid());
    347 
    348         fMatrixState.fViewMatrix = drawState.getViewMatrix();
    349         fMatrixState.fRenderTargetSize = size;
    350         fMatrixState.fRenderTargetOrigin = rt->origin();
    351 
    352         GrGLfloat viewMatrix[3 * 3];
    353         fMatrixState.getGLMatrix<3>(viewMatrix);
    354         fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix);
    355     }
    356 }
    357