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
11 #include "GrInOrderDrawBuffer.h"
12 #include "GrRenderTarget.h"
13 #include "GrTexture.h"
14 #include "GrBufferAllocPool.h"
15 #include "GrIndexBuffer.h"
16 #include "GrVertexBuffer.h"
17 #include "GrGpu.h"
18
GrInOrderDrawBuffer(const GrGpu * gpu,GrVertexBufferAllocPool * vertexPool,GrIndexBufferAllocPool * indexPool)19 GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
20 GrVertexBufferAllocPool* vertexPool,
21 GrIndexBufferAllocPool* indexPool)
22 : fClipSet(true)
23 , fLastRectVertexLayout(0)
24 , fQuadIndexBuffer(NULL)
25 , fMaxQuads(0)
26 , fCurrQuad(0)
27 , fVertexPool(*vertexPool)
28 , fIndexPool(*indexPool) {
29
30 fCaps = gpu->getCaps();
31
32 GrAssert(NULL != vertexPool);
33 GrAssert(NULL != indexPool);
34
35 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
36 poolState.fUsedPoolVertexBytes = 0;
37 poolState.fUsedPoolIndexBytes = 0;
38 #if GR_DEBUG
39 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
40 poolState.fPoolStartVertex = ~0;
41 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
42 poolState.fPoolStartIndex = ~0;
43 #endif
44 }
45
~GrInOrderDrawBuffer()46 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
47 this->reset();
48 // This must be called by before the GrDrawTarget destructor
49 this->releaseGeometry();
50 GrSafeUnref(fQuadIndexBuffer);
51 }
52
initializeDrawStateAndClip(const GrDrawTarget & target)53 void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
54 this->copyDrawState(target);
55 this->setClip(target.getClip());
56 }
57
setQuadIndexBuffer(const GrIndexBuffer * indexBuffer)58 void GrInOrderDrawBuffer::setQuadIndexBuffer(const GrIndexBuffer* indexBuffer) {
59 bool newIdxBuffer = fQuadIndexBuffer != indexBuffer;
60 if (newIdxBuffer) {
61 GrSafeUnref(fQuadIndexBuffer);
62 fQuadIndexBuffer = indexBuffer;
63 GrSafeRef(fQuadIndexBuffer);
64 fCurrQuad = 0;
65 fMaxQuads = (NULL == indexBuffer) ? 0 : indexBuffer->maxQuads();
66 } else {
67 GrAssert((NULL == indexBuffer && 0 == fMaxQuads) ||
68 (indexBuffer->maxQuads() == fMaxQuads));
69 }
70 }
71
drawRect(const GrRect & rect,const GrMatrix * matrix,StageMask stageMask,const GrRect * srcRects[],const GrMatrix * srcMatrices[])72 void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
73 const GrMatrix* matrix,
74 StageMask stageMask,
75 const GrRect* srcRects[],
76 const GrMatrix* srcMatrices[]) {
77
78 GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad));
79 GrAssert(!(fDraws.empty() && fCurrQuad));
80 GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer));
81
82 GrDrawState* drawState = this->drawState();
83
84 // if we have a quad IB then either append to the previous run of
85 // rects or start a new run
86 if (fMaxQuads) {
87
88 bool appendToPreviousDraw = false;
89 GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
90 AutoReleaseGeometry geo(this, layout, 4, 0);
91 if (!geo.succeeded()) {
92 GrPrintf("Failed to get space for vertices!\n");
93 return;
94 }
95 GrMatrix combinedMatrix = drawState->getViewMatrix();
96 GrDrawState::AutoViewMatrixRestore avmr(drawState, GrMatrix::I());
97 if (NULL != matrix) {
98 combinedMatrix.preConcat(*matrix);
99 }
100
101 SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices, layout, geo.vertices());
102
103 // we don't want to miss an opportunity to batch rects together
104 // simply because the clip has changed if the clip doesn't affect
105 // the rect.
106 bool disabledClip = false;
107 if (drawState->isClipState() && fClip.isRect()) {
108
109 GrRect clipRect = fClip.getRect(0);
110 // If the clip rect touches the edge of the viewport, extended it
111 // out (close) to infinity to avoid bogus intersections.
112 // We might consider a more exact clip to viewport if this
113 // conservative test fails.
114 const GrRenderTarget* target = drawState->getRenderTarget();
115 if (0 >= clipRect.fLeft) {
116 clipRect.fLeft = GR_ScalarMin;
117 }
118 if (target->width() <= clipRect.fRight) {
119 clipRect.fRight = GR_ScalarMax;
120 }
121 if (0 >= clipRect.top()) {
122 clipRect.fTop = GR_ScalarMin;
123 }
124 if (target->height() <= clipRect.fBottom) {
125 clipRect.fBottom = GR_ScalarMax;
126 }
127 int stride = VertexSize(layout);
128 bool insideClip = true;
129 for (int v = 0; v < 4; ++v) {
130 const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride);
131 if (!clipRect.contains(p)) {
132 insideClip = false;
133 break;
134 }
135 }
136 if (insideClip) {
137 drawState->disableState(GrDrawState::kClip_StateBit);
138 disabledClip = true;
139 }
140 }
141 if (!needsNewClip() && !needsNewState() && fCurrQuad > 0 &&
142 fCurrQuad < fMaxQuads && layout == fLastRectVertexLayout) {
143
144 int vsize = VertexSize(layout);
145
146 Draw& lastDraw = fDraws.back();
147
148 GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer);
149 GrAssert(kTriangles_PrimitiveType == lastDraw.fPrimitiveType);
150 GrAssert(0 == lastDraw.fVertexCount % 4);
151 GrAssert(0 == lastDraw.fIndexCount % 6);
152 GrAssert(0 == lastDraw.fStartIndex);
153
154 GeometryPoolState& poolState = fGeoPoolStateStack.back();
155 bool clearSinceLastDraw =
156 fClears.count() &&
157 fClears.back().fBeforeDrawIdx == fDraws.count();
158
159 appendToPreviousDraw =
160 !clearSinceLastDraw &&
161 lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer &&
162 (fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex;
163
164 if (appendToPreviousDraw) {
165 lastDraw.fVertexCount += 4;
166 lastDraw.fIndexCount += 6;
167 fCurrQuad += 1;
168 // we reserved above, so we should be the first
169 // use of this vertex reserveation.
170 GrAssert(0 == poolState.fUsedPoolVertexBytes);
171 poolState.fUsedPoolVertexBytes = 4 * vsize;
172 }
173 }
174 if (!appendToPreviousDraw) {
175 this->setIndexSourceToBuffer(fQuadIndexBuffer);
176 drawIndexed(kTriangles_PrimitiveType, 0, 0, 4, 6);
177 fCurrQuad = 1;
178 fLastRectVertexLayout = layout;
179 }
180 if (disabledClip) {
181 drawState->enableState(GrDrawState::kClip_StateBit);
182 }
183 } else {
184 INHERITED::drawRect(rect, matrix, stageMask, srcRects, srcMatrices);
185 }
186 }
187
onDrawIndexed(GrPrimitiveType primitiveType,int startVertex,int startIndex,int vertexCount,int indexCount)188 void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType,
189 int startVertex,
190 int startIndex,
191 int vertexCount,
192 int indexCount) {
193
194 if (!vertexCount || !indexCount) {
195 return;
196 }
197
198 fCurrQuad = 0;
199
200 GeometryPoolState& poolState = fGeoPoolStateStack.back();
201
202 Draw& draw = fDraws.push_back();
203 draw.fPrimitiveType = primitiveType;
204 draw.fStartVertex = startVertex;
205 draw.fStartIndex = startIndex;
206 draw.fVertexCount = vertexCount;
207 draw.fIndexCount = indexCount;
208
209 draw.fClipChanged = this->needsNewClip();
210 if (draw.fClipChanged) {
211 this->pushClip();
212 }
213
214 draw.fStateChanged = this->needsNewState();
215 if (draw.fStateChanged) {
216 this->pushState();
217 }
218
219 draw.fVertexLayout = this->getGeomSrc().fVertexLayout;
220 switch (this->getGeomSrc().fVertexSrc) {
221 case kBuffer_GeometrySrcType:
222 draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer;
223 break;
224 case kReserved_GeometrySrcType: // fallthrough
225 case kArray_GeometrySrcType: {
226 size_t vertexBytes = (vertexCount + startVertex) *
227 VertexSize(this->getGeomSrc().fVertexLayout);
228 poolState.fUsedPoolVertexBytes =
229 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
230 draw.fVertexBuffer = poolState.fPoolVertexBuffer;
231 draw.fStartVertex += poolState.fPoolStartVertex;
232 break;
233 }
234 default:
235 GrCrash("unknown geom src type");
236 }
237 draw.fVertexBuffer->ref();
238
239 switch (this->getGeomSrc().fIndexSrc) {
240 case kBuffer_GeometrySrcType:
241 draw.fIndexBuffer = this->getGeomSrc().fIndexBuffer;
242 break;
243 case kReserved_GeometrySrcType: // fallthrough
244 case kArray_GeometrySrcType: {
245 size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
246 poolState.fUsedPoolIndexBytes =
247 GrMax(poolState.fUsedPoolIndexBytes, indexBytes);
248 draw.fIndexBuffer = poolState.fPoolIndexBuffer;
249 draw.fStartIndex += poolState.fPoolStartIndex;
250 break;
251 }
252 default:
253 GrCrash("unknown geom src type");
254 }
255 draw.fIndexBuffer->ref();
256 }
257
onDrawNonIndexed(GrPrimitiveType primitiveType,int startVertex,int vertexCount)258 void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
259 int startVertex,
260 int vertexCount) {
261 if (!vertexCount) {
262 return;
263 }
264
265 fCurrQuad = 0;
266
267 GeometryPoolState& poolState = fGeoPoolStateStack.back();
268
269 Draw& draw = fDraws.push_back();
270 draw.fPrimitiveType = primitiveType;
271 draw.fStartVertex = startVertex;
272 draw.fStartIndex = 0;
273 draw.fVertexCount = vertexCount;
274 draw.fIndexCount = 0;
275
276 draw.fClipChanged = this->needsNewClip();
277 if (draw.fClipChanged) {
278 this->pushClip();
279 }
280
281 draw.fStateChanged = this->needsNewState();
282 if (draw.fStateChanged) {
283 this->pushState();
284 }
285
286 draw.fVertexLayout = this->getGeomSrc().fVertexLayout;
287 switch (this->getGeomSrc().fVertexSrc) {
288 case kBuffer_GeometrySrcType:
289 draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer;
290 break;
291 case kReserved_GeometrySrcType: // fallthrough
292 case kArray_GeometrySrcType: {
293 size_t vertexBytes = (vertexCount + startVertex) *
294 VertexSize(this->getGeomSrc().fVertexLayout);
295 poolState.fUsedPoolVertexBytes =
296 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
297 draw.fVertexBuffer = poolState.fPoolVertexBuffer;
298 draw.fStartVertex += poolState.fPoolStartVertex;
299 break;
300 }
301 default:
302 GrCrash("unknown geom src type");
303 }
304 draw.fVertexBuffer->ref();
305 draw.fIndexBuffer = NULL;
306 }
307
clear(const GrIRect * rect,GrColor color)308 void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) {
309 GrIRect r;
310 if (NULL == rect) {
311 // We could do something smart and remove previous draws and clears to
312 // the current render target. If we get that smart we have to make sure
313 // those draws aren't read before this clear (render-to-texture).
314 r.setLTRB(0, 0,
315 this->getDrawState().getRenderTarget()->width(),
316 this->getDrawState().getRenderTarget()->height());
317 rect = &r;
318 }
319 Clear& clr = fClears.push_back();
320 clr.fColor = color;
321 clr.fBeforeDrawIdx = fDraws.count();
322 clr.fRect = *rect;
323 }
324
reset()325 void GrInOrderDrawBuffer::reset() {
326 GrAssert(1 == fGeoPoolStateStack.count());
327 this->resetVertexSource();
328 this->resetIndexSource();
329 uint32_t numStates = fStates.count();
330 for (uint32_t i = 0; i < numStates; ++i) {
331 const GrDrawState& dstate = this->accessSavedDrawState(fStates[i]);
332 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
333 GrSafeUnref(dstate.getTexture(s));
334 }
335 GrSafeUnref(dstate.getRenderTarget());
336 }
337 int numDraws = fDraws.count();
338 for (int d = 0; d < numDraws; ++d) {
339 // we always have a VB, but not always an IB
340 GrAssert(NULL != fDraws[d].fVertexBuffer);
341 fDraws[d].fVertexBuffer->unref();
342 GrSafeUnref(fDraws[d].fIndexBuffer);
343 }
344 fDraws.reset();
345 fStates.reset();
346
347 fClears.reset();
348
349 fVertexPool.reset();
350 fIndexPool.reset();
351
352 fClips.reset();
353
354 fCurrQuad = 0;
355 }
356
playback(GrDrawTarget * target)357 void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
358 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
359 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
360 GrAssert(NULL != target);
361 GrAssert(target != this); // not considered and why?
362
363 int numDraws = fDraws.count();
364 if (!numDraws) {
365 return;
366 }
367
368 fVertexPool.unlock();
369 fIndexPool.unlock();
370
371 GrDrawTarget::AutoStateRestore asr(target);
372 GrDrawTarget::AutoClipRestore acr(target);
373 AutoGeometryPush agp(target);
374
375 int currState = ~0;
376 int currClip = ~0;
377 int currClear = 0;
378
379 for (int i = 0; i < numDraws; ++i) {
380 while (currClear < fClears.count() &&
381 i == fClears[currClear].fBeforeDrawIdx) {
382 target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
383 ++currClear;
384 }
385
386 const Draw& draw = fDraws[i];
387 if (draw.fStateChanged) {
388 ++currState;
389 target->restoreDrawState(fStates[currState]);
390 }
391 if (draw.fClipChanged) {
392 ++currClip;
393 target->setClip(fClips[currClip]);
394 }
395
396 target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
397
398 if (draw.fIndexCount) {
399 target->setIndexSourceToBuffer(draw.fIndexBuffer);
400 }
401
402 if (draw.fIndexCount) {
403 target->drawIndexed(draw.fPrimitiveType,
404 draw.fStartVertex,
405 draw.fStartIndex,
406 draw.fVertexCount,
407 draw.fIndexCount);
408 } else {
409 target->drawNonIndexed(draw.fPrimitiveType,
410 draw.fStartVertex,
411 draw.fVertexCount);
412 }
413 }
414 while (currClear < fClears.count()) {
415 GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx);
416 target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
417 ++currClear;
418 }
419 }
420
geometryHints(GrVertexLayout vertexLayout,int * vertexCount,int * indexCount) const421 bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
422 int* vertexCount,
423 int* indexCount) const {
424 // we will recommend a flush if the data could fit in a single
425 // preallocated buffer but none are left and it can't fit
426 // in the current buffer (which may not be prealloced).
427 bool flush = false;
428 if (NULL != indexCount) {
429 int32_t currIndices = fIndexPool.currentBufferIndices();
430 if (*indexCount > currIndices &&
431 (!fIndexPool.preallocatedBuffersRemaining() &&
432 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
433
434 flush = true;
435 }
436 *indexCount = currIndices;
437 }
438 if (NULL != vertexCount) {
439 int32_t currVertices = fVertexPool.currentBufferVertices(vertexLayout);
440 if (*vertexCount > currVertices &&
441 (!fVertexPool.preallocatedBuffersRemaining() &&
442 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexLayout))) {
443
444 flush = true;
445 }
446 *vertexCount = currVertices;
447 }
448 return flush;
449 }
450
onReserveVertexSpace(GrVertexLayout vertexLayout,int vertexCount,void ** vertices)451 bool GrInOrderDrawBuffer::onReserveVertexSpace(GrVertexLayout vertexLayout,
452 int vertexCount,
453 void** vertices) {
454 GeometryPoolState& poolState = fGeoPoolStateStack.back();
455 GrAssert(vertexCount > 0);
456 GrAssert(NULL != vertices);
457 GrAssert(0 == poolState.fUsedPoolVertexBytes);
458
459 *vertices = fVertexPool.makeSpace(vertexLayout,
460 vertexCount,
461 &poolState.fPoolVertexBuffer,
462 &poolState.fPoolStartVertex);
463 return NULL != *vertices;
464 }
465
onReserveIndexSpace(int indexCount,void ** indices)466 bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
467 GeometryPoolState& poolState = fGeoPoolStateStack.back();
468 GrAssert(indexCount > 0);
469 GrAssert(NULL != indices);
470 GrAssert(0 == poolState.fUsedPoolIndexBytes);
471
472 *indices = fIndexPool.makeSpace(indexCount,
473 &poolState.fPoolIndexBuffer,
474 &poolState.fPoolStartIndex);
475 return NULL != *indices;
476 }
477
releaseReservedVertexSpace()478 void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
479 GeometryPoolState& poolState = fGeoPoolStateStack.back();
480 const GeometrySrcState& geoSrc = this->getGeomSrc();
481
482 GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
483
484 size_t reservedVertexBytes = VertexSize(geoSrc.fVertexLayout) *
485 geoSrc.fVertexCount;
486 fVertexPool.putBack(reservedVertexBytes -
487 poolState.fUsedPoolVertexBytes);
488 poolState.fUsedPoolVertexBytes = 0;
489 poolState.fPoolVertexBuffer = 0;
490 }
491
releaseReservedIndexSpace()492 void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
493 GeometryPoolState& poolState = fGeoPoolStateStack.back();
494 const GeometrySrcState& geoSrc = this->getGeomSrc();
495
496 GrAssert(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
497
498 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
499 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
500 poolState.fUsedPoolIndexBytes = 0;
501 poolState.fPoolStartVertex = 0;
502 }
503
onSetVertexSourceToArray(const void * vertexArray,int vertexCount)504 void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray,
505 int vertexCount) {
506
507 GeometryPoolState& poolState = fGeoPoolStateStack.back();
508 GrAssert(0 == poolState.fUsedPoolVertexBytes);
509 #if GR_DEBUG
510 bool success =
511 #endif
512 fVertexPool.appendVertices(this->getGeomSrc().fVertexLayout,
513 vertexCount,
514 vertexArray,
515 &poolState.fPoolVertexBuffer,
516 &poolState.fPoolStartVertex);
517 GR_DEBUGASSERT(success);
518 }
519
onSetIndexSourceToArray(const void * indexArray,int indexCount)520 void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
521 int indexCount) {
522 GeometryPoolState& poolState = fGeoPoolStateStack.back();
523 GrAssert(0 == poolState.fUsedPoolIndexBytes);
524 #if GR_DEBUG
525 bool success =
526 #endif
527 fIndexPool.appendIndices(indexCount,
528 indexArray,
529 &poolState.fPoolIndexBuffer,
530 &poolState.fPoolStartIndex);
531 GR_DEBUGASSERT(success);
532 }
533
geometrySourceWillPush()534 void GrInOrderDrawBuffer::geometrySourceWillPush() {
535 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
536 poolState.fUsedPoolVertexBytes = 0;
537 poolState.fUsedPoolIndexBytes = 0;
538 #if GR_DEBUG
539 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
540 poolState.fPoolStartVertex = ~0;
541 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
542 poolState.fPoolStartIndex = ~0;
543 #endif
544 }
545
releaseVertexArray()546 void GrInOrderDrawBuffer::releaseVertexArray() {
547 GeometryPoolState& poolState = fGeoPoolStateStack.back();
548 const GeometrySrcState& geoSrc = this->getGeomSrc();
549
550 size_t reservedVertexBytes = VertexSize(geoSrc.fVertexLayout) *
551 geoSrc.fVertexCount;
552 fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
553
554 poolState.fUsedPoolVertexBytes = 0;
555 }
556
releaseIndexArray()557 void GrInOrderDrawBuffer::releaseIndexArray() {
558 GeometryPoolState& poolState = fGeoPoolStateStack.back();
559 const GeometrySrcState& geoSrc = this->getGeomSrc();
560
561 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
562 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
563
564 poolState.fUsedPoolIndexBytes = 0;
565 }
566
geometrySourceWillPop(const GeometrySrcState & restoredState)567 void GrInOrderDrawBuffer::geometrySourceWillPop(
568 const GeometrySrcState& restoredState) {
569 GrAssert(fGeoPoolStateStack.count() > 1);
570 fGeoPoolStateStack.pop_back();
571 GeometryPoolState& poolState = fGeoPoolStateStack.back();
572 // we have to assume that any slack we had in our vertex/index data
573 // is now unreleasable because data may have been appended later in the
574 // pool.
575 if (kReserved_GeometrySrcType == restoredState.fVertexSrc ||
576 kArray_GeometrySrcType == restoredState.fVertexSrc) {
577 poolState.fUsedPoolVertexBytes =
578 VertexSize(restoredState.fVertexLayout) *
579 restoredState.fVertexCount;
580 }
581 if (kReserved_GeometrySrcType == restoredState.fIndexSrc ||
582 kArray_GeometrySrcType == restoredState.fIndexSrc) {
583 poolState.fUsedPoolVertexBytes = sizeof(uint16_t) *
584 restoredState.fIndexCount;
585 }
586 }
587
needsNewState() const588 bool GrInOrderDrawBuffer::needsNewState() const {
589 if (fStates.empty()) {
590 return true;
591 } else {
592 const GrDrawState& old = this->accessSavedDrawState(fStates.back());
593 return old != fCurrDrawState;
594 }
595 }
596
pushState()597 void GrInOrderDrawBuffer::pushState() {
598 const GrDrawState& drawState = this->getDrawState();
599 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
600 GrSafeRef(drawState.getTexture(s));
601 }
602 GrSafeRef(drawState.getRenderTarget());
603 this->saveCurrentDrawState(&fStates.push_back());
604 }
605
needsNewClip() const606 bool GrInOrderDrawBuffer::needsNewClip() const {
607 if (this->getDrawState().isClipState()) {
608 if (fClips.empty() || (fClipSet && fClips.back() != fClip)) {
609 return true;
610 }
611 }
612 return false;
613 }
614
pushClip()615 void GrInOrderDrawBuffer::pushClip() {
616 fClips.push_back() = fClip;
617 fClipSet = false;
618 }
619
clipWillBeSet(const GrClip & newClip)620 void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip) {
621 INHERITED::clipWillBeSet(newClip);
622 fClipSet = true;
623 }
624