1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrDrawState.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,475 @@ 1.4 +/* 1.5 + * Copyright 2012 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 "GrDrawState.h" 1.12 +#include "GrPaint.h" 1.13 + 1.14 +bool GrDrawState::setIdentityViewMatrix() { 1.15 + if (fColorStages.count() || fCoverageStages.count()) { 1.16 + SkMatrix invVM; 1.17 + if (!fCommon.fViewMatrix.invert(&invVM)) { 1.18 + // sad trombone sound 1.19 + return false; 1.20 + } 1.21 + for (int s = 0; s < fColorStages.count(); ++s) { 1.22 + fColorStages[s].localCoordChange(invVM); 1.23 + } 1.24 + for (int s = 0; s < fCoverageStages.count(); ++s) { 1.25 + fCoverageStages[s].localCoordChange(invVM); 1.26 + } 1.27 + } 1.28 + fCommon.fViewMatrix.reset(); 1.29 + return true; 1.30 +} 1.31 + 1.32 +void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) { 1.33 + SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages()); 1.34 + 1.35 + fColorStages.reset(); 1.36 + fCoverageStages.reset(); 1.37 + 1.38 + for (int i = 0; i < paint.numColorStages(); ++i) { 1.39 + fColorStages.push_back(paint.getColorStage(i)); 1.40 + } 1.41 + 1.42 + for (int i = 0; i < paint.numCoverageStages(); ++i) { 1.43 + fCoverageStages.push_back(paint.getCoverageStage(i)); 1.44 + } 1.45 + 1.46 + this->setRenderTarget(rt); 1.47 + 1.48 + fCommon.fViewMatrix = vm; 1.49 + 1.50 + // These have no equivalent in GrPaint, set them to defaults 1.51 + fCommon.fBlendConstant = 0x0; 1.52 + fCommon.fDrawFace = kBoth_DrawFace; 1.53 + fCommon.fStencilSettings.setDisabled(); 1.54 + this->resetStateFlags(); 1.55 + 1.56 + // Enable the clip bit 1.57 + this->enableState(GrDrawState::kClip_StateBit); 1.58 + 1.59 + this->setColor(paint.getColor()); 1.60 + this->setState(GrDrawState::kDither_StateBit, paint.isDither()); 1.61 + this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias()); 1.62 + 1.63 + this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff()); 1.64 + this->setCoverage(paint.getCoverage()); 1.65 +} 1.66 + 1.67 +//////////////////////////////////////////////////////////////////////////////// 1.68 + 1.69 +static size_t vertex_size(const GrVertexAttrib* attribs, int count) { 1.70 + // this works as long as we're 4 byte-aligned 1.71 +#ifdef SK_DEBUG 1.72 + uint32_t overlapCheck = 0; 1.73 +#endif 1.74 + SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt); 1.75 + size_t size = 0; 1.76 + for (int index = 0; index < count; ++index) { 1.77 + size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType); 1.78 + size += attribSize; 1.79 +#ifdef SK_DEBUG 1.80 + size_t dwordCount = attribSize >> 2; 1.81 + uint32_t mask = (1 << dwordCount)-1; 1.82 + size_t offsetShift = attribs[index].fOffset >> 2; 1.83 + SkASSERT(!(overlapCheck & (mask << offsetShift))); 1.84 + overlapCheck |= (mask << offsetShift); 1.85 +#endif 1.86 + } 1.87 + return size; 1.88 +} 1.89 + 1.90 +size_t GrDrawState::getVertexSize() const { 1.91 + return vertex_size(fCommon.fVAPtr, fCommon.fVACount); 1.92 +} 1.93 + 1.94 +//////////////////////////////////////////////////////////////////////////////// 1.95 + 1.96 +void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) { 1.97 + SkASSERT(count <= kMaxVertexAttribCnt); 1.98 + 1.99 + fCommon.fVAPtr = attribs; 1.100 + fCommon.fVACount = count; 1.101 + 1.102 + // Set all the indices to -1 1.103 + memset(fCommon.fFixedFunctionVertexAttribIndices, 1.104 + 0xff, 1.105 + sizeof(fCommon.fFixedFunctionVertexAttribIndices)); 1.106 +#ifdef SK_DEBUG 1.107 + uint32_t overlapCheck = 0; 1.108 +#endif 1.109 + for (int i = 0; i < count; ++i) { 1.110 + if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) { 1.111 + // The fixed function attribs can only be specified once 1.112 + SkASSERT(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]); 1.113 + SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) == 1.114 + GrVertexAttribTypeVectorCount(attribs[i].fType)); 1.115 + fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i; 1.116 + } 1.117 +#ifdef SK_DEBUG 1.118 + size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2; 1.119 + uint32_t mask = (1 << dwordCount)-1; 1.120 + size_t offsetShift = attribs[i].fOffset >> 2; 1.121 + SkASSERT(!(overlapCheck & (mask << offsetShift))); 1.122 + overlapCheck |= (mask << offsetShift); 1.123 +#endif 1.124 + } 1.125 + // Positions must be specified. 1.126 + SkASSERT(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]); 1.127 +} 1.128 + 1.129 +//////////////////////////////////////////////////////////////////////////////// 1.130 + 1.131 +void GrDrawState::setDefaultVertexAttribs() { 1.132 + static const GrVertexAttrib kPositionAttrib = 1.133 + {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}; 1.134 + 1.135 + fCommon.fVAPtr = &kPositionAttrib; 1.136 + fCommon.fVACount = 1; 1.137 + 1.138 + // set all the fixed function indices to -1 except position. 1.139 + memset(fCommon.fFixedFunctionVertexAttribIndices, 1.140 + 0xff, 1.141 + sizeof(fCommon.fFixedFunctionVertexAttribIndices)); 1.142 + fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0; 1.143 +} 1.144 + 1.145 +//////////////////////////////////////////////////////////////////////////////// 1.146 + 1.147 +bool GrDrawState::validateVertexAttribs() const { 1.148 + // check consistency of effects and attributes 1.149 + GrSLType slTypes[kMaxVertexAttribCnt]; 1.150 + for (int i = 0; i < kMaxVertexAttribCnt; ++i) { 1.151 + slTypes[i] = static_cast<GrSLType>(-1); 1.152 + } 1.153 + int totalStages = fColorStages.count() + fCoverageStages.count(); 1.154 + for (int s = 0; s < totalStages; ++s) { 1.155 + int covIdx = s - fColorStages.count(); 1.156 + const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx]; 1.157 + const GrEffectRef* effect = stage.getEffect(); 1.158 + SkASSERT(NULL != effect); 1.159 + // make sure that any attribute indices have the correct binding type, that the attrib 1.160 + // type and effect's shader lang type are compatible, and that attributes shared by 1.161 + // multiple effects use the same shader lang type. 1.162 + const int* attributeIndices = stage.getVertexAttribIndices(); 1.163 + int numAttributes = stage.getVertexAttribIndexCount(); 1.164 + for (int i = 0; i < numAttributes; ++i) { 1.165 + int attribIndex = attributeIndices[i]; 1.166 + if (attribIndex >= fCommon.fVACount || 1.167 + kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) { 1.168 + return false; 1.169 + } 1.170 + 1.171 + GrSLType effectSLType = (*effect)->vertexAttribType(i); 1.172 + GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType; 1.173 + int slVecCount = GrSLTypeVectorCount(effectSLType); 1.174 + int attribVecCount = GrVertexAttribTypeVectorCount(attribType); 1.175 + if (slVecCount != attribVecCount || 1.176 + (static_cast<GrSLType>(-1) != slTypes[attribIndex] && 1.177 + slTypes[attribIndex] != effectSLType)) { 1.178 + return false; 1.179 + } 1.180 + slTypes[attribIndex] = effectSLType; 1.181 + } 1.182 + } 1.183 + 1.184 + return true; 1.185 +} 1.186 + 1.187 +bool GrDrawState::willEffectReadDstColor() const { 1.188 + if (!this->isColorWriteDisabled()) { 1.189 + for (int s = 0; s < fColorStages.count(); ++s) { 1.190 + if ((*fColorStages[s].getEffect())->willReadDstColor()) { 1.191 + return true; 1.192 + } 1.193 + } 1.194 + } 1.195 + for (int s = 0; s < fCoverageStages.count(); ++s) { 1.196 + if ((*fCoverageStages[s].getEffect())->willReadDstColor()) { 1.197 + return true; 1.198 + } 1.199 + } 1.200 + return false; 1.201 +} 1.202 + 1.203 +//////////////////////////////////////////////////////////////////////////////// 1.204 + 1.205 +bool GrDrawState::srcAlphaWillBeOne() const { 1.206 + uint32_t validComponentFlags; 1.207 + GrColor color; 1.208 + // Check if per-vertex or constant color may have partial alpha 1.209 + if (this->hasColorVertexAttribute()) { 1.210 + validComponentFlags = 0; 1.211 + color = 0; // not strictly necessary but we get false alarms from tools about uninit. 1.212 + } else { 1.213 + validComponentFlags = kRGBA_GrColorComponentFlags; 1.214 + color = this->getColor(); 1.215 + } 1.216 + 1.217 + // Run through the color stages 1.218 + for (int s = 0; s < fColorStages.count(); ++s) { 1.219 + const GrEffectRef* effect = fColorStages[s].getEffect(); 1.220 + (*effect)->getConstantColorComponents(&color, &validComponentFlags); 1.221 + } 1.222 + 1.223 + // Check whether coverage is treated as color. If so we run through the coverage computation. 1.224 + if (this->isCoverageDrawing()) { 1.225 + GrColor coverageColor = this->getCoverageColor(); 1.226 + GrColor oldColor = color; 1.227 + color = 0; 1.228 + for (int c = 0; c < 4; ++c) { 1.229 + if (validComponentFlags & (1 << c)) { 1.230 + U8CPU a = (oldColor >> (c * 8)) & 0xff; 1.231 + U8CPU b = (coverageColor >> (c * 8)) & 0xff; 1.232 + color |= (SkMulDiv255Round(a, b) << (c * 8)); 1.233 + } 1.234 + } 1.235 + for (int s = 0; s < fCoverageStages.count(); ++s) { 1.236 + const GrEffectRef* effect = fCoverageStages[s].getEffect(); 1.237 + (*effect)->getConstantColorComponents(&color, &validComponentFlags); 1.238 + } 1.239 + } 1.240 + return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color); 1.241 +} 1.242 + 1.243 +bool GrDrawState::hasSolidCoverage() const { 1.244 + // If we're drawing coverage directly then coverage is effectively treated as color. 1.245 + if (this->isCoverageDrawing()) { 1.246 + return true; 1.247 + } 1.248 + 1.249 + GrColor coverage; 1.250 + uint32_t validComponentFlags; 1.251 + // Initialize to an unknown starting coverage if per-vertex coverage is specified. 1.252 + if (this->hasCoverageVertexAttribute()) { 1.253 + validComponentFlags = 0; 1.254 + } else { 1.255 + coverage = fCommon.fCoverage; 1.256 + validComponentFlags = kRGBA_GrColorComponentFlags; 1.257 + } 1.258 + 1.259 + // Run through the coverage stages and see if the coverage will be all ones at the end. 1.260 + for (int s = 0; s < fCoverageStages.count(); ++s) { 1.261 + const GrEffectRef* effect = fCoverageStages[s].getEffect(); 1.262 + (*effect)->getConstantColorComponents(&coverage, &validComponentFlags); 1.263 + } 1.264 + return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage); 1.265 +} 1.266 + 1.267 +//////////////////////////////////////////////////////////////////////////////// 1.268 + 1.269 +// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while 1.270 +// others will blend incorrectly. 1.271 +bool GrDrawState::canTweakAlphaForCoverage() const { 1.272 + /* 1.273 + The fractional coverage is f. 1.274 + The src and dst coeffs are Cs and Cd. 1.275 + The dst and src colors are S and D. 1.276 + We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha 1.277 + we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second 1.278 + term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we 1.279 + find that only 1, ISA, and ISC produce the correct destination when applied to S' and D. 1.280 + Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as 1.281 + color by definition. 1.282 + */ 1.283 + return kOne_GrBlendCoeff == fCommon.fDstBlend || 1.284 + kISA_GrBlendCoeff == fCommon.fDstBlend || 1.285 + kISC_GrBlendCoeff == fCommon.fDstBlend || 1.286 + this->isCoverageDrawing(); 1.287 +} 1.288 + 1.289 +GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, 1.290 + GrBlendCoeff* srcCoeff, 1.291 + GrBlendCoeff* dstCoeff) const { 1.292 + 1.293 + GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; 1.294 + if (NULL == srcCoeff) { 1.295 + srcCoeff = &bogusSrcCoeff; 1.296 + } 1.297 + *srcCoeff = this->getSrcBlendCoeff(); 1.298 + 1.299 + if (NULL == dstCoeff) { 1.300 + dstCoeff = &bogusDstCoeff; 1.301 + } 1.302 + *dstCoeff = this->getDstBlendCoeff(); 1.303 + 1.304 + if (this->isColorWriteDisabled()) { 1.305 + *srcCoeff = kZero_GrBlendCoeff; 1.306 + *dstCoeff = kOne_GrBlendCoeff; 1.307 + } 1.308 + 1.309 + bool srcAIsOne = this->srcAlphaWillBeOne(); 1.310 + bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || 1.311 + (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); 1.312 + bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || 1.313 + (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); 1.314 + 1.315 + bool covIsZero = !this->isCoverageDrawing() && 1.316 + !this->hasCoverageVertexAttribute() && 1.317 + 0 == this->getCoverageColor(); 1.318 + // When coeffs are (0,1) there is no reason to draw at all, unless 1.319 + // stenciling is enabled. Having color writes disabled is effectively 1.320 + // (0,1). The same applies when coverage is known to be 0. 1.321 + if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) { 1.322 + if (this->getStencil().doesWrite()) { 1.323 + return kDisableBlend_BlendOptFlag | 1.324 + kEmitCoverage_BlendOptFlag; 1.325 + } else { 1.326 + return kSkipDraw_BlendOptFlag; 1.327 + } 1.328 + } 1.329 + 1.330 + // check for coverage due to constant coverage, per-vertex coverage, or coverage stage 1.331 + bool hasCoverage = forceCoverage || 1.332 + 0xffffffff != this->getCoverageColor() || 1.333 + this->hasCoverageVertexAttribute() || 1.334 + fCoverageStages.count() > 0; 1.335 + 1.336 + // if we don't have coverage we can check whether the dst 1.337 + // has to read at all. If not, we'll disable blending. 1.338 + if (!hasCoverage) { 1.339 + if (dstCoeffIsZero) { 1.340 + if (kOne_GrBlendCoeff == *srcCoeff) { 1.341 + // if there is no coverage and coeffs are (1,0) then we 1.342 + // won't need to read the dst at all, it gets replaced by src 1.343 + return kDisableBlend_BlendOptFlag; 1.344 + } else if (kZero_GrBlendCoeff == *srcCoeff) { 1.345 + // if the op is "clear" then we don't need to emit a color 1.346 + // or blend, just write transparent black into the dst. 1.347 + *srcCoeff = kOne_GrBlendCoeff; 1.348 + *dstCoeff = kZero_GrBlendCoeff; 1.349 + return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag; 1.350 + } 1.351 + } 1.352 + } else if (this->isCoverageDrawing()) { 1.353 + // we have coverage but we aren't distinguishing it from alpha by request. 1.354 + return kCoverageAsAlpha_BlendOptFlag; 1.355 + } else { 1.356 + // check whether coverage can be safely rolled into alpha 1.357 + // of if we can skip color computation and just emit coverage 1.358 + if (this->canTweakAlphaForCoverage()) { 1.359 + return kCoverageAsAlpha_BlendOptFlag; 1.360 + } 1.361 + if (dstCoeffIsZero) { 1.362 + if (kZero_GrBlendCoeff == *srcCoeff) { 1.363 + // the source color is not included in the blend 1.364 + // the dst coeff is effectively zero so blend works out to: 1.365 + // (c)(0)D + (1-c)D = (1-c)D. 1.366 + *dstCoeff = kISA_GrBlendCoeff; 1.367 + return kEmitCoverage_BlendOptFlag; 1.368 + } else if (srcAIsOne) { 1.369 + // the dst coeff is effectively zero so blend works out to: 1.370 + // cS + (c)(0)D + (1-c)D = cS + (1-c)D. 1.371 + // If Sa is 1 then we can replace Sa with c 1.372 + // and set dst coeff to 1-Sa. 1.373 + *dstCoeff = kISA_GrBlendCoeff; 1.374 + return kCoverageAsAlpha_BlendOptFlag; 1.375 + } 1.376 + } else if (dstCoeffIsOne) { 1.377 + // the dst coeff is effectively one so blend works out to: 1.378 + // cS + (c)(1)D + (1-c)D = cS + D. 1.379 + *dstCoeff = kOne_GrBlendCoeff; 1.380 + return kCoverageAsAlpha_BlendOptFlag; 1.381 + } 1.382 + } 1.383 + if (kOne_GrBlendCoeff == *srcCoeff && 1.384 + kZero_GrBlendCoeff == *dstCoeff && 1.385 + this->willEffectReadDstColor()) { 1.386 + // In this case the shader will fully resolve the color, coverage, and dst and we don't 1.387 + // need blending. 1.388 + return kDisableBlend_BlendOptFlag; 1.389 + } 1.390 + return kNone_BlendOpt; 1.391 +} 1.392 + 1.393 +//////////////////////////////////////////////////////////////////////////////// 1.394 + 1.395 +void GrDrawState::AutoViewMatrixRestore::restore() { 1.396 + if (NULL != fDrawState) { 1.397 + SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;) 1.398 + fDrawState->fCommon.fViewMatrix = fViewMatrix; 1.399 + SkASSERT(fDrawState->numColorStages() >= fNumColorStages); 1.400 + int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages; 1.401 + SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages); 1.402 + 1.403 + int i = 0; 1.404 + for (int s = 0; s < fNumColorStages; ++s, ++i) { 1.405 + fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]); 1.406 + } 1.407 + for (int s = 0; s < numCoverageStages; ++s, ++i) { 1.408 + fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]); 1.409 + } 1.410 + fDrawState = NULL; 1.411 + } 1.412 +} 1.413 + 1.414 +void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState, 1.415 + const SkMatrix& preconcatMatrix) { 1.416 + this->restore(); 1.417 + 1.418 + SkASSERT(NULL == fDrawState); 1.419 + if (NULL == drawState || preconcatMatrix.isIdentity()) { 1.420 + return; 1.421 + } 1.422 + fDrawState = drawState; 1.423 + 1.424 + fViewMatrix = drawState->getViewMatrix(); 1.425 + drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix); 1.426 + 1.427 + this->doEffectCoordChanges(preconcatMatrix); 1.428 + SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;) 1.429 +} 1.430 + 1.431 +bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) { 1.432 + this->restore(); 1.433 + 1.434 + if (NULL == drawState) { 1.435 + return false; 1.436 + } 1.437 + 1.438 + if (drawState->getViewMatrix().isIdentity()) { 1.439 + return true; 1.440 + } 1.441 + 1.442 + fViewMatrix = drawState->getViewMatrix(); 1.443 + if (0 == drawState->numTotalStages()) { 1.444 + drawState->fCommon.fViewMatrix.reset(); 1.445 + fDrawState = drawState; 1.446 + fNumColorStages = 0; 1.447 + fSavedCoordChanges.reset(0); 1.448 + SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;) 1.449 + return true; 1.450 + } else { 1.451 + SkMatrix inv; 1.452 + if (!fViewMatrix.invert(&inv)) { 1.453 + return false; 1.454 + } 1.455 + drawState->fCommon.fViewMatrix.reset(); 1.456 + fDrawState = drawState; 1.457 + this->doEffectCoordChanges(inv); 1.458 + SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;) 1.459 + return true; 1.460 + } 1.461 +} 1.462 + 1.463 +void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) { 1.464 + fSavedCoordChanges.reset(fDrawState->numTotalStages()); 1.465 + int i = 0; 1.466 + 1.467 + fNumColorStages = fDrawState->numColorStages(); 1.468 + for (int s = 0; s < fNumColorStages; ++s, ++i) { 1.469 + fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]); 1.470 + fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix); 1.471 + } 1.472 + 1.473 + int numCoverageStages = fDrawState->numCoverageStages(); 1.474 + for (int s = 0; s < numCoverageStages; ++s, ++i) { 1.475 + fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]); 1.476 + fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix); 1.477 + } 1.478 +}