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