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     GrGLShaderBuilder::GenProgramOutput output;
     28     SkAutoTUnref<GrGLUniformManager> uman(SkNEW_ARGS(GrGLUniformManager, (gpu)));
     29     if (GrGLShaderBuilder::GenProgram(gpu, uman, desc, colorStages, coverageStages,
     30                                       &output)) {
     31         SkASSERT(0 != output.fProgramID);
     32         return SkNEW_ARGS(GrGLProgram, (gpu, desc, uman, output));
     33     }
     34     return NULL;
     35 }
     36 
     37 GrGLProgram::GrGLProgram(GrGpuGL* gpu,
     38                          const GrGLProgramDesc& desc,
     39                          GrGLUniformManager* uman,
     40                          const GrGLShaderBuilder::GenProgramOutput& builderOutput)
     41     : fColor(GrColor_ILLEGAL)
     42     , fCoverage(GrColor_ILLEGAL)
     43     , fDstCopyTexUnit(-1)
     44     , fBuilderOutput(builderOutput)
     45     , fDesc(desc)
     46     , fGpu(gpu)
     47     , fUniformManager(SkRef(uman)) {
     48     this->initSamplerUniforms();
     49 }
     50 
     51 GrGLProgram::~GrGLProgram() {
     52     if (fBuilderOutput.fProgramID) {
     53         GL_CALL(DeleteProgram(fBuilderOutput.fProgramID));
     54     }
     55 }
     56 
     57 void GrGLProgram::abandon() {
     58     fBuilderOutput.fProgramID = 0;
     59 }
     60 
     61 void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
     62                                 GrBlendCoeff* dstCoeff) const {
     63     switch (fDesc.getHeader().fCoverageOutput) {
     64         case GrGLProgramDesc::kModulate_CoverageOutput:
     65             break;
     66         // The prog will write a coverage value to the secondary
     67         // output and the dst is blended by one minus that value.
     68         case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
     69         case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
     70         case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
     71             *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
     72             break;
     73         case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
     74             // We should only have set this if the blend was specified as (1, 0)
     75             SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
     76             break;
     77         default:
     78             SkFAIL("Unexpected coverage output");
     79             break;
     80     }
     81 }
     82 
     83 void GrGLProgram::initSamplerUniforms() {
     84     GL_CALL(UseProgram(fBuilderOutput.fProgramID));
     85     GrGLint texUnitIdx = 0;
     86     if (fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid()) {
     87         fUniformManager->setSampler(fBuilderOutput.fUniformHandles.fDstCopySamplerUni, texUnitIdx);
     88         fDstCopyTexUnit = texUnitIdx++;
     89     }
     90     fBuilderOutput.fColorEffects->initSamplers(*fUniformManager, &texUnitIdx);
     91     fBuilderOutput.fCoverageEffects->initSamplers(*fUniformManager, &texUnitIdx);
     92 }
     93 
     94 ///////////////////////////////////////////////////////////////////////////////
     95 
     96 void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
     97                           const GrEffectStage* colorStages[],
     98                           const GrEffectStage* coverageStages[],
     99                           const GrDeviceCoordTexture* dstCopy,
    100                           SharedGLState* sharedState) {
    101     const GrDrawState& drawState = fGpu->getDrawState();
    102 
    103     GrColor color;
    104     GrColor coverage;
    105     if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
    106         color = 0;
    107         coverage = 0;
    108     } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
    109         color = 0xffffffff;
    110         coverage = drawState.getCoverageColor();
    111     } else {
    112         color = drawState.getColor();
    113         coverage = drawState.getCoverageColor();
    114     }
    115 
    116     this->setColor(drawState, color, sharedState);
    117     this->setCoverage(drawState, coverage, sharedState);
    118     this->setMatrixAndRenderTargetHeight(drawState);
    119 
    120     if (NULL != dstCopy) {
    121         if (fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni.isValid()) {
    122             fUniformManager->set2f(fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni,
    123                                    static_cast<GrGLfloat>(dstCopy->offset().fX),
    124                                    static_cast<GrGLfloat>(dstCopy->offset().fY));
    125             fUniformManager->set2f(fBuilderOutput.fUniformHandles.fDstCopyScaleUni,
    126                                    1.f / dstCopy->texture()->width(),
    127                                    1.f / dstCopy->texture()->height());
    128             GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
    129             static GrTextureParams kParams; // the default is clamp, nearest filtering.
    130             fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
    131         } else {
    132             SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyScaleUni.isValid());
    133             SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid());
    134         }
    135     } else {
    136         SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni.isValid());
    137         SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyScaleUni.isValid());
    138         SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid());
    139     }
    140 
    141     fBuilderOutput.fColorEffects->setData(fGpu, *fUniformManager, colorStages);
    142     fBuilderOutput.fCoverageEffects->setData(fGpu, *fUniformManager, coverageStages);
    143 
    144 
    145     // PathTexGen state applies to the the fixed function vertex shader. For
    146     // custom shaders, it's ignored, so we don't need to change the texgen
    147     // settings in that case.
    148     if (!fBuilderOutput.fHasVertexShader) {
    149         fGpu->flushPathTexGenSettings(fBuilderOutput.fTexCoordSetCnt);
    150     }
    151 }
    152 
    153 void GrGLProgram::setColor(const GrDrawState& drawState,
    154                            GrColor color,
    155                            SharedGLState* sharedState) {
    156     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
    157     if (!drawState.hasColorVertexAttribute()) {
    158         switch (header.fColorInput) {
    159             case GrGLProgramDesc::kAttribute_ColorInput:
    160                 SkASSERT(-1 != header.fColorAttributeIndex);
    161                 if (sharedState->fConstAttribColor != color ||
    162                     sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
    163                     // OpenGL ES only supports the float varieties of glVertexAttrib
    164                     GrGLfloat c[4];
    165                     GrColorToRGBAFloat(color, c);
    166                     GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
    167                     sharedState->fConstAttribColor = color;
    168                     sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
    169                 }
    170                 break;
    171             case GrGLProgramDesc::kUniform_ColorInput:
    172                 if (fColor != color && fBuilderOutput.fUniformHandles.fColorUni.isValid()) {
    173                     // OpenGL ES doesn't support unsigned byte varieties of glUniform
    174                     GrGLfloat c[4];
    175                     GrColorToRGBAFloat(color, c);
    176                     fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fColorUni, 1, c);
    177                     fColor = color;
    178                 }
    179                 sharedState->fConstAttribColorIndex = -1;
    180                 break;
    181             case GrGLProgramDesc::kSolidWhite_ColorInput:
    182             case GrGLProgramDesc::kTransBlack_ColorInput:
    183                 sharedState->fConstAttribColorIndex = -1;
    184                 break;
    185             default:
    186                 SkFAIL("Unknown color type.");
    187         }
    188     } else {
    189         sharedState->fConstAttribColorIndex = -1;
    190     }
    191 }
    192 
    193 void GrGLProgram::setCoverage(const GrDrawState& drawState,
    194                               GrColor coverage,
    195                               SharedGLState* sharedState) {
    196     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
    197     if (!drawState.hasCoverageVertexAttribute()) {
    198         switch (header.fCoverageInput) {
    199             case GrGLProgramDesc::kAttribute_ColorInput:
    200                 if (sharedState->fConstAttribCoverage != coverage ||
    201                     sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
    202                     // OpenGL ES only supports the float varieties of  glVertexAttrib
    203                     GrGLfloat c[4];
    204                     GrColorToRGBAFloat(coverage, c);
    205                     GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
    206                     sharedState->fConstAttribCoverage = coverage;
    207                     sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
    208                 }
    209                 break;
    210             case GrGLProgramDesc::kUniform_ColorInput:
    211                 if (fCoverage != coverage) {
    212                     // OpenGL ES doesn't support unsigned byte varieties of glUniform
    213                     GrGLfloat c[4];
    214                     GrColorToRGBAFloat(coverage, c);
    215                     fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fCoverageUni, 1, c);
    216                     fCoverage = coverage;
    217                 }
    218                 sharedState->fConstAttribCoverageIndex = -1;
    219                 break;
    220             case GrGLProgramDesc::kSolidWhite_ColorInput:
    221             case GrGLProgramDesc::kTransBlack_ColorInput:
    222                 sharedState->fConstAttribCoverageIndex = -1;
    223                 break;
    224             default:
    225                 SkFAIL("Unknown coverage type.");
    226         }
    227     } else {
    228         sharedState->fConstAttribCoverageIndex = -1;
    229     }
    230 }
    231 
    232 void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
    233     const GrRenderTarget* rt = drawState.getRenderTarget();
    234     SkISize size;
    235     size.set(rt->width(), rt->height());
    236 
    237     // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
    238     if (fBuilderOutput.fUniformHandles.fRTHeightUni.isValid() &&
    239         fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
    240         fUniformManager->set1f(fBuilderOutput.fUniformHandles.fRTHeightUni,
    241                                SkIntToScalar(size.fHeight));
    242     }
    243 
    244     if (!fBuilderOutput.fHasVertexShader) {
    245         SkASSERT(!fBuilderOutput.fUniformHandles.fViewMatrixUni.isValid());
    246         SkASSERT(!fBuilderOutput.fUniformHandles.fRTAdjustmentUni.isValid());
    247         fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
    248     } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
    249                fMatrixState.fRenderTargetSize != size ||
    250                !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
    251         SkASSERT(fBuilderOutput.fUniformHandles.fViewMatrixUni.isValid());
    252 
    253         fMatrixState.fViewMatrix = drawState.getViewMatrix();
    254         fMatrixState.fRenderTargetSize = size;
    255         fMatrixState.fRenderTargetOrigin = rt->origin();
    256 
    257         GrGLfloat viewMatrix[3 * 3];
    258         fMatrixState.getGLMatrix<3>(viewMatrix);
    259         fUniformManager->setMatrix3f(fBuilderOutput.fUniformHandles.fViewMatrixUni, viewMatrix);
    260 
    261         GrGLfloat rtAdjustmentVec[4];
    262         fMatrixState.getRTAdjustmentVec(rtAdjustmentVec);
    263         fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
    264     }
    265 }
    266