blob: f9d9e19658016e7650d19f642c162a3ae1deba64 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 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.
bsalomon@google.com1c13c962011-02-14 16:51:21 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
bsalomon@google.com1c13c962011-02-14 16:51:21 +000011#ifndef GrBufferAllocPool_DEFINED
12#define GrBufferAllocPool_DEFINED
13
14#include "GrNoncopyable.h"
15#include "GrTDArray.h"
16#include "GrTArray.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000017
18class GrGeometryBuffer;
19class GrGpu;
20
21/**
22 * A pool of geometry buffers tied to a GrGpu.
23 *
24 * The pool allows a client to make space for geometry and then put back excess
25 * space if it over allocated. When a client is ready to draw from the pool
26 * it calls unlock on the pool ensure buffers are ready for drawing. The pool
27 * can be reset after drawing is completed to recycle space.
28 *
29 * At creation time a minimum per-buffer size can be specified. Additionally,
30 * a number of buffers to preallocate can be specified. These will
31 * be allocated at the min size and kept around until the pool is destroyed.
32 */
33class GrBufferAllocPool : GrNoncopyable {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000034
bsalomon@google.com11f0b512011-03-29 20:52:23 +000035public:
36 /**
37 * Ensures all buffers are unlocked and have all data written to them.
38 * Call before drawing using buffers from the pool.
39 */
40 void unlock();
41
42 /**
43 * Invalidates all the data in the pool, unrefs non-preallocated buffers.
44 */
45 void reset();
46
47 /**
48 * Gets the number of preallocated buffers that are yet to be used.
49 */
50 int preallocatedBuffersRemaining() const;
51
52 /**
53 * gets the number of preallocated buffers
54 */
55 int preallocatedBufferCount() const;
56
57 /**
58 * Frees data from makeSpaces in LIFO order.
59 */
60 void putBack(size_t bytes);
61
62 /**
63 * Gets the GrGpu that this pool is associated with.
64 */
65 GrGpu* getGpu() { return fGpu; }
66
67protected:
68 /**
69 * Used to determine what type of buffers to create. We could make the
70 * createBuffer a virtual except that we want to use it in the cons for
71 * pre-allocated buffers.
72 */
bsalomon@google.com1c13c962011-02-14 16:51:21 +000073 enum BufferType {
74 kVertex_BufferType,
75 kIndex_BufferType,
76 };
77
78 /**
79 * Constructor
80 *
81 * @param gpu The GrGpu used to create the buffers.
82 * @param bufferType The type of buffers to create.
83 * @param frequentResetHint A hint that indicates that the pool
84 * should expect frequent unlock() calls
85 * (as opposed to many makeSpace / acquires
86 * between resets).
87 * @param bufferSize The minimum size of created buffers.
88 * This value will be clamped to some
89 * reasonable minimum.
90 * @param preallocBufferCnt The pool will allocate this number of
91 * buffers at bufferSize and keep them until it
92 * is destroyed.
93 */
94 GrBufferAllocPool(GrGpu* gpu,
95 BufferType bufferType,
96 bool frequentResetHint,
97 size_t bufferSize = 0,
98 int preallocBufferCnt = 0);
99
100 virtual ~GrBufferAllocPool();
101
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000102 /**
103 * Gets the size of the preallocated buffers.
104 *
105 * @return the size of preallocated buffers.
106 */
107 size_t preallocatedBufferSize() const {
108 return fPreallocBuffers.count() ? fMinBlockSize : 0;
109 }
110
111 /**
112 * Returns a block of memory to hold data. A buffer designated to hold the
113 * data is given to the caller. The buffer may or may not be locked. The
114 * returned ptr remains valid until any of the following:
115 * *makeSpace is called again.
116 * *unlock is called.
117 * *reset is called.
118 * *this object is destroyed.
119 *
120 * Once unlock on the pool is called the data is guaranteed to be in the
121 * buffer at the offset indicated by offset. Until that time it may be
122 * in temporary storage and/or the buffer may be locked.
123 *
124 * @param size the amount of data to make space for
125 * @param alignment alignment constraint from start of buffer
126 * @param buffer returns the buffer that will hold the data.
127 * @param offset returns the offset into buffer of the data.
128 * @return pointer to where the client should write the data.
129 */
130 void* makeSpace(size_t size,
131 size_t alignment,
132 const GrGeometryBuffer** buffer,
133 size_t* offset);
134
135 /**
136 * Gets the number of items of a size that can be added to the current
137 * buffer without spilling to another buffer. If the pool has been reset, or
138 * the previous makeSpace completely exhausted a buffer then the returned
139 * size will be the size of the next available preallocated buffer, or zero
140 * if no preallocated buffer remains available. It is assumed that items
141 * should be itemSize-aligned from the start of a buffer.
142 *
143 * @return the number of items that would fit in the current buffer.
144 */
145 int currentBufferItems(size_t itemSize) const;
146
147 GrGeometryBuffer* createBuffer(size_t size);
148
149private:
150
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000151 // The GrGpu must be able to clear the ref of pools it creates as members
152 friend class GrGpu;
153 void releaseGpuRef();
154
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000155 struct BufferBlock {
156 size_t fBytesFree;
157 GrGeometryBuffer* fBuffer;
158 };
159
160 bool createBlock(size_t requestSize);
161 void destroyBlock();
162 void flushCpuData(GrGeometryBuffer* buffer, size_t flushSize);
163#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000164 void validate(bool unusedBlockAllowed = false) const;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000165#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000166
167 size_t fBytesInUse;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000168
169 GrGpu* fGpu;
bsalomon@google.com11f0b512011-03-29 20:52:23 +0000170 bool fGpuIsReffed;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000171 bool fFrequentResetHint;
172 GrTDArray<GrGeometryBuffer*> fPreallocBuffers;
173 size_t fMinBlockSize;
174 BufferType fBufferType;
175
176 GrTArray<BufferBlock> fBlocks;
177 int fPreallocBuffersInUse;
178 int fFirstPreallocBuffer;
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000179 SkAutoMalloc fCpuData;
180 void* fBufferPtr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000181};
182
183class GrVertexBuffer;
184
185/**
186 * A GrBufferAllocPool of vertex buffers
187 */
188class GrVertexBufferAllocPool : public GrBufferAllocPool {
189public:
190 /**
191 * Constructor
192 *
193 * @param gpu The GrGpu used to create the vertex buffers.
194 * @param frequentResetHint A hint that indicates that the pool
195 * should expect frequent unlock() calls
196 * (as opposed to many makeSpace / acquires
197 * between resets).
198 * @param bufferSize The minimum size of created VBs This value
199 * will be clamped to some reasonable minimum.
200 * @param preallocBufferCnt The pool will allocate this number of VBs at
201 * bufferSize and keep them until it is
202 * destroyed.
203 */
204 GrVertexBufferAllocPool(GrGpu* gpu,
205 bool frequentResetHint,
206 size_t bufferSize = 0,
207 int preallocBufferCnt = 0);
208
209 /**
210 * Returns a block of memory to hold vertices. A buffer designated to hold
211 * the vertices given to the caller. The buffer may or may not be locked.
212 * The returned ptr remains valid until any of the following:
213 * *makeSpace is called again.
214 * *unlock is called.
215 * *reset is called.
216 * *this object is destroyed.
217 *
218 * Once unlock on the pool is called the vertices are guaranteed to be in
219 * the buffer at the offset indicated by startVertex. Until that time they
220 * may be in temporary storage and/or the buffer may be locked.
221 *
222 * @param layout specifies type of vertices to allocate space for
223 * @param vertexCount number of vertices to allocate space for
224 * @param buffer returns the vertex buffer that will hold the
225 * vertices.
226 * @param startVertex returns the offset into buffer of the first vertex.
227 * In units of the size of a vertex from layout param.
228 * @return pointer to first vertex.
229 */
230 void* makeSpace(GrVertexLayout layout,
231 int vertexCount,
232 const GrVertexBuffer** buffer,
233 int* startVertex);
234
235 /**
236 * Shortcut to make space and then write verts into the made space.
237 */
238 bool appendVertices(GrVertexLayout layout,
239 int vertexCount,
240 const void* vertices,
241 const GrVertexBuffer** buffer,
242 int* startVertex);
243
244 /**
245 * Gets the number of vertices that can be added to the current VB without
246 * spilling to another VB. If the pool has been reset, or the previous
247 * makeSpace completely exhausted a VB then the returned number of vertices
248 * would fit in the next available preallocated buffer. If any makeSpace
249 * would force a new VB to be created the return value will be zero.
250 *
251 * @param the format of vertices to compute space for.
252 * @return the number of vertices that would fit in the current buffer.
253 */
254 int currentBufferVertices(GrVertexLayout layout) const;
255
256 /**
257 * Gets the number of vertices that can fit in a preallocated vertex buffer.
258 * Zero if no preallocated buffers.
259 *
260 * @param the format of vertices to compute space for.
261 *
262 * @return number of vertices that fit in one of the preallocated vertex
263 * buffers.
264 */
265 int preallocatedBufferVertices(GrVertexLayout layout) const;
266
267private:
268 typedef GrBufferAllocPool INHERITED;
269};
270
271class GrIndexBuffer;
272
273/**
274 * A GrBufferAllocPool of index buffers
275 */
276class GrIndexBufferAllocPool : public GrBufferAllocPool {
277public:
278 /**
279 * Constructor
280 *
281 * @param gpu The GrGpu used to create the index buffers.
282 * @param frequentResetHint A hint that indicates that the pool
283 * should expect frequent unlock() calls
284 * (as opposed to many makeSpace / acquires
285 * between resets).
286 * @param bufferSize The minimum size of created IBs This value
287 * will be clamped to some reasonable minimum.
288 * @param preallocBufferCnt The pool will allocate this number of VBs at
289 * bufferSize and keep them until it is
290 * destroyed.
291 */
292 GrIndexBufferAllocPool(GrGpu* gpu,
293 bool frequentResetHint,
294 size_t bufferSize = 0,
295 int preallocBufferCnt = 0);
296
297 /**
298 * Returns a block of memory to hold indices. A buffer designated to hold
299 * the indices is given to the caller. The buffer may or may not be locked.
300 * The returned ptr remains valid until any of the following:
301 * *makeSpace is called again.
302 * *unlock is called.
303 * *reset is called.
304 * *this object is destroyed.
305 *
306 * Once unlock on the pool is called the indices are guaranteed to be in the
307 * buffer at the offset indicated by startIndex. Until that time they may be
308 * in temporary storage and/or the buffer may be locked.
309 *
310 * @param indexCount number of indices to allocate space for
311 * @param buffer returns the index buffer that will hold the indices.
312 * @param startIndex returns the offset into buffer of the first index.
313 * @return pointer to first index.
314 */
315 void* makeSpace(int indexCount,
316 const GrIndexBuffer** buffer,
317 int* startIndex);
318
319 /**
320 * Shortcut to make space and then write indices into the made space.
321 */
322 bool appendIndices(int indexCount,
323 const void* indices,
324 const GrIndexBuffer** buffer,
325 int* startIndex);
326
327 /**
328 * Gets the number of indices that can be added to the current IB without
329 * spilling to another IB. If the pool has been reset, or the previous
330 * makeSpace completely exhausted a IB then the returned number of indices
331 * would fit in the next available preallocated buffer. If any makeSpace
332 * would force a new IB to be created the return value will be zero.
333 */
334 int currentBufferIndices() const;
335
336 /**
337 * Gets the number of indices that can fit in a preallocated index buffer.
338 * Zero if no preallocated buffers.
339 *
340 * @return number of indices that fit in one of the preallocated index
341 * buffers.
342 */
343 int preallocatedBufferIndices() const;
344
345private:
346 typedef GrBufferAllocPool INHERITED;
347};
348
349#endif