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