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