GrDrawTarget.cpp revision 054ae99d93711c26e40682a0e3a03a47ea605c53
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 "GrRenderTarget.h" 15#include "GrTexture.h" 16#include "GrVertexBuffer.h" 17 18#include "SkStrokeRec.h" 19 20SK_DEFINE_INST_COUNT(GrDrawTarget) 21 22//////////////////////////////////////////////////////////////////////////////// 23 24GrDrawTarget::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 (NULL != di.fDevBounds) { 36 GrAssert(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#if GR_DEBUG 49bool GrDrawTarget::DrawInfo::isInstanced() const { 50 if (fInstanceCount > 0) { 51 GrAssert(0 == fIndexCount % fIndicesPerInstance); 52 GrAssert(0 == fVertexCount % fVerticesPerInstance); 53 GrAssert(fIndexCount / fIndicesPerInstance == fInstanceCount); 54 GrAssert(fVertexCount / fVerticesPerInstance == fInstanceCount); 55 // there is no way to specify a non-zero start index to drawIndexedInstances(). 56 GrAssert(0 == fStartIndex); 57 return true; 58 } else { 59 GrAssert(!fVerticesPerInstance); 60 GrAssert(!fIndicesPerInstance); 61 return false; 62 } 63} 64#endif 65 66void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) { 67 GrAssert(this->isInstanced()); 68 GrAssert(instanceOffset + fInstanceCount >= 0); 69 fInstanceCount += instanceOffset; 70 fVertexCount = fVerticesPerInstance * fInstanceCount; 71 fIndexCount = fIndicesPerInstance * fInstanceCount; 72} 73 74void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) { 75 fStartVertex += vertexOffset; 76 GrAssert(fStartVertex >= 0); 77} 78 79void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) { 80 GrAssert(this->isIndexed()); 81 fStartIndex += indexOffset; 82 GrAssert(fStartIndex >= 0); 83} 84 85//////////////////////////////////////////////////////////////////////////////// 86 87#define DEBUG_INVAL_BUFFER 0xdeadcafe 88#define DEBUG_INVAL_START_IDX -1 89 90GrDrawTarget::GrDrawTarget(GrContext* context) 91 : fClip(NULL) 92 , fContext(context) { 93 GrAssert(NULL != context); 94 95 fDrawState = &fDefaultDrawState; 96 // We assume that fDrawState always owns a ref to the object it points at. 97 fDefaultDrawState.ref(); 98 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back(); 99#if GR_DEBUG 100 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX; 101 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 102 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX; 103 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 104#endif 105 geoSrc.fVertexSrc = kNone_GeometrySrcType; 106 geoSrc.fIndexSrc = kNone_GeometrySrcType; 107} 108 109GrDrawTarget::~GrDrawTarget() { 110 GrAssert(1 == fGeoSrcStateStack.count()); 111 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back()); 112 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc); 113 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc); 114 fDrawState->unref(); 115} 116 117void GrDrawTarget::releaseGeometry() { 118 int popCnt = fGeoSrcStateStack.count() - 1; 119 while (popCnt) { 120 this->popGeometrySource(); 121 --popCnt; 122 } 123 this->resetVertexSource(); 124 this->resetIndexSource(); 125} 126 127void GrDrawTarget::setClip(const GrClipData* clip) { 128 clipWillBeSet(clip); 129 fClip = clip; 130} 131 132const GrClipData* GrDrawTarget::getClip() const { 133 return fClip; 134} 135 136void GrDrawTarget::setDrawState(GrDrawState* drawState) { 137 GrAssert(NULL != fDrawState); 138 if (NULL == drawState) { 139 drawState = &fDefaultDrawState; 140 } 141 if (fDrawState != drawState) { 142 fDrawState->unref(); 143 drawState->ref(); 144 fDrawState = drawState; 145 } 146} 147 148bool GrDrawTarget::reserveVertexSpace(size_t vertexSize, 149 int vertexCount, 150 void** vertices) { 151 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 152 bool acquired = false; 153 if (vertexCount > 0) { 154 GrAssert(NULL != vertices); 155 this->releasePreviousVertexSource(); 156 geoSrc.fVertexSrc = kNone_GeometrySrcType; 157 158 acquired = this->onReserveVertexSpace(vertexSize, 159 vertexCount, 160 vertices); 161 } 162 if (acquired) { 163 geoSrc.fVertexSrc = kReserved_GeometrySrcType; 164 geoSrc.fVertexCount = vertexCount; 165 geoSrc.fVertexSize = vertexSize; 166 } else if (NULL != vertices) { 167 *vertices = NULL; 168 } 169 return acquired; 170} 171 172bool GrDrawTarget::reserveIndexSpace(int indexCount, 173 void** indices) { 174 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 175 bool acquired = false; 176 if (indexCount > 0) { 177 GrAssert(NULL != indices); 178 this->releasePreviousIndexSource(); 179 geoSrc.fIndexSrc = kNone_GeometrySrcType; 180 181 acquired = this->onReserveIndexSpace(indexCount, indices); 182 } 183 if (acquired) { 184 geoSrc.fIndexSrc = kReserved_GeometrySrcType; 185 geoSrc.fIndexCount = indexCount; 186 } else if (NULL != indices) { 187 *indices = NULL; 188 } 189 return acquired; 190 191} 192 193bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount, 194 int indexCount, 195 void** vertices, 196 void** indices) { 197 size_t vertexSize = this->drawState()->getVertexSize(); 198 this->willReserveVertexAndIndexSpace(vertexCount, indexCount); 199 if (vertexCount) { 200 if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) { 201 if (indexCount) { 202 this->resetIndexSource(); 203 } 204 return false; 205 } 206 } 207 if (indexCount) { 208 if (!this->reserveIndexSpace(indexCount, indices)) { 209 if (vertexCount) { 210 this->resetVertexSource(); 211 } 212 return false; 213 } 214 } 215 return true; 216} 217 218bool GrDrawTarget::geometryHints(int32_t* vertexCount, 219 int32_t* indexCount) const { 220 if (NULL != vertexCount) { 221 *vertexCount = -1; 222 } 223 if (NULL != indexCount) { 224 *indexCount = -1; 225 } 226 return false; 227} 228 229void GrDrawTarget::releasePreviousVertexSource() { 230 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 231 switch (geoSrc.fVertexSrc) { 232 case kNone_GeometrySrcType: 233 break; 234 case kArray_GeometrySrcType: 235 this->releaseVertexArray(); 236 break; 237 case kReserved_GeometrySrcType: 238 this->releaseReservedVertexSpace(); 239 break; 240 case kBuffer_GeometrySrcType: 241 geoSrc.fVertexBuffer->unref(); 242#if GR_DEBUG 243 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 244#endif 245 break; 246 default: 247 GrCrash("Unknown Vertex Source Type."); 248 break; 249 } 250} 251 252void GrDrawTarget::releasePreviousIndexSource() { 253 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 254 switch (geoSrc.fIndexSrc) { 255 case kNone_GeometrySrcType: // these two don't require 256 break; 257 case kArray_GeometrySrcType: 258 this->releaseIndexArray(); 259 break; 260 case kReserved_GeometrySrcType: 261 this->releaseReservedIndexSpace(); 262 break; 263 case kBuffer_GeometrySrcType: 264 geoSrc.fIndexBuffer->unref(); 265#if GR_DEBUG 266 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 267#endif 268 break; 269 default: 270 GrCrash("Unknown Index Source Type."); 271 break; 272 } 273} 274 275void GrDrawTarget::setVertexSourceToArray(const void* vertexArray, 276 int vertexCount) { 277 this->releasePreviousVertexSource(); 278 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 279 geoSrc.fVertexSrc = kArray_GeometrySrcType; 280 geoSrc.fVertexSize = this->drawState()->getVertexSize(); 281 geoSrc.fVertexCount = vertexCount; 282 this->onSetVertexSourceToArray(vertexArray, vertexCount); 283} 284 285void GrDrawTarget::setIndexSourceToArray(const void* indexArray, 286 int indexCount) { 287 this->releasePreviousIndexSource(); 288 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 289 geoSrc.fIndexSrc = kArray_GeometrySrcType; 290 geoSrc.fIndexCount = indexCount; 291 this->onSetIndexSourceToArray(indexArray, indexCount); 292} 293 294void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) { 295 this->releasePreviousVertexSource(); 296 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 297 geoSrc.fVertexSrc = kBuffer_GeometrySrcType; 298 geoSrc.fVertexBuffer = buffer; 299 buffer->ref(); 300 geoSrc.fVertexSize = this->drawState()->getVertexSize(); 301} 302 303void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) { 304 this->releasePreviousIndexSource(); 305 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 306 geoSrc.fIndexSrc = kBuffer_GeometrySrcType; 307 geoSrc.fIndexBuffer = buffer; 308 buffer->ref(); 309} 310 311void GrDrawTarget::resetVertexSource() { 312 this->releasePreviousVertexSource(); 313 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 314 geoSrc.fVertexSrc = kNone_GeometrySrcType; 315} 316 317void GrDrawTarget::resetIndexSource() { 318 this->releasePreviousIndexSource(); 319 GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 320 geoSrc.fIndexSrc = kNone_GeometrySrcType; 321} 322 323void GrDrawTarget::pushGeometrySource() { 324 this->geometrySourceWillPush(); 325 GeometrySrcState& newState = fGeoSrcStateStack.push_back(); 326 newState.fIndexSrc = kNone_GeometrySrcType; 327 newState.fVertexSrc = kNone_GeometrySrcType; 328#if GR_DEBUG 329 newState.fVertexCount = ~0; 330 newState.fVertexBuffer = (GrVertexBuffer*)~0; 331 newState.fIndexCount = ~0; 332 newState.fIndexBuffer = (GrIndexBuffer*)~0; 333#endif 334} 335 336void GrDrawTarget::popGeometrySource() { 337 // if popping last element then pops are unbalanced with pushes 338 GrAssert(fGeoSrcStateStack.count() > 1); 339 340 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1)); 341 this->releasePreviousVertexSource(); 342 this->releasePreviousIndexSource(); 343 fGeoSrcStateStack.pop_back(); 344} 345 346//////////////////////////////////////////////////////////////////////////////// 347 348bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex, 349 int startIndex, int vertexCount, 350 int indexCount) const { 351 const GrDrawState& drawState = this->getDrawState(); 352#if GR_DEBUG 353 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back(); 354 int maxVertex = startVertex + vertexCount; 355 int maxValidVertex; 356 switch (geoSrc.fVertexSrc) { 357 case kNone_GeometrySrcType: 358 GrCrash("Attempting to draw without vertex src."); 359 case kReserved_GeometrySrcType: // fallthrough 360 case kArray_GeometrySrcType: 361 maxValidVertex = geoSrc.fVertexCount; 362 break; 363 case kBuffer_GeometrySrcType: 364 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize; 365 break; 366 } 367 if (maxVertex > maxValidVertex) { 368 GrCrash("Drawing outside valid vertex range."); 369 } 370 if (indexCount > 0) { 371 int maxIndex = startIndex + indexCount; 372 int maxValidIndex; 373 switch (geoSrc.fIndexSrc) { 374 case kNone_GeometrySrcType: 375 GrCrash("Attempting to draw indexed geom without index src."); 376 case kReserved_GeometrySrcType: // fallthrough 377 case kArray_GeometrySrcType: 378 maxValidIndex = geoSrc.fIndexCount; 379 break; 380 case kBuffer_GeometrySrcType: 381 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t); 382 break; 383 } 384 if (maxIndex > maxValidIndex) { 385 GrCrash("Index reads outside valid index range."); 386 } 387 } 388 389 GrAssert(NULL != drawState.getRenderTarget()); 390 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 391 if (drawState.isStageEnabled(s)) { 392 const GrEffectRef& effect = *drawState.getStage(s).getEffect(); 393 int numTextures = effect->numTextures(); 394 for (int t = 0; t < numTextures; ++t) { 395 GrTexture* texture = effect->texture(t); 396 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget()); 397 } 398 } 399 } 400 401 GrAssert(drawState.validateVertexAttribs()); 402#endif 403 if (NULL == drawState.getRenderTarget()) { 404 return false; 405 } 406 return true; 407} 408 409bool GrDrawTarget::setupDstReadIfNecessary(DrawInfo* info) { 410 if (!this->getDrawState().willEffectReadDst()) { 411 return true; 412 } 413 GrRenderTarget* rt = this->drawState()->getRenderTarget(); 414 // If the dst is not a texture then we don't currently have a way of copying the 415 // texture. TODO: make copying RT->Tex (or Surface->Surface) a GrDrawTarget operation that can 416 // be built on top of GL/D3D APIs. 417 if (NULL == rt->asTexture()) { 418 GrPrintf("Reading Dst of non-texture render target is not currently supported.\n"); 419 return false; 420 } 421 422 const GrClipData* clip = this->getClip(); 423 GrIRect copyRect; 424 clip->getConservativeBounds(this->getDrawState().getRenderTarget(), ©Rect); 425 SkIRect drawIBounds; 426 if (info->getDevIBounds(&drawIBounds)) { 427 if (!copyRect.intersect(drawIBounds)) { 428#if GR_DEBUG 429 GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n"); 430#endif 431 return false; 432 } 433 } else { 434#if GR_DEBUG 435 //GrPrintf("No dev bounds when dst copy is made.\n"); 436#endif 437 } 438 439 GrDrawTarget::AutoGeometryAndStatePush agasp(this, kReset_ASRInit); 440 441 // The draw will resolve dst if it has MSAA. Two things to consider in the future: 442 // 1) to make the dst values be pre-resolve we'd need to be able to copy to MSAA 443 // texture and sample it correctly in the shader. 2) If 1 isn't available then we 444 // should just resolve and use the resolved texture directly rather than making a 445 // copy of it. 446 GrTextureDesc desc; 447 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 448 desc.fWidth = copyRect.width(); 449 desc.fHeight = copyRect.height(); 450 desc.fSampleCnt = 0; 451 desc.fConfig = rt->config(); 452 453 GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch); 454 455 if (NULL == ast.texture()) { 456 GrPrintf("Failed to create temporary copy of destination texture.\n"); 457 return false; 458 } 459 this->drawState()->disableState(GrDrawState::kClip_StateBit); 460 this->drawState()->setRenderTarget(ast.texture()->asRenderTarget()); 461 static const int kTextureStage = 0; 462 SkMatrix matrix; 463 matrix.setIDiv(rt->width(), rt->height()); 464 this->drawState()->createTextureEffect(kTextureStage, rt->asTexture(), matrix); 465 466 SkRect srcRect = SkRect::MakeFromIRect(copyRect); 467 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(copyRect.width()), 468 SkIntToScalar(copyRect.height())); 469 this->drawRect(dstRect, NULL, &srcRect, NULL); 470 471 info->fDstCopy.setTexture(ast.texture()); 472 info->fDstCopy.setOffset(copyRect.fLeft, copyRect.fTop); 473 return true; 474} 475 476void GrDrawTarget::drawIndexed(GrPrimitiveType type, 477 int startVertex, 478 int startIndex, 479 int vertexCount, 480 int indexCount, 481 const SkRect* devBounds) { 482 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) { 483 DrawInfo info; 484 info.fPrimitiveType = type; 485 info.fStartVertex = startVertex; 486 info.fStartIndex = startIndex; 487 info.fVertexCount = vertexCount; 488 info.fIndexCount = indexCount; 489 490 info.fInstanceCount = 0; 491 info.fVerticesPerInstance = 0; 492 info.fIndicesPerInstance = 0; 493 494 if (NULL != devBounds) { 495 info.setDevBounds(*devBounds); 496 } 497 // TODO: We should continue with incorrect blending. 498 if (!this->setupDstReadIfNecessary(&info)) { 499 return; 500 } 501 this->onDraw(info); 502 } 503} 504 505void GrDrawTarget::drawNonIndexed(GrPrimitiveType type, 506 int startVertex, 507 int vertexCount, 508 const SkRect* devBounds) { 509 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) { 510 DrawInfo info; 511 info.fPrimitiveType = type; 512 info.fStartVertex = startVertex; 513 info.fStartIndex = 0; 514 info.fVertexCount = vertexCount; 515 info.fIndexCount = 0; 516 517 info.fInstanceCount = 0; 518 info.fVerticesPerInstance = 0; 519 info.fIndicesPerInstance = 0; 520 521 if (NULL != devBounds) { 522 info.setDevBounds(*devBounds); 523 } 524 // TODO: We should continue with incorrect blending. 525 if (!this->setupDstReadIfNecessary(&info)) { 526 return; 527 } 528 this->onDraw(info); 529 } 530} 531 532void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) { 533 // TODO: extract portions of checkDraw that are relevant to path stenciling. 534 GrAssert(NULL != path); 535 GrAssert(this->caps()->pathStencilingSupport()); 536 GrAssert(!stroke.isHairlineStyle()); 537 GrAssert(!SkPath::IsInverseFillType(fill)); 538 this->onStencilPath(path, stroke, fill); 539} 540 541//////////////////////////////////////////////////////////////////////////////// 542 543bool GrDrawTarget::willUseHWAALines() const { 544 // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth 545 // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when 546 // our alpha is 0xff and tweaking the color for partial coverage is OK 547 if (!this->caps()->hwAALineSupport() || 548 !this->getDrawState().isHWAntialiasState()) { 549 return false; 550 } 551 GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts(); 552 return (GrDrawState::kDisableBlend_BlendOptFlag & opts) && 553 (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts); 554} 555 556bool GrDrawTarget::canApplyCoverage() const { 557 // we can correctly apply coverage if a) we have dual source blending 558 // or b) one of our blend optimizations applies. 559 return this->caps()->dualSourceBlendingSupport() || 560 GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true); 561} 562 563//////////////////////////////////////////////////////////////////////////////// 564 565void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type, 566 int instanceCount, 567 int verticesPerInstance, 568 int indicesPerInstance, 569 const SkRect* devBounds) { 570 if (!verticesPerInstance || !indicesPerInstance) { 571 return; 572 } 573 574 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance; 575 if (!maxInstancesPerDraw) { 576 return; 577 } 578 579 DrawInfo info; 580 info.fPrimitiveType = type; 581 info.fStartIndex = 0; 582 info.fStartVertex = 0; 583 info.fIndicesPerInstance = indicesPerInstance; 584 info.fVerticesPerInstance = verticesPerInstance; 585 586 // Set the same bounds for all the draws. 587 if (NULL != devBounds) { 588 info.setDevBounds(*devBounds); 589 } 590 // TODO: We should continue with incorrect blending. 591 if (!this->setupDstReadIfNecessary(&info)) { 592 return; 593 } 594 595 while (instanceCount) { 596 info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw); 597 info.fVertexCount = info.fInstanceCount * verticesPerInstance; 598 info.fIndexCount = info.fInstanceCount * indicesPerInstance; 599 600 if (this->checkDraw(type, 601 info.fStartVertex, 602 info.fStartIndex, 603 info.fVertexCount, 604 info.fIndexCount)) { 605 this->onDraw(info); 606 } 607 info.fStartVertex += info.fVertexCount; 608 instanceCount -= info.fInstanceCount; 609 } 610} 611 612//////////////////////////////////////////////////////////////////////////////// 613 614void GrDrawTarget::drawRect(const GrRect& rect, 615 const SkMatrix* matrix, 616 const GrRect* localRect, 617 const SkMatrix* localMatrix) { 618 // position + (optional) texture coord 619 static const GrVertexAttrib kAttribs[] = { 620 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 621 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding} 622 }; 623 int attribCount = 1; 624 625 if (NULL != localRect) { 626 attribCount = 2; 627 } 628 629 GrDrawState::AutoViewMatrixRestore avmr; 630 if (NULL != matrix) { 631 avmr.set(this->drawState(), *matrix); 632 } 633 634 this->drawState()->setVertexAttribs(kAttribs, attribCount); 635 AutoReleaseGeometry geo(this, 4, 0); 636 if (!geo.succeeded()) { 637 GrPrintf("Failed to get space for vertices!\n"); 638 return; 639 } 640 641 size_t vsize = this->drawState()->getVertexSize(); 642 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); 643 if (NULL != localRect) { 644 GrAssert(attribCount == 2); 645 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + 646 kAttribs[1].fOffset); 647 coords->setRectFan(localRect->fLeft, localRect->fTop, 648 localRect->fRight, localRect->fBottom, 649 vsize); 650 if (NULL != localMatrix) { 651 localMatrix->mapPointsWithStride(coords, vsize, 4); 652 } 653 } 654 SkTLazy<SkRect> bounds; 655 if (this->getDrawState().willEffectReadDst()) { 656 bounds.init(); 657 this->getDrawState().getViewMatrix().mapRect(bounds.get(), rect); 658 } 659 660 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, bounds.getMaybeNull()); 661} 662 663void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) { 664} 665 666//////////////////////////////////////////////////////////////////////////////// 667 668GrDrawTarget::AutoStateRestore::AutoStateRestore() { 669 fDrawTarget = NULL; 670} 671 672GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target, 673 ASRInit init) { 674 fDrawTarget = NULL; 675 this->set(target, init); 676} 677 678GrDrawTarget::AutoStateRestore::~AutoStateRestore() { 679 if (NULL != fDrawTarget) { 680 fDrawTarget->setDrawState(fSavedState); 681 fSavedState->unref(); 682 } 683} 684 685void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) { 686 GrAssert(NULL == fDrawTarget); 687 fDrawTarget = target; 688 fSavedState = target->drawState(); 689 GrAssert(fSavedState); 690 fSavedState->ref(); 691 if (kReset_ASRInit == init) { 692 // calls the default cons 693 fTempState.init(); 694 } else { 695 GrAssert(kPreserve_ASRInit == init); 696 // calls the copy cons 697 fTempState.set(*fSavedState); 698 } 699 target->setDrawState(fTempState.get()); 700} 701 702//////////////////////////////////////////////////////////////////////////////// 703 704GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry( 705 GrDrawTarget* target, 706 int vertexCount, 707 int indexCount) { 708 fTarget = NULL; 709 this->set(target, vertexCount, indexCount); 710} 711 712GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() { 713 fTarget = NULL; 714} 715 716GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() { 717 this->reset(); 718} 719 720bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target, 721 int vertexCount, 722 int indexCount) { 723 this->reset(); 724 fTarget = target; 725 bool success = true; 726 if (NULL != fTarget) { 727 fTarget = target; 728 success = target->reserveVertexAndIndexSpace(vertexCount, 729 indexCount, 730 &fVertices, 731 &fIndices); 732 if (!success) { 733 fTarget = NULL; 734 this->reset(); 735 } 736 } 737 GrAssert(success == (NULL != fTarget)); 738 return success; 739} 740 741void GrDrawTarget::AutoReleaseGeometry::reset() { 742 if (NULL != fTarget) { 743 if (NULL != fVertices) { 744 fTarget->resetVertexSource(); 745 } 746 if (NULL != fIndices) { 747 fTarget->resetIndexSource(); 748 } 749 fTarget = NULL; 750 } 751 fVertices = NULL; 752 fIndices = NULL; 753} 754 755GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) { 756 fTarget = target; 757 fClip = fTarget->getClip(); 758 fStack.init(); 759 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op); 760 fReplacementClip.fClipStack = fStack.get(); 761 target->setClip(&fReplacementClip); 762} 763 764/////////////////////////////////////////////////////////////////////////////// 765 766SK_DEFINE_INST_COUNT(GrDrawTargetCaps) 767 768void GrDrawTargetCaps::reset() { 769 f8BitPaletteSupport = false; 770 fNPOTTextureTileSupport = false; 771 fTwoSidedStencilSupport = false; 772 fStencilWrapOpsSupport = false; 773 fHWAALineSupport = false; 774 fShaderDerivativeSupport = false; 775 fGeometryShaderSupport = false; 776 fDualSourceBlendingSupport = false; 777 fBufferLockSupport = false; 778 fPathStencilingSupport = false; 779 780 fMaxRenderTargetSize = 0; 781 fMaxTextureSize = 0; 782 fMaxSampleCount = 0; 783} 784 785GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) { 786 f8BitPaletteSupport = other.f8BitPaletteSupport; 787 fNPOTTextureTileSupport = other.fNPOTTextureTileSupport; 788 fTwoSidedStencilSupport = other.fTwoSidedStencilSupport; 789 fStencilWrapOpsSupport = other.fStencilWrapOpsSupport; 790 fHWAALineSupport = other.fHWAALineSupport; 791 fShaderDerivativeSupport = other.fShaderDerivativeSupport; 792 fGeometryShaderSupport = other.fGeometryShaderSupport; 793 fDualSourceBlendingSupport = other.fDualSourceBlendingSupport; 794 fBufferLockSupport = other.fBufferLockSupport; 795 fPathStencilingSupport = other.fPathStencilingSupport; 796 797 fMaxRenderTargetSize = other.fMaxRenderTargetSize; 798 fMaxTextureSize = other.fMaxTextureSize; 799 fMaxSampleCount = other.fMaxSampleCount; 800 801 return *this; 802} 803 804void GrDrawTargetCaps::print() const { 805 static const char* gNY[] = {"NO", "YES"}; 806 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]); 807 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); 808 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); 809 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); 810 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); 811 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); 812 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); 813 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]); 814 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]); 815 GrPrintf("Path Stenciling Support : %s\n", gNY[fPathStencilingSupport]); 816 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize); 817 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize); 818 GrPrintf("Max Sample Count : %d\n", fMaxSampleCount); 819} 820