blob: 3f25f2fa6867285b86d703be1546d9dadd37a719 [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) {
159 GrTexture* tex = accessSavedDrawState(fStates[i]).fTexture;
160 if (NULL != tex) {
161 tex->unref();
162 }
163 }
164 fDraws.reset();
165 fStates.reset();
166 if (NULL == fBufferVertices) {
167 fCPUVertices.reset();
168 } else {
169 fBufferVertices->reset();
170 }
171 fIndices.reset();
172 fClips.reset();
173}
174
175void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
176 GrAssert(NULL != target);
177 GrAssert(target != this); // not considered and why?
178
179 uint32_t numDraws = fDraws.count();
180 if (!numDraws) {
181 return;
182 }
183
184 if (NULL != fBufferVertices) {
185 fBufferVertices->unlock();
186 }
187
188 GrDrawTarget::AutoStateRestore asr(target);
189 GrDrawTarget::AutoClipRestore acr(target);
190 // important to not mess with reserve/lock geometry in the target with this
191 // on the stack.
192 GrDrawTarget::AutoGeometrySrcRestore agsr(target);
193
194 uint32_t currState = ~0;
195 uint32_t currClip = ~0;
196
197 for (uint32_t i = 0; i < numDraws; ++i) {
198 const Draw& draw = fDraws[i];
199 if (draw.fStateChange) {
200 ++currState;
201 target->restoreDrawState(fStates[currState]);
202 }
203 if (draw.fClipChanged) {
204 ++currClip;
205 target->setClip(fClips[currClip]);
206 }
207 if (draw.fUseVertexBuffer) {
208 target->setVertexSourceToBuffer(draw.fVertexBuffer, draw.fVertexLayout);
209 } else {
210 target->setVertexSourceToArray(draw.fVertexArray, draw.fVertexLayout);
211 }
212 if (draw.fIndexCount) {
213 if (draw.fUseIndexBuffer) {
214 target->setIndexSourceToBuffer(draw.fIndexBuffer);
215 } else {
216 target->setIndexSourceToArray(draw.fIndexArray);
217 }
218 target->drawIndexed(draw.fType,
219 draw.fStartVertex,
220 draw.fStartIndex,
221 draw.fVertexCount,
222 draw.fIndexCount);
223 } else {
224 target->drawNonIndexed(draw.fType,
225 draw.fStartVertex,
226 draw.fVertexCount);
227 }
228 }
229}
230
231bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
232 int32_t* vertexCount,
233 int32_t* indexCount) const {
234 bool flush = false;
235 if (NULL != indexCount) {
236 *indexCount = -1;
237 }
238 if (NULL != vertexCount) {
239 if (NULL != fBufferVertices) {
240 // we will recommend a flush if the verts could fit in a single
241 // preallocated vertex buffer but none are left and it can't fit
242 // in the current VB (which may not be prealloced).
243 if (*vertexCount > fBufferVertices->currentBufferVertices(vertexLayout) &&
244 (!fBufferVertices->preallocatedBuffersRemaining() &&
245 *vertexCount <= fBufferVertices->preallocatedBufferVertices(vertexLayout))) {
246
247 flush = true;
248 }
249 *vertexCount = fBufferVertices->currentBufferVertices(vertexLayout);
250 } else {
251 *vertexCount = -1;
252 }
253 }
254 return flush;
255}
256
257bool GrInOrderDrawBuffer::acquireGeometryHelper(GrVertexLayout vertexLayout,
258 void** vertices,
259 void** indices) {
260 if (fReservedGeometry.fVertexCount) {
261 fReservedVertexBytes = VertexSize(vertexLayout) *
262 fReservedGeometry.fVertexCount;
263 if (NULL == fBufferVertices) {
264 fCurrReservedVertices = fCPUVertices.alloc(fReservedVertexBytes);
265 } else {
266 fCurrReservedVertices = fBufferVertices->alloc(vertexLayout,
267 fReservedGeometry.fVertexCount,
268 &fCurrVertexBuffer,
269 &fCurrStartVertex);
270 }
271 if (NULL != vertices) {
272 *vertices = fCurrReservedVertices;
273 }
274 if (NULL == fCurrReservedVertices) {
275 return false;
276 }
277 }
278 if (fReservedGeometry.fIndexCount) {
279 fReservedIndexBytes = sizeof(uint16_t) * fReservedGeometry.fIndexCount;
280 fCurrReservedIndices = fIndices.alloc(fReservedIndexBytes);
281 if (NULL != indices) {
282 *indices = fCurrReservedIndices;
283 }
284 if (NULL == fCurrReservedIndices) {
285 return false;
286 }
287 }
288 return true;
289}
290
291void GrInOrderDrawBuffer::releaseGeometryHelper() {
292 GrAssert(fUsedReservedVertexBytes <= fReservedVertexBytes);
293 GrAssert(fUsedReservedIndexBytes <= fReservedIndexBytes);
294
295 size_t vertexSlack = fReservedVertexBytes - fUsedReservedVertexBytes;
296 if (NULL == fBufferVertices) {
297 fCPUVertices.release(vertexSlack);
298 } else {
299 fBufferVertices->release(vertexSlack);
300 GR_DEBUGCODE(fCurrVertexBuffer = NULL);
301 GR_DEBUGCODE(fCurrStartVertex = 0);
302 }
303
304 fIndices.release(fReservedIndexBytes - fUsedReservedIndexBytes);
305
306 fCurrReservedVertices = NULL;
307 fCurrReservedIndices = NULL;
308 fReservedVertexBytes = 0;
309 fReservedIndexBytes = 0;
310 fUsedReservedVertexBytes = 0;
311 fUsedReservedIndexBytes = 0;
312}
313
314bool GrInOrderDrawBuffer::grabState() {
315 bool newState;
316 if (fStates.empty()) {
317 newState = true;
318 } else {
319 const DrawState& old = accessSavedDrawState(fStates.back());
320 newState = old != fCurrDrawState;
321 }
322 if (newState) {
323 if (NULL != fCurrDrawState.fTexture) {
324 fCurrDrawState.fTexture->ref();
325 }
326 saveCurrentDrawState(&fStates.push_back());
327 }
328 return newState;
329}
330
331bool GrInOrderDrawBuffer::grabClip() {
332 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
333 (fClipChanged || fClips.empty())) {
334
335 fClips.push_back() = fClip;
336 fClipChanged = false;
337 return true;
338 }
339 return false;
340}
341
342void GrInOrderDrawBuffer::clipWillChange(const GrClip& clip) {
343 fClipChanged = true;
344}
345