Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2013 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 "GrGLProgramDesc.h"
      9 #include "GrBackendEffectFactory.h"
     10 #include "GrDrawEffect.h"
     11 #include "GrEffect.h"
     12 #include "GrGLShaderBuilder.h"
     13 #include "GrGpuGL.h"
     14 
     15 #include "SkChecksum.h"
     16 
     17 namespace {
     18 inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage,
     19                                                       const GrGLCaps& caps,
     20                                                       bool useExplicitLocalCoords,
     21                                                       bool* setTrueIfReadsDst,
     22                                                       bool* setTrueIfReadsPos) {
     23     const GrEffectRef& effect = *stage.getEffect();
     24     const GrBackendEffectFactory& factory = effect->getFactory();
     25     GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
     26     if (effect->willReadDstColor()) {
     27         *setTrueIfReadsDst = true;
     28     }
     29     if (effect->willReadFragmentPosition()) {
     30         *setTrueIfReadsPos = true;
     31     }
     32     return factory.glEffectKey(drawEffect, caps);
     33 }
     34 }
     35 void GrGLProgramDesc::Build(const GrDrawState& drawState,
     36                             bool isPoints,
     37                             GrDrawState::BlendOptFlags blendOpts,
     38                             GrBlendCoeff srcCoeff,
     39                             GrBlendCoeff dstCoeff,
     40                             const GrGpuGL* gpu,
     41                             const GrDeviceCoordTexture* dstCopy,
     42                             SkTArray<const GrEffectStage*, true>* colorStages,
     43                             SkTArray<const GrEffectStage*, true>* coverageStages,
     44                             GrGLProgramDesc* desc) {
     45     colorStages->reset();
     46     coverageStages->reset();
     47 
     48     // This should already have been caught
     49     GrAssert(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
     50 
     51     bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
     52 
     53     bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
     54                                            GrDrawState::kEmitCoverage_BlendOptFlag));
     55 
     56     // The descriptor is used as a cache key. Thus when a field of the
     57     // descriptor will not affect program generation (because of the attribute
     58     // bindings in use or other descriptor field settings) it should be set
     59     // to a canonical value to avoid duplicate programs with different keys.
     60 
     61     bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
     62     bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
     63     // we only need the local coords if we're actually going to generate effect code
     64     bool requiresLocalCoordAttrib = !(skipCoverage  && skipColor) &&
     65                                     drawState.hasLocalCoordAttribute();
     66 
     67     bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
     68     bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
     69                              (!requiresColorAttrib && 0xffffffff == drawState.getColor());
     70 
     71     int numEffects = (skipColor ? 0 : drawState.numColorStages()) +
     72                      (skipCoverage ? 0 : drawState.numCoverageStages());
     73 
     74     size_t newKeyLength = KeyLength(numEffects);
     75     bool allocChanged;
     76     desc->fKey.reset(newKeyLength, SkAutoMalloc::kAlloc_OnShrink, &allocChanged);
     77     if (allocChanged || !desc->fInitialized) {
     78         // make sure any padding in the header is zero if we we haven't used this allocation before.
     79         memset(desc->header(), 0, kHeaderSize);
     80     }
     81     // write the key length
     82     *desc->atOffset<uint32_t, kLengthOffset>() = newKeyLength;
     83 
     84     KeyHeader* header = desc->header();
     85     EffectKey* effectKeys = desc->effectKeys();
     86 
     87     int currEffectKey = 0;
     88     bool readsDst = false;
     89     bool readFragPosition = false;
     90     if (!skipColor) {
     91         for (int s = 0; s < drawState.numColorStages(); ++s) {
     92             effectKeys[currEffectKey++] =
     93                 get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(),
     94                                          requiresLocalCoordAttrib, &readsDst, &readFragPosition);
     95         }
     96     }
     97     if (!skipCoverage) {
     98         for (int s = 0; s < drawState.numCoverageStages(); ++s) {
     99             effectKeys[currEffectKey++] =
    100                 get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(),
    101                                          requiresLocalCoordAttrib, &readsDst, &readFragPosition);
    102         }
    103     }
    104 
    105     header->fEmitsPointSize = isPoints;
    106     header->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
    107 
    108     // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
    109     // other than pass through values from the VS to the FS anyway).
    110 #if GR_GL_EXPERIMENTAL_GS
    111 #if 0
    112     header->fExperimentalGS = gpu->caps().geometryShaderSupport();
    113 #else
    114     header->fExperimentalGS = false;
    115 #endif
    116 #endif
    117     if (colorIsTransBlack) {
    118         header->fColorInput = kTransBlack_ColorInput;
    119     } else if (colorIsSolidWhite) {
    120         header->fColorInput = kSolidWhite_ColorInput;
    121     } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
    122         header->fColorInput = kUniform_ColorInput;
    123     } else {
    124         header->fColorInput = kAttribute_ColorInput;
    125     }
    126 
    127     bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
    128 
    129     if (skipCoverage) {
    130         header->fCoverageInput = kTransBlack_ColorInput;
    131     } else if (covIsSolidWhite) {
    132         header->fCoverageInput = kSolidWhite_ColorInput;
    133     } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
    134         header->fCoverageInput = kUniform_ColorInput;
    135     } else {
    136         header->fCoverageInput = kAttribute_ColorInput;
    137     }
    138 
    139     if (readsDst) {
    140         GrAssert(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport());
    141         const GrTexture* dstCopyTexture = NULL;
    142         if (NULL != dstCopy) {
    143             dstCopyTexture = dstCopy->texture();
    144         }
    145         header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
    146         GrAssert(0 != header->fDstReadKey);
    147     } else {
    148         header->fDstReadKey = 0;
    149     }
    150 
    151     if (readFragPosition) {
    152         header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(),
    153                                                                       gpu->glCaps());
    154     } else {
    155         header->fFragPosKey = 0;
    156     }
    157 
    158     // Record attribute indices
    159     header->fPositionAttributeIndex = drawState.positionAttributeIndex();
    160     header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
    161 
    162     // For constant color and coverage we need an attribute with an index beyond those already set
    163     int availableAttributeIndex = drawState.getVertexAttribCount();
    164     if (requiresColorAttrib) {
    165         header->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
    166     } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) {
    167         GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
    168         header->fColorAttributeIndex = availableAttributeIndex;
    169         availableAttributeIndex++;
    170     } else {
    171         header->fColorAttributeIndex = -1;
    172     }
    173 
    174     if (requiresCoverageAttrib) {
    175         header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
    176     } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) {
    177         GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
    178         header->fCoverageAttributeIndex = availableAttributeIndex;
    179     } else {
    180         header->fCoverageAttributeIndex = -1;
    181     }
    182 
    183     // Here we deal with whether/how we handle color and coverage separately.
    184 
    185     // Set these defaults and then possibly change our mind if there is coverage.
    186     header->fDiscardIfZeroCoverage = false;
    187     header->fCoverageOutput = kModulate_CoverageOutput;
    188 
    189     // If we do have coverage determine whether it matters.
    190     bool separateCoverageFromColor = false;
    191     if (!drawState.isCoverageDrawing() && !skipCoverage &&
    192         (drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
    193         // color filter is applied between color/coverage computation
    194         if (SkXfermode::kDst_Mode != header->fColorFilterXfermode) {
    195             separateCoverageFromColor = true;
    196         }
    197 
    198         // If we're stenciling then we want to discard samples that have zero coverage
    199         if (drawState.getStencil().doesWrite()) {
    200             header->fDiscardIfZeroCoverage = true;
    201             separateCoverageFromColor = true;
    202         }
    203 
    204         if (gpu->caps()->dualSourceBlendingSupport() &&
    205             !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
    206                            GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
    207             if (kZero_GrBlendCoeff == dstCoeff) {
    208                 // write the coverage value to second color
    209                 header->fCoverageOutput =  kSecondaryCoverage_CoverageOutput;
    210                 separateCoverageFromColor = true;
    211             } else if (kSA_GrBlendCoeff == dstCoeff) {
    212                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
    213                 header->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
    214                 separateCoverageFromColor = true;
    215             } else if (kSC_GrBlendCoeff == dstCoeff) {
    216                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
    217                 header->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
    218                 separateCoverageFromColor = true;
    219             }
    220         } else if (readsDst &&
    221                    kOne_GrBlendCoeff == srcCoeff &&
    222                    kZero_GrBlendCoeff == dstCoeff) {
    223             header->fCoverageOutput = kCombineWithDst_CoverageOutput;
    224             separateCoverageFromColor = true;
    225         }
    226     }
    227     if (!skipColor) {
    228         for (int s = 0; s < drawState.numColorStages(); ++s) {
    229             colorStages->push_back(&drawState.getColorStage(s));
    230         }
    231         header->fColorEffectCnt = drawState.numColorStages();
    232     }
    233     if (!skipCoverage) {
    234         SkTArray<const GrEffectStage*, true>* array;
    235         if (separateCoverageFromColor) {
    236             array = coverageStages;
    237             header->fCoverageEffectCnt = drawState.numCoverageStages();
    238         } else {
    239             array = colorStages;
    240             header->fColorEffectCnt += drawState.numCoverageStages();
    241         }
    242         for (int s = 0; s < drawState.numCoverageStages(); ++s) {
    243             array->push_back(&drawState.getCoverageStage(s));
    244         }
    245     }
    246 
    247     *desc->checksum() = 0;
    248     *desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()),
    249                                             newKeyLength);
    250     desc->fInitialized = true;
    251 }
    252 
    253 GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) {
    254     fInitialized = other.fInitialized;
    255     if (fInitialized) {
    256         size_t keyLength = other.keyLength();
    257         fKey.reset(keyLength);
    258         memcpy(fKey.get(), other.fKey.get(), keyLength);
    259     }
    260     return *this;
    261 }
    262