GrGpu.cpp revision 979432ba2621b617f5e85a9ff48c6b6cd1504a0d
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#include "GrGpu.h" 11 12#include "GrBufferAllocPool.h" 13#include "GrClipIterator.h" 14#include "GrContext.h" 15#include "GrIndexBuffer.h" 16#include "GrPathRenderer.h" 17#include "GrGLStencilBuffer.h" 18#include "GrVertexBuffer.h" 19 20// probably makes no sense for this to be less than a page 21static const size_t VERTEX_POOL_VB_SIZE = 1 << 18; 22static const int VERTEX_POOL_VB_COUNT = 4; 23static const size_t INDEX_POOL_IB_SIZE = 1 << 16; 24static const int INDEX_POOL_IB_COUNT = 4; 25 26//////////////////////////////////////////////////////////////////////////////// 27 28extern void gr_run_unittests(); 29 30#define DEBUG_INVAL_BUFFER 0xdeadcafe 31#define DEBUG_INVAL_START_IDX -1 32 33GrGpu::GrGpu() 34 : fContext(NULL) 35 , fResetTimestamp(kExpiredTimestamp+1) 36 , fVertexPool(NULL) 37 , fIndexPool(NULL) 38 , fVertexPoolUseCnt(0) 39 , fIndexPoolUseCnt(0) 40 , fQuadIndexBuffer(NULL) 41 , fUnitSquareVertexBuffer(NULL) 42 , fPathRendererChain(NULL) 43 , fContextIsDirty(true) 44 , fResourceHead(NULL) { 45 46#if GR_DEBUG 47 //gr_run_unittests(); 48#endif 49 50 fGeomPoolStateStack.push_back(); 51#if GR_DEBUG 52 GeometryPoolState& poolState = fGeomPoolStateStack.back(); 53 poolState.fPoolVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 54 poolState.fPoolStartVertex = DEBUG_INVAL_START_IDX; 55 poolState.fPoolIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 56 poolState.fPoolStartIndex = DEBUG_INVAL_START_IDX; 57#endif 58 resetStats(); 59} 60 61GrGpu::~GrGpu() { 62 this->releaseResources(); 63} 64 65void GrGpu::abandonResources() { 66 67 while (NULL != fResourceHead) { 68 fResourceHead->abandon(); 69 } 70 71 GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid()); 72 GrAssert(NULL == fUnitSquareVertexBuffer || 73 !fUnitSquareVertexBuffer->isValid()); 74 GrSafeSetNull(fQuadIndexBuffer); 75 GrSafeSetNull(fUnitSquareVertexBuffer); 76 delete fVertexPool; 77 fVertexPool = NULL; 78 delete fIndexPool; 79 fIndexPool = NULL; 80 // in case path renderer has any GrResources, start from scratch 81 GrSafeSetNull(fPathRendererChain); 82} 83 84void GrGpu::releaseResources() { 85 86 while (NULL != fResourceHead) { 87 fResourceHead->release(); 88 } 89 90 GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid()); 91 GrAssert(NULL == fUnitSquareVertexBuffer || 92 !fUnitSquareVertexBuffer->isValid()); 93 GrSafeSetNull(fQuadIndexBuffer); 94 GrSafeSetNull(fUnitSquareVertexBuffer); 95 delete fVertexPool; 96 fVertexPool = NULL; 97 delete fIndexPool; 98 fIndexPool = NULL; 99 // in case path renderer has any GrResources, start from scratch 100 GrSafeSetNull(fPathRendererChain); 101} 102 103void GrGpu::insertResource(GrResource* resource) { 104 GrAssert(NULL != resource); 105 GrAssert(this == resource->getGpu()); 106 GrAssert(NULL == resource->fNext); 107 GrAssert(NULL == resource->fPrevious); 108 109 resource->fNext = fResourceHead; 110 if (NULL != fResourceHead) { 111 GrAssert(NULL == fResourceHead->fPrevious); 112 fResourceHead->fPrevious = resource; 113 } 114 fResourceHead = resource; 115} 116 117void GrGpu::removeResource(GrResource* resource) { 118 GrAssert(NULL != resource); 119 GrAssert(NULL != fResourceHead); 120 121 if (fResourceHead == resource) { 122 GrAssert(NULL == resource->fPrevious); 123 fResourceHead = resource->fNext; 124 } else { 125 GrAssert(NULL != fResourceHead); 126 resource->fPrevious->fNext = resource->fNext; 127 } 128 if (NULL != resource->fNext) { 129 resource->fNext->fPrevious = resource->fPrevious; 130 } 131 resource->fNext = NULL; 132 resource->fPrevious = NULL; 133} 134 135 136void GrGpu::unimpl(const char msg[]) { 137#if GR_DEBUG 138 GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg); 139#endif 140} 141 142//////////////////////////////////////////////////////////////////////////////// 143 144GrTexture* GrGpu::createTexture(const GrTextureDesc& desc, 145 const void* srcData, size_t rowBytes) { 146 this->handleDirtyContext(); 147 GrTexture* tex = this->onCreateTexture(desc, srcData, rowBytes); 148 if (NULL != tex && 149 (kRenderTarget_GrTextureFlagBit & desc.fFlags) && 150 !(kNoStencil_GrTextureFlagBit & desc.fFlags)) { 151 GrAssert(NULL != tex->asRenderTarget()); 152 // TODO: defer this and attach dynamically 153 if (!this->attachStencilBufferToRenderTarget(tex->asRenderTarget())) { 154 tex->unref(); 155 return NULL; 156 } 157 } 158 return tex; 159} 160 161bool GrGpu::attachStencilBufferToRenderTarget(GrRenderTarget* rt) { 162 GrAssert(NULL == rt->getStencilBuffer()); 163 GrStencilBuffer* sb = 164 this->getContext()->findStencilBuffer(rt->allocatedWidth(), 165 rt->allocatedHeight(), 166 rt->numSamples()); 167 if (NULL != sb) { 168 rt->setStencilBuffer(sb); 169 bool attached = this->attachStencilBufferToRenderTarget(sb, rt); 170 if (!attached) { 171 rt->setStencilBuffer(NULL); 172 } 173 return attached; 174 } 175 if (this->createStencilBufferForRenderTarget(rt, rt->allocatedWidth(), 176 rt->allocatedHeight())) { 177 rt->getStencilBuffer()->ref(); 178 rt->getStencilBuffer()->transferToCacheAndLock(); 179 180 // Right now we're clearing the stencil buffer here after it is 181 // attached to an RT for the first time. When we start matching 182 // stencil buffers with smaller color targets this will no longer 183 // be correct because it won't be guaranteed to clear the entire 184 // sb. 185 // We used to clear down in the GL subclass using a special purpose 186 // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported 187 // FBO status. 188 GrRenderTarget* oldRT = fCurrDrawState.fRenderTarget; 189 fCurrDrawState.fRenderTarget = rt; 190 this->clearStencil(); 191 fCurrDrawState.fRenderTarget = oldRT; 192 return true; 193 } else { 194 return false; 195 } 196} 197 198GrResource* GrGpu::createPlatformSurface(const GrPlatformSurfaceDesc& desc) { 199 this->handleDirtyContext(); 200 return this->onCreatePlatformSurface(desc); 201} 202 203GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) { 204 this->handleDirtyContext(); 205 return this->onCreateVertexBuffer(size, dynamic); 206} 207 208GrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) { 209 this->handleDirtyContext(); 210 return this->onCreateIndexBuffer(size, dynamic); 211} 212 213void GrGpu::clear(const GrIRect* rect, GrColor color) { 214 this->handleDirtyContext(); 215 this->onClear(rect, color); 216} 217 218void GrGpu::forceRenderTargetFlush() { 219 this->handleDirtyContext(); 220 this->onForceRenderTargetFlush(); 221} 222 223bool GrGpu::readPixels(GrRenderTarget* target, 224 int left, int top, int width, int height, 225 GrPixelConfig config, void* buffer, 226 size_t rowBytes) { 227 228 this->handleDirtyContext(); 229 return this->onReadPixels(target, left, top, width, height, 230 config, buffer, rowBytes); 231} 232 233//////////////////////////////////////////////////////////////////////////////// 234 235static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1; 236 237GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535); 238 239static inline void fill_indices(uint16_t* indices, int quadCount) { 240 for (int i = 0; i < quadCount; ++i) { 241 indices[6 * i + 0] = 4 * i + 0; 242 indices[6 * i + 1] = 4 * i + 1; 243 indices[6 * i + 2] = 4 * i + 2; 244 indices[6 * i + 3] = 4 * i + 0; 245 indices[6 * i + 4] = 4 * i + 2; 246 indices[6 * i + 5] = 4 * i + 3; 247 } 248} 249 250const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const { 251 if (NULL == fQuadIndexBuffer) { 252 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS; 253 GrGpu* me = const_cast<GrGpu*>(this); 254 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false); 255 if (NULL != fQuadIndexBuffer) { 256 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock(); 257 if (NULL != indices) { 258 fill_indices(indices, MAX_QUADS); 259 fQuadIndexBuffer->unlock(); 260 } else { 261 indices = (uint16_t*)GrMalloc(SIZE); 262 fill_indices(indices, MAX_QUADS); 263 if (!fQuadIndexBuffer->updateData(indices, SIZE)) { 264 fQuadIndexBuffer->unref(); 265 fQuadIndexBuffer = NULL; 266 GrCrash("Can't get indices into buffer!"); 267 } 268 GrFree(indices); 269 } 270 } 271 } 272 273 return fQuadIndexBuffer; 274} 275 276const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const { 277 if (NULL == fUnitSquareVertexBuffer) { 278 279 static const GrPoint DATA[] = { 280 { 0, 0 }, 281 { GR_Scalar1, 0 }, 282 { GR_Scalar1, GR_Scalar1 }, 283 { 0, GR_Scalar1 } 284#if 0 285 GrPoint(0, 0), 286 GrPoint(GR_Scalar1,0), 287 GrPoint(GR_Scalar1,GR_Scalar1), 288 GrPoint(0, GR_Scalar1) 289#endif 290 }; 291 static const size_t SIZE = sizeof(DATA); 292 293 GrGpu* me = const_cast<GrGpu*>(this); 294 fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false); 295 if (NULL != fUnitSquareVertexBuffer) { 296 if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) { 297 fUnitSquareVertexBuffer->unref(); 298 fUnitSquareVertexBuffer = NULL; 299 GrCrash("Can't get vertices into buffer!"); 300 } 301 } 302 } 303 304 return fUnitSquareVertexBuffer; 305} 306 307//////////////////////////////////////////////////////////////////////////////// 308 309// stencil settings to use when clip is in stencil 310const GrStencilSettings GrGpu::gClipStencilSettings = { 311 kKeep_StencilOp, kKeep_StencilOp, 312 kKeep_StencilOp, kKeep_StencilOp, 313 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc, 314 0, 0, 315 0, 0, 316 0, 0 317}; 318 319// mapping of clip-respecting stencil funcs to normal stencil funcs 320// mapping depends on whether stencil-clipping is in effect. 321static const GrStencilFunc gGrClipToNormalStencilFunc[2][kClipStencilFuncCount] = { 322 {// Stencil-Clipping is DISABLED, effectively always inside the clip 323 // In the Clip Funcs 324 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc 325 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 326 kLess_StencilFunc, // kLessIfInClip_StencilFunc 327 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 328 // Special in the clip func that forces user's ref to be 0. 329 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc 330 // make ref 0 and do normal nequal. 331 }, 332 {// Stencil-Clipping is ENABLED 333 // In the Clip Funcs 334 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc 335 // eq stencil clip bit, mask 336 // out user bits. 337 338 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 339 // add stencil bit to mask and ref 340 341 kLess_StencilFunc, // kLessIfInClip_StencilFunc 342 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 343 // for both of these we can add 344 // the clip bit to the mask and 345 // ref and compare as normal 346 // Special in the clip func that forces user's ref to be 0. 347 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc 348 // make ref have only the clip bit set 349 // and make comparison be less 350 // 10..0 < 1..user_bits.. 351 } 352}; 353 354GrStencilFunc GrGpu::ConvertStencilFunc(bool stencilInClip, GrStencilFunc func) { 355 GrAssert(func >= 0); 356 if (func >= kBasicStencilFuncCount) { 357 GrAssert(func < kStencilFuncCount); 358 func = gGrClipToNormalStencilFunc[stencilInClip ? 1 : 0][func - kBasicStencilFuncCount]; 359 GrAssert(func >= 0 && func < kBasicStencilFuncCount); 360 } 361 return func; 362} 363 364void GrGpu::ConvertStencilFuncAndMask(GrStencilFunc func, 365 bool clipInStencil, 366 unsigned int clipBit, 367 unsigned int userBits, 368 unsigned int* ref, 369 unsigned int* mask) { 370 if (func < kBasicStencilFuncCount) { 371 *mask &= userBits; 372 *ref &= userBits; 373 } else { 374 if (clipInStencil) { 375 switch (func) { 376 case kAlwaysIfInClip_StencilFunc: 377 *mask = clipBit; 378 *ref = clipBit; 379 break; 380 case kEqualIfInClip_StencilFunc: 381 case kLessIfInClip_StencilFunc: 382 case kLEqualIfInClip_StencilFunc: 383 *mask = (*mask & userBits) | clipBit; 384 *ref = (*ref & userBits) | clipBit; 385 break; 386 case kNonZeroIfInClip_StencilFunc: 387 *mask = (*mask & userBits) | clipBit; 388 *ref = clipBit; 389 break; 390 default: 391 GrCrash("Unknown stencil func"); 392 } 393 } else { 394 *mask &= userBits; 395 *ref &= userBits; 396 } 397 } 398} 399 400//////////////////////////////////////////////////////////////////////////////// 401 402#define VISUALIZE_COMPLEX_CLIP 0 403 404#if VISUALIZE_COMPLEX_CLIP 405 #include "GrRandom.h" 406 GrRandom gRandom; 407 #define SET_RANDOM_COLOR this->setColor(0xff000000 | gRandom.nextU()); 408#else 409 #define SET_RANDOM_COLOR 410#endif 411 412namespace { 413// determines how many elements at the head of the clip can be skipped and 414// whether the initial clear should be to the inside- or outside-the-clip value, 415// and what op should be used to draw the first element that isn't skipped. 416int process_initial_clip_elements(const GrClip& clip, 417 bool* clearToInside, 418 GrSetOp* startOp) { 419 420 // logically before the first element of the clip stack is 421 // processed the clip is entirely open. However, depending on the 422 // first set op we may prefer to clear to 0 for performance. We may 423 // also be able to skip the initial clip paths/rects. We loop until 424 // we cannot skip an element. 425 int curr; 426 bool done = false; 427 *clearToInside = true; 428 int count = clip.getElementCount(); 429 430 for (curr = 0; curr < count && !done; ++curr) { 431 switch (clip.getOp(curr)) { 432 case kReplace_SetOp: 433 // replace ignores everything previous 434 *startOp = kReplace_SetOp; 435 *clearToInside = false; 436 done = true; 437 break; 438 case kIntersect_SetOp: 439 // if everything is initially clearToInside then intersect is 440 // same as clear to 0 and treat as a replace. Otherwise, 441 // set stays empty. 442 if (*clearToInside) { 443 *startOp = kReplace_SetOp; 444 *clearToInside = false; 445 done = true; 446 } 447 break; 448 // we can skip a leading union. 449 case kUnion_SetOp: 450 // if everything is initially outside then union is 451 // same as replace. Otherwise, every pixel is still 452 // clearToInside 453 if (!*clearToInside) { 454 *startOp = kReplace_SetOp; 455 done = true; 456 } 457 break; 458 case kXor_SetOp: 459 // xor is same as difference or replace both of which 460 // can be 1-pass instead of 2 for xor. 461 if (*clearToInside) { 462 *startOp = kDifference_SetOp; 463 } else { 464 *startOp = kReplace_SetOp; 465 } 466 done = true; 467 break; 468 case kDifference_SetOp: 469 // if all pixels are clearToInside then we have to process the 470 // difference, otherwise it has no effect and all pixels 471 // remain outside. 472 if (*clearToInside) { 473 *startOp = kDifference_SetOp; 474 done = true; 475 } 476 break; 477 case kReverseDifference_SetOp: 478 // if all pixels are clearToInside then reverse difference 479 // produces empty set. Otherise it is same as replace 480 if (*clearToInside) { 481 *clearToInside = false; 482 } else { 483 *startOp = kReplace_SetOp; 484 done = true; 485 } 486 break; 487 default: 488 GrCrash("Unknown set op."); 489 } 490 } 491 return done ? curr-1 : count; 492} 493} 494 495bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { 496 const GrIRect* r = NULL; 497 GrIRect clipRect; 498 499 // we check this early because we need a valid 500 // render target to setup stencil clipping 501 // before even going into flushGraphicsState 502 if (NULL == fCurrDrawState.fRenderTarget) { 503 GrAssert(!"No render target bound."); 504 return false; 505 } 506 507 if (fCurrDrawState.fFlagBits & kClip_StateBit) { 508 GrRenderTarget& rt = *fCurrDrawState.fRenderTarget; 509 510 GrRect bounds; 511 GrRect rtRect; 512 rtRect.setLTRB(0, 0, 513 GrIntToScalar(rt.width()), GrIntToScalar(rt.height())); 514 if (fClip.hasConservativeBounds()) { 515 bounds = fClip.getConservativeBounds(); 516 if (!bounds.intersect(rtRect)) { 517 bounds.setEmpty(); 518 } 519 } else { 520 bounds = rtRect; 521 } 522 523 bounds.roundOut(&clipRect); 524 if (clipRect.isEmpty()) { 525 clipRect.setLTRB(0,0,0,0); 526 } 527 r = &clipRect; 528 529 // use the stencil clip if we can't represent the clip as a rectangle. 530 fClipInStencil = !fClip.isRect() && !fClip.isEmpty() && 531 !bounds.isEmpty(); 532 533 // TODO: dynamically attach a SB when needed. 534 GrStencilBuffer* stencilBuffer = rt.getStencilBuffer(); 535 if (fClipInStencil && NULL == stencilBuffer) { 536 return false; 537 } 538 539 if (fClipInStencil && 540 stencilBuffer->mustRenderClip(fClip, rt.width(), rt.height())) { 541 542 stencilBuffer->setLastClip(fClip, rt.width(), rt.height()); 543 544 // we set the current clip to the bounds so that our recursive 545 // draws are scissored to them. We use the copy of the complex clip 546 // we just stashed on the SB to render from. We set it back after 547 // we finish drawing it into the stencil. 548 const GrClip& clip = stencilBuffer->getLastClip(); 549 fClip.setFromRect(bounds); 550 551 AutoStateRestore asr(this); 552 AutoGeometryPush agp(this); 553 554 this->setViewMatrix(GrMatrix::I()); 555 this->flushScissor(NULL); 556#if !VISUALIZE_COMPLEX_CLIP 557 this->enableState(kNoColorWrites_StateBit); 558#else 559 this->disableState(kNoColorWrites_StateBit); 560#endif 561 int count = clip.getElementCount(); 562 int clipBit = stencilBuffer->bits(); 563 clipBit = (1 << (clipBit-1)); 564 565 bool clearToInside; 566 GrSetOp startOp = kReplace_SetOp; // suppress warning 567 int start = process_initial_clip_elements(clip, &clearToInside, 568 &startOp); 569 570 this->clearStencilClip(clipRect, clearToInside); 571 572 // walk through each clip element and perform its set op 573 // with the existing clip. 574 for (int c = start; c < count; ++c) { 575 GrPathFill fill; 576 bool fillInverted; 577 // enabled at bottom of loop 578 this->disableState(kModifyStencilClip_StateBit); 579 580 bool canRenderDirectToStencil; // can the clip element be drawn 581 // directly to the stencil buffer 582 // with a non-inverted fill rule 583 // without extra passes to 584 // resolve in/out status. 585 586 GrPathRenderer* pr = NULL; 587 const GrPath* clipPath = NULL; 588 GrPathRenderer::AutoClearPath arp; 589 if (kRect_ClipType == clip.getElementType(c)) { 590 canRenderDirectToStencil = true; 591 fill = kEvenOdd_PathFill; 592 fillInverted = false; 593 } else { 594 fill = clip.getPathFill(c); 595 fillInverted = GrIsFillInverted(fill); 596 fill = GrNonInvertedFill(fill); 597 clipPath = &clip.getPath(c); 598 pr = this->getClipPathRenderer(*clipPath, fill); 599 if (NULL == pr) { 600 fClipInStencil = false; 601 fClip = clip; 602 return false; 603 } 604 canRenderDirectToStencil = 605 !pr->requiresStencilPass(this, *clipPath, fill); 606 arp.set(pr, this, clipPath, fill, false, NULL); 607 } 608 609 GrSetOp op = (c == start) ? startOp : clip.getOp(c); 610 int passes; 611 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; 612 613 bool canDrawDirectToClip; // Given the renderer, the element, 614 // fill rule, and set operation can 615 // we render the element directly to 616 // stencil bit used for clipping. 617 canDrawDirectToClip = 618 GrStencilSettings::GetClipPasses(op, 619 canRenderDirectToStencil, 620 clipBit, 621 fillInverted, 622 &passes, stencilSettings); 623 624 // draw the element to the client stencil bits if necessary 625 if (!canDrawDirectToClip) { 626 static const GrStencilSettings gDrawToStencil = { 627 kIncClamp_StencilOp, kIncClamp_StencilOp, 628 kIncClamp_StencilOp, kIncClamp_StencilOp, 629 kAlways_StencilFunc, kAlways_StencilFunc, 630 0xffffffff, 0xffffffff, 631 0x00000000, 0x00000000, 632 0xffffffff, 0xffffffff, 633 }; 634 SET_RANDOM_COLOR 635 if (kRect_ClipType == clip.getElementType(c)) { 636 this->setStencil(gDrawToStencil); 637 this->drawSimpleRect(clip.getRect(c), NULL, 0); 638 } else { 639 if (canRenderDirectToStencil) { 640 this->setStencil(gDrawToStencil); 641 pr->drawPath(0); 642 } else { 643 pr->drawPathToStencil(); 644 } 645 } 646 } 647 648 // now we modify the clip bit by rendering either the clip 649 // element directly or a bounding rect of the entire clip. 650 this->enableState(kModifyStencilClip_StateBit); 651 for (int p = 0; p < passes; ++p) { 652 this->setStencil(stencilSettings[p]); 653 if (canDrawDirectToClip) { 654 if (kRect_ClipType == clip.getElementType(c)) { 655 SET_RANDOM_COLOR 656 this->drawSimpleRect(clip.getRect(c), NULL, 0); 657 } else { 658 SET_RANDOM_COLOR 659 pr->drawPath(0); 660 } 661 } else { 662 SET_RANDOM_COLOR 663 this->drawSimpleRect(bounds, NULL, 0); 664 } 665 } 666 } 667 // restore clip 668 fClip = clip; 669 // recusive draws would have disabled this since they drew with 670 // the clip bounds as clip. 671 fClipInStencil = true; 672 } 673 } 674 675 // Must flush the scissor after graphics state 676 if (!this->flushGraphicsState(type)) { 677 return false; 678 } 679 this->flushScissor(r); 680 return true; 681} 682 683GrPathRenderer* GrGpu::getClipPathRenderer(const GrPath& path, 684 GrPathFill fill) { 685 if (NULL == fPathRendererChain) { 686 fPathRendererChain = 687 new GrPathRendererChain(this->getContext(), 688 GrPathRendererChain::kNonAAOnly_UsageFlag); 689 } 690 return fPathRendererChain->getPathRenderer(this->getCaps(), 691 path, fill, false); 692} 693 694 695//////////////////////////////////////////////////////////////////////////////// 696 697void GrGpu::geometrySourceWillPush() { 698 const GeometrySrcState& geoSrc = this->getGeomSrc(); 699 if (kArray_GeometrySrcType == geoSrc.fVertexSrc || 700 kReserved_GeometrySrcType == geoSrc.fVertexSrc) { 701 this->finalizeReservedVertices(); 702 } 703 if (kArray_GeometrySrcType == geoSrc.fIndexSrc || 704 kReserved_GeometrySrcType == geoSrc.fIndexSrc) { 705 this->finalizeReservedIndices(); 706 } 707 GeometryPoolState& newState = fGeomPoolStateStack.push_back(); 708#if GR_DEBUG 709 newState.fPoolVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 710 newState.fPoolStartVertex = DEBUG_INVAL_START_IDX; 711 newState.fPoolIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 712 newState.fPoolStartIndex = DEBUG_INVAL_START_IDX; 713#endif 714} 715 716void GrGpu::geometrySourceWillPop(const GeometrySrcState& restoredState) { 717 // if popping last entry then pops are unbalanced with pushes 718 GrAssert(fGeomPoolStateStack.count() > 1); 719 fGeomPoolStateStack.pop_back(); 720} 721 722void GrGpu::onDrawIndexed(GrPrimitiveType type, 723 int startVertex, 724 int startIndex, 725 int vertexCount, 726 int indexCount) { 727 728 this->handleDirtyContext(); 729 730 if (!this->setupClipAndFlushState(type)) { 731 return; 732 } 733 734#if GR_COLLECT_STATS 735 fStats.fVertexCnt += vertexCount; 736 fStats.fIndexCnt += indexCount; 737 fStats.fDrawCnt += 1; 738#endif 739 740 int sVertex = startVertex; 741 int sIndex = startIndex; 742 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount); 743 744 this->onGpuDrawIndexed(type, sVertex, sIndex, 745 vertexCount, indexCount); 746} 747 748void GrGpu::onDrawNonIndexed(GrPrimitiveType type, 749 int startVertex, 750 int vertexCount) { 751 this->handleDirtyContext(); 752 753 if (!this->setupClipAndFlushState(type)) { 754 return; 755 } 756#if GR_COLLECT_STATS 757 fStats.fVertexCnt += vertexCount; 758 fStats.fDrawCnt += 1; 759#endif 760 761 int sVertex = startVertex; 762 setupGeometry(&sVertex, NULL, vertexCount, 0); 763 764 this->onGpuDrawNonIndexed(type, sVertex, vertexCount); 765} 766 767void GrGpu::finalizeReservedVertices() { 768 GrAssert(NULL != fVertexPool); 769 fVertexPool->unlock(); 770} 771 772void GrGpu::finalizeReservedIndices() { 773 GrAssert(NULL != fIndexPool); 774 fIndexPool->unlock(); 775} 776 777void GrGpu::prepareVertexPool() { 778 if (NULL == fVertexPool) { 779 GrAssert(0 == fVertexPoolUseCnt); 780 fVertexPool = new GrVertexBufferAllocPool(this, true, 781 VERTEX_POOL_VB_SIZE, 782 VERTEX_POOL_VB_COUNT); 783 fVertexPool->releaseGpuRef(); 784 } else if (!fVertexPoolUseCnt) { 785 // the client doesn't have valid data in the pool 786 fVertexPool->reset(); 787 } 788} 789 790void GrGpu::prepareIndexPool() { 791 if (NULL == fIndexPool) { 792 GrAssert(0 == fIndexPoolUseCnt); 793 fIndexPool = new GrIndexBufferAllocPool(this, true, 794 INDEX_POOL_IB_SIZE, 795 INDEX_POOL_IB_COUNT); 796 fIndexPool->releaseGpuRef(); 797 } else if (!fIndexPoolUseCnt) { 798 // the client doesn't have valid data in the pool 799 fIndexPool->reset(); 800 } 801} 802 803bool GrGpu::onReserveVertexSpace(GrVertexLayout vertexLayout, 804 int vertexCount, 805 void** vertices) { 806 GeometryPoolState& geomPoolState = fGeomPoolStateStack.back(); 807 808 GrAssert(vertexCount > 0); 809 GrAssert(NULL != vertices); 810 811 this->prepareVertexPool(); 812 813 *vertices = fVertexPool->makeSpace(vertexLayout, 814 vertexCount, 815 &geomPoolState.fPoolVertexBuffer, 816 &geomPoolState.fPoolStartVertex); 817 if (NULL == *vertices) { 818 return false; 819 } 820 ++fVertexPoolUseCnt; 821 return true; 822} 823 824bool GrGpu::onReserveIndexSpace(int indexCount, void** indices) { 825 GeometryPoolState& geomPoolState = fGeomPoolStateStack.back(); 826 827 GrAssert(indexCount > 0); 828 GrAssert(NULL != indices); 829 830 this->prepareIndexPool(); 831 832 *indices = fIndexPool->makeSpace(indexCount, 833 &geomPoolState.fPoolIndexBuffer, 834 &geomPoolState.fPoolStartIndex); 835 if (NULL == *indices) { 836 return false; 837 } 838 ++fIndexPoolUseCnt; 839 return true; 840} 841 842void GrGpu::releaseReservedVertexSpace() { 843 const GeometrySrcState& geoSrc = this->getGeomSrc(); 844 GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc); 845 size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout); 846 fVertexPool->putBack(bytes); 847 --fVertexPoolUseCnt; 848} 849 850void GrGpu::releaseReservedIndexSpace() { 851 const GeometrySrcState& geoSrc = this->getGeomSrc(); 852 GrAssert(kReserved_GeometrySrcType == geoSrc.fIndexSrc); 853 size_t bytes = geoSrc.fIndexCount * sizeof(uint16_t); 854 fIndexPool->putBack(bytes); 855 --fIndexPoolUseCnt; 856} 857 858void GrGpu::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) { 859 this->prepareVertexPool(); 860 GeometryPoolState& geomPoolState = fGeomPoolStateStack.back(); 861#if GR_DEBUG 862 bool success = 863#endif 864 fVertexPool->appendVertices(this->getGeomSrc().fVertexLayout, 865 vertexCount, 866 vertexArray, 867 &geomPoolState.fPoolVertexBuffer, 868 &geomPoolState.fPoolStartVertex); 869 ++fVertexPoolUseCnt; 870 GR_DEBUGASSERT(success); 871} 872 873void GrGpu::onSetIndexSourceToArray(const void* indexArray, int indexCount) { 874 this->prepareIndexPool(); 875 GeometryPoolState& geomPoolState = fGeomPoolStateStack.back(); 876#if GR_DEBUG 877 bool success = 878#endif 879 fIndexPool->appendIndices(indexCount, 880 indexArray, 881 &geomPoolState.fPoolIndexBuffer, 882 &geomPoolState.fPoolStartIndex); 883 ++fIndexPoolUseCnt; 884 GR_DEBUGASSERT(success); 885} 886 887void GrGpu::releaseVertexArray() { 888 // if vertex source was array, we stowed data in the pool 889 const GeometrySrcState& geoSrc = this->getGeomSrc(); 890 GrAssert(kArray_GeometrySrcType == geoSrc.fVertexSrc); 891 size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout); 892 fVertexPool->putBack(bytes); 893 --fVertexPoolUseCnt; 894} 895 896void GrGpu::releaseIndexArray() { 897 // if index source was array, we stowed data in the pool 898 const GeometrySrcState& geoSrc = this->getGeomSrc(); 899 GrAssert(kArray_GeometrySrcType == geoSrc.fIndexSrc); 900 size_t bytes = geoSrc.fIndexCount * sizeof(uint16_t); 901 fIndexPool->putBack(bytes); 902 --fIndexPoolUseCnt; 903} 904 905//////////////////////////////////////////////////////////////////////////////// 906 907const GrGpuStats& GrGpu::getStats() const { 908 return fStats; 909} 910 911void GrGpu::resetStats() { 912 memset(&fStats, 0, sizeof(fStats)); 913} 914 915void GrGpu::printStats() const { 916 if (GR_COLLECT_STATS) { 917 GrPrintf( 918 "-v-------------------------GPU STATS----------------------------v-\n" 919 "Stats collection is: %s\n" 920 "Draws: %04d, Verts: %04d, Indices: %04d\n" 921 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n" 922 "TexCreates: %04d, RTCreates:%04d\n" 923 "-^--------------------------------------------------------------^-\n", 924 (GR_COLLECT_STATS ? "ON" : "OFF"), 925 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt, 926 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt, 927 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt); 928 } 929} 930 931//////////////////////////////////////////////////////////////////////////////// 932const GrSamplerState GrSamplerState::gClampNoFilter( 933 GrSamplerState::kClamp_WrapMode, 934 GrSamplerState::kClamp_WrapMode, 935 GrSamplerState::kNormal_SampleMode, 936 GrMatrix::I(), 937 GrSamplerState::kNearest_Filter); 938 939 940 941 942