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