blob: 722ea429641dfefe4f3a731c7ab10fd787161572 [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.com4b90c622011-09-28 17:52:15 +000022 : fClipSet(true)
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000023 , fLastRectVertexLayout(0)
24 , fQuadIndexBuffer(NULL)
25 , fMaxQuads(0)
26 , fCurrQuad(0)
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000027 , fVertexPool(*vertexPool)
bsalomon@google.com92669012011-09-27 19:10:05 +000028 , fIndexPool(*indexPool) {
bsalomon@google.com18c9c192011-09-22 21:01:31 +000029
30 fCaps = gpu->getCaps();
31
bsalomon@google.com1c13c962011-02-14 16:51:21 +000032 GrAssert(NULL != vertexPool);
33 GrAssert(NULL != indexPool);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000034
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
reed@google.comac10a2d2010-12-22 21:39:39 +000044}
45
46GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000047 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000048 // This must be called by before the GrDrawTarget destructor
49 this->releaseGeometry();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000050 GrSafeUnref(fQuadIndexBuffer);
reed@google.comac10a2d2010-12-22 21:39:39 +000051}
52
53void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
54 this->copyDrawState(target);
55 this->setClip(target.getClip());
56}
57
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000058void 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 {
bsalomon@google.comd302f142011-03-03 13:54:13 +000067 GrAssert((NULL == indexBuffer && 0 == fMaxQuads) ||
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000068 (indexBuffer->maxQuads() == fMaxQuads));
69 }
70}
71
bsalomon@google.comd302f142011-03-03 13:54:13 +000072void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000073 const GrMatrix* matrix,
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000074 StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000075 const GrRect* srcRects[],
76 const GrMatrix* srcMatrices[]) {
bsalomon@google.comd302f142011-03-03 13:54:13 +000077
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000078 GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad));
79 GrAssert(!(fDraws.empty() && fCurrQuad));
80 GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer));
81
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000082 GrDrawState* drawState = this->drawState();
83
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000084 // if we have a quad IB then either append to the previous run of
85 // rects or start a new run
86 if (fMaxQuads) {
bsalomon@google.comd302f142011-03-03 13:54:13 +000087
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000088 bool appendToPreviousDraw = false;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000089 GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000090 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +000091 if (!geo.succeeded()) {
92 GrPrintf("Failed to get space for vertices!\n");
93 return;
94 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000095 GrMatrix combinedMatrix = drawState->getViewMatrix();
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +000096 // We go to device space so that matrix changes allow us to concat
97 // rect draws. When the caller has provided explicit source rects
98 // then we don't want to modify the sampler matrices. Otherwise we do
99 // we have to account for the view matrix change in the sampler
100 // matrices.
101 StageMask devCoordMask = (NULL == srcRects) ? stageMask : 0;
102 GrDrawTarget::AutoDeviceCoordDraw adcd(this, devCoordMask);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000103 if (NULL != matrix) {
104 combinedMatrix.preConcat(*matrix);
105 }
106
107 SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices, layout, geo.vertices());
108
109 // we don't want to miss an opportunity to batch rects together
110 // simply because the clip has changed if the clip doesn't affect
111 // the rect.
112 bool disabledClip = false;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000113 if (drawState->isClipState() && fClip.isRect()) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000114
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000115 GrRect clipRect = fClip.getRect(0);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000116 // If the clip rect touches the edge of the viewport, extended it
117 // out (close) to infinity to avoid bogus intersections.
bsalomon@google.comd302f142011-03-03 13:54:13 +0000118 // We might consider a more exact clip to viewport if this
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000119 // conservative test fails.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000120 const GrRenderTarget* target = drawState->getRenderTarget();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000121 if (0 >= clipRect.fLeft) {
122 clipRect.fLeft = GR_ScalarMin;
123 }
124 if (target->width() <= clipRect.fRight) {
125 clipRect.fRight = GR_ScalarMax;
126 }
127 if (0 >= clipRect.top()) {
128 clipRect.fTop = GR_ScalarMin;
129 }
130 if (target->height() <= clipRect.fBottom) {
131 clipRect.fBottom = GR_ScalarMax;
132 }
133 int stride = VertexSize(layout);
134 bool insideClip = true;
135 for (int v = 0; v < 4; ++v) {
136 const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride);
137 if (!clipRect.contains(p)) {
138 insideClip = false;
139 break;
140 }
141 }
142 if (insideClip) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000143 drawState->disableState(GrDrawState::kClip_StateBit);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000144 disabledClip = true;
145 }
146 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000147 if (!needsNewClip() && !needsNewState() && fCurrQuad > 0 &&
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000148 fCurrQuad < fMaxQuads && layout == fLastRectVertexLayout) {
149
150 int vsize = VertexSize(layout);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000151
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000152 Draw& lastDraw = fDraws.back();
153
154 GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer);
155 GrAssert(kTriangles_PrimitiveType == lastDraw.fPrimitiveType);
156 GrAssert(0 == lastDraw.fVertexCount % 4);
157 GrAssert(0 == lastDraw.fIndexCount % 6);
158 GrAssert(0 == lastDraw.fStartIndex);
159
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000160 GeometryPoolState& poolState = fGeoPoolStateStack.back();
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000161 bool clearSinceLastDraw =
162 fClears.count() &&
163 fClears.back().fBeforeDrawIdx == fDraws.count();
164
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000165 appendToPreviousDraw =
166 !clearSinceLastDraw &&
167 lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer &&
168 (fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex;
169
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000170 if (appendToPreviousDraw) {
171 lastDraw.fVertexCount += 4;
172 lastDraw.fIndexCount += 6;
173 fCurrQuad += 1;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000174 // we reserved above, so we should be the first
175 // use of this vertex reserveation.
176 GrAssert(0 == poolState.fUsedPoolVertexBytes);
177 poolState.fUsedPoolVertexBytes = 4 * vsize;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000178 }
179 }
180 if (!appendToPreviousDraw) {
181 this->setIndexSourceToBuffer(fQuadIndexBuffer);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000182 this->drawIndexed(kTriangles_PrimitiveType, 0, 0, 4, 6);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000183 fCurrQuad = 1;
184 fLastRectVertexLayout = layout;
185 }
186 if (disabledClip) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000187 drawState->enableState(GrDrawState::kClip_StateBit);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000188 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000189 } else {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +0000190 INHERITED::drawRect(rect, matrix, stageMask, srcRects, srcMatrices);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000191 }
192}
193
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000194void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType,
195 int startVertex,
196 int startIndex,
197 int vertexCount,
198 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000199
200 if (!vertexCount || !indexCount) {
201 return;
202 }
203
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000204 fCurrQuad = 0;
205
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000206 GeometryPoolState& poolState = fGeoPoolStateStack.back();
207
reed@google.comac10a2d2010-12-22 21:39:39 +0000208 Draw& draw = fDraws.push_back();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000209 draw.fPrimitiveType = primitiveType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000210 draw.fStartVertex = startVertex;
211 draw.fStartIndex = startIndex;
212 draw.fVertexCount = vertexCount;
213 draw.fIndexCount = indexCount;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000214
215 draw.fClipChanged = this->needsNewClip();
216 if (draw.fClipChanged) {
217 this->pushClip();
218 }
219
220 draw.fStateChanged = this->needsNewState();
221 if (draw.fStateChanged) {
222 this->pushState();
223 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000224
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000225 draw.fVertexLayout = this->getGeomSrc().fVertexLayout;
226 switch (this->getGeomSrc().fVertexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000227 case kBuffer_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000228 draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000229 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000230 case kReserved_GeometrySrcType: // fallthrough
231 case kArray_GeometrySrcType: {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000232 size_t vertexBytes = (vertexCount + startVertex) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000233 VertexSize(this->getGeomSrc().fVertexLayout);
234 poolState.fUsedPoolVertexBytes =
235 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
236 draw.fVertexBuffer = poolState.fPoolVertexBuffer;
237 draw.fStartVertex += poolState.fPoolStartVertex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000238 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000239 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000240 default:
241 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000242 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000243 draw.fVertexBuffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000244
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000245 switch (this->getGeomSrc().fIndexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000246 case kBuffer_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000247 draw.fIndexBuffer = this->getGeomSrc().fIndexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000248 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000249 case kReserved_GeometrySrcType: // fallthrough
250 case kArray_GeometrySrcType: {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000251 size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000252 poolState.fUsedPoolIndexBytes =
253 GrMax(poolState.fUsedPoolIndexBytes, indexBytes);
254 draw.fIndexBuffer = poolState.fPoolIndexBuffer;
bsalomon@google.comd127ffe2012-02-24 20:11:52 +0000255 draw.fStartIndex += poolState.fPoolStartIndex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000256 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000257 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000258 default:
259 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000260 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000261 draw.fIndexBuffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000262}
263
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000264void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
265 int startVertex,
266 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000267 if (!vertexCount) {
268 return;
269 }
270
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000271 fCurrQuad = 0;
272
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000273 GeometryPoolState& poolState = fGeoPoolStateStack.back();
274
reed@google.comac10a2d2010-12-22 21:39:39 +0000275 Draw& draw = fDraws.push_back();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000276 draw.fPrimitiveType = primitiveType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000277 draw.fStartVertex = startVertex;
278 draw.fStartIndex = 0;
279 draw.fVertexCount = vertexCount;
280 draw.fIndexCount = 0;
281
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000282 draw.fClipChanged = this->needsNewClip();
283 if (draw.fClipChanged) {
284 this->pushClip();
285 }
286
287 draw.fStateChanged = this->needsNewState();
288 if (draw.fStateChanged) {
289 this->pushState();
290 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000291
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000292 draw.fVertexLayout = this->getGeomSrc().fVertexLayout;
293 switch (this->getGeomSrc().fVertexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000294 case kBuffer_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000295 draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000296 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000297 case kReserved_GeometrySrcType: // fallthrough
298 case kArray_GeometrySrcType: {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000299 size_t vertexBytes = (vertexCount + startVertex) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000300 VertexSize(this->getGeomSrc().fVertexLayout);
301 poolState.fUsedPoolVertexBytes =
302 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
303 draw.fVertexBuffer = poolState.fPoolVertexBuffer;
304 draw.fStartVertex += poolState.fPoolStartVertex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000305 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000306 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000307 default:
308 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000309 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000310 draw.fVertexBuffer->ref();
311 draw.fIndexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000312}
313
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000314void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) {
315 GrIRect r;
316 if (NULL == rect) {
317 // We could do something smart and remove previous draws and clears to
318 // the current render target. If we get that smart we have to make sure
319 // those draws aren't read before this clear (render-to-texture).
320 r.setLTRB(0, 0,
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000321 this->getDrawState().getRenderTarget()->width(),
322 this->getDrawState().getRenderTarget()->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000323 rect = &r;
324 }
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000325 Clear& clr = fClears.push_back();
326 clr.fColor = color;
327 clr.fBeforeDrawIdx = fDraws.count();
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000328 clr.fRect = *rect;
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000329}
330
reed@google.comac10a2d2010-12-22 21:39:39 +0000331void GrInOrderDrawBuffer::reset() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000332 GrAssert(1 == fGeoPoolStateStack.count());
333 this->resetVertexSource();
334 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000335 uint32_t numStates = fStates.count();
336 for (uint32_t i = 0; i < numStates; ++i) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000337 const GrDrawState& dstate = this->accessSavedDrawState(fStates[i]);
338 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000339 GrSafeUnref(dstate.getTexture(s));
reed@google.comac10a2d2010-12-22 21:39:39 +0000340 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000341 GrSafeUnref(dstate.getRenderTarget());
reed@google.comac10a2d2010-12-22 21:39:39 +0000342 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000343 int numDraws = fDraws.count();
344 for (int d = 0; d < numDraws; ++d) {
345 // we always have a VB, but not always an IB
346 GrAssert(NULL != fDraws[d].fVertexBuffer);
347 fDraws[d].fVertexBuffer->unref();
348 GrSafeUnref(fDraws[d].fIndexBuffer);
349 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000350 fDraws.reset();
351 fStates.reset();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000352
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000353 fClears.reset();
354
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000355 fVertexPool.reset();
356 fIndexPool.reset();
357
reed@google.comac10a2d2010-12-22 21:39:39 +0000358 fClips.reset();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000359
360 fCurrQuad = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000361}
362
363void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000364 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
365 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000366
reed@google.comac10a2d2010-12-22 21:39:39 +0000367 GrAssert(NULL != target);
368 GrAssert(target != this); // not considered and why?
369
bsalomon@google.com898d9e52011-04-26 13:22:33 +0000370 int numDraws = fDraws.count();
reed@google.comac10a2d2010-12-22 21:39:39 +0000371 if (!numDraws) {
372 return;
373 }
374
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000375 fVertexPool.unlock();
376 fIndexPool.unlock();
reed@google.comac10a2d2010-12-22 21:39:39 +0000377
378 GrDrawTarget::AutoStateRestore asr(target);
379 GrDrawTarget::AutoClipRestore acr(target);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000380 AutoGeometryPush agp(target);
reed@google.comac10a2d2010-12-22 21:39:39 +0000381
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000382 int currState = ~0;
383 int currClip = ~0;
384 int currClear = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000385
bsalomon@google.com898d9e52011-04-26 13:22:33 +0000386 for (int i = 0; i < numDraws; ++i) {
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000387 while (currClear < fClears.count() &&
388 i == fClears[currClear].fBeforeDrawIdx) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000389 target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000390 ++currClear;
391 }
392
reed@google.comac10a2d2010-12-22 21:39:39 +0000393 const Draw& draw = fDraws[i];
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000394 if (draw.fStateChanged) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000395 ++currState;
396 target->restoreDrawState(fStates[currState]);
397 }
398 if (draw.fClipChanged) {
399 ++currClip;
400 target->setClip(fClips[currClip]);
401 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000402
403 target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
404
reed@google.comac10a2d2010-12-22 21:39:39 +0000405 if (draw.fIndexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000406 target->setIndexSourceToBuffer(draw.fIndexBuffer);
407 }
408
409 if (draw.fIndexCount) {
410 target->drawIndexed(draw.fPrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000411 draw.fStartVertex,
412 draw.fStartIndex,
413 draw.fVertexCount,
414 draw.fIndexCount);
415 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000416 target->drawNonIndexed(draw.fPrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000417 draw.fStartVertex,
418 draw.fVertexCount);
419 }
420 }
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000421 while (currClear < fClears.count()) {
422 GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000423 target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000424 ++currClear;
425 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000426}
427
428bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000429 int* vertexCount,
430 int* indexCount) const {
431 // we will recommend a flush if the data could fit in a single
432 // preallocated buffer but none are left and it can't fit
433 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000434 bool flush = false;
435 if (NULL != indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000436 int32_t currIndices = fIndexPool.currentBufferIndices();
437 if (*indexCount > currIndices &&
438 (!fIndexPool.preallocatedBuffersRemaining() &&
439 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
440
441 flush = true;
442 }
443 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000444 }
445 if (NULL != vertexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000446 int32_t currVertices = fVertexPool.currentBufferVertices(vertexLayout);
447 if (*vertexCount > currVertices &&
448 (!fVertexPool.preallocatedBuffersRemaining() &&
449 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexLayout))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000450
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000451 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000452 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000453 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000454 }
455 return flush;
456}
457
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000458bool GrInOrderDrawBuffer::onReserveVertexSpace(GrVertexLayout vertexLayout,
459 int vertexCount,
460 void** vertices) {
461 GeometryPoolState& poolState = fGeoPoolStateStack.back();
462 GrAssert(vertexCount > 0);
463 GrAssert(NULL != vertices);
464 GrAssert(0 == poolState.fUsedPoolVertexBytes);
465
466 *vertices = fVertexPool.makeSpace(vertexLayout,
467 vertexCount,
468 &poolState.fPoolVertexBuffer,
469 &poolState.fPoolStartVertex);
470 return NULL != *vertices;
471}
472
473bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
474 GeometryPoolState& poolState = fGeoPoolStateStack.back();
475 GrAssert(indexCount > 0);
476 GrAssert(NULL != indices);
477 GrAssert(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000478
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000479 *indices = fIndexPool.makeSpace(indexCount,
480 &poolState.fPoolIndexBuffer,
481 &poolState.fPoolStartIndex);
482 return NULL != *indices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000483}
484
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000485void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
486 GeometryPoolState& poolState = fGeoPoolStateStack.back();
487 const GeometrySrcState& geoSrc = this->getGeomSrc();
488
489 GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000490
491 // When the caller reserved vertex buffer space we gave it back a pointer
492 // provided by the vertex buffer pool. At each draw we tracked the largest
493 // offset into the pool's pointer that was referenced. Now we return to the
494 // pool any portion at the tail of the allocation that no draw referenced.
495 size_t reservedVertexBytes = VertexSize(geoSrc.fVertexLayout) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000496 geoSrc.fVertexCount;
497 fVertexPool.putBack(reservedVertexBytes -
498 poolState.fUsedPoolVertexBytes);
499 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000500 poolState.fPoolVertexBuffer = NULL;
501 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000502}
503
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000504void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
505 GeometryPoolState& poolState = fGeoPoolStateStack.back();
506 const GeometrySrcState& geoSrc = this->getGeomSrc();
507
508 GrAssert(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000509
510 // Similar to releaseReservedVertexSpace we return any unused portion at
511 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000512 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
513 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
514 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000515 poolState.fPoolIndexBuffer = NULL;
516 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000517}
518
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000519void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray,
520 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000521
522 GeometryPoolState& poolState = fGeoPoolStateStack.back();
523 GrAssert(0 == poolState.fUsedPoolVertexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000524#if GR_DEBUG
525 bool success =
526#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000527 fVertexPool.appendVertices(this->getGeomSrc().fVertexLayout,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000528 vertexCount,
529 vertexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000530 &poolState.fPoolVertexBuffer,
531 &poolState.fPoolStartVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000532 GR_DEBUGASSERT(success);
533}
534
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000535void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
536 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000537 GeometryPoolState& poolState = fGeoPoolStateStack.back();
538 GrAssert(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000539#if GR_DEBUG
540 bool success =
541#endif
542 fIndexPool.appendIndices(indexCount,
543 indexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000544 &poolState.fPoolIndexBuffer,
545 &poolState.fPoolStartIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000546 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000547}
548
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000549void GrInOrderDrawBuffer::releaseVertexArray() {
550 // When the client provides an array as the vertex source we handled it
551 // by copying their array into reserved space.
552 this->GrInOrderDrawBuffer::releaseReservedVertexSpace();
553}
554
555void GrInOrderDrawBuffer::releaseIndexArray() {
556 // When the client provides an array as the index source we handled it
557 // by copying their array into reserved space.
558 this->GrInOrderDrawBuffer::releaseReservedIndexSpace();
559}
560
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000561void GrInOrderDrawBuffer::geometrySourceWillPush() {
562 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
563 poolState.fUsedPoolVertexBytes = 0;
564 poolState.fUsedPoolIndexBytes = 0;
565#if GR_DEBUG
566 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
567 poolState.fPoolStartVertex = ~0;
568 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
569 poolState.fPoolStartIndex = ~0;
570#endif
571}
572
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000573void GrInOrderDrawBuffer::geometrySourceWillPop(
574 const GeometrySrcState& restoredState) {
575 GrAssert(fGeoPoolStateStack.count() > 1);
576 fGeoPoolStateStack.pop_back();
577 GeometryPoolState& poolState = fGeoPoolStateStack.back();
578 // we have to assume that any slack we had in our vertex/index data
579 // is now unreleasable because data may have been appended later in the
580 // pool.
581 if (kReserved_GeometrySrcType == restoredState.fVertexSrc ||
582 kArray_GeometrySrcType == restoredState.fVertexSrc) {
583 poolState.fUsedPoolVertexBytes =
584 VertexSize(restoredState.fVertexLayout) *
585 restoredState.fVertexCount;
586 }
587 if (kReserved_GeometrySrcType == restoredState.fIndexSrc ||
588 kArray_GeometrySrcType == restoredState.fIndexSrc) {
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000589 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000590 restoredState.fIndexCount;
591 }
592}
593
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000594bool GrInOrderDrawBuffer::needsNewState() const {
595 if (fStates.empty()) {
596 return true;
597 } else {
tomhudson@google.com93813632011-10-27 20:21:16 +0000598 const GrDrawState& old = this->accessSavedDrawState(fStates.back());
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000599 return old != fCurrDrawState;
600 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000601}
602
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000603void GrInOrderDrawBuffer::pushState() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000604 const GrDrawState& drawState = this->getDrawState();
tomhudson@google.com93813632011-10-27 20:21:16 +0000605 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000606 GrSafeRef(drawState.getTexture(s));
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000607 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000608 GrSafeRef(drawState.getRenderTarget());
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000609 this->saveCurrentDrawState(&fStates.push_back());
610 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000611
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000612bool GrInOrderDrawBuffer::needsNewClip() const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000613 if (this->getDrawState().isClipState()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000614 if (fClips.empty() || (fClipSet && fClips.back() != fClip)) {
615 return true;
616 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000617 }
618 return false;
619}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000620
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000621void GrInOrderDrawBuffer::pushClip() {
622 fClips.push_back() = fClip;
623 fClipSet = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000624}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000625
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +0000626void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip) {
627 INHERITED::clipWillBeSet(newClip);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000628 fClipSet = true;
629}