blob: d51dca4fde6fe32ee2631bbcd0ee9eeb2a90d945 [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
10#include "GrInOrderDrawBuffer.h"
bsalomon@google.comded4f4b2012-06-28 18:48:06 +000011#include "GrBufferAllocPool.h"
12#include "GrGpu.h"
13#include "GrIndexBuffer.h"
14#include "GrPath.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000015#include "GrRenderTarget.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016#include "GrTexture.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000017#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000018
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)
robertphillips@google.com69705572012-03-21 19:46:50 +000024 , fVertexPool(*vertexPool)
25 , fIndexPool(*indexPool)
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000026 , fLastRectVertexLayout(0)
27 , fQuadIndexBuffer(NULL)
28 , fMaxQuads(0)
robertphillips@google.comc82a8b72012-06-21 20:15:48 +000029 , fFlushing(false) {
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
bsalomon@google.coma4f6b102012-06-26 21:04:22 +000045 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000046}
47
48GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000049 this->reset();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000050 // This must be called by before the GrDrawTarget destructor
51 this->releaseGeometry();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000052 GrSafeUnref(fQuadIndexBuffer);
bsalomon@google.com97805382012-03-13 14:32:07 +000053 GrSafeUnref(fAutoFlushTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +000054}
55
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000056void GrInOrderDrawBuffer::setQuadIndexBuffer(const GrIndexBuffer* indexBuffer) {
57 bool newIdxBuffer = fQuadIndexBuffer != indexBuffer;
58 if (newIdxBuffer) {
59 GrSafeUnref(fQuadIndexBuffer);
60 fQuadIndexBuffer = indexBuffer;
61 GrSafeRef(fQuadIndexBuffer);
62 fCurrQuad = 0;
63 fMaxQuads = (NULL == indexBuffer) ? 0 : indexBuffer->maxQuads();
64 } else {
bsalomon@google.comd302f142011-03-03 13:54:13 +000065 GrAssert((NULL == indexBuffer && 0 == fMaxQuads) ||
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000066 (indexBuffer->maxQuads() == fMaxQuads));
67 }
68}
69
bsalomon@google.com934c5702012-03-20 21:17:58 +000070////////////////////////////////////////////////////////////////////////////////
71
72void GrInOrderDrawBuffer::resetDrawTracking() {
73 fCurrQuad = 0;
74 fInstancedDrawTracker.reset();
75}
76
bsalomon@google.comd302f142011-03-03 13:54:13 +000077void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +000078 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000079 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +000080 const SkMatrix* srcMatrices[]) {
bsalomon@google.comd302f142011-03-03 13:54:13 +000081
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000082 GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad));
83 GrAssert(!(fDraws.empty() && fCurrQuad));
84 GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer));
85
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000086 GrDrawState* drawState = this->drawState();
87
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000088 // if we have a quad IB then either append to the previous run of
89 // rects or start a new run
90 if (fMaxQuads) {
bsalomon@google.comd302f142011-03-03 13:54:13 +000091
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000092 bool appendToPreviousDraw = false;
bsalomon@google.come3d32162012-07-20 13:37:06 +000093 GrVertexLayout layout = GetRectVertexLayout(srcRects);
robertphillips@google.com8b129aa2012-10-05 15:37:00 +000094
robertphillips@google.comf04c40e2012-10-09 17:40:32 +000095 // Batching across colors means we move the draw color into the
96 // rect's vertex colors to allow greater batching (a lot of rects
97 // in a row differing only in color is a common occurence in tables).
98 bool batchAcrossColors = true;
99 if (!this->getCaps().dualSourceBlendingSupport()) {
100 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
101 if (this->getDrawState().isStageEnabled(s)) {
skia.committer@gmail.com439cb512012-10-10 02:01:30 +0000102 // We disable batching across colors when there is a texture
robertphillips@google.comf04c40e2012-10-09 17:40:32 +0000103 // present because (by pushing the the color to the vertices)
104 // Ganesh loses track of the rect's opacity. This, in turn, can
105 // cause some of the blending optimizations to be disabled. This
106 // becomes a huge problem on some of the smaller devices where
107 // shader derivatives and dual source blending aren't supported.
108 // In those cases paths are often drawn to a texture and then
109 // drawn as a texture (using this method). Because dual source
110 // blending is disabled (and the blend optimizations are short
111 // circuited) some of the more esoteric blend modes can no longer
112 // be supported.
113 // TODO: add tracking of batchAcrossColors's opacity
114 batchAcrossColors = false;
115 break;
116 }
117 }
118 }
119
120 if (batchAcrossColors) {
121 layout |= kColor_VertexLayoutBit;
122 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000123
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000124 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000125 if (!geo.succeeded()) {
126 GrPrintf("Failed to get space for vertices!\n");
127 return;
128 }
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000129 SkMatrix combinedMatrix = drawState->getViewMatrix();
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000130 // We go to device space so that matrix changes allow us to concat
131 // rect draws. When the caller has provided explicit source rects
bsalomon@google.com08283af2012-10-26 13:01:20 +0000132 // then we don't want to modify the stages' matrices. Otherwise
133 // we have to account for the view matrix change in the stage
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000134 // matrices.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000135 uint32_t explicitCoordMask = 0;
136 if (srcRects) {
137 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
138 if (srcRects[s]) {
139 explicitCoordMask |= (1 << s);
140 }
141 }
142 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000143 GrDrawState::AutoDeviceCoordDraw adcd(this->drawState(), explicitCoordMask);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000144 if (!adcd.succeeded()) {
145 return;
146 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000147 if (NULL != matrix) {
148 combinedMatrix.preConcat(*matrix);
149 }
150
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +0000151 SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000152 this->getDrawState().getColor(), layout, geo.vertices());
153
154 // Now that the paint's color is stored in the vertices set it to
155 // white so that the following code can batch all the rects regardless
156 // of paint color
skia.committer@gmail.com439cb512012-10-10 02:01:30 +0000157 GrDrawState::AutoColorRestore acr(this->drawState(),
robertphillips@google.comf04c40e2012-10-09 17:40:32 +0000158 batchAcrossColors ? SK_ColorWHITE
159 : this->getDrawState().getColor());
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000160
161 // we don't want to miss an opportunity to batch rects together
162 // simply because the clip has changed if the clip doesn't affect
163 // the rect.
164 bool disabledClip = false;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000165
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000166 if (drawState->isClipState()) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000167
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000168 GrRect devClipRect;
169 bool isIntersectionOfRects = false;
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000170
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000171 fClip->fClipStack->getConservativeBounds(-fClip->fOrigin.fX,
172 -fClip->fOrigin.fY,
173 drawState->getRenderTarget()->width(),
174 drawState->getRenderTarget()->height(),
175 &devClipRect,
176 &isIntersectionOfRects);
robertphillips@google.coma6f11c42012-07-23 17:39:44 +0000177
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000178 if (isIntersectionOfRects) {
179 // If the clip rect touches the edge of the viewport, extended it
180 // out (close) to infinity to avoid bogus intersections.
181 // We might consider a more exact clip to viewport if this
182 // conservative test fails.
183 const GrRenderTarget* target = drawState->getRenderTarget();
184 if (0 >= devClipRect.fLeft) {
bsalomon@google.com81712882012-11-01 17:12:34 +0000185 devClipRect.fLeft = SK_ScalarMin;
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000186 }
187 if (target->width() <= devClipRect.fRight) {
bsalomon@google.com81712882012-11-01 17:12:34 +0000188 devClipRect.fRight = SK_ScalarMax;
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000189 }
190 if (0 >= devClipRect.top()) {
bsalomon@google.com81712882012-11-01 17:12:34 +0000191 devClipRect.fTop = SK_ScalarMin;
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000192 }
193 if (target->height() <= devClipRect.fBottom) {
bsalomon@google.com81712882012-11-01 17:12:34 +0000194 devClipRect.fBottom = SK_ScalarMax;
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000195 }
196 int stride = VertexSize(layout);
197 bool insideClip = true;
198 for (int v = 0; v < 4; ++v) {
199 const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride);
200 if (!devClipRect.contains(p)) {
201 insideClip = false;
202 break;
203 }
204 }
205 if (insideClip) {
206 drawState->disableState(GrDrawState::kClip_StateBit);
207 disabledClip = true;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000208 }
209 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000210 }
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000211
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000212 if (!this->needsNewClip() &&
213 !this->needsNewState() &&
214 fCurrQuad > 0 &&
215 fCurrQuad < fMaxQuads &&
216 layout == fLastRectVertexLayout) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000217
218 int vsize = VertexSize(layout);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000219
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000220 Draw& lastDraw = fDraws.back();
221
222 GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer);
bsalomon@google.com47059542012-06-06 20:51:20 +0000223 GrAssert(kTriangles_GrPrimitiveType == lastDraw.fPrimitiveType);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000224 GrAssert(0 == lastDraw.fVertexCount % 4);
225 GrAssert(0 == lastDraw.fIndexCount % 6);
226 GrAssert(0 == lastDraw.fStartIndex);
227
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000228 GeometryPoolState& poolState = fGeoPoolStateStack.back();
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000229
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000230 appendToPreviousDraw =
robertphillips@google.com837ec432012-10-04 17:57:05 +0000231 kDraw_Cmd == fCmds.back() &&
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000232 lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer &&
233 (fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex;
234
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000235 if (appendToPreviousDraw) {
236 lastDraw.fVertexCount += 4;
237 lastDraw.fIndexCount += 6;
238 fCurrQuad += 1;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000239 // we reserved above, so we should be the first
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000240 // use of this vertex reservation.
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000241 GrAssert(0 == poolState.fUsedPoolVertexBytes);
242 poolState.fUsedPoolVertexBytes = 4 * vsize;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000243 }
244 }
245 if (!appendToPreviousDraw) {
246 this->setIndexSourceToBuffer(fQuadIndexBuffer);
bsalomon@google.com47059542012-06-06 20:51:20 +0000247 this->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 4, 6);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000248 fCurrQuad = 1;
249 fLastRectVertexLayout = layout;
250 }
251 if (disabledClip) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000252 drawState->enableState(GrDrawState::kClip_StateBit);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000253 }
bsalomon@google.com934c5702012-03-20 21:17:58 +0000254 fInstancedDrawTracker.reset();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000255 } else {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000256 INHERITED::drawRect(rect, matrix, srcRects, srcMatrices);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000257 }
258}
259
bsalomon@google.com934c5702012-03-20 21:17:58 +0000260void GrInOrderDrawBuffer::drawIndexedInstances(GrPrimitiveType type,
261 int instanceCount,
262 int verticesPerInstance,
263 int indicesPerInstance) {
264 if (!verticesPerInstance || !indicesPerInstance) {
265 return;
266 }
267
268 const GeometrySrcState& geomSrc = this->getGeomSrc();
269
270 // we only attempt to concat the case when reserved verts are used with
271 // an index buffer.
272 if (kReserved_GeometrySrcType == geomSrc.fVertexSrc &&
273 kBuffer_GeometrySrcType == geomSrc.fIndexSrc) {
274
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000275 if (this->needsNewClip()) {
276 this->recordClip();
277 }
278 if (this->needsNewState()) {
279 this->recordState();
280 }
281
bsalomon@google.com934c5702012-03-20 21:17:58 +0000282 Draw* draw = NULL;
283 // if the last draw used the same indices/vertices per shape then we
284 // may be able to append to it.
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000285 if (kDraw_Cmd == fCmds.back() &&
286 verticesPerInstance == fInstancedDrawTracker.fVerticesPerInstance &&
bsalomon@google.com934c5702012-03-20 21:17:58 +0000287 indicesPerInstance == fInstancedDrawTracker.fIndicesPerInstance) {
288 GrAssert(fDraws.count());
289 draw = &fDraws.back();
290 }
291
bsalomon@google.com934c5702012-03-20 21:17:58 +0000292 GeometryPoolState& poolState = fGeoPoolStateStack.back();
293 const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
294
295 // Check whether the draw is compatible with this draw in order to
296 // append
297 if (NULL == draw ||
bsalomon@google.com934c5702012-03-20 21:17:58 +0000298 draw->fIndexBuffer != geomSrc.fIndexBuffer ||
299 draw->fPrimitiveType != type ||
300 draw->fVertexBuffer != vertexBuffer) {
301
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000302 draw = this->recordDraw();
robertphillips@google.com6d067302012-12-18 21:47:47 +0000303 draw->fPrimitiveType = type;
304 draw->fStartVertex = poolState.fPoolStartVertex;
305 draw->fStartIndex = 0;
306 draw->fVertexCount = 0;
307 draw->fIndexCount = 0;
308 draw->fVertexLayout = geomSrc.fVertexLayout;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000309 draw->fVertexBuffer = vertexBuffer;
310 vertexBuffer->ref();
robertphillips@google.com6d067302012-12-18 21:47:47 +0000311 draw->fIndexBuffer = geomSrc.fIndexBuffer;
312 geomSrc.fIndexBuffer->ref();
bsalomon@google.com934c5702012-03-20 21:17:58 +0000313 } else {
314 GrAssert(!(draw->fIndexCount % indicesPerInstance));
315 GrAssert(!(draw->fVertexCount % verticesPerInstance));
316 GrAssert(poolState.fPoolStartVertex == draw->fStartVertex +
317 draw->fVertexCount);
318 }
319
320 // how many instances can be in a single draw
321 int maxInstancesPerDraw = this->indexCountInCurrentSource() /
322 indicesPerInstance;
323 if (!maxInstancesPerDraw) {
324 return;
325 }
326 // how many instances should be concat'ed onto draw
327 int instancesToConcat = maxInstancesPerDraw - draw->fVertexCount /
328 verticesPerInstance;
329 if (maxInstancesPerDraw > instanceCount) {
330 maxInstancesPerDraw = instanceCount;
331 if (instancesToConcat > instanceCount) {
332 instancesToConcat = instanceCount;
333 }
334 }
335
336 // update the amount of reserved data actually referenced in draws
337 size_t vertexBytes = instanceCount * verticesPerInstance *
338 VertexSize(draw->fVertexLayout);
339 poolState.fUsedPoolVertexBytes =
340 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
341
342 while (instanceCount) {
343 if (!instancesToConcat) {
344 int startVertex = draw->fStartVertex + draw->fVertexCount;
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000345 draw = this->recordDraw();
robertphillips@google.com6d067302012-12-18 21:47:47 +0000346 draw->fPrimitiveType = type;
347 draw->fStartVertex = startVertex;
348 draw->fStartIndex = 0;
349 draw->fVertexCount = 0;
350 draw->fIndexCount = 0;
351 draw->fVertexLayout = geomSrc.fVertexLayout;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000352 draw->fVertexBuffer = vertexBuffer;
353 vertexBuffer->ref();
robertphillips@google.com6d067302012-12-18 21:47:47 +0000354 draw->fIndexBuffer = geomSrc.fIndexBuffer;
355 geomSrc.fIndexBuffer->ref();
bsalomon@google.com934c5702012-03-20 21:17:58 +0000356 instancesToConcat = maxInstancesPerDraw;
357 }
358 draw->fVertexCount += instancesToConcat * verticesPerInstance;
359 draw->fIndexCount += instancesToConcat * indicesPerInstance;
360 instanceCount -= instancesToConcat;
361 instancesToConcat = 0;
362 }
363
364 // update draw tracking for next draw
365 fCurrQuad = 0;
366 fInstancedDrawTracker.fVerticesPerInstance = verticesPerInstance;
367 fInstancedDrawTracker.fIndicesPerInstance = indicesPerInstance;
368 } else {
369 this->INHERITED::drawIndexedInstances(type,
370 instanceCount,
371 verticesPerInstance,
372 indicesPerInstance);
373 }
374
375}
376
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000377void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType,
378 int startVertex,
379 int startIndex,
380 int vertexCount,
381 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000382
383 if (!vertexCount || !indexCount) {
384 return;
385 }
386
bsalomon@google.com934c5702012-03-20 21:17:58 +0000387 this->resetDrawTracking();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000388
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000389 GeometryPoolState& poolState = fGeoPoolStateStack.back();
390
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000391 if (this->needsNewClip()) {
392 this->recordClip();
393 }
394 if (this->needsNewState()) {
395 this->recordState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000396 }
397
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000398 Draw* draw = this->recordDraw();
reed@google.comac10a2d2010-12-22 21:39:39 +0000399
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000400 draw->fPrimitiveType = primitiveType;
401 draw->fStartVertex = startVertex;
402 draw->fStartIndex = startIndex;
403 draw->fVertexCount = vertexCount;
404 draw->fIndexCount = indexCount;
405
406 draw->fVertexLayout = this->getVertexLayout();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000407 switch (this->getGeomSrc().fVertexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000408 case kBuffer_GeometrySrcType:
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000409 draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000410 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000411 case kReserved_GeometrySrcType: // fallthrough
412 case kArray_GeometrySrcType: {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000413 size_t vertexBytes = (vertexCount + startVertex) *
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000414 VertexSize(draw->fVertexLayout);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000415 poolState.fUsedPoolVertexBytes =
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000416 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000417 draw->fVertexBuffer = poolState.fPoolVertexBuffer;
418 draw->fStartVertex += poolState.fPoolStartVertex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000419 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000420 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000421 default:
422 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000423 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000424 draw->fVertexBuffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000425
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000426 switch (this->getGeomSrc().fIndexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000427 case kBuffer_GeometrySrcType:
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000428 draw->fIndexBuffer = this->getGeomSrc().fIndexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000429 break;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000430 case kReserved_GeometrySrcType: // fallthrough
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000431 case kArray_GeometrySrcType: {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000432 size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000433 poolState.fUsedPoolIndexBytes =
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000434 GrMax(poolState.fUsedPoolIndexBytes, indexBytes);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000435 draw->fIndexBuffer = poolState.fPoolIndexBuffer;
436 draw->fStartIndex += poolState.fPoolStartIndex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000437 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000438 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000439 default:
440 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000441 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000442 draw->fIndexBuffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000443}
444
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000445void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
446 int startVertex,
447 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000448 if (!vertexCount) {
449 return;
450 }
451
bsalomon@google.com934c5702012-03-20 21:17:58 +0000452 this->resetDrawTracking();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000453
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000454 GeometryPoolState& poolState = fGeoPoolStateStack.back();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000455 if (this->needsNewClip()) {
456 this->recordClip();
457 }
458 if (this->needsNewState()) {
459 this->recordState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000460 }
461
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000462 Draw* draw = this->recordDraw();
463 draw->fPrimitiveType = primitiveType;
464 draw->fStartVertex = startVertex;
465 draw->fStartIndex = 0;
466 draw->fVertexCount = vertexCount;
467 draw->fIndexCount = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000468
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000469 draw->fVertexLayout = this->getVertexLayout();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000470 switch (this->getGeomSrc().fVertexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000471 case kBuffer_GeometrySrcType:
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000472 draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer;
reed@google.comac10a2d2010-12-22 21:39:39 +0000473 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000474 case kReserved_GeometrySrcType: // fallthrough
475 case kArray_GeometrySrcType: {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000476 size_t vertexBytes = (vertexCount + startVertex) *
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000477 VertexSize(draw->fVertexLayout);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000478 poolState.fUsedPoolVertexBytes =
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000479 GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000480 draw->fVertexBuffer = poolState.fPoolVertexBuffer;
481 draw->fStartVertex += poolState.fPoolStartVertex;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000482 break;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000483 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000484 default:
485 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000486 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000487 draw->fVertexBuffer->ref();
488 draw->fIndexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000489}
490
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000491GrInOrderDrawBuffer::StencilPath::StencilPath() : fStroke(SkStrokeRec::kFill_InitStyle) {}
492
493void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, const SkStrokeRec& stroke,
sugoi@google.com12b4e272012-12-06 20:13:11 +0000494 SkPath::FillType fill) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000495 if (this->needsNewClip()) {
496 this->recordClip();
497 }
498 // Only compare the subset of GrDrawState relevant to path stenciling?
499 if (this->needsNewState()) {
500 this->recordState();
501 }
502 StencilPath* sp = this->recordStencilPath();
503 sp->fPath.reset(path);
504 path->ref();
505 sp->fFill = fill;
sugoi@google.com12b4e272012-12-06 20:13:11 +0000506 sp->fStroke = stroke;
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000507}
508
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000509void GrInOrderDrawBuffer::clear(const GrIRect* rect,
robertphillips@google.comc82a8b72012-06-21 20:15:48 +0000510 GrColor color,
511 GrRenderTarget* renderTarget) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000512 GrIRect r;
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000513 if (NULL == renderTarget) {
514 renderTarget = this->drawState()->getRenderTarget();
515 GrAssert(NULL != renderTarget);
516 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000517 if (NULL == rect) {
518 // We could do something smart and remove previous draws and clears to
519 // the current render target. If we get that smart we have to make sure
520 // those draws aren't read before this clear (render-to-texture).
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000521 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
bsalomon@google.com6aa25c32011-04-27 19:55:29 +0000522 rect = &r;
523 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000524 Clear* clr = this->recordClear();
525 clr->fColor = color;
526 clr->fRect = *rect;
527 clr->fRenderTarget = renderTarget;
bsalomon@google.com1b3ce472012-08-17 13:43:08 +0000528 renderTarget->ref();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000529}
530
reed@google.comac10a2d2010-12-22 21:39:39 +0000531void GrInOrderDrawBuffer::reset() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000532 GrAssert(1 == fGeoPoolStateStack.count());
533 this->resetVertexSource();
534 this->resetIndexSource();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000535 int numDraws = fDraws.count();
536 for (int d = 0; d < numDraws; ++d) {
537 // we always have a VB, but not always an IB
538 GrAssert(NULL != fDraws[d].fVertexBuffer);
539 fDraws[d].fVertexBuffer->unref();
540 GrSafeUnref(fDraws[d].fIndexBuffer);
541 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000542 fCmds.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000543 fDraws.reset();
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000544 fStencilPaths.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000545 fStates.reset();
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000546 fClears.reset();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000547 fVertexPool.reset();
548 fIndexPool.reset();
reed@google.comac10a2d2010-12-22 21:39:39 +0000549 fClips.reset();
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000550 fClipOrigins.reset();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000551 fClipSet = true;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000552
bsalomon@google.com934c5702012-03-20 21:17:58 +0000553 this->resetDrawTracking();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000554
555 // we start off with a default clip and state so that we don't have
556 // to do count checks on fClips, fStates, or fCmds before checking their
557 // last entry.
558 this->recordDefaultState();
559 this->recordDefaultClip();
reed@google.comac10a2d2010-12-22 21:39:39 +0000560}
561
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000562bool GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000563 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
564 GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000565
reed@google.comac10a2d2010-12-22 21:39:39 +0000566 GrAssert(NULL != target);
567 GrAssert(target != this); // not considered and why?
568
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000569 int numCmds = fCmds.count();
570 GrAssert(numCmds >= 2);
571 if (2 == numCmds) {
572 GrAssert(kSetState_Cmd == fCmds[0]);
573 GrAssert(kSetClip_Cmd == fCmds[1]);
574 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000575 }
576
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000577 fVertexPool.unlock();
578 fIndexPool.unlock();
reed@google.comac10a2d2010-12-22 21:39:39 +0000579
reed@google.comac10a2d2010-12-22 21:39:39 +0000580 GrDrawTarget::AutoClipRestore acr(target);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000581 AutoGeometryPush agp(target);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000582 GrDrawState* prevDrawState = target->drawState();
583 prevDrawState->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000584
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000585 GrClipData clipData;
586
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000587 int currState = 0;
588 int currClip = 0;
589 int currClear = 0;
590 int currDraw = 0;
591 int currStencilPath = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000592
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000593 for (int c = 0; c < numCmds; ++c) {
594 switch (fCmds[c]) {
595 case kDraw_Cmd: {
596 const Draw& draw = fDraws[currDraw];
597 target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
598 if (draw.fIndexCount) {
599 target->setIndexSourceToBuffer(draw.fIndexBuffer);
600 }
bsalomon@google.com0b335c12011-04-25 19:17:44 +0000601
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000602 if (draw.fIndexCount) {
603 target->drawIndexed(draw.fPrimitiveType,
604 draw.fStartVertex,
605 draw.fStartIndex,
606 draw.fVertexCount,
607 draw.fIndexCount);
608 } else {
609 target->drawNonIndexed(draw.fPrimitiveType,
610 draw.fStartVertex,
611 draw.fVertexCount);
612 }
613 ++currDraw;
614 break;
615 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000616 case kStencilPath_Cmd: {
617 const StencilPath& sp = fStencilPaths[currStencilPath];
sugoi@google.com12b4e272012-12-06 20:13:11 +0000618 target->stencilPath(sp.fPath.get(), sp.fStroke, sp.fFill);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000619 ++currStencilPath;
620 break;
621 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000622 case kSetState_Cmd:
623 target->setDrawState(&fStates[currState]);
624 ++currState;
625 break;
626 case kSetClip_Cmd:
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000627 clipData.fClipStack = &fClips[currClip];
628 clipData.fOrigin = fClipOrigins[currClip];
629 target->setClip(&clipData);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000630 ++currClip;
631 break;
632 case kClear_Cmd:
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000633 target->clear(&fClears[currClear].fRect,
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000634 fClears[currClear].fColor,
635 fClears[currClear].fRenderTarget);
636 ++currClear;
637 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000638 }
639 }
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000640 // we should have consumed all the states, clips, etc.
641 GrAssert(fStates.count() == currState);
642 GrAssert(fClips.count() == currClip);
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000643 GrAssert(fClipOrigins.count() == currClip);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000644 GrAssert(fClears.count() == currClear);
645 GrAssert(fDraws.count() == currDraw);
646
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000647 target->setDrawState(prevDrawState);
648 prevDrawState->unref();
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000649 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000650}
651
bsalomon@google.com97805382012-03-13 14:32:07 +0000652void GrInOrderDrawBuffer::setAutoFlushTarget(GrDrawTarget* target) {
653 GrSafeAssign(fAutoFlushTarget, target);
654}
655
656void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(
657 GrVertexLayout vertexLayout,
658 int vertexCount,
659 int indexCount) {
660 if (NULL != fAutoFlushTarget) {
661 // We use geometryHints() to know whether to flush the draw buffer. We
662 // can't flush if we are inside an unbalanced pushGeometrySource.
663 // Moreover, flushing blows away vertex and index data that was
664 // previously reserved. So if the vertex or index data is pulled from
665 // reserved space and won't be released by this request then we can't
666 // flush.
667 bool insideGeoPush = fGeoPoolStateStack.count() > 1;
668
669 bool unreleasedVertexSpace =
670 !vertexCount &&
671 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
672
673 bool unreleasedIndexSpace =
674 !indexCount &&
675 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
676
677 // we don't want to finalize any reserved geom on the target since
678 // we don't know that the client has finished writing to it.
679 bool targetHasReservedGeom =
680 fAutoFlushTarget->hasReservedVerticesOrIndices();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000681
bsalomon@google.com97805382012-03-13 14:32:07 +0000682 int vcount = vertexCount;
683 int icount = indexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000684
bsalomon@google.com97805382012-03-13 14:32:07 +0000685 if (!insideGeoPush &&
686 !unreleasedVertexSpace &&
687 !unreleasedIndexSpace &&
688 !targetHasReservedGeom &&
689 this->geometryHints(vertexLayout, &vcount, &icount)) {
690
691 this->flushTo(fAutoFlushTarget);
692 }
693 }
694}
695
reed@google.comac10a2d2010-12-22 21:39:39 +0000696bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000697 int* vertexCount,
698 int* indexCount) const {
699 // we will recommend a flush if the data could fit in a single
700 // preallocated buffer but none are left and it can't fit
701 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000702 bool flush = false;
703 if (NULL != indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000704 int32_t currIndices = fIndexPool.currentBufferIndices();
705 if (*indexCount > currIndices &&
706 (!fIndexPool.preallocatedBuffersRemaining() &&
707 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
708
709 flush = true;
710 }
711 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000712 }
713 if (NULL != vertexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000714 int32_t currVertices = fVertexPool.currentBufferVertices(vertexLayout);
715 if (*vertexCount > currVertices &&
716 (!fVertexPool.preallocatedBuffersRemaining() &&
717 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexLayout))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000718
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000719 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000720 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000721 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000722 }
723 return flush;
724}
725
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000726bool GrInOrderDrawBuffer::onReserveVertexSpace(GrVertexLayout vertexLayout,
727 int vertexCount,
728 void** vertices) {
729 GeometryPoolState& poolState = fGeoPoolStateStack.back();
730 GrAssert(vertexCount > 0);
731 GrAssert(NULL != vertices);
732 GrAssert(0 == poolState.fUsedPoolVertexBytes);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000733
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000734 *vertices = fVertexPool.makeSpace(vertexLayout,
735 vertexCount,
736 &poolState.fPoolVertexBuffer,
737 &poolState.fPoolStartVertex);
738 return NULL != *vertices;
739}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000740
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000741bool GrInOrderDrawBuffer::onReserveIndexSpace(int indexCount, void** indices) {
742 GeometryPoolState& poolState = fGeoPoolStateStack.back();
743 GrAssert(indexCount > 0);
744 GrAssert(NULL != indices);
745 GrAssert(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000746
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000747 *indices = fIndexPool.makeSpace(indexCount,
748 &poolState.fPoolIndexBuffer,
749 &poolState.fPoolStartIndex);
750 return NULL != *indices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000751}
752
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000753void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
754 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000755 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000756
757 // If we get a release vertex space call then our current source should either be reserved
758 // or array (which we copied into reserved space).
759 GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc ||
760 kArray_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000761
762 // When the caller reserved vertex buffer space we gave it back a pointer
763 // provided by the vertex buffer pool. At each draw we tracked the largest
764 // offset into the pool's pointer that was referenced. Now we return to the
765 // pool any portion at the tail of the allocation that no draw referenced.
766 size_t reservedVertexBytes = VertexSize(geoSrc.fVertexLayout) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000767 geoSrc.fVertexCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000768 fVertexPool.putBack(reservedVertexBytes -
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000769 poolState.fUsedPoolVertexBytes);
770 poolState.fUsedPoolVertexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000771 poolState.fPoolVertexBuffer = NULL;
772 poolState.fPoolStartVertex = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000773}
774
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000775void GrInOrderDrawBuffer::releaseReservedIndexSpace() {
776 GeometryPoolState& poolState = fGeoPoolStateStack.back();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000777 const GeometrySrcState& geoSrc = this->getGeomSrc();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000778
bsalomon@google.comd57d71a2012-08-16 16:26:33 +0000779 // If we get a release index space call then our current source should either be reserved
780 // or array (which we copied into reserved space).
781 GrAssert(kReserved_GeometrySrcType == geoSrc.fIndexSrc ||
782 kArray_GeometrySrcType == geoSrc.fIndexSrc);
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000783
784 // Similar to releaseReservedVertexSpace we return any unused portion at
785 // the tail
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000786 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount;
787 fIndexPool.putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes);
788 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000789 poolState.fPoolIndexBuffer = NULL;
790 poolState.fPoolStartIndex = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000791}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000792
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000793void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray,
794 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000795
796 GeometryPoolState& poolState = fGeoPoolStateStack.back();
797 GrAssert(0 == poolState.fUsedPoolVertexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000798#if GR_DEBUG
799 bool success =
800#endif
bsalomon@google.come79c8152012-03-29 19:07:12 +0000801 fVertexPool.appendVertices(this->getVertexLayout(),
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000802 vertexCount,
803 vertexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000804 &poolState.fPoolVertexBuffer,
805 &poolState.fPoolStartVertex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000806 GR_DEBUGASSERT(success);
807}
808
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000809void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
810 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000811 GeometryPoolState& poolState = fGeoPoolStateStack.back();
812 GrAssert(0 == poolState.fUsedPoolIndexBytes);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000813#if GR_DEBUG
814 bool success =
815#endif
816 fIndexPool.appendIndices(indexCount,
817 indexArray,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000818 &poolState.fPoolIndexBuffer,
819 &poolState.fPoolStartIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000820 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000821}
822
bsalomon@google.com3f5a95e2012-03-08 16:41:42 +0000823void GrInOrderDrawBuffer::releaseVertexArray() {
824 // When the client provides an array as the vertex source we handled it
825 // by copying their array into reserved space.
826 this->GrInOrderDrawBuffer::releaseReservedVertexSpace();
827}
828
829void GrInOrderDrawBuffer::releaseIndexArray() {
830 // When the client provides an array as the index source we handled it
831 // by copying their array into reserved space.
832 this->GrInOrderDrawBuffer::releaseReservedIndexSpace();
833}
834
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000835void GrInOrderDrawBuffer::geometrySourceWillPush() {
836 GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
837 poolState.fUsedPoolVertexBytes = 0;
838 poolState.fUsedPoolIndexBytes = 0;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000839 this->resetDrawTracking();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000840#if GR_DEBUG
841 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0;
842 poolState.fPoolStartVertex = ~0;
843 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
844 poolState.fPoolStartIndex = ~0;
845#endif
846}
847
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000848void GrInOrderDrawBuffer::geometrySourceWillPop(
849 const GeometrySrcState& restoredState) {
850 GrAssert(fGeoPoolStateStack.count() > 1);
851 fGeoPoolStateStack.pop_back();
852 GeometryPoolState& poolState = fGeoPoolStateStack.back();
853 // we have to assume that any slack we had in our vertex/index data
854 // is now unreleasable because data may have been appended later in the
855 // pool.
856 if (kReserved_GeometrySrcType == restoredState.fVertexSrc ||
857 kArray_GeometrySrcType == restoredState.fVertexSrc) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000858 poolState.fUsedPoolVertexBytes =
859 VertexSize(restoredState.fVertexLayout) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000860 restoredState.fVertexCount;
861 }
862 if (kReserved_GeometrySrcType == restoredState.fIndexSrc ||
863 kArray_GeometrySrcType == restoredState.fIndexSrc) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000864 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) *
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000865 restoredState.fIndexCount;
866 }
bsalomon@google.com934c5702012-03-20 21:17:58 +0000867 this->resetDrawTracking();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000868}
869
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000870bool GrInOrderDrawBuffer::needsNewState() const {
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000871 // we should have recorded a default state in reset()
872 GrAssert(!fStates.empty());
873 return fStates.back() != this->getDrawState();
reed@google.comac10a2d2010-12-22 21:39:39 +0000874}
875
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000876bool GrInOrderDrawBuffer::needsNewClip() const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000877 if (this->getDrawState().isClipState()) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000878 if (fClipSet &&
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000879 (fClips.back() != *fClip->fClipStack ||
880 fClipOrigins.back() != fClip->fOrigin)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000881 return true;
882 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000883 }
884 return false;
885}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000886
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000887void GrInOrderDrawBuffer::recordClip() {
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000888 fClips.push_back() = *fClip->fClipStack;
889 fClipOrigins.push_back() = fClip->fOrigin;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000890 fClipSet = false;
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000891 fCmds.push_back(kSetClip_Cmd);
892}
893
894void GrInOrderDrawBuffer::recordDefaultClip() {
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000895 fClips.push_back() = SkClipStack();
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000896 fClipOrigins.push_back() = SkIPoint::Make(0, 0);
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000897 fCmds.push_back(kSetClip_Cmd);
898}
899
900void GrInOrderDrawBuffer::recordState() {
901 fStates.push_back(this->getDrawState());
902 fCmds.push_back(kSetState_Cmd);
903}
904
905void GrInOrderDrawBuffer::recordDefaultState() {
906 fStates.push_back(GrDrawState());
907 fCmds.push_back(kSetState_Cmd);
908}
909
910GrInOrderDrawBuffer::Draw* GrInOrderDrawBuffer::recordDraw() {
911 fCmds.push_back(kDraw_Cmd);
912 return &fDraws.push_back();
913}
914
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000915GrInOrderDrawBuffer::StencilPath* GrInOrderDrawBuffer::recordStencilPath() {
916 fCmds.push_back(kStencilPath_Cmd);
917 return &fStencilPaths.push_back();
918}
919
bsalomon@google.coma4f6b102012-06-26 21:04:22 +0000920GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear() {
921 fCmds.push_back(kClear_Cmd);
922 return &fClears.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000923}
bsalomon@google.comd302f142011-03-03 13:54:13 +0000924
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000925void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) {
926 INHERITED::clipWillBeSet(newClipData);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000927 fClipSet = true;
928}