GrInOrderDrawBuffer.cpp revision 1b3ce47c7b6c14c84d7aaee249b33f9d3b473050
1 2/* 3 * Copyright 2011 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 "GrInOrderDrawBuffer.h" 11#include "GrBufferAllocPool.h" 12#include "GrGpu.h" 13#include "GrIndexBuffer.h" 14#include "GrPath.h" 15#include "GrRenderTarget.h" 16#include "GrTexture.h" 17#include "GrVertexBuffer.h" 18 19GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu, 20 GrVertexBufferAllocPool* vertexPool, 21 GrIndexBufferAllocPool* indexPool) 22 : fAutoFlushTarget(NULL) 23 , fClipSet(true) 24 , fVertexPool(*vertexPool) 25 , fIndexPool(*indexPool) 26 , fLastRectVertexLayout(0) 27 , fQuadIndexBuffer(NULL) 28 , fMaxQuads(0) 29 , fFlushing(false) { 30 31 fCaps = gpu->getCaps(); 32 33 GrAssert(NULL != vertexPool); 34 GrAssert(NULL != indexPool); 35 36 GeometryPoolState& poolState = fGeoPoolStateStack.push_back(); 37 poolState.fUsedPoolVertexBytes = 0; 38 poolState.fUsedPoolIndexBytes = 0; 39#if GR_DEBUG 40 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0; 41 poolState.fPoolStartVertex = ~0; 42 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0; 43 poolState.fPoolStartIndex = ~0; 44#endif 45 this->reset(); 46} 47 48GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { 49 this->reset(); 50 // This must be called by before the GrDrawTarget destructor 51 this->releaseGeometry(); 52 GrSafeUnref(fQuadIndexBuffer); 53 GrSafeUnref(fAutoFlushTarget); 54} 55 56void GrInOrderDrawBuffer::setQuadIndexBuffer(const GrIndexBuffer* indexBuffer) { 57 bool newIdxBuffer = fQuadIndexBuffer != indexBuffer; 58 if (newIdxBuffer) { 59 GrSafeUnref(fQuadIndexBuffer); 60 fQuadIndexBuffer = indexBuffer; 61 GrSafeRef(fQuadIndexBuffer); 62 fCurrQuad = 0; 63 fMaxQuads = (NULL == indexBuffer) ? 0 : indexBuffer->maxQuads(); 64 } else { 65 GrAssert((NULL == indexBuffer && 0 == fMaxQuads) || 66 (indexBuffer->maxQuads() == fMaxQuads)); 67 } 68} 69 70//////////////////////////////////////////////////////////////////////////////// 71 72void GrInOrderDrawBuffer::resetDrawTracking() { 73 fCurrQuad = 0; 74 fInstancedDrawTracker.reset(); 75} 76 77void GrInOrderDrawBuffer::drawRect(const GrRect& rect, 78 const GrMatrix* matrix, 79 const GrRect* srcRects[], 80 const GrMatrix* srcMatrices[]) { 81 82 GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad)); 83 GrAssert(!(fDraws.empty() && fCurrQuad)); 84 GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer)); 85 86 GrDrawState* drawState = this->drawState(); 87 88 // if we have a quad IB then either append to the previous run of 89 // rects or start a new run 90 if (fMaxQuads) { 91 92 bool appendToPreviousDraw = false; 93 GrVertexLayout layout = GetRectVertexLayout(srcRects); 94 AutoReleaseGeometry geo(this, layout, 4, 0); 95 if (!geo.succeeded()) { 96 GrPrintf("Failed to get space for vertices!\n"); 97 return; 98 } 99 GrMatrix combinedMatrix = drawState->getViewMatrix(); 100 // We go to device space so that matrix changes allow us to concat 101 // rect draws. When the caller has provided explicit source rects 102 // then we don't want to modify the sampler matrices. Otherwise we do 103 // we have to account for the view matrix change in the sampler 104 // matrices. 105 uint32_t explicitCoordMask = 0; 106 if (srcRects) { 107 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 108 if (srcRects[s]) { 109 explicitCoordMask |= (1 << s); 110 } 111 } 112 } 113 GrDrawTarget::AutoDeviceCoordDraw adcd(this, explicitCoordMask); 114 if (!adcd.succeeded()) { 115 return; 116 } 117 if (NULL != matrix) { 118 combinedMatrix.preConcat(*matrix); 119 } 120 121 SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices, layout, geo.vertices()); 122 123 // we don't want to miss an opportunity to batch rects together 124 // simply because the clip has changed if the clip doesn't affect 125 // the rect. 126 bool disabledClip = false; 127 128 if (drawState->isClipState()) { 129 130 GrRect devClipRect; 131 bool isIntersectionOfRects = false; 132 133 fClip->fClipStack->getConservativeBounds(-fClip->fOrigin.fX, 134 -fClip->fOrigin.fY, 135 drawState->getRenderTarget()->width(), 136 drawState->getRenderTarget()->height(), 137 &devClipRect, 138 &isIntersectionOfRects); 139 140 if (isIntersectionOfRects) { 141 // If the clip rect touches the edge of the viewport, extended it 142 // out (close) to infinity to avoid bogus intersections. 143 // We might consider a more exact clip to viewport if this 144 // conservative test fails. 145 const GrRenderTarget* target = drawState->getRenderTarget(); 146 if (0 >= devClipRect.fLeft) { 147 devClipRect.fLeft = GR_ScalarMin; 148 } 149 if (target->width() <= devClipRect.fRight) { 150 devClipRect.fRight = GR_ScalarMax; 151 } 152 if (0 >= devClipRect.top()) { 153 devClipRect.fTop = GR_ScalarMin; 154 } 155 if (target->height() <= devClipRect.fBottom) { 156 devClipRect.fBottom = GR_ScalarMax; 157 } 158 int stride = VertexSize(layout); 159 bool insideClip = true; 160 for (int v = 0; v < 4; ++v) { 161 const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride); 162 if (!devClipRect.contains(p)) { 163 insideClip = false; 164 break; 165 } 166 } 167 if (insideClip) { 168 drawState->disableState(GrDrawState::kClip_StateBit); 169 disabledClip = true; 170 } 171 } 172 } 173 174 if (!this->needsNewClip() && 175 !this->needsNewState() && 176 fCurrQuad > 0 && 177 fCurrQuad < fMaxQuads && 178 layout == fLastRectVertexLayout) { 179 180 int vsize = VertexSize(layout); 181 182 Draw& lastDraw = fDraws.back(); 183 184 GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer); 185 GrAssert(kTriangles_GrPrimitiveType == lastDraw.fPrimitiveType); 186 GrAssert(0 == lastDraw.fVertexCount % 4); 187 GrAssert(0 == lastDraw.fIndexCount % 6); 188 GrAssert(0 == lastDraw.fStartIndex); 189 190 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 191 192 appendToPreviousDraw = 193 kDraw_Cmd != fCmds.back() && 194 lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer && 195 (fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex; 196 197 if (appendToPreviousDraw) { 198 lastDraw.fVertexCount += 4; 199 lastDraw.fIndexCount += 6; 200 fCurrQuad += 1; 201 // we reserved above, so we should be the first 202 // use of this vertex reservation. 203 GrAssert(0 == poolState.fUsedPoolVertexBytes); 204 poolState.fUsedPoolVertexBytes = 4 * vsize; 205 } 206 } 207 if (!appendToPreviousDraw) { 208 this->setIndexSourceToBuffer(fQuadIndexBuffer); 209 this->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 4, 6); 210 fCurrQuad = 1; 211 fLastRectVertexLayout = layout; 212 } 213 if (disabledClip) { 214 drawState->enableState(GrDrawState::kClip_StateBit); 215 } 216 fInstancedDrawTracker.reset(); 217 } else { 218 INHERITED::drawRect(rect, matrix, srcRects, srcMatrices); 219 } 220} 221 222void GrInOrderDrawBuffer::drawIndexedInstances(GrPrimitiveType type, 223 int instanceCount, 224 int verticesPerInstance, 225 int indicesPerInstance) { 226 if (!verticesPerInstance || !indicesPerInstance) { 227 return; 228 } 229 230 const GeometrySrcState& geomSrc = this->getGeomSrc(); 231 232 // we only attempt to concat the case when reserved verts are used with 233 // an index buffer. 234 if (kReserved_GeometrySrcType == geomSrc.fVertexSrc && 235 kBuffer_GeometrySrcType == geomSrc.fIndexSrc) { 236 237 if (this->needsNewClip()) { 238 this->recordClip(); 239 } 240 if (this->needsNewState()) { 241 this->recordState(); 242 } 243 244 Draw* draw = NULL; 245 // if the last draw used the same indices/vertices per shape then we 246 // may be able to append to it. 247 if (kDraw_Cmd == fCmds.back() && 248 verticesPerInstance == fInstancedDrawTracker.fVerticesPerInstance && 249 indicesPerInstance == fInstancedDrawTracker.fIndicesPerInstance) { 250 GrAssert(fDraws.count()); 251 draw = &fDraws.back(); 252 } 253 254 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 255 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer; 256 257 // Check whether the draw is compatible with this draw in order to 258 // append 259 if (NULL == draw || 260 draw->fIndexBuffer != geomSrc.fIndexBuffer || 261 draw->fPrimitiveType != type || 262 draw->fVertexBuffer != vertexBuffer) { 263 264 draw = this->recordDraw(); 265 draw->fIndexBuffer = geomSrc.fIndexBuffer; 266 geomSrc.fIndexBuffer->ref(); 267 draw->fVertexBuffer = vertexBuffer; 268 vertexBuffer->ref(); 269 draw->fPrimitiveType = type; 270 draw->fStartIndex = 0; 271 draw->fIndexCount = 0; 272 draw->fStartVertex = poolState.fPoolStartVertex; 273 draw->fVertexCount = 0; 274 draw->fVertexLayout = geomSrc.fVertexLayout; 275 } else { 276 GrAssert(!(draw->fIndexCount % indicesPerInstance)); 277 GrAssert(!(draw->fVertexCount % verticesPerInstance)); 278 GrAssert(poolState.fPoolStartVertex == draw->fStartVertex + 279 draw->fVertexCount); 280 } 281 282 // how many instances can be in a single draw 283 int maxInstancesPerDraw = this->indexCountInCurrentSource() / 284 indicesPerInstance; 285 if (!maxInstancesPerDraw) { 286 return; 287 } 288 // how many instances should be concat'ed onto draw 289 int instancesToConcat = maxInstancesPerDraw - draw->fVertexCount / 290 verticesPerInstance; 291 if (maxInstancesPerDraw > instanceCount) { 292 maxInstancesPerDraw = instanceCount; 293 if (instancesToConcat > instanceCount) { 294 instancesToConcat = instanceCount; 295 } 296 } 297 298 // update the amount of reserved data actually referenced in draws 299 size_t vertexBytes = instanceCount * verticesPerInstance * 300 VertexSize(draw->fVertexLayout); 301 poolState.fUsedPoolVertexBytes = 302 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes); 303 304 while (instanceCount) { 305 if (!instancesToConcat) { 306 int startVertex = draw->fStartVertex + draw->fVertexCount; 307 draw = this->recordDraw(); 308 draw->fIndexBuffer = geomSrc.fIndexBuffer; 309 geomSrc.fIndexBuffer->ref(); 310 draw->fVertexBuffer = vertexBuffer; 311 vertexBuffer->ref(); 312 draw->fPrimitiveType = type; 313 draw->fStartIndex = 0; 314 draw->fStartVertex = startVertex; 315 draw->fVertexCount = 0; 316 draw->fVertexLayout = geomSrc.fVertexLayout; 317 instancesToConcat = maxInstancesPerDraw; 318 } 319 draw->fVertexCount += instancesToConcat * verticesPerInstance; 320 draw->fIndexCount += instancesToConcat * indicesPerInstance; 321 instanceCount -= instancesToConcat; 322 instancesToConcat = 0; 323 } 324 325 // update draw tracking for next draw 326 fCurrQuad = 0; 327 fInstancedDrawTracker.fVerticesPerInstance = verticesPerInstance; 328 fInstancedDrawTracker.fIndicesPerInstance = indicesPerInstance; 329 } else { 330 this->INHERITED::drawIndexedInstances(type, 331 instanceCount, 332 verticesPerInstance, 333 indicesPerInstance); 334 } 335 336} 337 338void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType, 339 int startVertex, 340 int startIndex, 341 int vertexCount, 342 int indexCount) { 343 344 if (!vertexCount || !indexCount) { 345 return; 346 } 347 348 this->resetDrawTracking(); 349 350 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 351 352 if (this->needsNewClip()) { 353 this->recordClip(); 354 } 355 if (this->needsNewState()) { 356 this->recordState(); 357 } 358 359 Draw* draw = this->recordDraw(); 360 361 draw->fPrimitiveType = primitiveType; 362 draw->fStartVertex = startVertex; 363 draw->fStartIndex = startIndex; 364 draw->fVertexCount = vertexCount; 365 draw->fIndexCount = indexCount; 366 367 draw->fVertexLayout = this->getVertexLayout(); 368 switch (this->getGeomSrc().fVertexSrc) { 369 case kBuffer_GeometrySrcType: 370 draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer; 371 break; 372 case kReserved_GeometrySrcType: // fallthrough 373 case kArray_GeometrySrcType: { 374 size_t vertexBytes = (vertexCount + startVertex) * 375 VertexSize(draw->fVertexLayout); 376 poolState.fUsedPoolVertexBytes = 377 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes); 378 draw->fVertexBuffer = poolState.fPoolVertexBuffer; 379 draw->fStartVertex += poolState.fPoolStartVertex; 380 break; 381 } 382 default: 383 GrCrash("unknown geom src type"); 384 } 385 draw->fVertexBuffer->ref(); 386 387 switch (this->getGeomSrc().fIndexSrc) { 388 case kBuffer_GeometrySrcType: 389 draw->fIndexBuffer = this->getGeomSrc().fIndexBuffer; 390 break; 391 case kReserved_GeometrySrcType: // fallthrough 392 case kArray_GeometrySrcType: { 393 size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t); 394 poolState.fUsedPoolIndexBytes = 395 GrMax(poolState.fUsedPoolIndexBytes, indexBytes); 396 draw->fIndexBuffer = poolState.fPoolIndexBuffer; 397 draw->fStartIndex += poolState.fPoolStartIndex; 398 break; 399 } 400 default: 401 GrCrash("unknown geom src type"); 402 } 403 draw->fIndexBuffer->ref(); 404} 405 406void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType, 407 int startVertex, 408 int vertexCount) { 409 if (!vertexCount) { 410 return; 411 } 412 413 this->resetDrawTracking(); 414 415 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 416 if (this->needsNewClip()) { 417 this->recordClip(); 418 } 419 if (this->needsNewState()) { 420 this->recordState(); 421 } 422 423 Draw* draw = this->recordDraw(); 424 draw->fPrimitiveType = primitiveType; 425 draw->fStartVertex = startVertex; 426 draw->fStartIndex = 0; 427 draw->fVertexCount = vertexCount; 428 draw->fIndexCount = 0; 429 430 draw->fVertexLayout = this->getVertexLayout(); 431 switch (this->getGeomSrc().fVertexSrc) { 432 case kBuffer_GeometrySrcType: 433 draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer; 434 break; 435 case kReserved_GeometrySrcType: // fallthrough 436 case kArray_GeometrySrcType: { 437 size_t vertexBytes = (vertexCount + startVertex) * 438 VertexSize(draw->fVertexLayout); 439 poolState.fUsedPoolVertexBytes = 440 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes); 441 draw->fVertexBuffer = poolState.fPoolVertexBuffer; 442 draw->fStartVertex += poolState.fPoolStartVertex; 443 break; 444 } 445 default: 446 GrCrash("unknown geom src type"); 447 } 448 draw->fVertexBuffer->ref(); 449 draw->fIndexBuffer = NULL; 450} 451 452void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, GrPathFill fill) { 453 if (this->needsNewClip()) { 454 this->recordClip(); 455 } 456 // Only compare the subset of GrDrawState relevant to path stenciling? 457 if (this->needsNewState()) { 458 this->recordState(); 459 } 460 StencilPath* sp = this->recordStencilPath(); 461 sp->fPath.reset(path); 462 path->ref(); 463 sp->fFill = fill; 464} 465 466void GrInOrderDrawBuffer::clear(const GrIRect* rect, 467 GrColor color, 468 GrRenderTarget* renderTarget) { 469 GrIRect r; 470 if (NULL == renderTarget) { 471 renderTarget = this->drawState()->getRenderTarget(); 472 GrAssert(NULL != renderTarget); 473 } 474 if (NULL == rect) { 475 // We could do something smart and remove previous draws and clears to 476 // the current render target. If we get that smart we have to make sure 477 // those draws aren't read before this clear (render-to-texture). 478 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height()); 479 rect = &r; 480 } 481 Clear* clr = this->recordClear(); 482 clr->fColor = color; 483 clr->fRect = *rect; 484 clr->fRenderTarget = renderTarget; 485 renderTarget->ref(); 486} 487 488void GrInOrderDrawBuffer::reset() { 489 GrAssert(1 == fGeoPoolStateStack.count()); 490 this->resetVertexSource(); 491 this->resetIndexSource(); 492 int numDraws = fDraws.count(); 493 for (int d = 0; d < numDraws; ++d) { 494 // we always have a VB, but not always an IB 495 GrAssert(NULL != fDraws[d].fVertexBuffer); 496 fDraws[d].fVertexBuffer->unref(); 497 GrSafeUnref(fDraws[d].fIndexBuffer); 498 } 499 fCmds.reset(); 500 fDraws.reset(); 501 fStencilPaths.reset(); 502 fStates.reset(); 503 fClears.reset(); 504 fVertexPool.reset(); 505 fIndexPool.reset(); 506 fClips.reset(); 507 fClipOrigins.reset(); 508 fClipSet = true; 509 510 this->resetDrawTracking(); 511 512 // we start off with a default clip and state so that we don't have 513 // to do count checks on fClips, fStates, or fCmds before checking their 514 // last entry. 515 this->recordDefaultState(); 516 this->recordDefaultClip(); 517} 518 519bool GrInOrderDrawBuffer::playback(GrDrawTarget* target) { 520 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc); 521 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc); 522 523 GrAssert(NULL != target); 524 GrAssert(target != this); // not considered and why? 525 526 int numCmds = fCmds.count(); 527 GrAssert(numCmds >= 2); 528 if (2 == numCmds) { 529 GrAssert(kSetState_Cmd == fCmds[0]); 530 GrAssert(kSetClip_Cmd == fCmds[1]); 531 return false; 532 } 533 534 fVertexPool.unlock(); 535 fIndexPool.unlock(); 536 537 GrDrawTarget::AutoClipRestore acr(target); 538 AutoGeometryPush agp(target); 539 GrDrawState* prevDrawState = target->drawState(); 540 prevDrawState->ref(); 541 542 GrClipData clipData; 543 544 int currState = 0; 545 int currClip = 0; 546 int currClear = 0; 547 int currDraw = 0; 548 int currStencilPath = 0; 549 550 for (int c = 0; c < numCmds; ++c) { 551 switch (fCmds[c]) { 552 case kDraw_Cmd: { 553 const Draw& draw = fDraws[currDraw]; 554 target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer); 555 if (draw.fIndexCount) { 556 target->setIndexSourceToBuffer(draw.fIndexBuffer); 557 } 558 559 if (draw.fIndexCount) { 560 target->drawIndexed(draw.fPrimitiveType, 561 draw.fStartVertex, 562 draw.fStartIndex, 563 draw.fVertexCount, 564 draw.fIndexCount); 565 } else { 566 target->drawNonIndexed(draw.fPrimitiveType, 567 draw.fStartVertex, 568 draw.fVertexCount); 569 } 570 ++currDraw; 571 break; 572 } 573 case kStencilPath_Cmd: { 574 const StencilPath& sp = fStencilPaths[currStencilPath]; 575 target->stencilPath(sp.fPath.get(), sp.fFill); 576 ++currStencilPath; 577 break; 578 } 579 case kSetState_Cmd: 580 target->setDrawState(&fStates[currState]); 581 ++currState; 582 break; 583 case kSetClip_Cmd: 584 clipData.fClipStack = &fClips[currClip]; 585 clipData.fOrigin = fClipOrigins[currClip]; 586 target->setClip(&clipData); 587 ++currClip; 588 break; 589 case kClear_Cmd: 590 target->clear(&fClears[currClear].fRect, 591 fClears[currClear].fColor, 592 fClears[currClear].fRenderTarget); 593 ++currClear; 594 break; 595 } 596 } 597 // we should have consumed all the states, clips, etc. 598 GrAssert(fStates.count() == currState); 599 GrAssert(fClips.count() == currClip); 600 GrAssert(fClipOrigins.count() == currClip); 601 GrAssert(fClears.count() == currClear); 602 GrAssert(fDraws.count() == currDraw); 603 604 target->setDrawState(prevDrawState); 605 prevDrawState->unref(); 606 return true; 607} 608 609void GrInOrderDrawBuffer::setAutoFlushTarget(GrDrawTarget* target) { 610 GrSafeAssign(fAutoFlushTarget, target); 611} 612 613void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace( 614 GrVertexLayout vertexLayout, 615 int vertexCount, 616 int indexCount) { 617 if (NULL != fAutoFlushTarget) { 618 // We use geometryHints() to know whether to flush the draw buffer. We 619 // can't flush if we are inside an unbalanced pushGeometrySource. 620 // Moreover, flushing blows away vertex and index data that was 621 // previously reserved. So if the vertex or index data is pulled from 622 // reserved space and won't be released by this request then we can't 623 // flush. 624 bool insideGeoPush = fGeoPoolStateStack.count() > 1; 625 626 bool unreleasedVertexSpace = 627 !vertexCount && 628 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc; 629 630 bool unreleasedIndexSpace = 631 !indexCount && 632 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc; 633 634 // we don't want to finalize any reserved geom on the target since 635 // we don't know that the client has finished writing to it. 636 bool targetHasReservedGeom = 637 fAutoFlushTarget->hasReservedVerticesOrIndices(); 638 639 int vcount = vertexCount; 640 int icount = indexCount; 641 642 if (!insideGeoPush && 643 !unreleasedVertexSpace && 644 !unreleasedIndexSpace && 645 !targetHasReservedGeom && 646 this->geometryHints(vertexLayout, &vcount, &icount)) { 647 648 this->flushTo(fAutoFlushTarget); 649 } 650 } 651} 652 653bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout, 654 int* vertexCount, 655 int* indexCount) const { 656 // we will recommend a flush if the data could fit in a single 657 // preallocated buffer but none are left and it can't fit 658 // in the current buffer (which may not be prealloced). 659 bool flush = false; 660 if (NULL != indexCount) { 661 int32_t currIndices = fIndexPool.currentBufferIndices(); 662 if (*indexCount > currIndices && 663 (!fIndexPool.preallocatedBuffersRemaining() && 664 *indexCount <= fIndexPool.preallocatedBufferIndices())) { 665 666 flush = true; 667 } 668 *indexCount = currIndices; 669 } 670 if (NULL != vertexCount) { 671 int32_t currVertices = fVertexPool.currentBufferVertices(vertexLayout); 672 if (*vertexCount > currVertices && 673 (!fVertexPool.preallocatedBuffersRemaining() && 674 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexLayout))) { 675 676 flush = true; 677 } 678 *vertexCount = currVertices; 679 } 680 return flush; 681} 682 683bool GrInOrderDrawBuffer::onReserveVertexSpace(GrVertexLayout vertexLayout, 684 int vertexCount, 685 void** vertices) { 686 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 687 GrAssert(vertexCount > 0); 688 GrAssert(NULL != vertices); 689 GrAssert(0 == poolState.fUsedPoolVertexBytes); 690 691 *vertices = fVertexPool.makeSpace(vertexLayout, 692 vertexCount, 693 &poolState.fPoolVertexBuffer, 694 &poolState.fPoolStartVertex); 695 return NULL != *vertices; 696} 697 698bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) { 699 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 700 GrAssert(indexCount > 0); 701 GrAssert(NULL != indices); 702 GrAssert(0 == poolState.fUsedPoolIndexBytes); 703 704 *indices = fIndexPool.makeSpace(indexCount, 705 &poolState.fPoolIndexBuffer, 706 &poolState.fPoolStartIndex); 707 return NULL != *indices; 708} 709 710void GrInOrderDrawBuffer::releaseReservedVertexSpace() { 711 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 712 const GeometrySrcState& geoSrc = this->getGeomSrc(); 713 714 // If we get a release vertex space call then our current source should either be reserved 715 // or array (which we copied into reserved space). 716 GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc || 717 kArray_GeometrySrcType == geoSrc.fVertexSrc); 718 719 // When the caller reserved vertex buffer space we gave it back a pointer 720 // provided by the vertex buffer pool. At each draw we tracked the largest 721 // offset into the pool's pointer that was referenced. Now we return to the 722 // pool any portion at the tail of the allocation that no draw referenced. 723 size_t reservedVertexBytes = VertexSize(geoSrc.fVertexLayout) * 724 geoSrc.fVertexCount; 725 fVertexPool.putBack(reservedVertexBytes - 726 poolState.fUsedPoolVertexBytes); 727 poolState.fUsedPoolVertexBytes = 0; 728 poolState.fPoolVertexBuffer = NULL; 729 poolState.fPoolStartVertex = 0; 730} 731 732void GrInOrderDrawBuffer::releaseReservedIndexSpace() { 733 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 734 const GeometrySrcState& geoSrc = this->getGeomSrc(); 735 736 // If we get a release index space call then our current source should either be reserved 737 // or array (which we copied into reserved space). 738 GrAssert(kReserved_GeometrySrcType == geoSrc.fIndexSrc || 739 kArray_GeometrySrcType == geoSrc.fIndexSrc); 740 741 // Similar to releaseReservedVertexSpace we return any unused portion at 742 // the tail 743 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount; 744 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes); 745 poolState.fUsedPoolIndexBytes = 0; 746 poolState.fPoolIndexBuffer = NULL; 747 poolState.fPoolStartIndex = 0; 748} 749 750void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray, 751 int vertexCount) { 752 753 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 754 GrAssert(0 == poolState.fUsedPoolVertexBytes); 755#if GR_DEBUG 756 bool success = 757#endif 758 fVertexPool.appendVertices(this->getVertexLayout(), 759 vertexCount, 760 vertexArray, 761 &poolState.fPoolVertexBuffer, 762 &poolState.fPoolStartVertex); 763 GR_DEBUGASSERT(success); 764} 765 766void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray, 767 int indexCount) { 768 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 769 GrAssert(0 == poolState.fUsedPoolIndexBytes); 770#if GR_DEBUG 771 bool success = 772#endif 773 fIndexPool.appendIndices(indexCount, 774 indexArray, 775 &poolState.fPoolIndexBuffer, 776 &poolState.fPoolStartIndex); 777 GR_DEBUGASSERT(success); 778} 779 780void GrInOrderDrawBuffer::releaseVertexArray() { 781 // When the client provides an array as the vertex source we handled it 782 // by copying their array into reserved space. 783 this->GrInOrderDrawBuffer::releaseReservedVertexSpace(); 784} 785 786void GrInOrderDrawBuffer::releaseIndexArray() { 787 // When the client provides an array as the index source we handled it 788 // by copying their array into reserved space. 789 this->GrInOrderDrawBuffer::releaseReservedIndexSpace(); 790} 791 792void GrInOrderDrawBuffer::geometrySourceWillPush() { 793 GeometryPoolState& poolState = fGeoPoolStateStack.push_back(); 794 poolState.fUsedPoolVertexBytes = 0; 795 poolState.fUsedPoolIndexBytes = 0; 796 this->resetDrawTracking(); 797#if GR_DEBUG 798 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0; 799 poolState.fPoolStartVertex = ~0; 800 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0; 801 poolState.fPoolStartIndex = ~0; 802#endif 803} 804 805void GrInOrderDrawBuffer::geometrySourceWillPop( 806 const GeometrySrcState& restoredState) { 807 GrAssert(fGeoPoolStateStack.count() > 1); 808 fGeoPoolStateStack.pop_back(); 809 GeometryPoolState& poolState = fGeoPoolStateStack.back(); 810 // we have to assume that any slack we had in our vertex/index data 811 // is now unreleasable because data may have been appended later in the 812 // pool. 813 if (kReserved_GeometrySrcType == restoredState.fVertexSrc || 814 kArray_GeometrySrcType == restoredState.fVertexSrc) { 815 poolState.fUsedPoolVertexBytes = 816 VertexSize(restoredState.fVertexLayout) * 817 restoredState.fVertexCount; 818 } 819 if (kReserved_GeometrySrcType == restoredState.fIndexSrc || 820 kArray_GeometrySrcType == restoredState.fIndexSrc) { 821 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * 822 restoredState.fIndexCount; 823 } 824 this->resetDrawTracking(); 825} 826 827bool GrInOrderDrawBuffer::needsNewState() const { 828 // we should have recorded a default state in reset() 829 GrAssert(!fStates.empty()); 830 return fStates.back() != this->getDrawState(); 831} 832 833bool GrInOrderDrawBuffer::needsNewClip() const { 834 if (this->getDrawState().isClipState()) { 835 if (fClipSet && 836 (fClips.back() != *fClip->fClipStack || 837 fClipOrigins.back() != fClip->fOrigin)) { 838 return true; 839 } 840 } 841 return false; 842} 843 844void GrInOrderDrawBuffer::recordClip() { 845 fClips.push_back() = *fClip->fClipStack; 846 fClipOrigins.push_back() = fClip->fOrigin; 847 fClipSet = false; 848 fCmds.push_back(kSetClip_Cmd); 849} 850 851void GrInOrderDrawBuffer::recordDefaultClip() { 852 fClips.push_back() = SkClipStack(); 853 fClipOrigins.push_back() = SkIPoint::Make(0, 0); 854 fCmds.push_back(kSetClip_Cmd); 855} 856 857void GrInOrderDrawBuffer::recordState() { 858 fStates.push_back(this->getDrawState()); 859 fCmds.push_back(kSetState_Cmd); 860} 861 862void GrInOrderDrawBuffer::recordDefaultState() { 863 fStates.push_back(GrDrawState()); 864 fCmds.push_back(kSetState_Cmd); 865} 866 867GrInOrderDrawBuffer::Draw* GrInOrderDrawBuffer::recordDraw() { 868 fCmds.push_back(kDraw_Cmd); 869 return &fDraws.push_back(); 870} 871 872GrInOrderDrawBuffer::StencilPath* GrInOrderDrawBuffer::recordStencilPath() { 873 fCmds.push_back(kStencilPath_Cmd); 874 return &fStencilPaths.push_back(); 875} 876 877GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear() { 878 fCmds.push_back(kClear_Cmd); 879 return &fClears.push_back(); 880} 881 882void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) { 883 INHERITED::clipWillBeSet(newClipData); 884 fClipSet = true; 885} 886