blob: b6581c04e34ef95b0e3c26d236f33d52ab2bf510 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#include "GrInOrderDrawBuffer.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000012#include "GrRenderTarget.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000013#include "GrTexture.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000014#include "GrBufferAllocPool.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000015#include "GrIndexBuffer.h"
16#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017#include "GrGpu.h"
18
bsalomon@google.com471d4712011-08-23 15:45:25 +000019GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
20 GrVertexBufferAllocPool* vertexPool,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000021 GrIndexBufferAllocPool* indexPool)
bsalomon@google.com97805382012-03-13 14:32:07 +000022 : fAutoFlushTarget(NULL)
23 , fClipSet(true)
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000024 , fLastRectVertexLayout(0)
25 , fQuadIndexBuffer(NULL)
26 , fMaxQuads(0)
27 , fCurrQuad(0)
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000028 , fVertexPool(*vertexPool)
bsalomon@google.com92669012011-09-27 19:10:05 +000029 , fIndexPool(*indexPool) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000030
31 fCaps = gpu->getCaps();
32
bsalomon@google.com1c13c962011-02-14 16:51:21 +000033 GrAssert(NULL != vertexPool);
34 GrAssert(NULL != indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000035
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
reed@google.comac10a2d2010-12-22 21:39:39 +000045}
46
47GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000048 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000049 // This must be called by before the GrDrawTarget destructor
50 this->releaseGeometry();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000051 GrSafeUnref(fQuadIndexBuffer);
bsalomon@google.com97805382012-03-13 14:32:07 +000052 GrSafeUnref(fAutoFlushTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +000053}
54
55void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
56 this->copyDrawState(target);
57 this->setClip(target.getClip());
58}
59
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000060void GrInOrderDrawBuffer::setQuadIndexBuffer(const GrIndexBuffer* indexBuffer) {
61 bool newIdxBuffer = fQuadIndexBuffer != indexBuffer;
62 if (newIdxBuffer) {
63 GrSafeUnref(fQuadIndexBuffer);
64 fQuadIndexBuffer = indexBuffer;
65 GrSafeRef(fQuadIndexBuffer);
66 fCurrQuad = 0;
67 fMaxQuads = (NULL == indexBuffer) ? 0 : indexBuffer->maxQuads();
68 } else {
bsalomon@google.comd302f142011-03-03 13:54:13 +000069 GrAssert((NULL == indexBuffer && 0 == fMaxQuads) ||
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000070 (indexBuffer->maxQuads() == fMaxQuads));
71 }
72}
73
bsalomon@google.comd302f142011-03-03 13:54:13 +000074void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000075 const GrMatrix* matrix,
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000076 StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000077 const GrRect* srcRects[],
78 const GrMatrix* srcMatrices[]) {
bsalomon@google.comd302f142011-03-03 13:54:13 +000079
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000080 GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad));
81 GrAssert(!(fDraws.empty() && fCurrQuad));
82 GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer));
83
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000084 GrDrawState* drawState = this->drawState();
85
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000086 // if we have a quad IB then either append to the previous run of
87 // rects or start a new run
88 if (fMaxQuads) {
bsalomon@google.comd302f142011-03-03 13:54:13 +000089
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000090 bool appendToPreviousDraw = false;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000091 GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000092 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +000093 if (!geo.succeeded()) {
94 GrPrintf("Failed to get space for vertices!\n");
95 return;
96 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000097 GrMatrix combinedMatrix = drawState->getViewMatrix();
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +000098 // We go to device space so that matrix changes allow us to concat
99 // rect draws. When the caller has provided explicit source rects
100 // then we don't want to modify the sampler matrices. Otherwise we do
101 // we have to account for the view matrix change in the sampler
102 // matrices.
103 StageMask devCoordMask = (NULL == srcRects) ? stageMask : 0;
104 GrDrawTarget::AutoDeviceCoordDraw adcd(this, devCoordMask);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000105 if (NULL != matrix) {
106 combinedMatrix.preConcat(*matrix);
107 }
108
109 SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices, layout, geo.vertices());
110
111 // we don't want to miss an opportunity to batch rects together
112 // simply because the clip has changed if the clip doesn't affect
113 // the rect.
114 bool disabledClip = false;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000115 if (drawState->isClipState() && fClip.isRect()) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000116
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000117 GrRect clipRect = fClip.getRect(0);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000118 // If the clip rect touches the edge of the viewport, extended it
119 // out (close) to infinity to avoid bogus intersections.
bsalomon@google.comd302f142011-03-03 13:54:13 +0000120 // We might consider a more exact clip to viewport if this
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000121 // conservative test fails.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000122 const GrRenderTarget* target = drawState->getRenderTarget();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000123 if (0 >= clipRect.fLeft) {
124 clipRect.fLeft = GR_ScalarMin;
125 }
126 if (target->width() <= clipRect.fRight) {
127 clipRect.fRight = GR_ScalarMax;
128 }
129 if (0 >= clipRect.top()) {
130 clipRect.fTop = GR_ScalarMin;
131 }
132 if (target->height() <= clipRect.fBottom) {
133 clipRect.fBottom = GR_ScalarMax;
134 }
135 int stride = VertexSize(layout);
136 bool insideClip = true;
137 for (int v = 0; v < 4; ++v) {
138 const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride);
139 if (!clipRect.contains(p)) {
140 insideClip = false;
141 break;
142 }
143 }
144 if (insideClip) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000145 drawState->disableState(GrDrawState::kClip_StateBit);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000146 disabledClip = true;
147 }
148 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000149 if (!needsNewClip() && !needsNewState() && fCurrQuad > 0 &&
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000150 fCurrQuad < fMaxQuads && layout == fLastRectVertexLayout) {
151
152 int vsize = VertexSize(layout);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000153
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000154 Draw& lastDraw = fDraws.back();
155
156 GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer);
157 GrAssert(kTriangles_PrimitiveType == lastDraw.fPrimitiveType);
158 GrAssert(0 == lastDraw.fVertexCount % 4);
159 GrAssert(0 == lastDraw.fIndexCount % 6);
160 GrAssert(0 == lastDraw.fStartIndex);
161
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000162 GeometryPoolState& poolState = fGeoPoolStateStack.back();
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000163 bool clearSinceLastDraw =
164 fClears.count() &&
165 fClears.back().fBeforeDrawIdx == fDraws.count();
166
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000167 appendToPreviousDraw =
168 !clearSinceLastDraw &&
169 lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer &&
170 (fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex;
171
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000172 if (appendToPreviousDraw) {
173 lastDraw.fVertexCount += 4;
174 lastDraw.fIndexCount += 6;
175 fCurrQuad += 1;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000176 // we reserved above, so we should be the first
177 // use of this vertex reserveation.
178 GrAssert(0 == poolState.fUsedPoolVertexBytes);
179 poolState.fUsedPoolVertexBytes = 4 * vsize;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000180 }
181 }
182 if (!appendToPreviousDraw) {
183 this->setIndexSourceToBuffer(fQuadIndexBuffer);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000184 this->drawIndexed(kTriangles_PrimitiveType, 0, 0, 4, 6);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000185 fCurrQuad = 1;
186 fLastRectVertexLayout = layout;
187 }
188 if (disabledClip) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000189 drawState->enableState(GrDrawState::kClip_StateBit);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000190 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000191 } else {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000192 INHERITED::drawRect(rect, matrix, stageMask, srcRects, srcMatrices);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000193 }
194}
195
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000196void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType,
197 int startVertex,
198 int startIndex,
199 int vertexCount,
200 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000201
202 if (!vertexCount || !indexCount) {
203 return;
204 }
205
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000206 fCurrQuad = 0;
207
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000208 GeometryPoolState& poolState = fGeoPoolStateStack.back();
209
reed@google.comac10a2d2010-12-22 21:39:39 +0000210 Draw& draw = fDraws.push_back();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000211 draw.fPrimitiveType = primitiveType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000212 draw.fStartVertex = startVertex;
213 draw.fStartIndex = startIndex;
214 draw.fVertexCount = vertexCount;
215 draw.fIndexCount = indexCount;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000216
217 draw.fClipChanged = this->needsNewClip();
218 if (draw.fClipChanged) {
219 this->pushClip();
220 }
221
222 draw.fStateChanged = this->needsNewState();
223 if (draw.fStateChanged) {
224 this->pushState();
225 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000226
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000227 draw.fVertexLayout = this->getGeomSrc().fVertexLayout;
228 switch (this->getGeomSrc().fVertexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000229 case kBuffer_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000230 draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000231 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000232 case kReserved_GeometrySrcType: // fallthrough
233 case kArray_GeometrySrcType: {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000234 size_t vertexBytes = (vertexCount + startVertex) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000235 VertexSize(this->getGeomSrc().fVertexLayout);
236 poolState.fUsedPoolVertexBytes =
237 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
238 draw.fVertexBuffer = poolState.fPoolVertexBuffer;
239 draw.fStartVertex += poolState.fPoolStartVertex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000240 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000241 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000242 default:
243 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000244 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000245 draw.fVertexBuffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000246
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000247 switch (this->getGeomSrc().fIndexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000248 case kBuffer_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000249 draw.fIndexBuffer = this->getGeomSrc().fIndexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000250 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000251 case kReserved_GeometrySrcType: // fallthrough
252 case kArray_GeometrySrcType: {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000253 size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000254 poolState.fUsedPoolIndexBytes =
255 GrMax(poolState.fUsedPoolIndexBytes, indexBytes);
256 draw.fIndexBuffer = poolState.fPoolIndexBuffer;
bsalomon@google.comd127ffe2012-02-24 20:11:52 +0000257 draw.fStartIndex += poolState.fPoolStartIndex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000258 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000259 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000260 default:
261 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000262 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000263 draw.fIndexBuffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000264}
265
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000266void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
267 int startVertex,
268 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000269 if (!vertexCount) {
270 return;
271 }
272
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000273 fCurrQuad = 0;
274
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000275 GeometryPoolState& poolState = fGeoPoolStateStack.back();
276
reed@google.comac10a2d2010-12-22 21:39:39 +0000277 Draw& draw = fDraws.push_back();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000278 draw.fPrimitiveType = primitiveType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000279 draw.fStartVertex = startVertex;
280 draw.fStartIndex = 0;
281 draw.fVertexCount = vertexCount;
282 draw.fIndexCount = 0;
283
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000284 draw.fClipChanged = this->needsNewClip();
285 if (draw.fClipChanged) {
286 this->pushClip();
287 }
288
289 draw.fStateChanged = this->needsNewState();
290 if (draw.fStateChanged) {
291 this->pushState();
292 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000293
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000294 draw.fVertexLayout = this->getGeomSrc().fVertexLayout;
295 switch (this->getGeomSrc().fVertexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000296 case kBuffer_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000297 draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000298 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000299 case kReserved_GeometrySrcType: // fallthrough
300 case kArray_GeometrySrcType: {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000301 size_t vertexBytes = (vertexCount + startVertex) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000302 VertexSize(this->getGeomSrc().fVertexLayout);
303 poolState.fUsedPoolVertexBytes =
304 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
305 draw.fVertexBuffer = poolState.fPoolVertexBuffer;
306 draw.fStartVertex += poolState.fPoolStartVertex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000307 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000308 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000309 default:
310 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000311 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000312 draw.fVertexBuffer->ref();
313 draw.fIndexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000314}
315
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000316void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) {
317 GrIRect r;
318 if (NULL == rect) {
319 // We could do something smart and remove previous draws and clears to
320 // the current render target. If we get that smart we have to make sure
321 // those draws aren't read before this clear (render-to-texture).
322 r.setLTRB(0, 0,
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000323 this->getDrawState().getRenderTarget()->width(),
324 this->getDrawState().getRenderTarget()->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000325 rect = &r;
326 }
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000327 Clear& clr = fClears.push_back();
328 clr.fColor = color;
329 clr.fBeforeDrawIdx = fDraws.count();
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000330 clr.fRect = *rect;
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000331}
332
reed@google.comac10a2d2010-12-22 21:39:39 +0000333void GrInOrderDrawBuffer::reset() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000334 GrAssert(1 == fGeoPoolStateStack.count());
335 this->resetVertexSource();
336 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000337 uint32_t numStates = fStates.count();
338 for (uint32_t i = 0; i < numStates; ++i) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000339 const GrDrawState& dstate = this->accessSavedDrawState(fStates[i]);
340 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000341 GrSafeUnref(dstate.getTexture(s));
reed@google.comac10a2d2010-12-22 21:39:39 +0000342 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000343 GrSafeUnref(dstate.getRenderTarget());
reed@google.comac10a2d2010-12-22 21:39:39 +0000344 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000345 int numDraws = fDraws.count();
346 for (int d = 0; d < numDraws; ++d) {
347 // we always have a VB, but not always an IB
348 GrAssert(NULL != fDraws[d].fVertexBuffer);
349 fDraws[d].fVertexBuffer->unref();
350 GrSafeUnref(fDraws[d].fIndexBuffer);
351 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000352 fDraws.reset();
353 fStates.reset();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000354
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000355 fClears.reset();
356
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000357 fVertexPool.reset();
358 fIndexPool.reset();
359
reed@google.comac10a2d2010-12-22 21:39:39 +0000360 fClips.reset();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000361
362 fCurrQuad = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000363}
364
365void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000366 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
367 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000368
reed@google.comac10a2d2010-12-22 21:39:39 +0000369 GrAssert(NULL != target);
370 GrAssert(target != this); // not considered and why?
371
bsalomon@google.com898d9e52011-04-26 13:22:33 +0000372 int numDraws = fDraws.count();
reed@google.comac10a2d2010-12-22 21:39:39 +0000373 if (!numDraws) {
374 return;
375 }
376
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000377 fVertexPool.unlock();
378 fIndexPool.unlock();
reed@google.comac10a2d2010-12-22 21:39:39 +0000379
380 GrDrawTarget::AutoStateRestore asr(target);
381 GrDrawTarget::AutoClipRestore acr(target);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000382 AutoGeometryPush agp(target);
reed@google.comac10a2d2010-12-22 21:39:39 +0000383
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000384 int currState = ~0;
385 int currClip = ~0;
386 int currClear = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000387
bsalomon@google.com898d9e52011-04-26 13:22:33 +0000388 for (int i = 0; i < numDraws; ++i) {
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000389 while (currClear < fClears.count() &&
390 i == fClears[currClear].fBeforeDrawIdx) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000391 target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000392 ++currClear;
393 }
394
reed@google.comac10a2d2010-12-22 21:39:39 +0000395 const Draw& draw = fDraws[i];
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000396 if (draw.fStateChanged) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000397 ++currState;
398 target->restoreDrawState(fStates[currState]);
399 }
400 if (draw.fClipChanged) {
401 ++currClip;
402 target->setClip(fClips[currClip]);
403 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000404
405 target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
406
reed@google.comac10a2d2010-12-22 21:39:39 +0000407 if (draw.fIndexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000408 target->setIndexSourceToBuffer(draw.fIndexBuffer);
409 }
410
411 if (draw.fIndexCount) {
412 target->drawIndexed(draw.fPrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000413 draw.fStartVertex,
414 draw.fStartIndex,
415 draw.fVertexCount,
416 draw.fIndexCount);
417 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000418 target->drawNonIndexed(draw.fPrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000419 draw.fStartVertex,
420 draw.fVertexCount);
421 }
422 }
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000423 while (currClear < fClears.count()) {
424 GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000425 target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000426 ++currClear;
427 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000428}
429
bsalomon@google.com97805382012-03-13 14:32:07 +0000430void GrInOrderDrawBuffer::setAutoFlushTarget(GrDrawTarget* target) {
431 GrSafeAssign(fAutoFlushTarget, target);
432}
433
434void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(
435 GrVertexLayout vertexLayout,
436 int vertexCount,
437 int indexCount) {
438 if (NULL != fAutoFlushTarget) {
439 // We use geometryHints() to know whether to flush the draw buffer. We
440 // can't flush if we are inside an unbalanced pushGeometrySource.
441 // Moreover, flushing blows away vertex and index data that was
442 // previously reserved. So if the vertex or index data is pulled from
443 // reserved space and won't be released by this request then we can't
444 // flush.
445 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
446
447 bool unreleasedVertexSpace =
448 !vertexCount &&
449 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
450
451 bool unreleasedIndexSpace =
452 !indexCount &&
453 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
454
455 // we don't want to finalize any reserved geom on the target since
456 // we don't know that the client has finished writing to it.
457 bool targetHasReservedGeom =
458 fAutoFlushTarget->hasReservedVerticesOrIndices();
459
460 int vcount = vertexCount;
461 int icount = indexCount;
462
463 if (!insideGeoPush &&
464 !unreleasedVertexSpace &&
465 !unreleasedIndexSpace &&
466 !targetHasReservedGeom &&
467 this->geometryHints(vertexLayout, &vcount, &icount)) {
468
469 this->flushTo(fAutoFlushTarget);
470 }
471 }
472}
473
reed@google.comac10a2d2010-12-22 21:39:39 +0000474bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000475 int* vertexCount,
476 int* indexCount) const {
477 // we will recommend a flush if the data could fit in a single
478 // preallocated buffer but none are left and it can't fit
479 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000480 bool flush = false;
481 if (NULL != indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000482 int32_t currIndices = fIndexPool.currentBufferIndices();
483 if (*indexCount > currIndices &&
484 (!fIndexPool.preallocatedBuffersRemaining() &&
485 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
486
487 flush = true;
488 }
489 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000490 }
491 if (NULL != vertexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000492 int32_t currVertices = fVertexPool.currentBufferVertices(vertexLayout);
493 if (*vertexCount > currVertices &&
494 (!fVertexPool.preallocatedBuffersRemaining() &&
495 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexLayout))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000496
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000497 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000498 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000499 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000500 }
501 return flush;
502}
503
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000504bool GrInOrderDrawBuffer::onReserveVertexSpace(GrVertexLayout vertexLayout,
505 int vertexCount,
506 void** vertices) {
507 GeometryPoolState& poolState = fGeoPoolStateStack.back();
508 GrAssert(vertexCount > 0);
509 GrAssert(NULL != vertices);
510 GrAssert(0 == poolState.fUsedPoolVertexBytes);
511
512 *vertices = fVertexPool.makeSpace(vertexLayout,
513 vertexCount,
514 &poolState.fPoolVertexBuffer,
515 &poolState.fPoolStartVertex);
516 return NULL != *vertices;
517}
518
519bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
520 GeometryPoolState& poolState = fGeoPoolStateStack.back();
521 GrAssert(indexCount > 0);
522 GrAssert(NULL != indices);
523 GrAssert(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000524
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000525 *indices = fIndexPool.makeSpace(indexCount,
526 &poolState.fPoolIndexBuffer,
527 &poolState.fPoolStartIndex);
528 return NULL != *indices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000529}
530
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000531void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
532 GeometryPoolState& poolState = fGeoPoolStateStack.back();
533 const GeometrySrcState& geoSrc = this->getGeomSrc();
534
535 GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000536
537 // When the caller reserved vertex buffer space we gave it back a pointer
538 // provided by the vertex buffer pool. At each draw we tracked the largest
539 // offset into the pool's pointer that was referenced. Now we return to the
540 // pool any portion at the tail of the allocation that no draw referenced.
541 size_t reservedVertexBytes = VertexSize(geoSrc.fVertexLayout) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000542 geoSrc.fVertexCount;
543 fVertexPool.putBack(reservedVertexBytes -
544 poolState.fUsedPoolVertexBytes);
545 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000546 poolState.fPoolVertexBuffer = NULL;
547 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000548}
549
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000550void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
551 GeometryPoolState& poolState = fGeoPoolStateStack.back();
552 const GeometrySrcState& geoSrc = this->getGeomSrc();
553
554 GrAssert(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000555
556 // Similar to releaseReservedVertexSpace we return any unused portion at
557 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000558 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
559 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
560 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000561 poolState.fPoolIndexBuffer = NULL;
562 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000563}
564
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000565void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray,
566 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000567
568 GeometryPoolState& poolState = fGeoPoolStateStack.back();
569 GrAssert(0 == poolState.fUsedPoolVertexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000570#if GR_DEBUG
571 bool success =
572#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000573 fVertexPool.appendVertices(this->getGeomSrc().fVertexLayout,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000574 vertexCount,
575 vertexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000576 &poolState.fPoolVertexBuffer,
577 &poolState.fPoolStartVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000578 GR_DEBUGASSERT(success);
579}
580
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000581void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
582 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000583 GeometryPoolState& poolState = fGeoPoolStateStack.back();
584 GrAssert(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000585#if GR_DEBUG
586 bool success =
587#endif
588 fIndexPool.appendIndices(indexCount,
589 indexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000590 &poolState.fPoolIndexBuffer,
591 &poolState.fPoolStartIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000592 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000593}
594
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000595void GrInOrderDrawBuffer::releaseVertexArray() {
596 // When the client provides an array as the vertex source we handled it
597 // by copying their array into reserved space.
598 this->GrInOrderDrawBuffer::releaseReservedVertexSpace();
599}
600
601void GrInOrderDrawBuffer::releaseIndexArray() {
602 // When the client provides an array as the index source we handled it
603 // by copying their array into reserved space.
604 this->GrInOrderDrawBuffer::releaseReservedIndexSpace();
605}
606
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000607void GrInOrderDrawBuffer::geometrySourceWillPush() {
608 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
609 poolState.fUsedPoolVertexBytes = 0;
610 poolState.fUsedPoolIndexBytes = 0;
611#if GR_DEBUG
612 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
613 poolState.fPoolStartVertex = ~0;
614 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
615 poolState.fPoolStartIndex = ~0;
616#endif
617}
618
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000619void GrInOrderDrawBuffer::geometrySourceWillPop(
620 const GeometrySrcState& restoredState) {
621 GrAssert(fGeoPoolStateStack.count() > 1);
622 fGeoPoolStateStack.pop_back();
623 GeometryPoolState& poolState = fGeoPoolStateStack.back();
624 // we have to assume that any slack we had in our vertex/index data
625 // is now unreleasable because data may have been appended later in the
626 // pool.
627 if (kReserved_GeometrySrcType == restoredState.fVertexSrc ||
628 kArray_GeometrySrcType == restoredState.fVertexSrc) {
629 poolState.fUsedPoolVertexBytes =
630 VertexSize(restoredState.fVertexLayout) *
631 restoredState.fVertexCount;
632 }
633 if (kReserved_GeometrySrcType == restoredState.fIndexSrc ||
634 kArray_GeometrySrcType == restoredState.fIndexSrc) {
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000635 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000636 restoredState.fIndexCount;
637 }
638}
639
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000640bool GrInOrderDrawBuffer::needsNewState() const {
641 if (fStates.empty()) {
642 return true;
643 } else {
tomhudson@google.com93813632011-10-27 20:21:16 +0000644 const GrDrawState& old = this->accessSavedDrawState(fStates.back());
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000645 return old != fCurrDrawState;
646 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000647}
648
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000649void GrInOrderDrawBuffer::pushState() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000650 const GrDrawState& drawState = this->getDrawState();
tomhudson@google.com93813632011-10-27 20:21:16 +0000651 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000652 GrSafeRef(drawState.getTexture(s));
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000653 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000654 GrSafeRef(drawState.getRenderTarget());
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000655 this->saveCurrentDrawState(&fStates.push_back());
656 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000657
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000658bool GrInOrderDrawBuffer::needsNewClip() const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000659 if (this->getDrawState().isClipState()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000660 if (fClips.empty() || (fClipSet && fClips.back() != fClip)) {
661 return true;
662 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000663 }
664 return false;
665}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000666
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000667void GrInOrderDrawBuffer::pushClip() {
668 fClips.push_back() = fClip;
669 fClipSet = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000670}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000671
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +0000672void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip) {
673 INHERITED::clipWillBeSet(newClip);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000674 fClipSet = true;
675}