gfx/skia/trunk/src/gpu/gl/GrGLProgramDesc.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial