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