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