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 , fGpuTraceMarkerCount(0) { 93 SkASSERT(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 #ifdef SK_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 SkASSERT(1 == fGeoSrcStateStack.count()); 111 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back()); 112 SkASSERT(kNone_GeometrySrcType == geoSrc.fIndexSrc); 113 SkASSERT(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 SkASSERT(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 SkASSERT(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 SkASSERT(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 #ifdef SK_DEBUG 243 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 244 #endif 245 break; 246 default: 247 SkFAIL("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 #ifdef SK_DEBUG 266 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 267 #endif 268 break; 269 default: 270 SkFAIL("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 #ifdef SK_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 SkASSERT(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 #ifdef SK_DEBUG 353 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 354 int maxVertex = startVertex + vertexCount; 355 int maxValidVertex; 356 switch (geoSrc.fVertexSrc) { 357 case kNone_GeometrySrcType: 358 SkFAIL("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 = static_cast<int>(geoSrc.fVertexBuffer->gpuMemorySize() / geoSrc.fVertexSize); 365 break; 366 } 367 if (maxVertex > maxValidVertex) { 368 SkFAIL("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 SkFAIL("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 = static_cast<int>(geoSrc.fIndexBuffer->gpuMemorySize() / sizeof(uint16_t)); 382 break; 383 } 384 if (maxIndex > maxValidIndex) { 385 SkFAIL("Index reads outside valid index range."); 386 } 387 } 388 389 SkASSERT(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 SkASSERT(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 SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget()); 405 } 406 } 407 408 SkASSERT(drawState.validateVertexAttribs()); 409 #endif 410 if (NULL == drawState.getRenderTarget()) { 411 return false; 412 } 413 return true; 414 } 415 416 bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) { 417 if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) { 418 return true; 419 } 420 GrRenderTarget* rt = this->drawState()->getRenderTarget(); 421 SkIRect copyRect; 422 const GrClipData* clip = this->getClip(); 423 clip->getConservativeBounds(rt, ©Rect); 424 425 if (NULL != drawBounds) { 426 SkIRect drawIBounds; 427 drawBounds->roundOut(&drawIBounds); 428 if (!copyRect.intersect(drawIBounds)) { 429 #ifdef SK_DEBUG 430 GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n"); 431 #endif 432 return false; 433 } 434 } else { 435 #ifdef SK_DEBUG 436 //GrPrintf("No dev bounds when dst copy is made.\n"); 437 #endif 438 } 439 440 // MSAA consideration: When there is support for reading MSAA samples in the shader we could 441 // have per-sample dst values by making the copy multisampled. 442 GrTextureDesc desc; 443 this->initCopySurfaceDstDesc(rt, &desc); 444 desc.fWidth = copyRect.width(); 445 desc.fHeight = copyRect.height(); 446 447 GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch); 448 449 if (NULL == ast.texture()) { 450 GrPrintf("Failed to create temporary copy of destination texture.\n"); 451 return false; 452 } 453 SkIPoint dstPoint = {0, 0}; 454 if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) { 455 dstCopy->setTexture(ast.texture()); 456 dstCopy->setOffset(copyRect.fLeft, copyRect.fTop); 457 return true; 458 } else { 459 return false; 460 } 461 } 462 463 void GrDrawTarget::drawIndexed(GrPrimitiveType type, 464 int startVertex, 465 int startIndex, 466 int vertexCount, 467 int indexCount, 468 const SkRect* devBounds) { 469 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) { 470 DrawInfo info; 471 info.fPrimitiveType = type; 472 info.fStartVertex = startVertex; 473 info.fStartIndex = startIndex; 474 info.fVertexCount = vertexCount; 475 info.fIndexCount = indexCount; 476 477 info.fInstanceCount = 0; 478 info.fVerticesPerInstance = 0; 479 info.fIndicesPerInstance = 0; 480 481 if (NULL != devBounds) { 482 info.setDevBounds(*devBounds); 483 } 484 // TODO: We should continue with incorrect blending. 485 if (!this->setupDstReadIfNecessary(&info)) { 486 return; 487 } 488 this->onDraw(info); 489 } 490 } 491 492 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type, 493 int startVertex, 494 int vertexCount, 495 const SkRect* devBounds) { 496 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) { 497 DrawInfo info; 498 info.fPrimitiveType = type; 499 info.fStartVertex = startVertex; 500 info.fStartIndex = 0; 501 info.fVertexCount = vertexCount; 502 info.fIndexCount = 0; 503 504 info.fInstanceCount = 0; 505 info.fVerticesPerInstance = 0; 506 info.fIndicesPerInstance = 0; 507 508 if (NULL != devBounds) { 509 info.setDevBounds(*devBounds); 510 } 511 // TODO: We should continue with incorrect blending. 512 if (!this->setupDstReadIfNecessary(&info)) { 513 return; 514 } 515 this->onDraw(info); 516 } 517 } 518 519 void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) { 520 // TODO: extract portions of checkDraw that are relevant to path stenciling. 521 SkASSERT(NULL != path); 522 SkASSERT(this->caps()->pathRenderingSupport()); 523 SkASSERT(!SkPath::IsInverseFillType(fill)); 524 this->onStencilPath(path, fill); 525 } 526 527 void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) { 528 // TODO: extract portions of checkDraw that are relevant to path rendering. 529 SkASSERT(NULL != path); 530 SkASSERT(this->caps()->pathRenderingSupport()); 531 const GrDrawState* drawState = &getDrawState(); 532 533 SkRect devBounds; 534 if (SkPath::IsInverseFillType(fill)) { 535 devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()), 536 SkIntToScalar(drawState->getRenderTarget()->height())); 537 } else { 538 devBounds = path->getBounds(); 539 } 540 SkMatrix viewM = drawState->getViewMatrix(); 541 viewM.mapRect(&devBounds); 542 543 GrDeviceCoordTexture dstCopy; 544 if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) { 545 return; 546 } 547 548 this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL); 549 } 550 551 void GrDrawTarget::drawPaths(int pathCount, const GrPath** paths, 552 const SkMatrix* transforms, 553 SkPath::FillType fill, SkStrokeRec::Style stroke) { 554 SkASSERT(pathCount > 0); 555 SkASSERT(NULL != paths); 556 SkASSERT(NULL != paths[0]); 557 SkASSERT(this->caps()->pathRenderingSupport()); 558 SkASSERT(!SkPath::IsInverseFillType(fill)); 559 560 const GrDrawState* drawState = &getDrawState(); 561 562 SkRect devBounds; 563 for (int i = 0; i < pathCount; ++i) { 564 SkRect mappedPathBounds; 565 transforms[i].mapRect(&mappedPathBounds, paths[i]->getBounds()); 566 devBounds.join(mappedPathBounds); 567 } 568 569 SkMatrix viewM = drawState->getViewMatrix(); 570 viewM.mapRect(&devBounds); 571 572 GrDeviceCoordTexture dstCopy; 573 if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) { 574 return; 575 } 576 577 this->onDrawPaths(pathCount, paths, transforms, fill, stroke, 578 dstCopy.texture() ? &dstCopy : NULL); 579 } 580 581 typedef GrTraceMarkerSet::Iter TMIter; 582 void GrDrawTarget::saveActiveTraceMarkers() { 583 if (this->caps()->gpuTracingSupport()) { 584 SkASSERT(0 == fStoredTraceMarkers.count()); 585 fStoredTraceMarkers.addSet(fActiveTraceMarkers); 586 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 587 this->removeGpuTraceMarker(&(*iter)); 588 } 589 } 590 } 591 592 void GrDrawTarget::restoreActiveTraceMarkers() { 593 if (this->caps()->gpuTracingSupport()) { 594 SkASSERT(0 == fActiveTraceMarkers.count()); 595 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 596 this->addGpuTraceMarker(&(*iter)); 597 } 598 for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) { 599 this->fStoredTraceMarkers.remove(*iter); 600 } 601 } 602 } 603 604 void GrDrawTarget::addGpuTraceMarker(const GrGpuTraceMarker* marker) { 605 if (this->caps()->gpuTracingSupport()) { 606 SkASSERT(fGpuTraceMarkerCount >= 0); 607 this->fActiveTraceMarkers.add(*marker); 608 this->didAddGpuTraceMarker(); 609 ++fGpuTraceMarkerCount; 610 } 611 } 612 613 void GrDrawTarget::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { 614 if (this->caps()->gpuTracingSupport()) { 615 SkASSERT(fGpuTraceMarkerCount >= 1); 616 this->fActiveTraceMarkers.remove(*marker); 617 this->didRemoveGpuTraceMarker(); 618 --fGpuTraceMarkerCount; 619 } 620 } 621 622 //////////////////////////////////////////////////////////////////////////////// 623 624 bool GrDrawTarget::willUseHWAALines() const { 625 // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth 626 // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when 627 // our alpha is 0xff and tweaking the color for partial coverage is OK 628 if (!this->caps()->hwAALineSupport() || 629 !this->getDrawState().isHWAntialiasState()) { 630 return false; 631 } 632 GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts(); 633 return (GrDrawState::kDisableBlend_BlendOptFlag & opts) && 634 (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts); 635 } 636 637 bool GrDrawTarget::canApplyCoverage() const { 638 // we can correctly apply coverage if a) we have dual source blending 639 // or b) one of our blend optimizations applies. 640 return this->caps()->dualSourceBlendingSupport() || 641 GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true); 642 } 643 644 //////////////////////////////////////////////////////////////////////////////// 645 646 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type, 647 int instanceCount, 648 int verticesPerInstance, 649 int indicesPerInstance, 650 const SkRect* devBounds) { 651 if (!verticesPerInstance || !indicesPerInstance) { 652 return; 653 } 654 655 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance; 656 if (!maxInstancesPerDraw) { 657 return; 658 } 659 660 DrawInfo info; 661 info.fPrimitiveType = type; 662 info.fStartIndex = 0; 663 info.fStartVertex = 0; 664 info.fIndicesPerInstance = indicesPerInstance; 665 info.fVerticesPerInstance = verticesPerInstance; 666 667 // Set the same bounds for all the draws. 668 if (NULL != devBounds) { 669 info.setDevBounds(*devBounds); 670 } 671 // TODO: We should continue with incorrect blending. 672 if (!this->setupDstReadIfNecessary(&info)) { 673 return; 674 } 675 676 while (instanceCount) { 677 info.fInstanceCount = SkTMin(instanceCount, maxInstancesPerDraw); 678 info.fVertexCount = info.fInstanceCount * verticesPerInstance; 679 info.fIndexCount = info.fInstanceCount * indicesPerInstance; 680 681 if (this->checkDraw(type, 682 info.fStartVertex, 683 info.fStartIndex, 684 info.fVertexCount, 685 info.fIndexCount)) { 686 this->onDraw(info); 687 } 688 info.fStartVertex += info.fVertexCount; 689 instanceCount -= info.fInstanceCount; 690 } 691 } 692 693 //////////////////////////////////////////////////////////////////////////////// 694 695 namespace { 696 697 // position + (optional) texture coord 698 extern const GrVertexAttrib gBWRectPosUVAttribs[] = { 699 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 700 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding} 701 }; 702 703 void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) { 704 if (hasUVs) { 705 drawState->setVertexAttribs<gBWRectPosUVAttribs>(2); 706 } else { 707 drawState->setVertexAttribs<gBWRectPosUVAttribs>(1); 708 } 709 } 710 711 }; 712 713 void GrDrawTarget::onDrawRect(const SkRect& rect, 714 const SkMatrix* matrix, 715 const SkRect* localRect, 716 const SkMatrix* localMatrix) { 717 718 GrDrawState::AutoViewMatrixRestore avmr; 719 if (NULL != matrix) { 720 avmr.set(this->drawState(), *matrix); 721 } 722 723 set_vertex_attributes(this->drawState(), NULL != localRect); 724 725 AutoReleaseGeometry geo(this, 4, 0); 726 if (!geo.succeeded()) { 727 GrPrintf("Failed to get space for vertices!\n"); 728 return; 729 } 730 731 size_t vsize = this->drawState()->getVertexSize(); 732 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); 733 if (NULL != localRect) { 734 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + 735 sizeof(SkPoint)); 736 coords->setRectFan(localRect->fLeft, localRect->fTop, 737 localRect->fRight, localRect->fBottom, 738 vsize); 739 if (NULL != localMatrix) { 740 localMatrix->mapPointsWithStride(coords, vsize, 4); 741 } 742 } 743 SkRect bounds; 744 this->getDrawState().getViewMatrix().mapRect(&bounds, rect); 745 746 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, &bounds); 747 } 748 749 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) { 750 } 751 752 //////////////////////////////////////////////////////////////////////////////// 753 754 GrDrawTarget::AutoStateRestore::AutoStateRestore() { 755 fDrawTarget = NULL; 756 } 757 758 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target, 759 ASRInit init, 760 const SkMatrix* vm) { 761 fDrawTarget = NULL; 762 this->set(target, init, vm); 763 } 764 765 GrDrawTarget::AutoStateRestore::~AutoStateRestore() { 766 if (NULL != fDrawTarget) { 767 fDrawTarget->setDrawState(fSavedState); 768 fSavedState->unref(); 769 } 770 } 771 772 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) { 773 SkASSERT(NULL == fDrawTarget); 774 fDrawTarget = target; 775 fSavedState = target->drawState(); 776 SkASSERT(fSavedState); 777 fSavedState->ref(); 778 if (kReset_ASRInit == init) { 779 if (NULL == vm) { 780 // calls the default cons 781 fTempState.init(); 782 } else { 783 SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm)); 784 } 785 } else { 786 SkASSERT(kPreserve_ASRInit == init); 787 if (NULL == vm) { 788 fTempState.set(*fSavedState); 789 } else { 790 SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm)); 791 } 792 } 793 target->setDrawState(fTempState.get()); 794 } 795 796 bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) { 797 SkASSERT(NULL == fDrawTarget); 798 fDrawTarget = target; 799 fSavedState = target->drawState(); 800 SkASSERT(fSavedState); 801 fSavedState->ref(); 802 if (kReset_ASRInit == init) { 803 // calls the default cons 804 fTempState.init(); 805 } else { 806 SkASSERT(kPreserve_ASRInit == init); 807 // calls the copy cons 808 fTempState.set(*fSavedState); 809 if (!fTempState.get()->setIdentityViewMatrix()) { 810 // let go of any resources held by the temp 811 fTempState.get()->reset(); 812 fDrawTarget = NULL; 813 fSavedState->unref(); 814 fSavedState = NULL; 815 return false; 816 } 817 } 818 target->setDrawState(fTempState.get()); 819 return true; 820 } 821 822 //////////////////////////////////////////////////////////////////////////////// 823 824 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry( 825 GrDrawTarget* target, 826 int vertexCount, 827 int indexCount) { 828 fTarget = NULL; 829 this->set(target, vertexCount, indexCount); 830 } 831 832 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() { 833 fTarget = NULL; 834 } 835 836 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() { 837 this->reset(); 838 } 839 840 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target, 841 int vertexCount, 842 int indexCount) { 843 this->reset(); 844 fTarget = target; 845 bool success = true; 846 if (NULL != fTarget) { 847 fTarget = target; 848 success = target->reserveVertexAndIndexSpace(vertexCount, 849 indexCount, 850 &fVertices, 851 &fIndices); 852 if (!success) { 853 fTarget = NULL; 854 this->reset(); 855 } 856 } 857 SkASSERT(success == (NULL != fTarget)); 858 return success; 859 } 860 861 void GrDrawTarget::AutoReleaseGeometry::reset() { 862 if (NULL != fTarget) { 863 if (NULL != fVertices) { 864 fTarget->resetVertexSource(); 865 } 866 if (NULL != fIndices) { 867 fTarget->resetIndexSource(); 868 } 869 fTarget = NULL; 870 } 871 fVertices = NULL; 872 fIndices = NULL; 873 } 874 875 GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) { 876 fTarget = target; 877 fClip = fTarget->getClip(); 878 fStack.init(); 879 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op); 880 fReplacementClip.fClipStack = fStack.get(); 881 target->setClip(&fReplacementClip); 882 } 883 884 namespace { 885 // returns true if the read/written rect intersects the src/dst and false if not. 886 bool clip_srcrect_and_dstpoint(const GrSurface* dst, 887 const GrSurface* src, 888 const SkIRect& srcRect, 889 const SkIPoint& dstPoint, 890 SkIRect* clippedSrcRect, 891 SkIPoint* clippedDstPoint) { 892 *clippedSrcRect = srcRect; 893 *clippedDstPoint = dstPoint; 894 895 // clip the left edge to src and dst bounds, adjusting dstPoint if necessary 896 if (clippedSrcRect->fLeft < 0) { 897 clippedDstPoint->fX -= clippedSrcRect->fLeft; 898 clippedSrcRect->fLeft = 0; 899 } 900 if (clippedDstPoint->fX < 0) { 901 clippedSrcRect->fLeft -= clippedDstPoint->fX; 902 clippedDstPoint->fX = 0; 903 } 904 905 // clip the top edge to src and dst bounds, adjusting dstPoint if necessary 906 if (clippedSrcRect->fTop < 0) { 907 clippedDstPoint->fY -= clippedSrcRect->fTop; 908 clippedSrcRect->fTop = 0; 909 } 910 if (clippedDstPoint->fY < 0) { 911 clippedSrcRect->fTop -= clippedDstPoint->fY; 912 clippedDstPoint->fY = 0; 913 } 914 915 // clip the right edge to the src and dst bounds. 916 if (clippedSrcRect->fRight > src->width()) { 917 clippedSrcRect->fRight = src->width(); 918 } 919 if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) { 920 clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX; 921 } 922 923 // clip the bottom edge to the src and dst bounds. 924 if (clippedSrcRect->fBottom > src->height()) { 925 clippedSrcRect->fBottom = src->height(); 926 } 927 if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) { 928 clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY; 929 } 930 931 // The above clipping steps may have inverted the rect if it didn't intersect either the src or 932 // dst bounds. 933 return !clippedSrcRect->isEmpty(); 934 } 935 } 936 937 bool GrDrawTarget::copySurface(GrSurface* dst, 938 GrSurface* src, 939 const SkIRect& srcRect, 940 const SkIPoint& dstPoint) { 941 SkASSERT(NULL != dst); 942 SkASSERT(NULL != src); 943 944 SkIRect clippedSrcRect; 945 SkIPoint clippedDstPoint; 946 // If the rect is outside the src or dst then we've already succeeded. 947 if (!clip_srcrect_and_dstpoint(dst, 948 src, 949 srcRect, 950 dstPoint, 951 &clippedSrcRect, 952 &clippedDstPoint)) { 953 SkASSERT(this->canCopySurface(dst, src, srcRect, dstPoint)); 954 return true; 955 } 956 957 bool result = this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 958 SkASSERT(result == this->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint)); 959 return result; 960 } 961 962 bool GrDrawTarget::canCopySurface(GrSurface* dst, 963 GrSurface* src, 964 const SkIRect& srcRect, 965 const SkIPoint& dstPoint) { 966 SkASSERT(NULL != dst); 967 SkASSERT(NULL != src); 968 969 SkIRect clippedSrcRect; 970 SkIPoint clippedDstPoint; 971 // If the rect is outside the src or dst then we're guaranteed success 972 if (!clip_srcrect_and_dstpoint(dst, 973 src, 974 srcRect, 975 dstPoint, 976 &clippedSrcRect, 977 &clippedDstPoint)) { 978 return true; 979 } 980 return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 981 } 982 983 bool GrDrawTarget::onCanCopySurface(GrSurface* dst, 984 GrSurface* src, 985 const SkIRect& srcRect, 986 const SkIPoint& dstPoint) { 987 // Check that the read/write rects are contained within the src/dst bounds. 988 SkASSERT(!srcRect.isEmpty()); 989 SkASSERT(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect)); 990 SkASSERT(dstPoint.fX >= 0 && dstPoint.fY >= 0); 991 SkASSERT(dstPoint.fX + srcRect.width() <= dst->width() && 992 dstPoint.fY + srcRect.height() <= dst->height()); 993 994 return !dst->isSameAs(src) && NULL != dst->asRenderTarget() && NULL != src->asTexture(); 995 } 996 997 bool GrDrawTarget::onCopySurface(GrSurface* dst, 998 GrSurface* src, 999 const SkIRect& srcRect, 1000 const SkIPoint& dstPoint) { 1001 if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) { 1002 return false; 1003 } 1004 1005 GrRenderTarget* rt = dst->asRenderTarget(); 1006 GrTexture* tex = src->asTexture(); 1007 1008 GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit); 1009 this->drawState()->setRenderTarget(rt); 1010 SkMatrix matrix; 1011 matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX), 1012 SkIntToScalar(srcRect.fTop - dstPoint.fY)); 1013 matrix.postIDiv(tex->width(), tex->height()); 1014 this->drawState()->addColorTextureEffect(tex, matrix); 1015 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, 1016 dstPoint.fY, 1017 srcRect.width(), 1018 srcRect.height()); 1019 this->drawSimpleRect(dstRect); 1020 return true; 1021 } 1022 1023 void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) { 1024 // Make the dst of the copy be a render target because the default copySurface draws to the dst. 1025 desc->fOrigin = kDefault_GrSurfaceOrigin; 1026 desc->fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 1027 desc->fConfig = src->config(); 1028 } 1029 1030 /////////////////////////////////////////////////////////////////////////////// 1031 1032 void GrDrawTargetCaps::reset() { 1033 fMipMapSupport = false; 1034 fNPOTTextureTileSupport = false; 1035 fTwoSidedStencilSupport = false; 1036 fStencilWrapOpsSupport = false; 1037 fHWAALineSupport = false; 1038 fShaderDerivativeSupport = false; 1039 fGeometryShaderSupport = false; 1040 fDualSourceBlendingSupport = false; 1041 fPathRenderingSupport = false; 1042 fDstReadInShaderSupport = false; 1043 fDiscardRenderTargetSupport = false; 1044 fReuseScratchTextures = true; 1045 fGpuTracingSupport = false; 1046 1047 fMapBufferFlags = kNone_MapFlags; 1048 1049 fMaxRenderTargetSize = 0; 1050 fMaxTextureSize = 0; 1051 fMaxSampleCount = 0; 1052 1053 memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport)); 1054 memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport)); 1055 } 1056 1057 GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) { 1058 fMipMapSupport = other.fMipMapSupport; 1059 fNPOTTextureTileSupport = other.fNPOTTextureTileSupport; 1060 fTwoSidedStencilSupport = other.fTwoSidedStencilSupport; 1061 fStencilWrapOpsSupport = other.fStencilWrapOpsSupport; 1062 fHWAALineSupport = other.fHWAALineSupport; 1063 fShaderDerivativeSupport = other.fShaderDerivativeSupport; 1064 fGeometryShaderSupport = other.fGeometryShaderSupport; 1065 fDualSourceBlendingSupport = other.fDualSourceBlendingSupport; 1066 fPathRenderingSupport = other.fPathRenderingSupport; 1067 fDstReadInShaderSupport = other.fDstReadInShaderSupport; 1068 fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport; 1069 fReuseScratchTextures = other.fReuseScratchTextures; 1070 fGpuTracingSupport = other.fGpuTracingSupport; 1071 1072 fMapBufferFlags = other.fMapBufferFlags; 1073 1074 fMaxRenderTargetSize = other.fMaxRenderTargetSize; 1075 fMaxTextureSize = other.fMaxTextureSize; 1076 fMaxSampleCount = other.fMaxSampleCount; 1077 1078 memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport)); 1079 memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport)); 1080 1081 return *this; 1082 } 1083 1084 static SkString map_flags_to_string(uint32_t flags) { 1085 SkString str; 1086 if (GrDrawTargetCaps::kNone_MapFlags == flags) { 1087 str = "none"; 1088 } else { 1089 SkASSERT(GrDrawTargetCaps::kCanMap_MapFlag & flags); 1090 SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kCanMap_MapFlag); 1091 str = "can_map"; 1092 1093 if (GrDrawTargetCaps::kSubset_MapFlag & flags) { 1094 str.append(" partial"); 1095 } else { 1096 str.append(" full"); 1097 } 1098 SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kSubset_MapFlag); 1099 } 1100 SkASSERT(0 == flags); // Make sure we handled all the flags. 1101 return str; 1102 } 1103 1104 SkString GrDrawTargetCaps::dump() const { 1105 SkString r; 1106 static const char* gNY[] = {"NO", "YES"}; 1107 r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); 1108 r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); 1109 r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); 1110 r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); 1111 r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); 1112 r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); 1113 r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); 1114 r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]); 1115 r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); 1116 r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); 1117 r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]); 1118 r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); 1119 r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); 1120 r.appendf("Max Texture Size : %d\n", fMaxTextureSize); 1121 r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); 1122 r.appendf("Max Sample Count : %d\n", fMaxSampleCount); 1123 1124 r.appendf("Map Buffer Support : %s\n", map_flags_to_string(fMapBufferFlags).c_str()); 1125 1126 static const char* kConfigNames[] = { 1127 "Unknown", // kUnknown_GrPixelConfig 1128 "Alpha8", // kAlpha_8_GrPixelConfig, 1129 "Index8", // kIndex_8_GrPixelConfig, 1130 "RGB565", // kRGB_565_GrPixelConfig, 1131 "RGBA444", // kRGBA_4444_GrPixelConfig, 1132 "RGBA8888", // kRGBA_8888_GrPixelConfig, 1133 "BGRA8888", // kBGRA_8888_GrPixelConfig, 1134 "ETC1", // kETC1_GrPixelConfig, 1135 "LATC", // kLATC_GrPixelConfig, 1136 }; 1137 GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig); 1138 GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig); 1139 GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig); 1140 GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig); 1141 GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig); 1142 GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); 1143 GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); 1144 GR_STATIC_ASSERT(7 == kETC1_GrPixelConfig); 1145 GR_STATIC_ASSERT(8 == kLATC_GrPixelConfig); 1146 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); 1147 1148 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]); 1149 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]); 1150 1151 for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { 1152 r.appendf("%s is renderable: %s, with MSAA: %s\n", 1153 kConfigNames[i], 1154 gNY[fConfigRenderSupport[i][0]], 1155 gNY[fConfigRenderSupport[i][1]]); 1156 } 1157 1158 SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]); 1159 1160 for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { 1161 r.appendf("%s is uploadable to a texture: %s\n", 1162 kConfigNames[i], 1163 gNY[fConfigTextureSupport[i]]); 1164 } 1165 1166 return r; 1167 } 1168