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