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 GrGpu::DrawType drawType, 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 // We use vertexshader-less shader programs only when drawing paths. 117 bool hasVertexCode = !(GrGpu::kDrawPath_DrawType == drawType || 118 GrGpu::kDrawPaths_DrawType == drawType); 119 120 if (!skipColor) { 121 for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { 122 effectKeys[currEffectKey++] = 123 get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(), 124 requiresLocalCoordAttrib, &readsDst, &readFragPosition, 125 &hasVertexCode); 126 } 127 } 128 if (!skipCoverage) { 129 for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { 130 effectKeys[currEffectKey++] = 131 get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(), 132 requiresLocalCoordAttrib, &readsDst, &readFragPosition, 133 &hasVertexCode); 134 } 135 } 136 137 header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib; 138 header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType; 139 140 // Currently the experimental GS will only work with triangle prims (and it doesn't do anything 141 // other than pass through values from the VS to the FS anyway). 142 #if GR_GL_EXPERIMENTAL_GS 143 #if 0 144 header->fExperimentalGS = gpu->caps().geometryShaderSupport(); 145 #else 146 header->fExperimentalGS = false; 147 #endif 148 #endif 149 bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport(); 150 151 if (colorIsTransBlack) { 152 header->fColorInput = kTransBlack_ColorInput; 153 } else if (colorIsSolidWhite) { 154 header->fColorInput = kSolidWhite_ColorInput; 155 } else if (defaultToUniformInputs && !requiresColorAttrib) { 156 header->fColorInput = kUniform_ColorInput; 157 } else { 158 header->fColorInput = kAttribute_ColorInput; 159 header->fHasVertexCode = true; 160 } 161 162 bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor(); 163 164 if (skipCoverage) { 165 header->fCoverageInput = kTransBlack_ColorInput; 166 } else if (covIsSolidWhite || !inputCoverageIsUsed) { 167 header->fCoverageInput = kSolidWhite_ColorInput; 168 } else if (defaultToUniformInputs && !requiresCoverageAttrib) { 169 header->fCoverageInput = kUniform_ColorInput; 170 } else { 171 header->fCoverageInput = kAttribute_ColorInput; 172 header->fHasVertexCode = true; 173 } 174 175 if (readsDst) { 176 SkASSERT(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport()); 177 const GrTexture* dstCopyTexture = NULL; 178 if (NULL != dstCopy) { 179 dstCopyTexture = dstCopy->texture(); 180 } 181 header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps()); 182 SkASSERT(0 != header->fDstReadKey); 183 } else { 184 header->fDstReadKey = 0; 185 } 186 187 if (readFragPosition) { 188 header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(), 189 gpu->glCaps()); 190 } else { 191 header->fFragPosKey = 0; 192 } 193 194 // Record attribute indices 195 header->fPositionAttributeIndex = drawState.positionAttributeIndex(); 196 header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex(); 197 198 // For constant color and coverage we need an attribute with an index beyond those already set 199 int availableAttributeIndex = drawState.getVertexAttribCount(); 200 if (requiresColorAttrib) { 201 header->fColorAttributeIndex = drawState.colorVertexAttributeIndex(); 202 } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) { 203 SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); 204 header->fColorAttributeIndex = availableAttributeIndex; 205 availableAttributeIndex++; 206 } else { 207 header->fColorAttributeIndex = -1; 208 } 209 210 if (requiresCoverageAttrib) { 211 header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex(); 212 } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) { 213 SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); 214 header->fCoverageAttributeIndex = availableAttributeIndex; 215 } else { 216 header->fCoverageAttributeIndex = -1; 217 } 218 219 // Here we deal with whether/how we handle color and coverage separately. 220 221 // Set this default and then possibly change our mind if there is coverage. 222 header->fCoverageOutput = kModulate_CoverageOutput; 223 224 // If we do have coverage determine whether it matters. 225 bool separateCoverageFromColor = false; 226 if (!drawState.isCoverageDrawing() && !skipCoverage && 227 (drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) { 228 229 if (gpu->caps()->dualSourceBlendingSupport() && 230 !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag | 231 GrDrawState::kCoverageAsAlpha_BlendOptFlag))) { 232 if (kZero_GrBlendCoeff == dstCoeff) { 233 // write the coverage value to second color 234 header->fCoverageOutput = kSecondaryCoverage_CoverageOutput; 235 separateCoverageFromColor = true; 236 } else if (kSA_GrBlendCoeff == dstCoeff) { 237 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. 238 header->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput; 239 separateCoverageFromColor = true; 240 } else if (kSC_GrBlendCoeff == dstCoeff) { 241 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. 242 header->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput; 243 separateCoverageFromColor = true; 244 } 245 } else if (readsDst && 246 kOne_GrBlendCoeff == srcCoeff && 247 kZero_GrBlendCoeff == dstCoeff) { 248 header->fCoverageOutput = kCombineWithDst_CoverageOutput; 249 separateCoverageFromColor = true; 250 } 251 } 252 if (!skipColor) { 253 for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { 254 colorStages->push_back(&drawState.getColorStage(s)); 255 } 256 } 257 if (!skipCoverage) { 258 SkTArray<const GrEffectStage*, true>* array; 259 if (separateCoverageFromColor) { 260 array = coverageStages; 261 } else { 262 array = colorStages; 263 } 264 for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { 265 array->push_back(&drawState.getCoverageStage(s)); 266 } 267 } 268 header->fColorEffectCnt = colorStages->count(); 269 header->fCoverageEffectCnt = coverageStages->count(); 270 271 *desc->checksum() = 0; 272 *desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()), 273 newKeyLength); 274 desc->fInitialized = true; 275 } 276 277 GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) { 278 fInitialized = other.fInitialized; 279 if (fInitialized) { 280 size_t keyLength = other.keyLength(); 281 fKey.reset(keyLength); 282 memcpy(fKey.get(), other.fKey.get(), keyLength); 283 } 284 return *this; 285 } 286