1 /* 2 * Copyright 2012 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 "GrDrawState.h" 9 10 #include "GrOptDrawState.h" 11 #include "GrPaint.h" 12 13 //////////////////////////////////////////////////////////////////////////////s 14 15 GrOptDrawState* GrDrawState::createOptState(const GrDrawTargetCaps& caps) const { 16 if (NULL == fCachedOptState || caps.getUniqueID() != fCachedCapsID) { 17 GrBlendCoeff srcCoeff; 18 GrBlendCoeff dstCoeff; 19 BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff); 20 fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this, blendFlags, srcCoeff, dstCoeff, caps)); 21 fCachedCapsID = caps.getUniqueID(); 22 } else { 23 #ifdef SK_DEBUG 24 GrBlendCoeff srcCoeff; 25 GrBlendCoeff dstCoeff; 26 BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff); 27 SkASSERT(GrOptDrawState(*this, blendFlags, srcCoeff, dstCoeff, caps) == *fCachedOptState); 28 #endif 29 } 30 fCachedOptState->ref(); 31 return fCachedOptState; 32 } 33 34 //////////////////////////////////////////////////////////////////////////////s 35 36 GrDrawState::CombinedState GrDrawState::CombineIfPossible( 37 const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) { 38 39 if (!a.isEqual(b)) { 40 return kIncompatible_CombinedState; 41 } 42 43 // If the general draw states are equal (from check above) we know hasColorVertexAttribute() 44 // is equivalent for both a and b 45 if (a.hasColorVertexAttribute()) { 46 // If one is opaque and the other is not then the combined state is not opaque. Moreover, 47 // if the opaqueness affects the ability to get color/coverage blending correct then we 48 // don't combine the draw states. 49 bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints); 50 bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints); 51 if (aIsOpaque != bIsOpaque) { 52 const GrDrawState* opaque; 53 const GrDrawState* nonOpaque; 54 if (aIsOpaque) { 55 opaque = &a; 56 nonOpaque = &b; 57 } else { 58 opaque = &b; 59 nonOpaque = &a; 60 } 61 if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) { 62 SkASSERT(!nonOpaque->hasSolidCoverage()); 63 if (!nonOpaque->couldApplyCoverage(caps)) { 64 return kIncompatible_CombinedState; 65 } 66 } 67 return aIsOpaque ? kB_CombinedState : kA_CombinedState; 68 } 69 } 70 return kAOrB_CombinedState; 71 } 72 73 //////////////////////////////////////////////////////////////////////////////s 74 75 GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) 76 : fCachedOptState(NULL) { 77 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;) 78 *this = state; 79 if (!preConcatMatrix.isIdentity()) { 80 if (this->hasGeometryProcessor()) { 81 fGeometryProcessor->localCoordChange(preConcatMatrix); 82 } 83 for (int i = 0; i < this->numColorStages(); ++i) { 84 fColorStages[i].localCoordChange(preConcatMatrix); 85 } 86 for (int i = 0; i < this->numCoverageStages(); ++i) { 87 fCoverageStages[i].localCoordChange(preConcatMatrix); 88 } 89 this->invalidateOptState(); 90 } 91 } 92 93 GrDrawState& GrDrawState::operator=(const GrDrawState& that) { 94 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages()); 95 SkASSERT(!that.fRenderTarget.ownsPendingIO()); 96 SkASSERT(!this->fRenderTarget.ownsPendingIO()); 97 this->setRenderTarget(that.getRenderTarget()); 98 fColor = that.fColor; 99 fViewMatrix = that.fViewMatrix; 100 fSrcBlend = that.fSrcBlend; 101 fDstBlend = that.fDstBlend; 102 fBlendConstant = that.fBlendConstant; 103 fFlagBits = that.fFlagBits; 104 fVACount = that.fVACount; 105 fVAPtr = that.fVAPtr; 106 fVAStride = that.fVAStride; 107 fStencilSettings = that.fStencilSettings; 108 fCoverage = that.fCoverage; 109 fDrawFace = that.fDrawFace; 110 if (that.hasGeometryProcessor()) { 111 fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*that.fGeometryProcessor.get()))); 112 } else { 113 fGeometryProcessor.reset(NULL); 114 } 115 fColorStages = that.fColorStages; 116 fCoverageStages = that.fCoverageStages; 117 118 fHints = that.fHints; 119 120 SkRefCnt_SafeAssign(fCachedOptState, that.fCachedOptState); 121 122 memcpy(fFixedFunctionVertexAttribIndices, 123 that.fFixedFunctionVertexAttribIndices, 124 sizeof(fFixedFunctionVertexAttribIndices)); 125 return *this; 126 } 127 128 void GrDrawState::onReset(const SkMatrix* initialViewMatrix) { 129 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages()); 130 SkASSERT(!fRenderTarget.ownsPendingIO()); 131 132 fGeometryProcessor.reset(NULL); 133 fColorStages.reset(); 134 fCoverageStages.reset(); 135 136 fRenderTarget.reset(); 137 138 this->setDefaultVertexAttribs(); 139 140 fColor = 0xffffffff; 141 if (NULL == initialViewMatrix) { 142 fViewMatrix.reset(); 143 } else { 144 fViewMatrix = *initialViewMatrix; 145 } 146 fSrcBlend = kOne_GrBlendCoeff; 147 fDstBlend = kZero_GrBlendCoeff; 148 fBlendConstant = 0x0; 149 fFlagBits = 0x0; 150 fStencilSettings.setDisabled(); 151 fCoverage = 0xff; 152 fDrawFace = kBoth_DrawFace; 153 154 fHints = 0; 155 156 this->invalidateOptState(); 157 } 158 159 bool GrDrawState::setIdentityViewMatrix() { 160 if (this->numTotalStages()) { 161 SkMatrix invVM; 162 if (!fViewMatrix.invert(&invVM)) { 163 // sad trombone sound 164 return false; 165 } 166 if (this->hasGeometryProcessor()) { 167 fGeometryProcessor->localCoordChange(invVM); 168 } 169 for (int s = 0; s < this->numColorStages(); ++s) { 170 fColorStages[s].localCoordChange(invVM); 171 } 172 for (int s = 0; s < this->numCoverageStages(); ++s) { 173 fCoverageStages[s].localCoordChange(invVM); 174 } 175 } 176 this->invalidateOptState(); 177 fViewMatrix.reset(); 178 return true; 179 } 180 181 void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) { 182 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages()); 183 184 fGeometryProcessor.reset(NULL); 185 fColorStages.reset(); 186 fCoverageStages.reset(); 187 188 for (int i = 0; i < paint.numColorStages(); ++i) { 189 fColorStages.push_back(paint.getColorStage(i)); 190 } 191 192 for (int i = 0; i < paint.numCoverageStages(); ++i) { 193 fCoverageStages.push_back(paint.getCoverageStage(i)); 194 } 195 196 this->setRenderTarget(rt); 197 198 fViewMatrix = vm; 199 200 // These have no equivalent in GrPaint, set them to defaults 201 fBlendConstant = 0x0; 202 fDrawFace = kBoth_DrawFace; 203 fStencilSettings.setDisabled(); 204 this->resetStateFlags(); 205 fHints = 0; 206 207 // Enable the clip bit 208 this->enableState(GrDrawState::kClip_StateBit); 209 210 this->setColor(paint.getColor()); 211 this->setState(GrDrawState::kDither_StateBit, paint.isDither()); 212 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias()); 213 214 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff()); 215 this->setCoverage(paint.getCoverage()); 216 this->invalidateOptState(); 217 } 218 219 //////////////////////////////////////////////////////////////////////////////// 220 221 static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) { 222 // this works as long as we're 4 byte-aligned 223 #ifdef SK_DEBUG 224 uint32_t overlapCheck = 0; 225 SkASSERT(count <= GrRODrawState::kMaxVertexAttribCnt); 226 for (int index = 0; index < count; ++index) { 227 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType); 228 size_t attribOffset = attribs[index].fOffset; 229 SkASSERT(attribOffset + attribSize <= stride); 230 size_t dwordCount = attribSize >> 2; 231 uint32_t mask = (1 << dwordCount)-1; 232 size_t offsetShift = attribOffset >> 2; 233 SkASSERT(!(overlapCheck & (mask << offsetShift))); 234 overlapCheck |= (mask << offsetShift); 235 } 236 #endif 237 } 238 239 //////////////////////////////////////////////////////////////////////////////// 240 241 void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count, 242 size_t stride) { 243 SkASSERT(count <= kMaxVertexAttribCnt); 244 245 fVAPtr = attribs; 246 fVACount = count; 247 fVAStride = stride; 248 validate_vertex_attribs(fVAPtr, fVACount, fVAStride); 249 250 // Set all the indices to -1 251 memset(fFixedFunctionVertexAttribIndices, 252 0xff, 253 sizeof(fFixedFunctionVertexAttribIndices)); 254 #ifdef SK_DEBUG 255 uint32_t overlapCheck = 0; 256 #endif 257 for (int i = 0; i < count; ++i) { 258 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) { 259 // The fixed function attribs can only be specified once 260 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]); 261 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) == 262 GrVertexAttribTypeVectorCount(attribs[i].fType)); 263 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i; 264 } 265 #ifdef SK_DEBUG 266 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2; 267 uint32_t mask = (1 << dwordCount)-1; 268 size_t offsetShift = attribs[i].fOffset >> 2; 269 SkASSERT(!(overlapCheck & (mask << offsetShift))); 270 overlapCheck |= (mask << offsetShift); 271 #endif 272 } 273 this->invalidateOptState(); 274 // Positions must be specified. 275 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]); 276 } 277 278 //////////////////////////////////////////////////////////////////////////////// 279 280 void GrDrawState::setDefaultVertexAttribs() { 281 static const GrVertexAttrib kPositionAttrib = 282 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}; 283 284 fVAPtr = &kPositionAttrib; 285 fVACount = 1; 286 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType); 287 288 // set all the fixed function indices to -1 except position. 289 memset(fFixedFunctionVertexAttribIndices, 290 0xff, 291 sizeof(fFixedFunctionVertexAttribIndices)); 292 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0; 293 this->invalidateOptState(); 294 } 295 296 //////////////////////////////////////////////////////////////////////////////// 297 298 bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const { 299 if (caps.dualSourceBlendingSupport()) { 300 return true; 301 } 302 // we can correctly apply coverage if a) we have dual source blending 303 // or b) one of our blend optimizations applies 304 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color 305 GrBlendCoeff srcCoeff; 306 GrBlendCoeff dstCoeff; 307 BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff); 308 return GrRODrawState::kNone_BlendOpt != flag || 309 (this->willEffectReadDstColor() && 310 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff); 311 } 312 313 ////////////////////////////////////////////////////////////////////////////// 314 315 GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) { 316 SkASSERT(drawState); 317 fDrawState = drawState; 318 fVAPtr = drawState->fVAPtr; 319 fVACount = drawState->fVACount; 320 fVAStride = drawState->fVAStride; 321 fDrawState->setDefaultVertexAttribs(); 322 } 323 324 //////////////////////////////////////////////////////////////////////////////s 325 326 void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) { 327 if (fDrawState) { 328 // See the big comment on the class definition about GPs. 329 if (SK_InvalidUniqueID == fOriginalGPID) { 330 fDrawState->fGeometryProcessor.reset(NULL); 331 } else { 332 SkASSERT(fDrawState->getGeometryProcessor()->getProcessor()->getUniqueID() == 333 fOriginalGPID); 334 fOriginalGPID = SK_InvalidUniqueID; 335 } 336 337 int m = fDrawState->numColorStages() - fColorEffectCnt; 338 SkASSERT(m >= 0); 339 fDrawState->fColorStages.pop_back_n(m); 340 341 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt; 342 SkASSERT(n >= 0); 343 fDrawState->fCoverageStages.pop_back_n(n); 344 if (m + n > 0) { 345 fDrawState->invalidateOptState(); 346 } 347 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;) 348 } 349 fDrawState = ds; 350 if (NULL != ds) { 351 SkASSERT(SK_InvalidUniqueID == fOriginalGPID); 352 if (NULL != ds->getGeometryProcessor()) { 353 fOriginalGPID = ds->getGeometryProcessor()->getProcessor()->getUniqueID(); 354 } 355 fColorEffectCnt = ds->numColorStages(); 356 fCoverageEffectCnt = ds->numCoverageStages(); 357 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;) 358 } 359 } 360 361 //////////////////////////////////////////////////////////////////////////////// 362 363 void GrDrawState::AutoViewMatrixRestore::restore() { 364 if (fDrawState) { 365 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;) 366 fDrawState->fViewMatrix = fViewMatrix; 367 SkASSERT(fDrawState->numColorStages() >= fNumColorStages); 368 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages; 369 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages); 370 371 int i = 0; 372 if (fHasGeometryProcessor) { 373 SkASSERT(fDrawState->hasGeometryProcessor()); 374 fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]); 375 } 376 for (int s = 0; s < fNumColorStages; ++s, ++i) { 377 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]); 378 } 379 for (int s = 0; s < numCoverageStages; ++s, ++i) { 380 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]); 381 } 382 fDrawState->invalidateOptState(); 383 fDrawState = NULL; 384 } 385 } 386 387 void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState, 388 const SkMatrix& preconcatMatrix) { 389 this->restore(); 390 391 SkASSERT(NULL == fDrawState); 392 if (NULL == drawState || preconcatMatrix.isIdentity()) { 393 return; 394 } 395 fDrawState = drawState; 396 397 fViewMatrix = drawState->getViewMatrix(); 398 drawState->fViewMatrix.preConcat(preconcatMatrix); 399 400 this->doEffectCoordChanges(preconcatMatrix); 401 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;) 402 drawState->invalidateOptState(); 403 } 404 405 bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) { 406 this->restore(); 407 408 if (NULL == drawState) { 409 return false; 410 } 411 412 if (drawState->getViewMatrix().isIdentity()) { 413 return true; 414 } 415 416 drawState->invalidateOptState(); 417 fViewMatrix = drawState->getViewMatrix(); 418 if (0 == drawState->numTotalStages()) { 419 drawState->fViewMatrix.reset(); 420 fDrawState = drawState; 421 fHasGeometryProcessor = false; 422 fNumColorStages = 0; 423 fSavedCoordChanges.reset(0); 424 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;) 425 return true; 426 } else { 427 SkMatrix inv; 428 if (!fViewMatrix.invert(&inv)) { 429 return false; 430 } 431 drawState->fViewMatrix.reset(); 432 fDrawState = drawState; 433 this->doEffectCoordChanges(inv); 434 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;) 435 return true; 436 } 437 } 438 439 void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) { 440 fSavedCoordChanges.reset(fDrawState->numTotalStages()); 441 int i = 0; 442 443 fHasGeometryProcessor = false; 444 if (fDrawState->hasGeometryProcessor()) { 445 fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]); 446 fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix); 447 fHasGeometryProcessor = true; 448 } 449 450 fNumColorStages = fDrawState->numColorStages(); 451 for (int s = 0; s < fNumColorStages; ++s, ++i) { 452 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]); 453 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix); 454 } 455 456 int numCoverageStages = fDrawState->numCoverageStages(); 457 for (int s = 0; s < numCoverageStages; ++s, ++i) { 458 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]); 459 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix); 460 } 461 } 462 463 //////////////////////////////////////////////////////////////////////////////// 464 465 void GrDrawState::invalidateOptState() const { 466 SkSafeSetNull(fCachedOptState); 467 } 468 469 //////////////////////////////////////////////////////////////////////////////// 470 471 GrDrawState::~GrDrawState() { 472 SkSafeUnref(fCachedOptState); 473 SkASSERT(0 == fBlockEffectRemovalCnt); 474 } 475 476