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