1 2 /* 3 * Copyright 2010 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 11 #include "GrDrawTarget.h" 12 #include "GrContext.h" 13 #include "GrDrawTargetCaps.h" 14 #include "GrRenderTarget.h" 15 #include "GrTexture.h" 16 #include "GrVertexBuffer.h" 17 18 #include "SkStrokeRec.h" 19 20 SK_DEFINE_INST_COUNT(GrDrawTarget) 21 22 //////////////////////////////////////////////////////////////////////////////// 23 24 GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) { 25 fPrimitiveType = di.fPrimitiveType; 26 fStartVertex = di.fStartVertex; 27 fStartIndex = di.fStartIndex; 28 fVertexCount = di.fVertexCount; 29 fIndexCount = di.fIndexCount; 30 31 fInstanceCount = di.fInstanceCount; 32 fVerticesPerInstance = di.fVerticesPerInstance; 33 fIndicesPerInstance = di.fIndicesPerInstance; 34 35 if (NULL != di.fDevBounds) { 36 GrAssert(di.fDevBounds == &di.fDevBoundsStorage); 37 fDevBoundsStorage = di.fDevBoundsStorage; 38 fDevBounds = &fDevBoundsStorage; 39 } else { 40 fDevBounds = NULL; 41 } 42 43 fDstCopy = di.fDstCopy; 44 45 return *this; 46 } 47 48 #if GR_DEBUG 49 bool GrDrawTarget::DrawInfo::isInstanced() const { 50 if (fInstanceCount > 0) { 51 GrAssert(0 == fIndexCount % fIndicesPerInstance); 52 GrAssert(0 == fVertexCount % fVerticesPerInstance); 53 GrAssert(fIndexCount / fIndicesPerInstance == fInstanceCount); 54 GrAssert(fVertexCount / fVerticesPerInstance == fInstanceCount); 55 // there is no way to specify a non-zero start index to drawIndexedInstances(). 56 GrAssert(0 == fStartIndex); 57 return true; 58 } else { 59 GrAssert(!fVerticesPerInstance); 60 GrAssert(!fIndicesPerInstance); 61 return false; 62 } 63 } 64 #endif 65 66 void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) { 67 GrAssert(this->isInstanced()); 68 GrAssert(instanceOffset + fInstanceCount >= 0); 69 fInstanceCount += instanceOffset; 70 fVertexCount = fVerticesPerInstance * fInstanceCount; 71 fIndexCount = fIndicesPerInstance * fInstanceCount; 72 } 73 74 void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) { 75 fStartVertex += vertexOffset; 76 GrAssert(fStartVertex >= 0); 77 } 78 79 void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) { 80 GrAssert(this->isIndexed()); 81 fStartIndex += indexOffset; 82 GrAssert(fStartIndex >= 0); 83 } 84 85 //////////////////////////////////////////////////////////////////////////////// 86 87 #define DEBUG_INVAL_BUFFER 0xdeadcafe 88 #define DEBUG_INVAL_START_IDX -1 89 90 GrDrawTarget::GrDrawTarget(GrContext* context) 91 : fClip(NULL) 92 , fContext(context) { 93 GrAssert(NULL != context); 94 95 fDrawState = &fDefaultDrawState; 96 // We assume that fDrawState always owns a ref to the object it points at. 97 fDefaultDrawState.ref(); 98 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back(); 99 #if GR_DEBUG 100 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX; 101 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 102 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX; 103 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 104 #endif 105 geoSrc.fVertexSrc = kNone_GeometrySrcType; 106 geoSrc.fIndexSrc = kNone_GeometrySrcType; 107 } 108 109 GrDrawTarget::~GrDrawTarget() { 110 GrAssert(1 == fGeoSrcStateStack.count()); 111 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back()); 112 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc); 113 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc); 114 fDrawState->unref(); 115 } 116 117 void GrDrawTarget::releaseGeometry() { 118 int popCnt = fGeoSrcStateStack.count() - 1; 119 while (popCnt) { 120 this->popGeometrySource(); 121 --popCnt; 122 } 123 this->resetVertexSource(); 124 this->resetIndexSource(); 125 } 126 127 void GrDrawTarget::setClip(const GrClipData* clip) { 128 clipWillBeSet(clip); 129 fClip = clip; 130 } 131 132 const GrClipData* GrDrawTarget::getClip() const { 133 return fClip; 134 } 135 136 void GrDrawTarget::setDrawState(GrDrawState* drawState) { 137 GrAssert(NULL != fDrawState); 138 if (NULL == drawState) { 139 drawState = &fDefaultDrawState; 140 } 141 if (fDrawState != drawState) { 142 fDrawState->unref(); 143 drawState->ref(); 144 fDrawState = drawState; 145 } 146 } 147 148 bool GrDrawTarget::reserveVertexSpace(size_t vertexSize, 149 int vertexCount, 150 void** vertices) { 151 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 152 bool acquired = false; 153 if (vertexCount > 0) { 154 GrAssert(NULL != vertices); 155 this->releasePreviousVertexSource(); 156 geoSrc.fVertexSrc = kNone_GeometrySrcType; 157 158 acquired = this->onReserveVertexSpace(vertexSize, 159 vertexCount, 160 vertices); 161 } 162 if (acquired) { 163 geoSrc.fVertexSrc = kReserved_GeometrySrcType; 164 geoSrc.fVertexCount = vertexCount; 165 geoSrc.fVertexSize = vertexSize; 166 } else if (NULL != vertices) { 167 *vertices = NULL; 168 } 169 return acquired; 170 } 171 172 bool GrDrawTarget::reserveIndexSpace(int indexCount, 173 void** indices) { 174 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 175 bool acquired = false; 176 if (indexCount > 0) { 177 GrAssert(NULL != indices); 178 this->releasePreviousIndexSource(); 179 geoSrc.fIndexSrc = kNone_GeometrySrcType; 180 181 acquired = this->onReserveIndexSpace(indexCount, indices); 182 } 183 if (acquired) { 184 geoSrc.fIndexSrc = kReserved_GeometrySrcType; 185 geoSrc.fIndexCount = indexCount; 186 } else if (NULL != indices) { 187 *indices = NULL; 188 } 189 return acquired; 190 191 } 192 193 bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount, 194 int indexCount, 195 void** vertices, 196 void** indices) { 197 size_t vertexSize = this->drawState()->getVertexSize(); 198 this->willReserveVertexAndIndexSpace(vertexCount, indexCount); 199 if (vertexCount) { 200 if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) { 201 if (indexCount) { 202 this->resetIndexSource(); 203 } 204 return false; 205 } 206 } 207 if (indexCount) { 208 if (!this->reserveIndexSpace(indexCount, indices)) { 209 if (vertexCount) { 210 this->resetVertexSource(); 211 } 212 return false; 213 } 214 } 215 return true; 216 } 217 218 bool GrDrawTarget::geometryHints(int32_t* vertexCount, 219 int32_t* indexCount) const { 220 if (NULL != vertexCount) { 221 *vertexCount = -1; 222 } 223 if (NULL != indexCount) { 224 *indexCount = -1; 225 } 226 return false; 227 } 228 229 void GrDrawTarget::releasePreviousVertexSource() { 230 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 231 switch (geoSrc.fVertexSrc) { 232 case kNone_GeometrySrcType: 233 break; 234 case kArray_GeometrySrcType: 235 this->releaseVertexArray(); 236 break; 237 case kReserved_GeometrySrcType: 238 this->releaseReservedVertexSpace(); 239 break; 240 case kBuffer_GeometrySrcType: 241 geoSrc.fVertexBuffer->unref(); 242 #if GR_DEBUG 243 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 244 #endif 245 break; 246 default: 247 GrCrash("Unknown Vertex Source Type."); 248 break; 249 } 250 } 251 252 void GrDrawTarget::releasePreviousIndexSource() { 253 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 254 switch (geoSrc.fIndexSrc) { 255 case kNone_GeometrySrcType: // these two don't require 256 break; 257 case kArray_GeometrySrcType: 258 this->releaseIndexArray(); 259 break; 260 case kReserved_GeometrySrcType: 261 this->releaseReservedIndexSpace(); 262 break; 263 case kBuffer_GeometrySrcType: 264 geoSrc.fIndexBuffer->unref(); 265 #if GR_DEBUG 266 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 267 #endif 268 break; 269 default: 270 GrCrash("Unknown Index Source Type."); 271 break; 272 } 273 } 274 275 void GrDrawTarget::setVertexSourceToArray(const void* vertexArray, 276 int vertexCount) { 277 this->releasePreviousVertexSource(); 278 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 279 geoSrc.fVertexSrc = kArray_GeometrySrcType; 280 geoSrc.fVertexSize = this->drawState()->getVertexSize(); 281 geoSrc.fVertexCount = vertexCount; 282 this->onSetVertexSourceToArray(vertexArray, vertexCount); 283 } 284 285 void GrDrawTarget::setIndexSourceToArray(const void* indexArray, 286 int indexCount) { 287 this->releasePreviousIndexSource(); 288 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 289 geoSrc.fIndexSrc = kArray_GeometrySrcType; 290 geoSrc.fIndexCount = indexCount; 291 this->onSetIndexSourceToArray(indexArray, indexCount); 292 } 293 294 void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) { 295 this->releasePreviousVertexSource(); 296 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 297 geoSrc.fVertexSrc = kBuffer_GeometrySrcType; 298 geoSrc.fVertexBuffer = buffer; 299 buffer->ref(); 300 geoSrc.fVertexSize = this->drawState()->getVertexSize(); 301 } 302 303 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) { 304 this->releasePreviousIndexSource(); 305 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 306 geoSrc.fIndexSrc = kBuffer_GeometrySrcType; 307 geoSrc.fIndexBuffer = buffer; 308 buffer->ref(); 309 } 310 311 void GrDrawTarget::resetVertexSource() { 312 this->releasePreviousVertexSource(); 313 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 314 geoSrc.fVertexSrc = kNone_GeometrySrcType; 315 } 316 317 void GrDrawTarget::resetIndexSource() { 318 this->releasePreviousIndexSource(); 319 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 320 geoSrc.fIndexSrc = kNone_GeometrySrcType; 321 } 322 323 void GrDrawTarget::pushGeometrySource() { 324 this->geometrySourceWillPush(); 325 GeometrySrcState& newState = fGeoSrcStateStack.push_back(); 326 newState.fIndexSrc = kNone_GeometrySrcType; 327 newState.fVertexSrc = kNone_GeometrySrcType; 328 #if GR_DEBUG 329 newState.fVertexCount = ~0; 330 newState.fVertexBuffer = (GrVertexBuffer*)~0; 331 newState.fIndexCount = ~0; 332 newState.fIndexBuffer = (GrIndexBuffer*)~0; 333 #endif 334 } 335 336 void GrDrawTarget::popGeometrySource() { 337 // if popping last element then pops are unbalanced with pushes 338 GrAssert(fGeoSrcStateStack.count() > 1); 339 340 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1)); 341 this->releasePreviousVertexSource(); 342 this->releasePreviousIndexSource(); 343 fGeoSrcStateStack.pop_back(); 344 } 345 346 //////////////////////////////////////////////////////////////////////////////// 347 348 bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex, 349 int startIndex, int vertexCount, 350 int indexCount) const { 351 const GrDrawState& drawState = this->getDrawState(); 352 #if GR_DEBUG 353 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 354 int maxVertex = startVertex + vertexCount; 355 int maxValidVertex; 356 switch (geoSrc.fVertexSrc) { 357 case kNone_GeometrySrcType: 358 GrCrash("Attempting to draw without vertex src."); 359 case kReserved_GeometrySrcType: // fallthrough 360 case kArray_GeometrySrcType: 361 maxValidVertex = geoSrc.fVertexCount; 362 break; 363 case kBuffer_GeometrySrcType: 364 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize; 365 break; 366 } 367 if (maxVertex > maxValidVertex) { 368 GrCrash("Drawing outside valid vertex range."); 369 } 370 if (indexCount > 0) { 371 int maxIndex = startIndex + indexCount; 372 int maxValidIndex; 373 switch (geoSrc.fIndexSrc) { 374 case kNone_GeometrySrcType: 375 GrCrash("Attempting to draw indexed geom without index src."); 376 case kReserved_GeometrySrcType: // fallthrough 377 case kArray_GeometrySrcType: 378 maxValidIndex = geoSrc.fIndexCount; 379 break; 380 case kBuffer_GeometrySrcType: 381 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t); 382 break; 383 } 384 if (maxIndex > maxValidIndex) { 385 GrCrash("Index reads outside valid index range."); 386 } 387 } 388 389 GrAssert(NULL != drawState.getRenderTarget()); 390 391 for (int s = 0; s < drawState.numColorStages(); ++s) { 392 const GrEffectRef& effect = *drawState.getColorStage(s).getEffect(); 393 int numTextures = effect->numTextures(); 394 for (int t = 0; t < numTextures; ++t) { 395 GrTexture* texture = effect->texture(t); 396 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget()); 397 } 398 } 399 for (int s = 0; s < drawState.numCoverageStages(); ++s) { 400 const GrEffectRef& effect = *drawState.getCoverageStage(s).getEffect(); 401 int numTextures = effect->numTextures(); 402 for (int t = 0; t < numTextures; ++t) { 403 GrTexture* texture = effect->texture(t); 404 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget()); 405 } 406 } 407 408 GrAssert(drawState.validateVertexAttribs()); 409 #endif 410 if (NULL == drawState.getRenderTarget()) { 411 return false; 412 } 413 return true; 414 } 415 416 bool GrDrawTarget::setupDstReadIfNecessary(DrawInfo* info) { 417 if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) { 418 return true; 419 } 420 GrRenderTarget* rt = this->drawState()->getRenderTarget(); 421 422 const GrClipData* clip = this->getClip(); 423 SkIRect copyRect; 424 clip->getConservativeBounds(this->getDrawState().getRenderTarget(), ©Rect); 425 SkIRect drawIBounds; 426 if (info->getDevIBounds(&drawIBounds)) { 427 if (!copyRect.intersect(drawIBounds)) { 428 #if GR_DEBUG 429 GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n"); 430 #endif 431 return false; 432 } 433 } else { 434 #if GR_DEBUG 435 //GrPrintf("No dev bounds when dst copy is made.\n"); 436 #endif 437 } 438 439 // MSAA consideration: When there is support for reading MSAA samples in the shader we could 440 // have per-sample dst values by making the copy multisampled. 441 GrTextureDesc desc; 442 this->initCopySurfaceDstDesc(rt, &desc); 443 desc.fWidth = copyRect.width(); 444 desc.fHeight = copyRect.height(); 445 446 GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch); 447 448 if (NULL == ast.texture()) { 449 GrPrintf("Failed to create temporary copy of destination texture.\n"); 450 return false; 451 } 452 SkIPoint dstPoint = {0, 0}; 453 if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) { 454 info->fDstCopy.setTexture(ast.texture()); 455 info->fDstCopy.setOffset(copyRect.fLeft, copyRect.fTop); 456 return true; 457 } else { 458 return false; 459 } 460 } 461 462 void GrDrawTarget::drawIndexed(GrPrimitiveType type, 463 int startVertex, 464 int startIndex, 465 int vertexCount, 466 int indexCount, 467 const SkRect* devBounds) { 468 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) { 469 DrawInfo info; 470 info.fPrimitiveType = type; 471 info.fStartVertex = startVertex; 472 info.fStartIndex = startIndex; 473 info.fVertexCount = vertexCount; 474 info.fIndexCount = indexCount; 475 476 info.fInstanceCount = 0; 477 info.fVerticesPerInstance = 0; 478 info.fIndicesPerInstance = 0; 479 480 if (NULL != devBounds) { 481 info.setDevBounds(*devBounds); 482 } 483 // TODO: We should continue with incorrect blending. 484 if (!this->setupDstReadIfNecessary(&info)) { 485 return; 486 } 487 this->onDraw(info); 488 } 489 } 490 491 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type, 492 int startVertex, 493 int vertexCount, 494 const SkRect* devBounds) { 495 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) { 496 DrawInfo info; 497 info.fPrimitiveType = type; 498 info.fStartVertex = startVertex; 499 info.fStartIndex = 0; 500 info.fVertexCount = vertexCount; 501 info.fIndexCount = 0; 502 503 info.fInstanceCount = 0; 504 info.fVerticesPerInstance = 0; 505 info.fIndicesPerInstance = 0; 506 507 if (NULL != devBounds) { 508 info.setDevBounds(*devBounds); 509 } 510 // TODO: We should continue with incorrect blending. 511 if (!this->setupDstReadIfNecessary(&info)) { 512 return; 513 } 514 this->onDraw(info); 515 } 516 } 517 518 void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) { 519 // TODO: extract portions of checkDraw that are relevant to path stenciling. 520 GrAssert(NULL != path); 521 GrAssert(this->caps()->pathStencilingSupport()); 522 GrAssert(!stroke.isHairlineStyle()); 523 GrAssert(!SkPath::IsInverseFillType(fill)); 524 this->onStencilPath(path, stroke, fill); 525 } 526 527 //////////////////////////////////////////////////////////////////////////////// 528 529 bool GrDrawTarget::willUseHWAALines() const { 530 // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth 531 // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when 532 // our alpha is 0xff and tweaking the color for partial coverage is OK 533 if (!this->caps()->hwAALineSupport() || 534 !this->getDrawState().isHWAntialiasState()) { 535 return false; 536 } 537 GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts(); 538 return (GrDrawState::kDisableBlend_BlendOptFlag & opts) && 539 (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts); 540 } 541 542 bool GrDrawTarget::canApplyCoverage() const { 543 // we can correctly apply coverage if a) we have dual source blending 544 // or b) one of our blend optimizations applies. 545 return this->caps()->dualSourceBlendingSupport() || 546 GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true); 547 } 548 549 //////////////////////////////////////////////////////////////////////////////// 550 551 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type, 552 int instanceCount, 553 int verticesPerInstance, 554 int indicesPerInstance, 555 const SkRect* devBounds) { 556 if (!verticesPerInstance || !indicesPerInstance) { 557 return; 558 } 559 560 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance; 561 if (!maxInstancesPerDraw) { 562 return; 563 } 564 565 DrawInfo info; 566 info.fPrimitiveType = type; 567 info.fStartIndex = 0; 568 info.fStartVertex = 0; 569 info.fIndicesPerInstance = indicesPerInstance; 570 info.fVerticesPerInstance = verticesPerInstance; 571 572 // Set the same bounds for all the draws. 573 if (NULL != devBounds) { 574 info.setDevBounds(*devBounds); 575 } 576 // TODO: We should continue with incorrect blending. 577 if (!this->setupDstReadIfNecessary(&info)) { 578 return; 579 } 580 581 while (instanceCount) { 582 info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw); 583 info.fVertexCount = info.fInstanceCount * verticesPerInstance; 584 info.fIndexCount = info.fInstanceCount * indicesPerInstance; 585 586 if (this->checkDraw(type, 587 info.fStartVertex, 588 info.fStartIndex, 589 info.fVertexCount, 590 info.fIndexCount)) { 591 this->onDraw(info); 592 } 593 info.fStartVertex += info.fVertexCount; 594 instanceCount -= info.fInstanceCount; 595 } 596 } 597 598 //////////////////////////////////////////////////////////////////////////////// 599 600 namespace { 601 602 // position + (optional) texture coord 603 extern const GrVertexAttrib gBWRectPosUVAttribs[] = { 604 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 605 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding} 606 }; 607 608 void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) { 609 if (hasUVs) { 610 drawState->setVertexAttribs<gBWRectPosUVAttribs>(2); 611 } else { 612 drawState->setVertexAttribs<gBWRectPosUVAttribs>(1); 613 } 614 } 615 616 }; 617 618 void GrDrawTarget::onDrawRect(const SkRect& rect, 619 const SkMatrix* matrix, 620 const SkRect* localRect, 621 const SkMatrix* localMatrix) { 622 623 GrDrawState::AutoViewMatrixRestore avmr; 624 if (NULL != matrix) { 625 avmr.set(this->drawState(), *matrix); 626 } 627 628 set_vertex_attributes(this->drawState(), NULL != localRect); 629 630 AutoReleaseGeometry geo(this, 4, 0); 631 if (!geo.succeeded()) { 632 GrPrintf("Failed to get space for vertices!\n"); 633 return; 634 } 635 636 size_t vsize = this->drawState()->getVertexSize(); 637 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); 638 if (NULL != localRect) { 639 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + 640 sizeof(GrPoint)); 641 coords->setRectFan(localRect->fLeft, localRect->fTop, 642 localRect->fRight, localRect->fBottom, 643 vsize); 644 if (NULL != localMatrix) { 645 localMatrix->mapPointsWithStride(coords, vsize, 4); 646 } 647 } 648 SkTLazy<SkRect> bounds; 649 if (this->getDrawState().willEffectReadDstColor()) { 650 bounds.init(); 651 this->getDrawState().getViewMatrix().mapRect(bounds.get(), rect); 652 } 653 654 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, bounds.getMaybeNull()); 655 } 656 657 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) { 658 } 659 660 //////////////////////////////////////////////////////////////////////////////// 661 662 GrDrawTarget::AutoStateRestore::AutoStateRestore() { 663 fDrawTarget = NULL; 664 } 665 666 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target, 667 ASRInit init, 668 const SkMatrix* vm) { 669 fDrawTarget = NULL; 670 this->set(target, init, vm); 671 } 672 673 GrDrawTarget::AutoStateRestore::~AutoStateRestore() { 674 if (NULL != fDrawTarget) { 675 fDrawTarget->setDrawState(fSavedState); 676 fSavedState->unref(); 677 } 678 } 679 680 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) { 681 GrAssert(NULL == fDrawTarget); 682 fDrawTarget = target; 683 fSavedState = target->drawState(); 684 GrAssert(fSavedState); 685 fSavedState->ref(); 686 if (kReset_ASRInit == init) { 687 if (NULL == vm) { 688 // calls the default cons 689 fTempState.init(); 690 } else { 691 SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm)); 692 } 693 } else { 694 GrAssert(kPreserve_ASRInit == init); 695 if (NULL == vm) { 696 fTempState.set(*fSavedState); 697 } else { 698 SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm)); 699 } 700 } 701 target->setDrawState(fTempState.get()); 702 } 703 704 bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) { 705 GrAssert(NULL == fDrawTarget); 706 fDrawTarget = target; 707 fSavedState = target->drawState(); 708 GrAssert(fSavedState); 709 fSavedState->ref(); 710 if (kReset_ASRInit == init) { 711 // calls the default cons 712 fTempState.init(); 713 } else { 714 GrAssert(kPreserve_ASRInit == init); 715 // calls the copy cons 716 fTempState.set(*fSavedState); 717 if (!fTempState.get()->setIdentityViewMatrix()) { 718 // let go of any resources held by the temp 719 fTempState.get()->reset(); 720 fDrawTarget = NULL; 721 fSavedState->unref(); 722 fSavedState = NULL; 723 return false; 724 } 725 } 726 target->setDrawState(fTempState.get()); 727 return true; 728 } 729 730 //////////////////////////////////////////////////////////////////////////////// 731 732 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry( 733 GrDrawTarget* target, 734 int vertexCount, 735 int indexCount) { 736 fTarget = NULL; 737 this->set(target, vertexCount, indexCount); 738 } 739 740 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() { 741 fTarget = NULL; 742 } 743 744 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() { 745 this->reset(); 746 } 747 748 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target, 749 int vertexCount, 750 int indexCount) { 751 this->reset(); 752 fTarget = target; 753 bool success = true; 754 if (NULL != fTarget) { 755 fTarget = target; 756 success = target->reserveVertexAndIndexSpace(vertexCount, 757 indexCount, 758 &fVertices, 759 &fIndices); 760 if (!success) { 761 fTarget = NULL; 762 this->reset(); 763 } 764 } 765 GrAssert(success == (NULL != fTarget)); 766 return success; 767 } 768 769 void GrDrawTarget::AutoReleaseGeometry::reset() { 770 if (NULL != fTarget) { 771 if (NULL != fVertices) { 772 fTarget->resetVertexSource(); 773 } 774 if (NULL != fIndices) { 775 fTarget->resetIndexSource(); 776 } 777 fTarget = NULL; 778 } 779 fVertices = NULL; 780 fIndices = NULL; 781 } 782 783 GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) { 784 fTarget = target; 785 fClip = fTarget->getClip(); 786 fStack.init(); 787 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op); 788 fReplacementClip.fClipStack = fStack.get(); 789 target->setClip(&fReplacementClip); 790 } 791 792 namespace { 793 // returns true if the read/written rect intersects the src/dst and false if not. 794 bool clip_srcrect_and_dstpoint(const GrSurface* dst, 795 const GrSurface* src, 796 const SkIRect& srcRect, 797 const SkIPoint& dstPoint, 798 SkIRect* clippedSrcRect, 799 SkIPoint* clippedDstPoint) { 800 *clippedSrcRect = srcRect; 801 *clippedDstPoint = dstPoint; 802 803 // clip the left edge to src and dst bounds, adjusting dstPoint if necessary 804 if (clippedSrcRect->fLeft < 0) { 805 clippedDstPoint->fX -= clippedSrcRect->fLeft; 806 clippedSrcRect->fLeft = 0; 807 } 808 if (clippedDstPoint->fX < 0) { 809 clippedSrcRect->fLeft -= clippedDstPoint->fX; 810 clippedDstPoint->fX = 0; 811 } 812 813 // clip the top edge to src and dst bounds, adjusting dstPoint if necessary 814 if (clippedSrcRect->fTop < 0) { 815 clippedDstPoint->fY -= clippedSrcRect->fTop; 816 clippedSrcRect->fTop = 0; 817 } 818 if (clippedDstPoint->fY < 0) { 819 clippedSrcRect->fTop -= clippedDstPoint->fY; 820 clippedDstPoint->fY = 0; 821 } 822 823 // clip the right edge to the src and dst bounds. 824 if (clippedSrcRect->fRight > src->width()) { 825 clippedSrcRect->fRight = src->width(); 826 } 827 if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) { 828 clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX; 829 } 830 831 // clip the bottom edge to the src and dst bounds. 832 if (clippedSrcRect->fBottom > src->height()) { 833 clippedSrcRect->fBottom = src->height(); 834 } 835 if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) { 836 clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY; 837 } 838 839 // The above clipping steps may have inverted the rect if it didn't intersect either the src or 840 // dst bounds. 841 return !clippedSrcRect->isEmpty(); 842 } 843 } 844 845 bool GrDrawTarget::copySurface(GrSurface* dst, 846 GrSurface* src, 847 const SkIRect& srcRect, 848 const SkIPoint& dstPoint) { 849 GrAssert(NULL != dst); 850 GrAssert(NULL != src); 851 852 SkIRect clippedSrcRect; 853 SkIPoint clippedDstPoint; 854 // If the rect is outside the src or dst then we've already succeeded. 855 if (!clip_srcrect_and_dstpoint(dst, 856 src, 857 srcRect, 858 dstPoint, 859 &clippedSrcRect, 860 &clippedDstPoint)) { 861 GrAssert(this->canCopySurface(dst, src, srcRect, dstPoint)); 862 return true; 863 } 864 865 bool result = this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 866 GrAssert(result == this->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint)); 867 return result; 868 } 869 870 bool GrDrawTarget::canCopySurface(GrSurface* dst, 871 GrSurface* src, 872 const SkIRect& srcRect, 873 const SkIPoint& dstPoint) { 874 GrAssert(NULL != dst); 875 GrAssert(NULL != src); 876 877 SkIRect clippedSrcRect; 878 SkIPoint clippedDstPoint; 879 // If the rect is outside the src or dst then we're guaranteed success 880 if (!clip_srcrect_and_dstpoint(dst, 881 src, 882 srcRect, 883 dstPoint, 884 &clippedSrcRect, 885 &clippedDstPoint)) { 886 return true; 887 } 888 return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 889 } 890 891 bool GrDrawTarget::onCanCopySurface(GrSurface* dst, 892 GrSurface* src, 893 const SkIRect& srcRect, 894 const SkIPoint& dstPoint) { 895 // Check that the read/write rects are contained within the src/dst bounds. 896 GrAssert(!srcRect.isEmpty()); 897 GrAssert(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect)); 898 GrAssert(dstPoint.fX >= 0 && dstPoint.fY >= 0); 899 GrAssert(dstPoint.fX + srcRect.width() <= dst->width() && 900 dstPoint.fY + srcRect.height() <= dst->height()); 901 902 return !dst->isSameAs(src) && NULL != dst->asRenderTarget() && NULL != src->asTexture(); 903 } 904 905 bool GrDrawTarget::onCopySurface(GrSurface* dst, 906 GrSurface* src, 907 const SkIRect& srcRect, 908 const SkIPoint& dstPoint) { 909 if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) { 910 return false; 911 } 912 913 GrRenderTarget* rt = dst->asRenderTarget(); 914 GrTexture* tex = src->asTexture(); 915 916 GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit); 917 this->drawState()->setRenderTarget(rt); 918 SkMatrix matrix; 919 matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX), 920 SkIntToScalar(srcRect.fTop - dstPoint.fY)); 921 matrix.postIDiv(tex->width(), tex->height()); 922 this->drawState()->addColorTextureEffect(tex, matrix); 923 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, 924 dstPoint.fY, 925 srcRect.width(), 926 srcRect.height()); 927 this->drawSimpleRect(dstRect); 928 return true; 929 } 930 931 void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) { 932 // Make the dst of the copy be a render target because the default copySurface draws to the dst. 933 desc->fOrigin = kDefault_GrSurfaceOrigin; 934 desc->fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 935 desc->fConfig = src->config(); 936 } 937 938 /////////////////////////////////////////////////////////////////////////////// 939 940 SK_DEFINE_INST_COUNT(GrDrawTargetCaps) 941 942 void GrDrawTargetCaps::reset() { 943 f8BitPaletteSupport = false; 944 fNPOTTextureTileSupport = false; 945 fTwoSidedStencilSupport = false; 946 fStencilWrapOpsSupport = false; 947 fHWAALineSupport = false; 948 fShaderDerivativeSupport = false; 949 fGeometryShaderSupport = false; 950 fDualSourceBlendingSupport = false; 951 fBufferLockSupport = false; 952 fPathStencilingSupport = false; 953 fDstReadInShaderSupport = false; 954 fReuseScratchTextures = true; 955 956 fMaxRenderTargetSize = 0; 957 fMaxTextureSize = 0; 958 fMaxSampleCount = 0; 959 } 960 961 GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) { 962 f8BitPaletteSupport = other.f8BitPaletteSupport; 963 fNPOTTextureTileSupport = other.fNPOTTextureTileSupport; 964 fTwoSidedStencilSupport = other.fTwoSidedStencilSupport; 965 fStencilWrapOpsSupport = other.fStencilWrapOpsSupport; 966 fHWAALineSupport = other.fHWAALineSupport; 967 fShaderDerivativeSupport = other.fShaderDerivativeSupport; 968 fGeometryShaderSupport = other.fGeometryShaderSupport; 969 fDualSourceBlendingSupport = other.fDualSourceBlendingSupport; 970 fBufferLockSupport = other.fBufferLockSupport; 971 fPathStencilingSupport = other.fPathStencilingSupport; 972 fDstReadInShaderSupport = other.fDstReadInShaderSupport; 973 fReuseScratchTextures = other.fReuseScratchTextures; 974 975 fMaxRenderTargetSize = other.fMaxRenderTargetSize; 976 fMaxTextureSize = other.fMaxTextureSize; 977 fMaxSampleCount = other.fMaxSampleCount; 978 979 return *this; 980 } 981 982 void GrDrawTargetCaps::print() const { 983 static const char* gNY[] = {"NO", "YES"}; 984 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]); 985 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); 986 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); 987 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); 988 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); 989 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); 990 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); 991 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]); 992 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]); 993 GrPrintf("Path Stenciling Support : %s\n", gNY[fPathStencilingSupport]); 994 GrPrintf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); 995 GrPrintf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); 996 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize); 997 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize); 998 GrPrintf("Max Sample Count : %d\n", fMaxSampleCount); 999 } 1000