1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/gl/GrGLProgramDesc.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,282 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "GrGLProgramDesc.h" 1.12 +#include "GrBackendEffectFactory.h" 1.13 +#include "GrDrawEffect.h" 1.14 +#include "GrEffect.h" 1.15 +#include "GrGLShaderBuilder.h" 1.16 +#include "GrGpuGL.h" 1.17 + 1.18 +#include "SkChecksum.h" 1.19 + 1.20 +namespace { 1.21 +inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage, 1.22 + const GrGLCaps& caps, 1.23 + bool useExplicitLocalCoords, 1.24 + bool* setTrueIfReadsDst, 1.25 + bool* setTrueIfReadsPos, 1.26 + bool* setTrueIfHasVertexCode) { 1.27 + const GrEffectRef& effect = *stage.getEffect(); 1.28 + const GrBackendEffectFactory& factory = effect->getFactory(); 1.29 + GrDrawEffect drawEffect(stage, useExplicitLocalCoords); 1.30 + if (effect->willReadDstColor()) { 1.31 + *setTrueIfReadsDst = true; 1.32 + } 1.33 + if (effect->willReadFragmentPosition()) { 1.34 + *setTrueIfReadsPos = true; 1.35 + } 1.36 + if (effect->hasVertexCode()) { 1.37 + *setTrueIfHasVertexCode = true; 1.38 + } 1.39 + return factory.glEffectKey(drawEffect, caps); 1.40 +} 1.41 +} 1.42 +void GrGLProgramDesc::Build(const GrDrawState& drawState, 1.43 + bool isPoints, 1.44 + GrDrawState::BlendOptFlags blendOpts, 1.45 + GrBlendCoeff srcCoeff, 1.46 + GrBlendCoeff dstCoeff, 1.47 + const GrGpuGL* gpu, 1.48 + const GrDeviceCoordTexture* dstCopy, 1.49 + SkTArray<const GrEffectStage*, true>* colorStages, 1.50 + SkTArray<const GrEffectStage*, true>* coverageStages, 1.51 + GrGLProgramDesc* desc) { 1.52 + colorStages->reset(); 1.53 + coverageStages->reset(); 1.54 + 1.55 + // This should already have been caught 1.56 + SkASSERT(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts)); 1.57 + 1.58 + bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); 1.59 + 1.60 + bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag | 1.61 + GrDrawState::kEmitCoverage_BlendOptFlag)); 1.62 + int firstEffectiveColorStage = 0; 1.63 + bool inputColorIsUsed = true; 1.64 + if (!skipColor) { 1.65 + firstEffectiveColorStage = drawState.numColorStages(); 1.66 + while (firstEffectiveColorStage > 0 && inputColorIsUsed) { 1.67 + --firstEffectiveColorStage; 1.68 + const GrEffect* effect = drawState.getColorStage(firstEffectiveColorStage).getEffect()->get(); 1.69 + inputColorIsUsed = effect->willUseInputColor(); 1.70 + } 1.71 + } 1.72 + 1.73 + int firstEffectiveCoverageStage = 0; 1.74 + bool inputCoverageIsUsed = true; 1.75 + if (!skipCoverage) { 1.76 + firstEffectiveCoverageStage = drawState.numCoverageStages(); 1.77 + while (firstEffectiveCoverageStage > 0 && inputCoverageIsUsed) { 1.78 + --firstEffectiveCoverageStage; 1.79 + const GrEffect* effect = drawState.getCoverageStage(firstEffectiveCoverageStage).getEffect()->get(); 1.80 + inputCoverageIsUsed = effect->willUseInputColor(); 1.81 + } 1.82 + } 1.83 + 1.84 + // The descriptor is used as a cache key. Thus when a field of the 1.85 + // descriptor will not affect program generation (because of the attribute 1.86 + // bindings in use or other descriptor field settings) it should be set 1.87 + // to a canonical value to avoid duplicate programs with different keys. 1.88 + 1.89 + bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute(); 1.90 + bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute(); 1.91 + // we only need the local coords if we're actually going to generate effect code 1.92 + bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) && 1.93 + drawState.hasLocalCoordAttribute(); 1.94 + 1.95 + bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); 1.96 + bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) || 1.97 + (!requiresColorAttrib && 0xffffffff == drawState.getColor()) || 1.98 + (!inputColorIsUsed); 1.99 + 1.100 + int numEffects = (skipColor ? 0 : (drawState.numColorStages() - firstEffectiveColorStage)) + 1.101 + (skipCoverage ? 0 : (drawState.numCoverageStages() - firstEffectiveCoverageStage)); 1.102 + 1.103 + size_t newKeyLength = KeyLength(numEffects); 1.104 + bool allocChanged; 1.105 + desc->fKey.reset(newKeyLength, SkAutoMalloc::kAlloc_OnShrink, &allocChanged); 1.106 + if (allocChanged || !desc->fInitialized) { 1.107 + // make sure any padding in the header is zero if we we haven't used this allocation before. 1.108 + memset(desc->header(), 0, kHeaderSize); 1.109 + } 1.110 + // write the key length 1.111 + *desc->atOffset<uint32_t, kLengthOffset>() = SkToU32(newKeyLength); 1.112 + 1.113 + KeyHeader* header = desc->header(); 1.114 + EffectKey* effectKeys = desc->effectKeys(); 1.115 + 1.116 + int currEffectKey = 0; 1.117 + bool readsDst = false; 1.118 + bool readFragPosition = false; 1.119 + bool hasVertexCode = false; 1.120 + if (!skipColor) { 1.121 + for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { 1.122 + effectKeys[currEffectKey++] = 1.123 + get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(), 1.124 + requiresLocalCoordAttrib, &readsDst, &readFragPosition, 1.125 + &hasVertexCode); 1.126 + } 1.127 + } 1.128 + if (!skipCoverage) { 1.129 + for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { 1.130 + effectKeys[currEffectKey++] = 1.131 + get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(), 1.132 + requiresLocalCoordAttrib, &readsDst, &readFragPosition, 1.133 + &hasVertexCode); 1.134 + } 1.135 + } 1.136 + 1.137 + header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib; 1.138 + header->fEmitsPointSize = isPoints; 1.139 + 1.140 + // Currently the experimental GS will only work with triangle prims (and it doesn't do anything 1.141 + // other than pass through values from the VS to the FS anyway). 1.142 +#if GR_GL_EXPERIMENTAL_GS 1.143 +#if 0 1.144 + header->fExperimentalGS = gpu->caps().geometryShaderSupport(); 1.145 +#else 1.146 + header->fExperimentalGS = false; 1.147 +#endif 1.148 +#endif 1.149 + bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport(); 1.150 + 1.151 + if (colorIsTransBlack) { 1.152 + header->fColorInput = kTransBlack_ColorInput; 1.153 + } else if (colorIsSolidWhite) { 1.154 + header->fColorInput = kSolidWhite_ColorInput; 1.155 + } else if (defaultToUniformInputs && !requiresColorAttrib) { 1.156 + header->fColorInput = kUniform_ColorInput; 1.157 + } else { 1.158 + header->fColorInput = kAttribute_ColorInput; 1.159 + header->fHasVertexCode = true; 1.160 + } 1.161 + 1.162 + bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor(); 1.163 + 1.164 + if (skipCoverage) { 1.165 + header->fCoverageInput = kTransBlack_ColorInput; 1.166 + } else if (covIsSolidWhite || !inputCoverageIsUsed) { 1.167 + header->fCoverageInput = kSolidWhite_ColorInput; 1.168 + } else if (defaultToUniformInputs && !requiresCoverageAttrib) { 1.169 + header->fCoverageInput = kUniform_ColorInput; 1.170 + } else { 1.171 + header->fCoverageInput = kAttribute_ColorInput; 1.172 + header->fHasVertexCode = true; 1.173 + } 1.174 + 1.175 + if (readsDst) { 1.176 + SkASSERT(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport()); 1.177 + const GrTexture* dstCopyTexture = NULL; 1.178 + if (NULL != dstCopy) { 1.179 + dstCopyTexture = dstCopy->texture(); 1.180 + } 1.181 + header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps()); 1.182 + SkASSERT(0 != header->fDstReadKey); 1.183 + } else { 1.184 + header->fDstReadKey = 0; 1.185 + } 1.186 + 1.187 + if (readFragPosition) { 1.188 + header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(), 1.189 + gpu->glCaps()); 1.190 + } else { 1.191 + header->fFragPosKey = 0; 1.192 + } 1.193 + 1.194 + // Record attribute indices 1.195 + header->fPositionAttributeIndex = drawState.positionAttributeIndex(); 1.196 + header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex(); 1.197 + 1.198 + // For constant color and coverage we need an attribute with an index beyond those already set 1.199 + int availableAttributeIndex = drawState.getVertexAttribCount(); 1.200 + if (requiresColorAttrib) { 1.201 + header->fColorAttributeIndex = drawState.colorVertexAttributeIndex(); 1.202 + } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) { 1.203 + SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); 1.204 + header->fColorAttributeIndex = availableAttributeIndex; 1.205 + availableAttributeIndex++; 1.206 + } else { 1.207 + header->fColorAttributeIndex = -1; 1.208 + } 1.209 + 1.210 + if (requiresCoverageAttrib) { 1.211 + header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex(); 1.212 + } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) { 1.213 + SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); 1.214 + header->fCoverageAttributeIndex = availableAttributeIndex; 1.215 + } else { 1.216 + header->fCoverageAttributeIndex = -1; 1.217 + } 1.218 + 1.219 + // Here we deal with whether/how we handle color and coverage separately. 1.220 + 1.221 + // Set this default and then possibly change our mind if there is coverage. 1.222 + header->fCoverageOutput = kModulate_CoverageOutput; 1.223 + 1.224 + // If we do have coverage determine whether it matters. 1.225 + bool separateCoverageFromColor = false; 1.226 + if (!drawState.isCoverageDrawing() && !skipCoverage && 1.227 + (drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) { 1.228 + 1.229 + if (gpu->caps()->dualSourceBlendingSupport() && 1.230 + !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag | 1.231 + GrDrawState::kCoverageAsAlpha_BlendOptFlag))) { 1.232 + if (kZero_GrBlendCoeff == dstCoeff) { 1.233 + // write the coverage value to second color 1.234 + header->fCoverageOutput = kSecondaryCoverage_CoverageOutput; 1.235 + separateCoverageFromColor = true; 1.236 + } else if (kSA_GrBlendCoeff == dstCoeff) { 1.237 + // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. 1.238 + header->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput; 1.239 + separateCoverageFromColor = true; 1.240 + } else if (kSC_GrBlendCoeff == dstCoeff) { 1.241 + // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. 1.242 + header->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput; 1.243 + separateCoverageFromColor = true; 1.244 + } 1.245 + } else if (readsDst && 1.246 + kOne_GrBlendCoeff == srcCoeff && 1.247 + kZero_GrBlendCoeff == dstCoeff) { 1.248 + header->fCoverageOutput = kCombineWithDst_CoverageOutput; 1.249 + separateCoverageFromColor = true; 1.250 + } 1.251 + } 1.252 + if (!skipColor) { 1.253 + for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { 1.254 + colorStages->push_back(&drawState.getColorStage(s)); 1.255 + } 1.256 + } 1.257 + if (!skipCoverage) { 1.258 + SkTArray<const GrEffectStage*, true>* array; 1.259 + if (separateCoverageFromColor) { 1.260 + array = coverageStages; 1.261 + } else { 1.262 + array = colorStages; 1.263 + } 1.264 + for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) { 1.265 + array->push_back(&drawState.getCoverageStage(s)); 1.266 + } 1.267 + } 1.268 + header->fColorEffectCnt = colorStages->count(); 1.269 + header->fCoverageEffectCnt = coverageStages->count(); 1.270 + 1.271 + *desc->checksum() = 0; 1.272 + *desc->checksum() = SkChecksum::Compute(reinterpret_cast<uint32_t*>(desc->fKey.get()), 1.273 + newKeyLength); 1.274 + desc->fInitialized = true; 1.275 +} 1.276 + 1.277 +GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) { 1.278 + fInitialized = other.fInitialized; 1.279 + if (fInitialized) { 1.280 + size_t keyLength = other.keyLength(); 1.281 + fKey.reset(keyLength); 1.282 + memcpy(fKey.get(), other.fKey.get(), keyLength); 1.283 + } 1.284 + return *this; 1.285 +}