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 "GrTemplates.h" 17 #include "GrTexture.h" 18 #include "GrVertexBuffer.h" 19 20 #include "SkStrokeRec.h" 21 22 //////////////////////////////////////////////////////////////////////////////// 23 24 GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) { 25 fPrimitiveType = di.fPrimitiveType; 26 fStartVertex = di.fStartVertex; 27 fStartIndex = di.fStartIndex; 28 fVertexCount = di.fVertexCount; 29 fIndexCount = di.fIndexCount; 30 31 fInstanceCount = di.fInstanceCount; 32 fVerticesPerInstance = di.fVerticesPerInstance; 33 fIndicesPerInstance = di.fIndicesPerInstance; 34 35 if (di.fDevBounds) { 36 SkASSERT(di.fDevBounds == &di.fDevBoundsStorage); 37 fDevBoundsStorage = di.fDevBoundsStorage; 38 fDevBounds = &fDevBoundsStorage; 39 } else { 40 fDevBounds = NULL; 41 } 42 43 fDstCopy = di.fDstCopy; 44 45 return *this; 46 } 47 48 #ifdef SK_DEBUG 49 bool GrDrawTarget::DrawInfo::isInstanced() const { 50 if (fInstanceCount > 0) { 51 SkASSERT(0 == fIndexCount % fIndicesPerInstance); 52 SkASSERT(0 == fVertexCount % fVerticesPerInstance); 53 SkASSERT(fIndexCount / fIndicesPerInstance == fInstanceCount); 54 SkASSERT(fVertexCount / fVerticesPerInstance == fInstanceCount); 55 // there is no way to specify a non-zero start index to drawIndexedInstances(). 56 SkASSERT(0 == fStartIndex); 57 return true; 58 } else { 59 SkASSERT(!fVerticesPerInstance); 60 SkASSERT(!fIndicesPerInstance); 61 return false; 62 } 63 } 64 #endif 65 66 void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) { 67 SkASSERT(this->isInstanced()); 68 SkASSERT(instanceOffset + fInstanceCount >= 0); 69 fInstanceCount += instanceOffset; 70 fVertexCount = fVerticesPerInstance * fInstanceCount; 71 fIndexCount = fIndicesPerInstance * fInstanceCount; 72 } 73 74 void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) { 75 fStartVertex += vertexOffset; 76 SkASSERT(fStartVertex >= 0); 77 } 78 79 void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) { 80 SkASSERT(this->isIndexed()); 81 fStartIndex += indexOffset; 82 SkASSERT(fStartIndex >= 0); 83 } 84 85 //////////////////////////////////////////////////////////////////////////////// 86 87 #define DEBUG_INVAL_BUFFER 0xdeadcafe 88 #define DEBUG_INVAL_START_IDX -1 89 90 GrDrawTarget::GrDrawTarget(GrContext* context) 91 : fClip(NULL) 92 , fContext(context) 93 , fGpuTraceMarkerCount(0) { 94 SkASSERT(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 110 GrDrawTarget::~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 118 void 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 128 void GrDrawTarget::setClip(const GrClipData* clip) { 129 clipWillBeSet(clip); 130 fClip = clip; 131 } 132 133 const GrClipData* GrDrawTarget::getClip() const { 134 return fClip; 135 } 136 137 void GrDrawTarget::setDrawState(GrDrawState* drawState) { 138 SkASSERT(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 149 bool 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(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 (vertices) { 168 *vertices = NULL; 169 } 170 return acquired; 171 } 172 173 bool GrDrawTarget::reserveIndexSpace(int indexCount, 174 void** indices) { 175 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 176 bool acquired = false; 177 if (indexCount > 0) { 178 SkASSERT(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 (indices) { 188 *indices = NULL; 189 } 190 return acquired; 191 192 } 193 194 bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount, 195 int indexCount, 196 void** vertices, 197 void** indices) { 198 size_t vertexStride = this->drawState()->getVertexStride(); 199 this->willReserveVertexAndIndexSpace(vertexCount, indexCount); 200 if (vertexCount) { 201 if (!this->reserveVertexSpace(vertexStride, 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 219 bool GrDrawTarget::geometryHints(int32_t* vertexCount, 220 int32_t* indexCount) const { 221 if (vertexCount) { 222 *vertexCount = -1; 223 } 224 if (indexCount) { 225 *indexCount = -1; 226 } 227 return false; 228 } 229 230 void 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 SkFAIL("Unknown Vertex Source Type."); 249 break; 250 } 251 } 252 253 void 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 SkFAIL("Unknown Index Source Type."); 272 break; 273 } 274 } 275 276 void 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()->getVertexStride(); 282 geoSrc.fVertexCount = vertexCount; 283 this->onSetVertexSourceToArray(vertexArray, vertexCount); 284 } 285 286 void 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 295 void 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()->getVertexStride(); 302 } 303 304 void 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 312 void GrDrawTarget::resetVertexSource() { 313 this->releasePreviousVertexSource(); 314 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 315 geoSrc.fVertexSrc = kNone_GeometrySrcType; 316 } 317 318 void GrDrawTarget::resetIndexSource() { 319 this->releasePreviousIndexSource(); 320 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 321 geoSrc.fIndexSrc = kNone_GeometrySrcType; 322 } 323 324 void 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 337 void 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 349 bool 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 SkFAIL("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->gpuMemorySize() / geoSrc.fVertexSize); 366 break; 367 } 368 if (maxVertex > maxValidVertex) { 369 SkFAIL("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 SkFAIL("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->gpuMemorySize() / sizeof(uint16_t)); 383 break; 384 } 385 if (maxIndex > maxValidIndex) { 386 SkFAIL("Index reads outside valid index range."); 387 } 388 } 389 390 SkASSERT(drawState.getRenderTarget()); 391 392 if (drawState.hasGeometryProcessor()) { 393 const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getGeometryProcessor(); 394 int numTextures = gp->numTextures(); 395 for (int t = 0; t < numTextures; ++t) { 396 GrTexture* texture = gp->texture(t); 397 SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget()); 398 } 399 } 400 401 for (int s = 0; s < drawState.numColorStages(); ++s) { 402 const GrProcessor* effect = drawState.getColorStage(s).getProcessor(); 403 int numTextures = effect->numTextures(); 404 for (int t = 0; t < numTextures; ++t) { 405 GrTexture* texture = effect->texture(t); 406 SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget()); 407 } 408 } 409 for (int s = 0; s < drawState.numCoverageStages(); ++s) { 410 const GrProcessor* effect = drawState.getCoverageStage(s).getProcessor(); 411 int numTextures = effect->numTextures(); 412 for (int t = 0; t < numTextures; ++t) { 413 GrTexture* texture = effect->texture(t); 414 SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget()); 415 } 416 } 417 418 SkASSERT(drawState.validateVertexAttribs()); 419 #endif 420 if (NULL == drawState.getRenderTarget()) { 421 return false; 422 } 423 return true; 424 } 425 426 bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) { 427 if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) { 428 return true; 429 } 430 GrRenderTarget* rt = this->drawState()->getRenderTarget(); 431 SkIRect copyRect; 432 const GrClipData* clip = this->getClip(); 433 clip->getConservativeBounds(rt, ©Rect); 434 435 if (drawBounds) { 436 SkIRect drawIBounds; 437 drawBounds->roundOut(&drawIBounds); 438 if (!copyRect.intersect(drawIBounds)) { 439 #ifdef SK_DEBUG 440 GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n"); 441 #endif 442 return false; 443 } 444 } else { 445 #ifdef SK_DEBUG 446 //GrPrintf("No dev bounds when dst copy is made.\n"); 447 #endif 448 } 449 450 // MSAA consideration: When there is support for reading MSAA samples in the shader we could 451 // have per-sample dst values by making the copy multisampled. 452 GrTextureDesc desc; 453 this->initCopySurfaceDstDesc(rt, &desc); 454 desc.fWidth = copyRect.width(); 455 desc.fHeight = copyRect.height(); 456 457 GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch); 458 459 if (NULL == ast.texture()) { 460 GrPrintf("Failed to create temporary copy of destination texture.\n"); 461 return false; 462 } 463 SkIPoint dstPoint = {0, 0}; 464 if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) { 465 dstCopy->setTexture(ast.texture()); 466 dstCopy->setOffset(copyRect.fLeft, copyRect.fTop); 467 return true; 468 } else { 469 return false; 470 } 471 } 472 473 void GrDrawTarget::drawIndexed(GrPrimitiveType type, 474 int startVertex, 475 int startIndex, 476 int vertexCount, 477 int indexCount, 478 const SkRect* devBounds) { 479 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) { 480 DrawInfo info; 481 info.fPrimitiveType = type; 482 info.fStartVertex = startVertex; 483 info.fStartIndex = startIndex; 484 info.fVertexCount = vertexCount; 485 info.fIndexCount = indexCount; 486 487 info.fInstanceCount = 0; 488 info.fVerticesPerInstance = 0; 489 info.fIndicesPerInstance = 0; 490 491 if (devBounds) { 492 info.setDevBounds(*devBounds); 493 } 494 // TODO: We should continue with incorrect blending. 495 if (!this->setupDstReadIfNecessary(&info)) { 496 return; 497 } 498 this->onDraw(info); 499 } 500 } 501 502 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type, 503 int startVertex, 504 int vertexCount, 505 const SkRect* devBounds) { 506 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) { 507 DrawInfo info; 508 info.fPrimitiveType = type; 509 info.fStartVertex = startVertex; 510 info.fStartIndex = 0; 511 info.fVertexCount = vertexCount; 512 info.fIndexCount = 0; 513 514 info.fInstanceCount = 0; 515 info.fVerticesPerInstance = 0; 516 info.fIndicesPerInstance = 0; 517 518 if (devBounds) { 519 info.setDevBounds(*devBounds); 520 } 521 // TODO: We should continue with incorrect blending. 522 if (!this->setupDstReadIfNecessary(&info)) { 523 return; 524 } 525 this->onDraw(info); 526 } 527 } 528 529 void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) { 530 // TODO: extract portions of checkDraw that are relevant to path stenciling. 531 SkASSERT(path); 532 SkASSERT(this->caps()->pathRenderingSupport()); 533 SkASSERT(!SkPath::IsInverseFillType(fill)); 534 this->onStencilPath(path, fill); 535 } 536 537 void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) { 538 // TODO: extract portions of checkDraw that are relevant to path rendering. 539 SkASSERT(path); 540 SkASSERT(this->caps()->pathRenderingSupport()); 541 const GrDrawState* drawState = &getDrawState(); 542 543 SkRect devBounds; 544 if (SkPath::IsInverseFillType(fill)) { 545 devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()), 546 SkIntToScalar(drawState->getRenderTarget()->height())); 547 } else { 548 devBounds = path->getBounds(); 549 } 550 SkMatrix viewM = drawState->getViewMatrix(); 551 viewM.mapRect(&devBounds); 552 553 GrDeviceCoordTexture dstCopy; 554 if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) { 555 return; 556 } 557 558 this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL); 559 } 560 561 void GrDrawTarget::drawPaths(const GrPathRange* pathRange, 562 const uint32_t indices[], int count, 563 const float transforms[], PathTransformType transformsType, 564 SkPath::FillType fill) { 565 SkASSERT(this->caps()->pathRenderingSupport()); 566 SkASSERT(pathRange); 567 SkASSERT(indices); 568 SkASSERT(transforms); 569 570 // Don't compute a bounding box for setupDstReadIfNecessary(), we'll opt 571 // instead for it to just copy the entire dst. Realistically this is a moot 572 // point, because any context that supports NV_path_rendering will also 573 // support NV_blend_equation_advanced. 574 GrDeviceCoordTexture dstCopy; 575 if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) { 576 return; 577 } 578 579 this->onDrawPaths(pathRange, indices, count, transforms, transformsType, fill, 580 dstCopy.texture() ? &dstCopy : NULL); 581 } 582 583 typedef GrTraceMarkerSet::Iter TMIter; 584 void GrDrawTarget::saveActiveTraceMarkers() { 585 if (this->caps()->gpuTracingSupport()) { 586 SkASSERT(0 == fStoredTraceMarkers.count()); 587 fStoredTraceMarkers.addSet(fActiveTraceMarkers); 588 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 589 this->removeGpuTraceMarker(&(*iter)); 590 } 591 } 592 } 593 594 void GrDrawTarget::restoreActiveTraceMarkers() { 595 if (this->caps()->gpuTracingSupport()) { 596 SkASSERT(0 == fActiveTraceMarkers.count()); 597 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 598 this->addGpuTraceMarker(&(*iter)); 599 } 600 for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) { 601 this->fStoredTraceMarkers.remove(*iter); 602 } 603 } 604 } 605 606 void GrDrawTarget::addGpuTraceMarker(const GrGpuTraceMarker* marker) { 607 if (this->caps()->gpuTracingSupport()) { 608 SkASSERT(fGpuTraceMarkerCount >= 0); 609 this->fActiveTraceMarkers.add(*marker); 610 this->didAddGpuTraceMarker(); 611 ++fGpuTraceMarkerCount; 612 } 613 } 614 615 void GrDrawTarget::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { 616 if (this->caps()->gpuTracingSupport()) { 617 SkASSERT(fGpuTraceMarkerCount >= 1); 618 this->fActiveTraceMarkers.remove(*marker); 619 this->didRemoveGpuTraceMarker(); 620 --fGpuTraceMarkerCount; 621 } 622 } 623 624 //////////////////////////////////////////////////////////////////////////////// 625 626 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type, 627 int instanceCount, 628 int verticesPerInstance, 629 int indicesPerInstance, 630 const SkRect* devBounds) { 631 if (!verticesPerInstance || !indicesPerInstance) { 632 return; 633 } 634 635 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance; 636 if (!maxInstancesPerDraw) { 637 return; 638 } 639 640 DrawInfo info; 641 info.fPrimitiveType = type; 642 info.fStartIndex = 0; 643 info.fStartVertex = 0; 644 info.fIndicesPerInstance = indicesPerInstance; 645 info.fVerticesPerInstance = verticesPerInstance; 646 647 // Set the same bounds for all the draws. 648 if (devBounds) { 649 info.setDevBounds(*devBounds); 650 } 651 // TODO: We should continue with incorrect blending. 652 if (!this->setupDstReadIfNecessary(&info)) { 653 return; 654 } 655 656 while (instanceCount) { 657 info.fInstanceCount = SkTMin(instanceCount, maxInstancesPerDraw); 658 info.fVertexCount = info.fInstanceCount * verticesPerInstance; 659 info.fIndexCount = info.fInstanceCount * indicesPerInstance; 660 661 if (this->checkDraw(type, 662 info.fStartVertex, 663 info.fStartIndex, 664 info.fVertexCount, 665 info.fIndexCount)) { 666 this->onDraw(info); 667 } 668 info.fStartVertex += info.fVertexCount; 669 instanceCount -= info.fInstanceCount; 670 } 671 } 672 673 //////////////////////////////////////////////////////////////////////////////// 674 675 namespace { 676 677 // position + (optional) texture coord 678 extern const GrVertexAttrib gBWRectPosUVAttribs[] = { 679 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 680 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding} 681 }; 682 683 void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) { 684 if (hasUVs) { 685 drawState->setVertexAttribs<gBWRectPosUVAttribs>(2, 2 * sizeof(SkPoint)); 686 } else { 687 drawState->setVertexAttribs<gBWRectPosUVAttribs>(1, sizeof(SkPoint)); 688 } 689 } 690 691 }; 692 693 void GrDrawTarget::onDrawRect(const SkRect& rect, 694 const SkRect* localRect, 695 const SkMatrix* localMatrix) { 696 697 set_vertex_attributes(this->drawState(), SkToBool(localRect)); 698 699 AutoReleaseGeometry geo(this, 4, 0); 700 if (!geo.succeeded()) { 701 GrPrintf("Failed to get space for vertices!\n"); 702 return; 703 } 704 705 size_t vstride = this->drawState()->getVertexStride(); 706 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride); 707 if (localRect) { 708 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + 709 sizeof(SkPoint)); 710 coords->setRectFan(localRect->fLeft, localRect->fTop, 711 localRect->fRight, localRect->fBottom, 712 vstride); 713 if (localMatrix) { 714 localMatrix->mapPointsWithStride(coords, vstride, 4); 715 } 716 } 717 SkRect bounds; 718 this->getDrawState().getViewMatrix().mapRect(&bounds, rect); 719 720 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, &bounds); 721 } 722 723 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) { 724 } 725 726 //////////////////////////////////////////////////////////////////////////////// 727 728 GrDrawTarget::AutoStateRestore::AutoStateRestore() { 729 fDrawTarget = NULL; 730 } 731 732 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target, 733 ASRInit init, 734 const SkMatrix* vm) { 735 fDrawTarget = NULL; 736 this->set(target, init, vm); 737 } 738 739 GrDrawTarget::AutoStateRestore::~AutoStateRestore() { 740 if (fDrawTarget) { 741 fDrawTarget->setDrawState(fSavedState); 742 fSavedState->unref(); 743 } 744 } 745 746 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) { 747 SkASSERT(NULL == fDrawTarget); 748 fDrawTarget = target; 749 fSavedState = target->drawState(); 750 SkASSERT(fSavedState); 751 fSavedState->ref(); 752 if (kReset_ASRInit == init) { 753 if (NULL == vm) { 754 // calls the default cons 755 fTempState.init(); 756 } else { 757 SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm)); 758 } 759 } else { 760 SkASSERT(kPreserve_ASRInit == init); 761 if (NULL == vm) { 762 fTempState.set(*fSavedState); 763 } else { 764 SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm)); 765 } 766 } 767 target->setDrawState(fTempState.get()); 768 } 769 770 bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) { 771 SkASSERT(NULL == fDrawTarget); 772 fDrawTarget = target; 773 fSavedState = target->drawState(); 774 SkASSERT(fSavedState); 775 fSavedState->ref(); 776 if (kReset_ASRInit == init) { 777 // calls the default cons 778 fTempState.init(); 779 } else { 780 SkASSERT(kPreserve_ASRInit == init); 781 // calls the copy cons 782 fTempState.set(*fSavedState); 783 if (!fTempState.get()->setIdentityViewMatrix()) { 784 // let go of any resources held by the temp 785 fTempState.get()->reset(); 786 fDrawTarget = NULL; 787 fSavedState->unref(); 788 fSavedState = NULL; 789 return false; 790 } 791 } 792 target->setDrawState(fTempState.get()); 793 return true; 794 } 795 796 //////////////////////////////////////////////////////////////////////////////// 797 798 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry( 799 GrDrawTarget* target, 800 int vertexCount, 801 int indexCount) { 802 fTarget = NULL; 803 this->set(target, vertexCount, indexCount); 804 } 805 806 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() { 807 fTarget = NULL; 808 } 809 810 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() { 811 this->reset(); 812 } 813 814 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target, 815 int vertexCount, 816 int indexCount) { 817 this->reset(); 818 fTarget = target; 819 bool success = true; 820 if (fTarget) { 821 success = target->reserveVertexAndIndexSpace(vertexCount, 822 indexCount, 823 &fVertices, 824 &fIndices); 825 if (!success) { 826 fTarget = NULL; 827 this->reset(); 828 } 829 } 830 SkASSERT(success == SkToBool(fTarget)); 831 return success; 832 } 833 834 void GrDrawTarget::AutoReleaseGeometry::reset() { 835 if (fTarget) { 836 if (fVertices) { 837 fTarget->resetVertexSource(); 838 } 839 if (fIndices) { 840 fTarget->resetIndexSource(); 841 } 842 fTarget = NULL; 843 } 844 fVertices = NULL; 845 fIndices = NULL; 846 } 847 848 GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) { 849 fTarget = target; 850 fClip = fTarget->getClip(); 851 fStack.init(); 852 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op); 853 fReplacementClip.fClipStack = fStack.get(); 854 target->setClip(&fReplacementClip); 855 } 856 857 namespace { 858 // returns true if the read/written rect intersects the src/dst and false if not. 859 bool clip_srcrect_and_dstpoint(const GrSurface* dst, 860 const GrSurface* src, 861 const SkIRect& srcRect, 862 const SkIPoint& dstPoint, 863 SkIRect* clippedSrcRect, 864 SkIPoint* clippedDstPoint) { 865 *clippedSrcRect = srcRect; 866 *clippedDstPoint = dstPoint; 867 868 // clip the left edge to src and dst bounds, adjusting dstPoint if necessary 869 if (clippedSrcRect->fLeft < 0) { 870 clippedDstPoint->fX -= clippedSrcRect->fLeft; 871 clippedSrcRect->fLeft = 0; 872 } 873 if (clippedDstPoint->fX < 0) { 874 clippedSrcRect->fLeft -= clippedDstPoint->fX; 875 clippedDstPoint->fX = 0; 876 } 877 878 // clip the top edge to src and dst bounds, adjusting dstPoint if necessary 879 if (clippedSrcRect->fTop < 0) { 880 clippedDstPoint->fY -= clippedSrcRect->fTop; 881 clippedSrcRect->fTop = 0; 882 } 883 if (clippedDstPoint->fY < 0) { 884 clippedSrcRect->fTop -= clippedDstPoint->fY; 885 clippedDstPoint->fY = 0; 886 } 887 888 // clip the right edge to the src and dst bounds. 889 if (clippedSrcRect->fRight > src->width()) { 890 clippedSrcRect->fRight = src->width(); 891 } 892 if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) { 893 clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX; 894 } 895 896 // clip the bottom edge to the src and dst bounds. 897 if (clippedSrcRect->fBottom > src->height()) { 898 clippedSrcRect->fBottom = src->height(); 899 } 900 if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) { 901 clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY; 902 } 903 904 // The above clipping steps may have inverted the rect if it didn't intersect either the src or 905 // dst bounds. 906 return !clippedSrcRect->isEmpty(); 907 } 908 } 909 910 bool GrDrawTarget::copySurface(GrSurface* dst, 911 GrSurface* src, 912 const SkIRect& srcRect, 913 const SkIPoint& dstPoint) { 914 SkASSERT(dst); 915 SkASSERT(src); 916 917 SkIRect clippedSrcRect; 918 SkIPoint clippedDstPoint; 919 // If the rect is outside the src or dst then we've already succeeded. 920 if (!clip_srcrect_and_dstpoint(dst, 921 src, 922 srcRect, 923 dstPoint, 924 &clippedSrcRect, 925 &clippedDstPoint)) { 926 SkASSERT(this->canCopySurface(dst, src, srcRect, dstPoint)); 927 return true; 928 } 929 930 bool result = this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 931 SkASSERT(result == this->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint)); 932 return result; 933 } 934 935 bool GrDrawTarget::canCopySurface(GrSurface* dst, 936 GrSurface* src, 937 const SkIRect& srcRect, 938 const SkIPoint& dstPoint) { 939 SkASSERT(dst); 940 SkASSERT(src); 941 942 SkIRect clippedSrcRect; 943 SkIPoint clippedDstPoint; 944 // If the rect is outside the src or dst then we're guaranteed success 945 if (!clip_srcrect_and_dstpoint(dst, 946 src, 947 srcRect, 948 dstPoint, 949 &clippedSrcRect, 950 &clippedDstPoint)) { 951 return true; 952 } 953 return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint); 954 } 955 956 bool GrDrawTarget::onCanCopySurface(GrSurface* dst, 957 GrSurface* src, 958 const SkIRect& srcRect, 959 const SkIPoint& dstPoint) { 960 // Check that the read/write rects are contained within the src/dst bounds. 961 SkASSERT(!srcRect.isEmpty()); 962 SkASSERT(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect)); 963 SkASSERT(dstPoint.fX >= 0 && dstPoint.fY >= 0); 964 SkASSERT(dstPoint.fX + srcRect.width() <= dst->width() && 965 dstPoint.fY + srcRect.height() <= dst->height()); 966 967 return !dst->isSameAs(src) && dst->asRenderTarget() && src->asTexture(); 968 } 969 970 bool GrDrawTarget::onCopySurface(GrSurface* dst, 971 GrSurface* src, 972 const SkIRect& srcRect, 973 const SkIPoint& dstPoint) { 974 if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) { 975 return false; 976 } 977 978 GrRenderTarget* rt = dst->asRenderTarget(); 979 GrTexture* tex = src->asTexture(); 980 981 GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit); 982 this->drawState()->setRenderTarget(rt); 983 SkMatrix matrix; 984 matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX), 985 SkIntToScalar(srcRect.fTop - dstPoint.fY)); 986 matrix.postIDiv(tex->width(), tex->height()); 987 this->drawState()->addColorTextureProcessor(tex, matrix); 988 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, 989 dstPoint.fY, 990 srcRect.width(), 991 srcRect.height()); 992 this->drawSimpleRect(dstRect); 993 return true; 994 } 995 996 void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) { 997 // Make the dst of the copy be a render target because the default copySurface draws to the dst. 998 desc->fOrigin = kDefault_GrSurfaceOrigin; 999 desc->fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 1000 desc->fConfig = src->config(); 1001 } 1002 1003 /////////////////////////////////////////////////////////////////////////////// 1004 1005 void GrDrawTargetCaps::reset() { 1006 fMipMapSupport = false; 1007 fNPOTTextureTileSupport = false; 1008 fTwoSidedStencilSupport = false; 1009 fStencilWrapOpsSupport = false; 1010 fHWAALineSupport = false; 1011 fShaderDerivativeSupport = false; 1012 fGeometryShaderSupport = false; 1013 fDualSourceBlendingSupport = false; 1014 fPathRenderingSupport = false; 1015 fDstReadInShaderSupport = false; 1016 fDiscardRenderTargetSupport = false; 1017 fReuseScratchTextures = true; 1018 fGpuTracingSupport = false; 1019 fCompressedTexSubImageSupport = false; 1020 1021 fMapBufferFlags = kNone_MapFlags; 1022 1023 fMaxRenderTargetSize = 0; 1024 fMaxTextureSize = 0; 1025 fMaxSampleCount = 0; 1026 1027 memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport)); 1028 memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport)); 1029 } 1030 1031 GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) { 1032 fMipMapSupport = other.fMipMapSupport; 1033 fNPOTTextureTileSupport = other.fNPOTTextureTileSupport; 1034 fTwoSidedStencilSupport = other.fTwoSidedStencilSupport; 1035 fStencilWrapOpsSupport = other.fStencilWrapOpsSupport; 1036 fHWAALineSupport = other.fHWAALineSupport; 1037 fShaderDerivativeSupport = other.fShaderDerivativeSupport; 1038 fGeometryShaderSupport = other.fGeometryShaderSupport; 1039 fDualSourceBlendingSupport = other.fDualSourceBlendingSupport; 1040 fPathRenderingSupport = other.fPathRenderingSupport; 1041 fDstReadInShaderSupport = other.fDstReadInShaderSupport; 1042 fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport; 1043 fReuseScratchTextures = other.fReuseScratchTextures; 1044 fGpuTracingSupport = other.fGpuTracingSupport; 1045 fCompressedTexSubImageSupport = other.fCompressedTexSubImageSupport; 1046 1047 fMapBufferFlags = other.fMapBufferFlags; 1048 1049 fMaxRenderTargetSize = other.fMaxRenderTargetSize; 1050 fMaxTextureSize = other.fMaxTextureSize; 1051 fMaxSampleCount = other.fMaxSampleCount; 1052 1053 memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport)); 1054 memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport)); 1055 1056 return *this; 1057 } 1058 1059 static SkString map_flags_to_string(uint32_t flags) { 1060 SkString str; 1061 if (GrDrawTargetCaps::kNone_MapFlags == flags) { 1062 str = "none"; 1063 } else { 1064 SkASSERT(GrDrawTargetCaps::kCanMap_MapFlag & flags); 1065 SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kCanMap_MapFlag); 1066 str = "can_map"; 1067 1068 if (GrDrawTargetCaps::kSubset_MapFlag & flags) { 1069 str.append(" partial"); 1070 } else { 1071 str.append(" full"); 1072 } 1073 SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kSubset_MapFlag); 1074 } 1075 SkASSERT(0 == flags); // Make sure we handled all the flags. 1076 return str; 1077 } 1078 1079 SkString GrDrawTargetCaps::dump() const { 1080 SkString r; 1081 static const char* gNY[] = {"NO", "YES"}; 1082 r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); 1083 r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); 1084 r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); 1085 r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); 1086 r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); 1087 r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); 1088 r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); 1089 r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]); 1090 r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); 1091 r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); 1092 r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]); 1093 r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); 1094 r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); 1095 r.appendf("Compressed Update Support : %s\n", gNY[fCompressedTexSubImageSupport]); 1096 r.appendf("Max Texture Size : %d\n", fMaxTextureSize); 1097 r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); 1098 r.appendf("Max Sample Count : %d\n", fMaxSampleCount); 1099 1100 r.appendf("Map Buffer Support : %s\n", map_flags_to_string(fMapBufferFlags).c_str()); 1101 1102 static const char* kConfigNames[] = { 1103 "Unknown", // kUnknown_GrPixelConfig 1104 "Alpha8", // kAlpha_8_GrPixelConfig, 1105 "Index8", // kIndex_8_GrPixelConfig, 1106 "RGB565", // kRGB_565_GrPixelConfig, 1107 "RGBA444", // kRGBA_4444_GrPixelConfig, 1108 "RGBA8888", // kRGBA_8888_GrPixelConfig, 1109 "BGRA8888", // kBGRA_8888_GrPixelConfig, 1110 "ETC1", // kETC1_GrPixelConfig, 1111 "LATC", // kLATC_GrPixelConfig, 1112 "R11EAC", // kR11_EAC_GrPixelConfig, 1113 "ASTC12x12",// kASTC_12x12_GrPixelConfig, 1114 "RGBAFloat", // kRGBA_float_GrPixelConfig 1115 }; 1116 GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig); 1117 GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig); 1118 GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig); 1119 GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig); 1120 GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig); 1121 GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); 1122 GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); 1123 GR_STATIC_ASSERT(7 == kETC1_GrPixelConfig); 1124 GR_STATIC_ASSERT(8 == kLATC_GrPixelConfig); 1125 GR_STATIC_ASSERT(9 == kR11_EAC_GrPixelConfig); 1126 GR_STATIC_ASSERT(10 == kASTC_12x12_GrPixelConfig); 1127 GR_STATIC_ASSERT(11 == kRGBA_float_GrPixelConfig); 1128 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); 1129 1130 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]); 1131 SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]); 1132 1133 for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { 1134 r.appendf("%s is renderable: %s, with MSAA: %s\n", 1135 kConfigNames[i], 1136 gNY[fConfigRenderSupport[i][0]], 1137 gNY[fConfigRenderSupport[i][1]]); 1138 } 1139 1140 SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]); 1141 1142 for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { 1143 r.appendf("%s is uploadable to a texture: %s\n", 1144 kConfigNames[i], 1145 gNY[fConfigTextureSupport[i]]); 1146 } 1147 1148 return r; 1149 } 1150 1151 uint32_t GrDrawTargetCaps::CreateUniqueID() { 1152 static int32_t gUniqueID = SK_InvalidUniqueID; 1153 uint32_t id; 1154 do { 1155 id = static_cast<uint32_t>(sk_atomic_inc(&gUniqueID) + 1); 1156 } while (id == SK_InvalidUniqueID); 1157 return id; 1158 } 1159 1160