blob: 494f2273839cea6881b664eb8576abd89bb2e3b6 [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"
20#include "GrVertexBufferAllocPool.h"
21#include "GrGpu.h"
22
23GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* pool) :
24 fDraws(DRAWS_BLOCK_SIZE, fDrawsStorage),
25 fStates(STATES_BLOCK_SIZE, fStatesStorage),
26 fClips(CLIPS_BLOCK_SIZE, fClipsStorage),
27 fClipChanged(true),
28 fCPUVertices((NULL == pool) ? 0 : VERTEX_BLOCK_SIZE),
29 fBufferVertices(pool),
30 fIndices(INDEX_BLOCK_SIZE),
31 fCurrReservedVertices(NULL),
32 fCurrReservedIndices(NULL),
33 fCurrVertexBuffer(NULL),
34 fReservedVertexBytes(0),
35 fReservedIndexBytes(0),
36 fUsedReservedVertexBytes(0),
37 fUsedReservedIndexBytes(0) {
38 GrAssert(NULL == pool || pool->getGpu()->supportsBufferLocking());
39}
40
41GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
42 reset();
43}
44
45void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
46 this->copyDrawState(target);
47 this->setClip(target.getClip());
48}
49
50void GrInOrderDrawBuffer::drawIndexed(PrimitiveType type,
51 uint32_t startVertex,
52 uint32_t startIndex,
53 uint32_t vertexCount,
54 uint32_t indexCount) {
55
56 if (!vertexCount || !indexCount) {
57 return;
58 }
59
60 Draw& draw = fDraws.push_back();
61 draw.fType = type;
62 draw.fStartVertex = startVertex;
63 draw.fStartIndex = startIndex;
64 draw.fVertexCount = vertexCount;
65 draw.fIndexCount = indexCount;
66 draw.fClipChanged = grabClip();
67 draw.fStateChange = grabState();
68
69 draw.fVertexLayout = fGeometrySrc.fVertexLayout;
70 switch (fGeometrySrc.fVertexSrc) {
71 case kArray_GeometrySrcType:
72 draw.fUseVertexBuffer = false;
73 draw.fVertexArray = fGeometrySrc.fVertexArray;
74 break;
75 case kReserved_GeometrySrcType: {
76 draw.fUseVertexBuffer = NULL != fBufferVertices;
77 if (draw.fUseVertexBuffer) {
78 draw.fVertexBuffer = fCurrVertexBuffer;
79 draw.fStartVertex += fCurrStartVertex;
80 } else {
81 draw.fVertexArray = fCurrReservedVertices;
82 }
83 size_t vertexBytes = (vertexCount + startVertex) *
84 VertexSize(fGeometrySrc.fVertexLayout);
85 fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
86 vertexBytes);
87 } break;
88 case kBuffer_GeometrySrcType:
89 draw.fUseVertexBuffer = true;
90 draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
91 break;
92 }
93
94 switch (fGeometrySrc.fIndexSrc) {
95 case kArray_GeometrySrcType:
96 draw.fUseIndexBuffer = false;
97 draw.fIndexArray = fGeometrySrc.fIndexArray;
98 break;
99 case kReserved_GeometrySrcType: {
100 draw.fUseIndexBuffer = false;
101 draw.fIndexArray = fCurrReservedIndices;
102 size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
103 fUsedReservedIndexBytes = GrMax(fUsedReservedIndexBytes, indexBytes);
104 } break;
105 case kBuffer_GeometrySrcType:
106 draw.fUseIndexBuffer = true;
107 draw.fIndexBuffer = fGeometrySrc.fIndexBuffer;
108 break;
109 }
110}
111
112void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType type,
113 uint32_t startVertex,
114 uint32_t vertexCount) {
115 if (!vertexCount) {
116 return;
117 }
118
119 Draw& draw = fDraws.push_back();
120 draw.fType = type;
121 draw.fStartVertex = startVertex;
122 draw.fStartIndex = 0;
123 draw.fVertexCount = vertexCount;
124 draw.fIndexCount = 0;
125
126 draw.fClipChanged = grabClip();
127 draw.fStateChange = grabState();
128
129 draw.fVertexLayout = fGeometrySrc.fVertexLayout;
130 switch (fGeometrySrc.fVertexSrc) {
131 case kArray_GeometrySrcType:
132 draw.fUseVertexBuffer = false;
133 draw.fVertexArray = fGeometrySrc.fVertexArray;
134 break;
135 case kReserved_GeometrySrcType: {
136 draw.fUseVertexBuffer = NULL != fBufferVertices;
137 if (draw.fUseVertexBuffer) {
138 draw.fVertexBuffer = fCurrVertexBuffer;
139 draw.fStartVertex += fCurrStartVertex;
140 } else {
141 draw.fVertexArray = fCurrReservedVertices;
142 }
143 size_t vertexBytes = (vertexCount + startVertex) *
144 VertexSize(fGeometrySrc.fVertexLayout);
145 fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
146 vertexBytes);
147 } break;
148 case kBuffer_GeometrySrcType:
149 draw.fUseVertexBuffer = true;
150 draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
151 break;
152 }
153}
154
155void GrInOrderDrawBuffer::reset() {
156 GrAssert(!fReservedGeometry.fLocked);
157 uint32_t numStates = fStates.count();
158 for (uint32_t i = 0; i < numStates; ++i) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000159 for (int s = 0; s < kNumStages; ++s) {
160 GrTexture* tex = accessSavedDrawState(fStates[i]).fTextures[s];
161 if (NULL != tex) {
162 tex->unref();
163 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000164 }
165 }
166 fDraws.reset();
167 fStates.reset();
168 if (NULL == fBufferVertices) {
169 fCPUVertices.reset();
170 } else {
171 fBufferVertices->reset();
172 }
173 fIndices.reset();
174 fClips.reset();
175}
176
177void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
178 GrAssert(NULL != target);
179 GrAssert(target != this); // not considered and why?
180
181 uint32_t numDraws = fDraws.count();
182 if (!numDraws) {
183 return;
184 }
185
186 if (NULL != fBufferVertices) {
187 fBufferVertices->unlock();
188 }
189
190 GrDrawTarget::AutoStateRestore asr(target);
191 GrDrawTarget::AutoClipRestore acr(target);
192 // important to not mess with reserve/lock geometry in the target with this
193 // on the stack.
194 GrDrawTarget::AutoGeometrySrcRestore agsr(target);
195
196 uint32_t currState = ~0;
197 uint32_t currClip = ~0;
198
199 for (uint32_t i = 0; i < numDraws; ++i) {
200 const Draw& draw = fDraws[i];
201 if (draw.fStateChange) {
202 ++currState;
203 target->restoreDrawState(fStates[currState]);
204 }
205 if (draw.fClipChanged) {
206 ++currClip;
207 target->setClip(fClips[currClip]);
208 }
209 if (draw.fUseVertexBuffer) {
210 target->setVertexSourceToBuffer(draw.fVertexBuffer, draw.fVertexLayout);
211 } else {
212 target->setVertexSourceToArray(draw.fVertexArray, draw.fVertexLayout);
213 }
214 if (draw.fIndexCount) {
215 if (draw.fUseIndexBuffer) {
216 target->setIndexSourceToBuffer(draw.fIndexBuffer);
217 } else {
218 target->setIndexSourceToArray(draw.fIndexArray);
219 }
220 target->drawIndexed(draw.fType,
221 draw.fStartVertex,
222 draw.fStartIndex,
223 draw.fVertexCount,
224 draw.fIndexCount);
225 } else {
226 target->drawNonIndexed(draw.fType,
227 draw.fStartVertex,
228 draw.fVertexCount);
229 }
230 }
231}
232
233bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
234 int32_t* vertexCount,
235 int32_t* indexCount) const {
236 bool flush = false;
237 if (NULL != indexCount) {
238 *indexCount = -1;
239 }
240 if (NULL != vertexCount) {
241 if (NULL != fBufferVertices) {
242 // we will recommend a flush if the verts could fit in a single
243 // preallocated vertex buffer but none are left and it can't fit
244 // in the current VB (which may not be prealloced).
245 if (*vertexCount > fBufferVertices->currentBufferVertices(vertexLayout) &&
246 (!fBufferVertices->preallocatedBuffersRemaining() &&
247 *vertexCount <= fBufferVertices->preallocatedBufferVertices(vertexLayout))) {
248
249 flush = true;
250 }
251 *vertexCount = fBufferVertices->currentBufferVertices(vertexLayout);
252 } else {
253 *vertexCount = -1;
254 }
255 }
256 return flush;
257}
258
259bool GrInOrderDrawBuffer::acquireGeometryHelper(GrVertexLayout vertexLayout,
260 void** vertices,
261 void** indices) {
262 if (fReservedGeometry.fVertexCount) {
263 fReservedVertexBytes = VertexSize(vertexLayout) *
264 fReservedGeometry.fVertexCount;
265 if (NULL == fBufferVertices) {
266 fCurrReservedVertices = fCPUVertices.alloc(fReservedVertexBytes);
267 } else {
268 fCurrReservedVertices = fBufferVertices->alloc(vertexLayout,
269 fReservedGeometry.fVertexCount,
270 &fCurrVertexBuffer,
271 &fCurrStartVertex);
272 }
273 if (NULL != vertices) {
274 *vertices = fCurrReservedVertices;
275 }
276 if (NULL == fCurrReservedVertices) {
277 return false;
278 }
279 }
280 if (fReservedGeometry.fIndexCount) {
281 fReservedIndexBytes = sizeof(uint16_t) * fReservedGeometry.fIndexCount;
282 fCurrReservedIndices = fIndices.alloc(fReservedIndexBytes);
283 if (NULL != indices) {
284 *indices = fCurrReservedIndices;
285 }
286 if (NULL == fCurrReservedIndices) {
287 return false;
288 }
289 }
290 return true;
291}
292
293void GrInOrderDrawBuffer::releaseGeometryHelper() {
294 GrAssert(fUsedReservedVertexBytes <= fReservedVertexBytes);
295 GrAssert(fUsedReservedIndexBytes <= fReservedIndexBytes);
296
297 size_t vertexSlack = fReservedVertexBytes - fUsedReservedVertexBytes;
298 if (NULL == fBufferVertices) {
299 fCPUVertices.release(vertexSlack);
300 } else {
301 fBufferVertices->release(vertexSlack);
302 GR_DEBUGCODE(fCurrVertexBuffer = NULL);
303 GR_DEBUGCODE(fCurrStartVertex = 0);
304 }
305
306 fIndices.release(fReservedIndexBytes - fUsedReservedIndexBytes);
307
308 fCurrReservedVertices = NULL;
309 fCurrReservedIndices = NULL;
310 fReservedVertexBytes = 0;
311 fReservedIndexBytes = 0;
312 fUsedReservedVertexBytes = 0;
313 fUsedReservedIndexBytes = 0;
314}
315
316bool GrInOrderDrawBuffer::grabState() {
317 bool newState;
318 if (fStates.empty()) {
319 newState = true;
320 } else {
reed@google.com8195f672011-01-12 18:14:28 +0000321 const DrState& old = accessSavedDrawState(fStates.back());
reed@google.comac10a2d2010-12-22 21:39:39 +0000322 newState = old != fCurrDrawState;
323 }
324 if (newState) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000325 for (int s = 0; s < kNumStages; ++s) {
326 if (NULL != fCurrDrawState.fTextures[s]) {
327 fCurrDrawState.fTextures[s]->ref();
328 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000329 }
330 saveCurrentDrawState(&fStates.push_back());
331 }
332 return newState;
333}
334
335bool GrInOrderDrawBuffer::grabClip() {
336 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
337 (fClipChanged || fClips.empty())) {
338
339 fClips.push_back() = fClip;
340 fClipChanged = false;
341 return true;
342 }
343 return false;
344}
345
346void GrInOrderDrawBuffer::clipWillChange(const GrClip& clip) {
347 fClipChanged = true;
348}
349