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