GrGpu.cpp revision b1caea00d8b852576bf3734b7088acdd505d0b8b
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->width(), 165 rt->height(), 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, 176 rt->width(), rt->height())) { 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 GrDrawState::AutoRenderTargetRestore artr(this->drawState(), rt); 189 this->clearStencil(); 190 return true; 191 } else { 192 return false; 193 } 194} 195 196GrTexture* GrGpu::createPlatformTexture(const GrPlatformTextureDesc& desc) { 197 this->handleDirtyContext(); 198 GrTexture* tex = this->onCreatePlatformTexture(desc); 199 if (NULL == tex) { 200 return NULL; 201 } 202 // TODO: defer this and attach dynamically 203 GrRenderTarget* tgt = tex->asRenderTarget(); 204 if (NULL != tgt && 205 !this->attachStencilBufferToRenderTarget(tgt)) { 206 tex->unref(); 207 return NULL; 208 } else { 209 return tex; 210 } 211} 212 213GrRenderTarget* GrGpu::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) { 214 this->handleDirtyContext(); 215 return this->onCreatePlatformRenderTarget(desc); 216} 217 218GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) { 219 this->handleDirtyContext(); 220 return this->onCreateVertexBuffer(size, dynamic); 221} 222 223GrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) { 224 this->handleDirtyContext(); 225 return this->onCreateIndexBuffer(size, dynamic); 226} 227 228void GrGpu::clear(const GrIRect* rect, GrColor color) { 229 if (NULL == this->getDrawState().getRenderTarget()) { 230 return; 231 } 232 this->handleDirtyContext(); 233 this->onClear(rect, color); 234} 235 236void GrGpu::forceRenderTargetFlush() { 237 this->handleDirtyContext(); 238 this->onForceRenderTargetFlush(); 239} 240 241bool GrGpu::readPixels(GrRenderTarget* target, 242 int left, int top, int width, int height, 243 GrPixelConfig config, void* buffer, 244 size_t rowBytes, bool invertY) { 245 GrAssert(GrPixelConfigIsUnpremultiplied(config) == 246 GrPixelConfigIsUnpremultiplied(target->config())); 247 this->handleDirtyContext(); 248 return this->onReadPixels(target, left, top, width, height, 249 config, buffer, rowBytes, invertY); 250} 251 252void GrGpu::writeTexturePixels(GrTexture* texture, 253 int left, int top, int width, int height, 254 GrPixelConfig config, const void* buffer, 255 size_t rowBytes) { 256 GrAssert(GrPixelConfigIsUnpremultiplied(config) == 257 GrPixelConfigIsUnpremultiplied(texture->config())); 258 this->handleDirtyContext(); 259 this->onWriteTexturePixels(texture, left, top, width, height, 260 config, buffer, rowBytes); 261} 262 263//////////////////////////////////////////////////////////////////////////////// 264 265static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1; 266 267GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535); 268 269static inline void fill_indices(uint16_t* indices, int quadCount) { 270 for (int i = 0; i < quadCount; ++i) { 271 indices[6 * i + 0] = 4 * i + 0; 272 indices[6 * i + 1] = 4 * i + 1; 273 indices[6 * i + 2] = 4 * i + 2; 274 indices[6 * i + 3] = 4 * i + 0; 275 indices[6 * i + 4] = 4 * i + 2; 276 indices[6 * i + 5] = 4 * i + 3; 277 } 278} 279 280const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const { 281 if (NULL == fQuadIndexBuffer) { 282 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS; 283 GrGpu* me = const_cast<GrGpu*>(this); 284 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false); 285 if (NULL != fQuadIndexBuffer) { 286 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock(); 287 if (NULL != indices) { 288 fill_indices(indices, MAX_QUADS); 289 fQuadIndexBuffer->unlock(); 290 } else { 291 indices = (uint16_t*)GrMalloc(SIZE); 292 fill_indices(indices, MAX_QUADS); 293 if (!fQuadIndexBuffer->updateData(indices, SIZE)) { 294 fQuadIndexBuffer->unref(); 295 fQuadIndexBuffer = NULL; 296 GrCrash("Can't get indices into buffer!"); 297 } 298 GrFree(indices); 299 } 300 } 301 } 302 303 return fQuadIndexBuffer; 304} 305 306const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const { 307 if (NULL == fUnitSquareVertexBuffer) { 308 309 static const GrPoint DATA[] = { 310 { 0, 0 }, 311 { GR_Scalar1, 0 }, 312 { GR_Scalar1, GR_Scalar1 }, 313 { 0, GR_Scalar1 } 314#if 0 315 GrPoint(0, 0), 316 GrPoint(GR_Scalar1,0), 317 GrPoint(GR_Scalar1,GR_Scalar1), 318 GrPoint(0, GR_Scalar1) 319#endif 320 }; 321 static const size_t SIZE = sizeof(DATA); 322 323 GrGpu* me = const_cast<GrGpu*>(this); 324 fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false); 325 if (NULL != fUnitSquareVertexBuffer) { 326 if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) { 327 fUnitSquareVertexBuffer->unref(); 328 fUnitSquareVertexBuffer = NULL; 329 GrCrash("Can't get vertices into buffer!"); 330 } 331 } 332 } 333 334 return fUnitSquareVertexBuffer; 335} 336 337//////////////////////////////////////////////////////////////////////////////// 338 339// stencil settings to use when clip is in stencil 340GR_STATIC_CONST_SAME_STENCIL(gClipStencilSettings, 341 kKeep_StencilOp, 342 kKeep_StencilOp, 343 kAlwaysIfInClip_StencilFunc, 344 0x0000, 345 0x0000, 346 0x0000); 347const GrStencilSettings& GrGpu::gClipStencilSettings = ::gClipStencilSettings; 348 349// mapping of clip-respecting stencil funcs to normal stencil funcs 350// mapping depends on whether stencil-clipping is in effect. 351static const GrStencilFunc gGrClipToNormalStencilFunc[2][kClipStencilFuncCount] = { 352 {// Stencil-Clipping is DISABLED, effectively always inside the clip 353 // In the Clip Funcs 354 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc 355 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 356 kLess_StencilFunc, // kLessIfInClip_StencilFunc 357 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 358 // Special in the clip func that forces user's ref to be 0. 359 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc 360 // make ref 0 and do normal nequal. 361 }, 362 {// Stencil-Clipping is ENABLED 363 // In the Clip Funcs 364 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc 365 // eq stencil clip bit, mask 366 // out user bits. 367 368 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 369 // add stencil bit to mask and ref 370 371 kLess_StencilFunc, // kLessIfInClip_StencilFunc 372 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 373 // for both of these we can add 374 // the clip bit to the mask and 375 // ref and compare as normal 376 // Special in the clip func that forces user's ref to be 0. 377 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc 378 // make ref have only the clip bit set 379 // and make comparison be less 380 // 10..0 < 1..user_bits.. 381 } 382}; 383 384GrStencilFunc GrGpu::ConvertStencilFunc(bool stencilInClip, GrStencilFunc func) { 385 GrAssert(func >= 0); 386 if (func >= kBasicStencilFuncCount) { 387 GrAssert(func < kStencilFuncCount); 388 func = gGrClipToNormalStencilFunc[stencilInClip ? 1 : 0][func - kBasicStencilFuncCount]; 389 GrAssert(func >= 0 && func < kBasicStencilFuncCount); 390 } 391 return func; 392} 393 394void GrGpu::ConvertStencilFuncAndMask(GrStencilFunc func, 395 bool clipInStencil, 396 unsigned int clipBit, 397 unsigned int userBits, 398 unsigned int* ref, 399 unsigned int* mask) { 400 if (func < kBasicStencilFuncCount) { 401 *mask &= userBits; 402 *ref &= userBits; 403 } else { 404 if (clipInStencil) { 405 switch (func) { 406 case kAlwaysIfInClip_StencilFunc: 407 *mask = clipBit; 408 *ref = clipBit; 409 break; 410 case kEqualIfInClip_StencilFunc: 411 case kLessIfInClip_StencilFunc: 412 case kLEqualIfInClip_StencilFunc: 413 *mask = (*mask & userBits) | clipBit; 414 *ref = (*ref & userBits) | clipBit; 415 break; 416 case kNonZeroIfInClip_StencilFunc: 417 *mask = (*mask & userBits) | clipBit; 418 *ref = clipBit; 419 break; 420 default: 421 GrCrash("Unknown stencil func"); 422 } 423 } else { 424 *mask &= userBits; 425 *ref &= userBits; 426 } 427 } 428} 429 430//////////////////////////////////////////////////////////////////////////////// 431 432#define VISUALIZE_COMPLEX_CLIP 0 433 434#if VISUALIZE_COMPLEX_CLIP 435 #include "GrRandom.h" 436 GrRandom gRandom; 437 #define SET_RANDOM_COLOR this->setColor(0xff000000 | gRandom.nextU()); 438#else 439 #define SET_RANDOM_COLOR 440#endif 441 442namespace { 443// determines how many elements at the head of the clip can be skipped and 444// whether the initial clear should be to the inside- or outside-the-clip value, 445// and what op should be used to draw the first element that isn't skipped. 446int process_initial_clip_elements(const GrClip& clip, 447 const GrRect& bounds, 448 bool* clearToInside, 449 GrSetOp* startOp) { 450 451 // logically before the first element of the clip stack is 452 // processed the clip is entirely open. However, depending on the 453 // first set op we may prefer to clear to 0 for performance. We may 454 // also be able to skip the initial clip paths/rects. We loop until 455 // we cannot skip an element. 456 int curr; 457 bool done = false; 458 *clearToInside = true; 459 int count = clip.getElementCount(); 460 461 for (curr = 0; curr < count && !done; ++curr) { 462 switch (clip.getOp(curr)) { 463 case kReplace_SetOp: 464 // replace ignores everything previous 465 *startOp = kReplace_SetOp; 466 *clearToInside = false; 467 done = true; 468 break; 469 case kIntersect_SetOp: 470 // if this element contains the entire bounds then we 471 // can skip it. 472 if (kRect_ClipType == clip.getElementType(curr) 473 && clip.getRect(curr).contains(bounds)) { 474 break; 475 } 476 // if everything is initially clearToInside then intersect is 477 // same as clear to 0 and treat as a replace. Otherwise, 478 // set stays empty. 479 if (*clearToInside) { 480 *startOp = kReplace_SetOp; 481 *clearToInside = false; 482 done = true; 483 } 484 break; 485 // we can skip a leading union. 486 case kUnion_SetOp: 487 // if everything is initially outside then union is 488 // same as replace. Otherwise, every pixel is still 489 // clearToInside 490 if (!*clearToInside) { 491 *startOp = kReplace_SetOp; 492 done = true; 493 } 494 break; 495 case kXor_SetOp: 496 // xor is same as difference or replace both of which 497 // can be 1-pass instead of 2 for xor. 498 if (*clearToInside) { 499 *startOp = kDifference_SetOp; 500 } else { 501 *startOp = kReplace_SetOp; 502 } 503 done = true; 504 break; 505 case kDifference_SetOp: 506 // if all pixels are clearToInside then we have to process the 507 // difference, otherwise it has no effect and all pixels 508 // remain outside. 509 if (*clearToInside) { 510 *startOp = kDifference_SetOp; 511 done = true; 512 } 513 break; 514 case kReverseDifference_SetOp: 515 // if all pixels are clearToInside then reverse difference 516 // produces empty set. Otherise it is same as replace 517 if (*clearToInside) { 518 *clearToInside = false; 519 } else { 520 *startOp = kReplace_SetOp; 521 done = true; 522 } 523 break; 524 default: 525 GrCrash("Unknown set op."); 526 } 527 } 528 return done ? curr-1 : count; 529} 530} 531 532bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { 533 const GrIRect* r = NULL; 534 GrIRect clipRect; 535 536 GrDrawState* drawState = this->drawState(); 537 const GrRenderTarget* rt = drawState->getRenderTarget(); 538 539 // GrDrawTarget should have filtered this for us 540 GrAssert(NULL != rt); 541 542 if (drawState->isClipState()) { 543 544 GrRect bounds; 545 GrRect rtRect; 546 rtRect.setLTRB(0, 0, 547 GrIntToScalar(rt->width()), GrIntToScalar(rt->height())); 548 if (fClip.hasConservativeBounds()) { 549 bounds = fClip.getConservativeBounds(); 550 if (!bounds.intersect(rtRect)) { 551 bounds.setEmpty(); 552 } 553 } else { 554 bounds = rtRect; 555 } 556 557 bounds.roundOut(&clipRect); 558 if (clipRect.isEmpty()) { 559 clipRect.setLTRB(0,0,0,0); 560 } 561 r = &clipRect; 562 563 // use the stencil clip if we can't represent the clip as a rectangle. 564 fClipInStencil = !fClip.isRect() && !fClip.isEmpty() && 565 !bounds.isEmpty(); 566 567 // TODO: dynamically attach a SB when needed. 568 GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); 569 if (fClipInStencil && NULL == stencilBuffer) { 570 return false; 571 } 572 573 if (fClipInStencil && 574 stencilBuffer->mustRenderClip(fClip, rt->width(), rt->height())) { 575 576 stencilBuffer->setLastClip(fClip, rt->width(), rt->height()); 577 578 // we set the current clip to the bounds so that our recursive 579 // draws are scissored to them. We use the copy of the complex clip 580 // we just stashed on the SB to render from. We set it back after 581 // we finish drawing it into the stencil. 582 const GrClip& clip = stencilBuffer->getLastClip(); 583 fClip.setFromRect(bounds); 584 585 AutoStateRestore asr(this); 586 AutoGeometryPush agp(this); 587 588 drawState->setViewMatrix(GrMatrix::I()); 589 this->flushScissor(NULL); 590#if !VISUALIZE_COMPLEX_CLIP 591 drawState->enableState(GrDrawState::kNoColorWrites_StateBit); 592#else 593 drawState->disableState(GrDrawState::kNoColorWrites_StateBit); 594#endif 595 int count = clip.getElementCount(); 596 int clipBit = stencilBuffer->bits(); 597 SkASSERT((clipBit <= 16) && 598 "Ganesh only handles 16b or smaller stencil buffers"); 599 clipBit = (1 << (clipBit-1)); 600 601 bool clearToInside; 602 GrSetOp startOp = kReplace_SetOp; // suppress warning 603 int start = process_initial_clip_elements(clip, 604 rtRect, 605 &clearToInside, 606 &startOp); 607 608 this->clearStencilClip(clipRect, clearToInside); 609 610 // walk through each clip element and perform its set op 611 // with the existing clip. 612 for (int c = start; c < count; ++c) { 613 GrPathFill fill; 614 bool fillInverted; 615 // enabled at bottom of loop 616 drawState->disableState(kModifyStencilClip_StateBit); 617 618 bool canRenderDirectToStencil; // can the clip element be drawn 619 // directly to the stencil buffer 620 // with a non-inverted fill rule 621 // without extra passes to 622 // resolve in/out status. 623 624 GrPathRenderer* pr = NULL; 625 const GrPath* clipPath = NULL; 626 GrPathRenderer::AutoClearPath arp; 627 if (kRect_ClipType == clip.getElementType(c)) { 628 canRenderDirectToStencil = true; 629 fill = kEvenOdd_PathFill; 630 fillInverted = false; 631 // there is no point in intersecting a screen filling 632 // rectangle. 633 if (kIntersect_SetOp == clip.getOp(c) && 634 clip.getRect(c).contains(rtRect)) { 635 continue; 636 } 637 } else { 638 fill = clip.getPathFill(c); 639 fillInverted = GrIsFillInverted(fill); 640 fill = GrNonInvertedFill(fill); 641 clipPath = &clip.getPath(c); 642 pr = this->getClipPathRenderer(*clipPath, fill); 643 if (NULL == pr) { 644 fClipInStencil = false; 645 fClip = clip; 646 return false; 647 } 648 canRenderDirectToStencil = 649 !pr->requiresStencilPass(this, *clipPath, fill); 650 arp.set(pr, this, clipPath, fill, false, NULL); 651 } 652 653 GrSetOp op = (c == start) ? startOp : clip.getOp(c); 654 int passes; 655 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; 656 657 bool canDrawDirectToClip; // Given the renderer, the element, 658 // fill rule, and set operation can 659 // we render the element directly to 660 // stencil bit used for clipping. 661 canDrawDirectToClip = 662 GrStencilSettings::GetClipPasses(op, 663 canRenderDirectToStencil, 664 clipBit, 665 fillInverted, 666 &passes, stencilSettings); 667 668 // draw the element to the client stencil bits if necessary 669 if (!canDrawDirectToClip) { 670 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, 671 kIncClamp_StencilOp, 672 kIncClamp_StencilOp, 673 kAlways_StencilFunc, 674 0xffff, 675 0x0000, 676 0xffff); 677 SET_RANDOM_COLOR 678 if (kRect_ClipType == clip.getElementType(c)) { 679 *drawState->stencil() = gDrawToStencil; 680 this->drawSimpleRect(clip.getRect(c), NULL, 0); 681 } else { 682 if (canRenderDirectToStencil) { 683 *drawState->stencil() = gDrawToStencil; 684 pr->drawPath(0); 685 } else { 686 pr->drawPathToStencil(); 687 } 688 } 689 } 690 691 // now we modify the clip bit by rendering either the clip 692 // element directly or a bounding rect of the entire clip. 693 drawState->enableState(kModifyStencilClip_StateBit); 694 for (int p = 0; p < passes; ++p) { 695 *drawState->stencil() = stencilSettings[p]; 696 if (canDrawDirectToClip) { 697 if (kRect_ClipType == clip.getElementType(c)) { 698 SET_RANDOM_COLOR 699 this->drawSimpleRect(clip.getRect(c), NULL, 0); 700 } else { 701 SET_RANDOM_COLOR 702 pr->drawPath(0); 703 } 704 } else { 705 SET_RANDOM_COLOR 706 this->drawSimpleRect(bounds, NULL, 0); 707 } 708 } 709 } 710 // restore clip 711 fClip = clip; 712 // recusive draws would have disabled this since they drew with 713 // the clip bounds as clip. 714 fClipInStencil = true; 715 } 716 } 717 718 // Must flush the scissor after graphics state 719 if (!this->flushGraphicsState(type)) { 720 return false; 721 } 722 this->flushScissor(r); 723 return true; 724} 725 726GrPathRenderer* GrGpu::getClipPathRenderer(const GrPath& path, 727 GrPathFill fill) { 728 if (NULL == fPathRendererChain) { 729 fPathRendererChain = 730 new GrPathRendererChain(this->getContext(), 731 GrPathRendererChain::kNonAAOnly_UsageFlag); 732 } 733 return fPathRendererChain->getPathRenderer(this->getCaps(), 734 path, fill, false); 735} 736 737 738//////////////////////////////////////////////////////////////////////////////// 739 740void GrGpu::geometrySourceWillPush() { 741 const GeometrySrcState& geoSrc = this->getGeomSrc(); 742 if (kArray_GeometrySrcType == geoSrc.fVertexSrc || 743 kReserved_GeometrySrcType == geoSrc.fVertexSrc) { 744 this->finalizeReservedVertices(); 745 } 746 if (kArray_GeometrySrcType == geoSrc.fIndexSrc || 747 kReserved_GeometrySrcType == geoSrc.fIndexSrc) { 748 this->finalizeReservedIndices(); 749 } 750 GeometryPoolState& newState = fGeomPoolStateStack.push_back(); 751#if GR_DEBUG 752 newState.fPoolVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER; 753 newState.fPoolStartVertex = DEBUG_INVAL_START_IDX; 754 newState.fPoolIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER; 755 newState.fPoolStartIndex = DEBUG_INVAL_START_IDX; 756#endif 757} 758 759void GrGpu::geometrySourceWillPop(const GeometrySrcState& restoredState) { 760 // if popping last entry then pops are unbalanced with pushes 761 GrAssert(fGeomPoolStateStack.count() > 1); 762 fGeomPoolStateStack.pop_back(); 763} 764 765void GrGpu::onDrawIndexed(GrPrimitiveType type, 766 int startVertex, 767 int startIndex, 768 int vertexCount, 769 int indexCount) { 770 771 this->handleDirtyContext(); 772 773 if (!this->setupClipAndFlushState(type)) { 774 return; 775 } 776 777#if GR_COLLECT_STATS 778 fStats.fVertexCnt += vertexCount; 779 fStats.fIndexCnt += indexCount; 780 fStats.fDrawCnt += 1; 781#endif 782 783 int sVertex = startVertex; 784 int sIndex = startIndex; 785 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount); 786 787 this->onGpuDrawIndexed(type, sVertex, sIndex, 788 vertexCount, indexCount); 789} 790 791void GrGpu::onDrawNonIndexed(GrPrimitiveType type, 792 int startVertex, 793 int vertexCount) { 794 this->handleDirtyContext(); 795 796 if (!this->setupClipAndFlushState(type)) { 797 return; 798 } 799#if GR_COLLECT_STATS 800 fStats.fVertexCnt += vertexCount; 801 fStats.fDrawCnt += 1; 802#endif 803 804 int sVertex = startVertex; 805 setupGeometry(&sVertex, NULL, vertexCount, 0); 806 807 this->onGpuDrawNonIndexed(type, sVertex, vertexCount); 808} 809 810void GrGpu::finalizeReservedVertices() { 811 GrAssert(NULL != fVertexPool); 812 fVertexPool->unlock(); 813} 814 815void GrGpu::finalizeReservedIndices() { 816 GrAssert(NULL != fIndexPool); 817 fIndexPool->unlock(); 818} 819 820void GrGpu::prepareVertexPool() { 821 if (NULL == fVertexPool) { 822 GrAssert(0 == fVertexPoolUseCnt); 823 fVertexPool = new GrVertexBufferAllocPool(this, true, 824 VERTEX_POOL_VB_SIZE, 825 VERTEX_POOL_VB_COUNT); 826 fVertexPool->releaseGpuRef(); 827 } else if (!fVertexPoolUseCnt) { 828 // the client doesn't have valid data in the pool 829 fVertexPool->reset(); 830 } 831} 832 833void GrGpu::prepareIndexPool() { 834 if (NULL == fIndexPool) { 835 GrAssert(0 == fIndexPoolUseCnt); 836 fIndexPool = new GrIndexBufferAllocPool(this, true, 837 INDEX_POOL_IB_SIZE, 838 INDEX_POOL_IB_COUNT); 839 fIndexPool->releaseGpuRef(); 840 } else if (!fIndexPoolUseCnt) { 841 // the client doesn't have valid data in the pool 842 fIndexPool->reset(); 843 } 844} 845 846bool GrGpu::onReserveVertexSpace(GrVertexLayout vertexLayout, 847 int vertexCount, 848 void** vertices) { 849 GeometryPoolState& geomPoolState = fGeomPoolStateStack.back(); 850 851 GrAssert(vertexCount > 0); 852 GrAssert(NULL != vertices); 853 854 this->prepareVertexPool(); 855 856 *vertices = fVertexPool->makeSpace(vertexLayout, 857 vertexCount, 858 &geomPoolState.fPoolVertexBuffer, 859 &geomPoolState.fPoolStartVertex); 860 if (NULL == *vertices) { 861 return false; 862 } 863 ++fVertexPoolUseCnt; 864 return true; 865} 866 867bool GrGpu::onReserveIndexSpace(int indexCount, void** indices) { 868 GeometryPoolState& geomPoolState = fGeomPoolStateStack.back(); 869 870 GrAssert(indexCount > 0); 871 GrAssert(NULL != indices); 872 873 this->prepareIndexPool(); 874 875 *indices = fIndexPool->makeSpace(indexCount, 876 &geomPoolState.fPoolIndexBuffer, 877 &geomPoolState.fPoolStartIndex); 878 if (NULL == *indices) { 879 return false; 880 } 881 ++fIndexPoolUseCnt; 882 return true; 883} 884 885void GrGpu::releaseReservedVertexSpace() { 886 const GeometrySrcState& geoSrc = this->getGeomSrc(); 887 GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc); 888 size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout); 889 fVertexPool->putBack(bytes); 890 --fVertexPoolUseCnt; 891} 892 893void GrGpu::releaseReservedIndexSpace() { 894 const GeometrySrcState& geoSrc = this->getGeomSrc(); 895 GrAssert(kReserved_GeometrySrcType == geoSrc.fIndexSrc); 896 size_t bytes = geoSrc.fIndexCount * sizeof(uint16_t); 897 fIndexPool->putBack(bytes); 898 --fIndexPoolUseCnt; 899} 900 901void GrGpu::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) { 902 this->prepareVertexPool(); 903 GeometryPoolState& geomPoolState = fGeomPoolStateStack.back(); 904#if GR_DEBUG 905 bool success = 906#endif 907 fVertexPool->appendVertices(this->getGeomSrc().fVertexLayout, 908 vertexCount, 909 vertexArray, 910 &geomPoolState.fPoolVertexBuffer, 911 &geomPoolState.fPoolStartVertex); 912 ++fVertexPoolUseCnt; 913 GR_DEBUGASSERT(success); 914} 915 916void GrGpu::onSetIndexSourceToArray(const void* indexArray, int indexCount) { 917 this->prepareIndexPool(); 918 GeometryPoolState& geomPoolState = fGeomPoolStateStack.back(); 919#if GR_DEBUG 920 bool success = 921#endif 922 fIndexPool->appendIndices(indexCount, 923 indexArray, 924 &geomPoolState.fPoolIndexBuffer, 925 &geomPoolState.fPoolStartIndex); 926 ++fIndexPoolUseCnt; 927 GR_DEBUGASSERT(success); 928} 929 930void GrGpu::releaseVertexArray() { 931 // if vertex source was array, we stowed data in the pool 932 const GeometrySrcState& geoSrc = this->getGeomSrc(); 933 GrAssert(kArray_GeometrySrcType == geoSrc.fVertexSrc); 934 size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout); 935 fVertexPool->putBack(bytes); 936 --fVertexPoolUseCnt; 937} 938 939void GrGpu::releaseIndexArray() { 940 // if index source was array, we stowed data in the pool 941 const GeometrySrcState& geoSrc = this->getGeomSrc(); 942 GrAssert(kArray_GeometrySrcType == geoSrc.fIndexSrc); 943 size_t bytes = geoSrc.fIndexCount * sizeof(uint16_t); 944 fIndexPool->putBack(bytes); 945 --fIndexPoolUseCnt; 946} 947 948//////////////////////////////////////////////////////////////////////////////// 949 950const GrGpuStats& GrGpu::getStats() const { 951 return fStats; 952} 953 954void GrGpu::resetStats() { 955 memset(&fStats, 0, sizeof(fStats)); 956} 957 958void GrGpu::printStats() const { 959 if (GR_COLLECT_STATS) { 960 GrPrintf( 961 "-v-------------------------GPU STATS----------------------------v-\n" 962 "Stats collection is: %s\n" 963 "Draws: %04d, Verts: %04d, Indices: %04d\n" 964 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n" 965 "TexCreates: %04d, RTCreates:%04d\n" 966 "-^--------------------------------------------------------------^-\n", 967 (GR_COLLECT_STATS ? "ON" : "OFF"), 968 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt, 969 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt, 970 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt); 971 } 972} 973 974