blob: 49b890181021222b356bae0484f3ca37e438d352 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "GrInOrderDrawBuffer.h"
19#include "GrTexture.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000020#include "GrBufferAllocPool.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000021#include "GrGpu.h"
22
bsalomon@google.com1c13c962011-02-14 16:51:21 +000023GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool,
24 GrIndexBufferAllocPool* indexPool) :
reed@google.comac10a2d2010-12-22 21:39:39 +000025 fDraws(DRAWS_BLOCK_SIZE, fDrawsStorage),
26 fStates(STATES_BLOCK_SIZE, fStatesStorage),
27 fClips(CLIPS_BLOCK_SIZE, fClipsStorage),
28 fClipChanged(true),
bsalomon@google.com1c13c962011-02-14 16:51:21 +000029 fVertexPool(*vertexPool),
30 fCurrPoolVertexBuffer(NULL),
31 fCurrPoolStartVertex(0),
32 fIndexPool(*indexPool),
33 fCurrPoolIndexBuffer(NULL),
34 fCurrPoolStartIndex(0),
reed@google.comac10a2d2010-12-22 21:39:39 +000035 fReservedVertexBytes(0),
36 fReservedIndexBytes(0),
37 fUsedReservedVertexBytes(0),
38 fUsedReservedIndexBytes(0) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000039 GrAssert(NULL != vertexPool);
40 GrAssert(NULL != indexPool);
reed@google.comac10a2d2010-12-22 21:39:39 +000041}
42
43GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
44 reset();
45}
46
47void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
48 this->copyDrawState(target);
49 this->setClip(target.getClip());
50}
51
bsalomon@google.com1c13c962011-02-14 16:51:21 +000052void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType,
53 int startVertex,
54 int startIndex,
55 int vertexCount,
56 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +000057
58 if (!vertexCount || !indexCount) {
59 return;
60 }
61
62 Draw& draw = fDraws.push_back();
bsalomon@google.com1c13c962011-02-14 16:51:21 +000063 draw.fPrimitiveType = primitiveType;
reed@google.comac10a2d2010-12-22 21:39:39 +000064 draw.fStartVertex = startVertex;
65 draw.fStartIndex = startIndex;
66 draw.fVertexCount = vertexCount;
67 draw.fIndexCount = indexCount;
68 draw.fClipChanged = grabClip();
bsalomon@google.com1c13c962011-02-14 16:51:21 +000069 draw.fStateChanged = grabState();
reed@google.comac10a2d2010-12-22 21:39:39 +000070
71 draw.fVertexLayout = fGeometrySrc.fVertexLayout;
72 switch (fGeometrySrc.fVertexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +000073 case kBuffer_GeometrySrcType:
reed@google.comac10a2d2010-12-22 21:39:39 +000074 draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
75 break;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000076 case kReserved_GeometrySrcType: {
77 size_t vertexBytes = (vertexCount + startVertex) *
78 VertexSize(fGeometrySrc.fVertexLayout);
79 fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
80 vertexBytes);
81 } // fallthrough
82 case kArray_GeometrySrcType:
83 draw.fVertexBuffer = fCurrPoolVertexBuffer;
84 draw.fStartVertex += fCurrPoolStartVertex;
85 break;
86 default:
87 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +000088 }
89
90 switch (fGeometrySrc.fIndexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +000091 case kBuffer_GeometrySrcType:
reed@google.comac10a2d2010-12-22 21:39:39 +000092 draw.fIndexBuffer = fGeometrySrc.fIndexBuffer;
93 break;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000094 case kReserved_GeometrySrcType: {
95 size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
96 fUsedReservedIndexBytes = GrMax(fUsedReservedIndexBytes, indexBytes);
97 } // fallthrough
98 case kArray_GeometrySrcType:
99 draw.fIndexBuffer = fCurrPoolIndexBuffer;
100 draw.fStartIndex += fCurrPoolStartVertex;
101 break;
102 default:
103 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000104 }
105}
106
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000107void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType primitiveType,
108 int startVertex,
109 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000110 if (!vertexCount) {
111 return;
112 }
113
114 Draw& draw = fDraws.push_back();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000115 draw.fPrimitiveType = primitiveType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000116 draw.fStartVertex = startVertex;
117 draw.fStartIndex = 0;
118 draw.fVertexCount = vertexCount;
119 draw.fIndexCount = 0;
120
121 draw.fClipChanged = grabClip();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000122 draw.fStateChanged = grabState();
reed@google.comac10a2d2010-12-22 21:39:39 +0000123
124 draw.fVertexLayout = fGeometrySrc.fVertexLayout;
125 switch (fGeometrySrc.fVertexSrc) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000126 case kBuffer_GeometrySrcType:
reed@google.comac10a2d2010-12-22 21:39:39 +0000127 draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
128 break;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000129 case kReserved_GeometrySrcType: {
130 size_t vertexBytes = (vertexCount + startVertex) *
131 VertexSize(fGeometrySrc.fVertexLayout);
132 fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
133 vertexBytes);
134 } // fallthrough
135 case kArray_GeometrySrcType:
136 draw.fVertexBuffer = fCurrPoolVertexBuffer;
137 draw.fStartVertex += fCurrPoolStartVertex;
138 break;
139 default:
140 GrCrash("unknown geom src type");
reed@google.comac10a2d2010-12-22 21:39:39 +0000141 }
142}
143
144void GrInOrderDrawBuffer::reset() {
145 GrAssert(!fReservedGeometry.fLocked);
146 uint32_t numStates = fStates.count();
147 for (uint32_t i = 0; i < numStates; ++i) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000148 for (int s = 0; s < kNumStages; ++s) {
149 GrTexture* tex = accessSavedDrawState(fStates[i]).fTextures[s];
150 if (NULL != tex) {
151 tex->unref();
152 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 }
154 }
155 fDraws.reset();
156 fStates.reset();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000157
158 fVertexPool.reset();
159 fIndexPool.reset();
160
reed@google.comac10a2d2010-12-22 21:39:39 +0000161 fClips.reset();
162}
163
164void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
165 GrAssert(NULL != target);
166 GrAssert(target != this); // not considered and why?
167
168 uint32_t numDraws = fDraws.count();
169 if (!numDraws) {
170 return;
171 }
172
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000173 fVertexPool.unlock();
174 fIndexPool.unlock();
reed@google.comac10a2d2010-12-22 21:39:39 +0000175
176 GrDrawTarget::AutoStateRestore asr(target);
177 GrDrawTarget::AutoClipRestore acr(target);
178 // important to not mess with reserve/lock geometry in the target with this
179 // on the stack.
180 GrDrawTarget::AutoGeometrySrcRestore agsr(target);
181
182 uint32_t currState = ~0;
183 uint32_t currClip = ~0;
184
185 for (uint32_t i = 0; i < numDraws; ++i) {
186 const Draw& draw = fDraws[i];
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000187 if (draw.fStateChanged) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000188 ++currState;
189 target->restoreDrawState(fStates[currState]);
190 }
191 if (draw.fClipChanged) {
192 ++currClip;
193 target->setClip(fClips[currClip]);
194 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000195 uint32_t vertexReserveCount = 0;
196 uint32_t indexReserveCount = 0;
197
198 target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
199
reed@google.comac10a2d2010-12-22 21:39:39 +0000200 if (draw.fIndexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000201 target->setIndexSourceToBuffer(draw.fIndexBuffer);
202 }
203
204 if (draw.fIndexCount) {
205 target->drawIndexed(draw.fPrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000206 draw.fStartVertex,
207 draw.fStartIndex,
208 draw.fVertexCount,
209 draw.fIndexCount);
210 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000211 target->drawNonIndexed(draw.fPrimitiveType,
reed@google.comac10a2d2010-12-22 21:39:39 +0000212 draw.fStartVertex,
213 draw.fVertexCount);
214 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000215 if (vertexReserveCount || indexReserveCount) {
216 target->releaseReservedGeometry();
217 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000218 }
219}
220
221bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000222 int* vertexCount,
223 int* indexCount) const {
224 // we will recommend a flush if the data could fit in a single
225 // preallocated buffer but none are left and it can't fit
226 // in the current buffer (which may not be prealloced).
reed@google.comac10a2d2010-12-22 21:39:39 +0000227 bool flush = false;
228 if (NULL != indexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000229 int32_t currIndices = fIndexPool.currentBufferIndices();
230 if (*indexCount > currIndices &&
231 (!fIndexPool.preallocatedBuffersRemaining() &&
232 *indexCount <= fIndexPool.preallocatedBufferIndices())) {
233
234 flush = true;
235 }
236 *indexCount = currIndices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000237 }
238 if (NULL != vertexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000239 int32_t currVertices = fVertexPool.currentBufferVertices(vertexLayout);
240 if (*vertexCount > currVertices &&
241 (!fVertexPool.preallocatedBuffersRemaining() &&
242 *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexLayout))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000243
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000244 flush = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000245 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000246 *vertexCount = currVertices;
reed@google.comac10a2d2010-12-22 21:39:39 +0000247 }
248 return flush;
249}
250
251bool GrInOrderDrawBuffer::acquireGeometryHelper(GrVertexLayout vertexLayout,
252 void** vertices,
253 void** indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000254 GrAssert(!fReservedGeometry.fLocked);
reed@google.comac10a2d2010-12-22 21:39:39 +0000255 if (fReservedGeometry.fVertexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000256 GrAssert(NULL != vertices);
257 GrAssert(0 == fReservedVertexBytes);
258 GrAssert(0 == fUsedReservedVertexBytes);
259
reed@google.comac10a2d2010-12-22 21:39:39 +0000260 fReservedVertexBytes = VertexSize(vertexLayout) *
261 fReservedGeometry.fVertexCount;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000262 *vertices = fVertexPool.makeSpace(vertexLayout,
263 fReservedGeometry.fVertexCount,
264 &fCurrPoolVertexBuffer,
265 &fCurrPoolStartVertex);
266 if (NULL == *vertices) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000267 return false;
268 }
269 }
270 if (fReservedGeometry.fIndexCount) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000271 GrAssert(NULL != indices);
272 GrAssert(0 == fReservedIndexBytes);
273 GrAssert(0 == fUsedReservedIndexBytes);
274
275 *indices = fIndexPool.makeSpace(fReservedGeometry.fIndexCount,
276 &fCurrPoolIndexBuffer,
277 &fCurrPoolStartIndex);
278 if (NULL == *indices) {
279 fVertexPool.putBack(fReservedVertexBytes);
280 fReservedVertexBytes = 0;
281 fCurrPoolVertexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000282 return false;
283 }
284 }
285 return true;
286}
287
288void GrInOrderDrawBuffer::releaseGeometryHelper() {
289 GrAssert(fUsedReservedVertexBytes <= fReservedVertexBytes);
290 GrAssert(fUsedReservedIndexBytes <= fReservedIndexBytes);
291
292 size_t vertexSlack = fReservedVertexBytes - fUsedReservedVertexBytes;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000293 fVertexPool.putBack(vertexSlack);
reed@google.comac10a2d2010-12-22 21:39:39 +0000294
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000295 size_t indexSlack = fReservedIndexBytes - fUsedReservedIndexBytes;
296 fIndexPool.putBack(indexSlack);
reed@google.comac10a2d2010-12-22 21:39:39 +0000297
reed@google.comac10a2d2010-12-22 21:39:39 +0000298 fReservedVertexBytes = 0;
299 fReservedIndexBytes = 0;
300 fUsedReservedVertexBytes = 0;
301 fUsedReservedIndexBytes = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000302 fCurrPoolVertexBuffer = 0;
303 fCurrPoolStartVertex = 0;
304
305}
306
307void GrInOrderDrawBuffer::setVertexSourceToArrayHelper(const void* vertexArray,
308 int vertexCount) {
309 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
310#if GR_DEBUG
311 bool success =
312#endif
313 fVertexPool.appendVertices(fGeometrySrc.fVertexLayout,
314 vertexCount,
315 vertexArray,
316 &fCurrPoolVertexBuffer,
317 &fCurrPoolStartVertex);
318 GR_DEBUGASSERT(success);
319}
320
321void GrInOrderDrawBuffer::setIndexSourceToArrayHelper(const void* indexArray,
322 int indexCount) {
323 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
324#if GR_DEBUG
325 bool success =
326#endif
327 fIndexPool.appendIndices(indexCount,
328 indexArray,
329 &fCurrPoolIndexBuffer,
330 &fCurrPoolStartIndex);
331 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000332}
333
334bool GrInOrderDrawBuffer::grabState() {
335 bool newState;
336 if (fStates.empty()) {
337 newState = true;
338 } else {
reed@google.com8195f672011-01-12 18:14:28 +0000339 const DrState& old = accessSavedDrawState(fStates.back());
reed@google.comac10a2d2010-12-22 21:39:39 +0000340 newState = old != fCurrDrawState;
341 }
342 if (newState) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000343 for (int s = 0; s < kNumStages; ++s) {
344 if (NULL != fCurrDrawState.fTextures[s]) {
345 fCurrDrawState.fTextures[s]->ref();
346 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000347 }
348 saveCurrentDrawState(&fStates.push_back());
349 }
350 return newState;
351}
352
353bool GrInOrderDrawBuffer::grabClip() {
354 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
355 (fClipChanged || fClips.empty())) {
356
357 fClips.push_back() = fClip;
358 fClipChanged = false;
359 return true;
360 }
361 return false;
362}
363
364void GrInOrderDrawBuffer::clipWillChange(const GrClip& clip) {
365 fClipChanged = true;
366}
367