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