• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * 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.
7  */
8 
9 
10 
11 #ifndef GrBufferAllocPool_DEFINED
12 #define GrBufferAllocPool_DEFINED
13 
14 #include "GrNoncopyable.h"
15 #include "GrTDArray.h"
16 
17 #include "SkTArray.h"
18 
19 class GrGeometryBuffer;
20 class 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  */
34 class GrBufferAllocPool : GrNoncopyable {
35 
36 public:
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      */
getGpu()66     GrGpu* getGpu() { return fGpu; }
67 
68 protected:
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      */
74     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 
103     /**
104      * Gets the size of the preallocated buffers.
105      *
106      * @return the size of preallocated buffers.
107      */
preallocatedBufferSize()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 
150 private:
151 
152     // The GrGpu must be able to clear the ref of pools it creates as members
153     friend class GrGpu;
154     void releaseGpuRef();
155 
156     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);
164 #if GR_DEBUG
165     void validate(bool unusedBlockAllowed = false) const;
166 #endif
167 
168     size_t                          fBytesInUse;
169 
170     GrGpu*                          fGpu;
171     bool                            fGpuIsReffed;
172     bool                            fFrequentResetHint;
173     GrTDArray<GrGeometryBuffer*>    fPreallocBuffers;
174     size_t                          fMinBlockSize;
175     BufferType                      fBufferType;
176 
177     SkTArray<BufferBlock>           fBlocks;
178     int                             fPreallocBuffersInUse;
179     // We attempt to cycle through the preallocated buffers rather than
180     // always starting from the first.
181     int                             fPreallocBufferStartIdx;
182     SkAutoMalloc                    fCpuData;
183     void*                           fBufferPtr;
184 };
185 
186 class GrVertexBuffer;
187 
188 /**
189  * A GrBufferAllocPool of vertex buffers
190  */
191 class GrVertexBufferAllocPool : public GrBufferAllocPool {
192 public:
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      *
225      * @param layout       specifies type of vertices to allocate space for
226      * @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      */
233     void* makeSpace(GrVertexLayout layout,
234                     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      */
241     bool appendVertices(GrVertexLayout layout,
242                         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      *
254      * @param   the format of vertices to compute space for.
255      * @return the number of vertices that would fit in the current buffer.
256      */
257     int currentBufferVertices(GrVertexLayout layout) const;
258 
259     /**
260      * Gets the number of vertices that can fit in a  preallocated vertex buffer.
261      * Zero if no preallocated buffers.
262      *
263      * @param   the format of vertices to compute space for.
264      *
265      * @return number of vertices that fit in one of the preallocated vertex
266      *         buffers.
267      */
268     int preallocatedBufferVertices(GrVertexLayout layout) const;
269 
270 private:
271     typedef GrBufferAllocPool INHERITED;
272 };
273 
274 class GrIndexBuffer;
275 
276 /**
277  * A GrBufferAllocPool of index buffers
278  */
279 class GrIndexBufferAllocPool : public GrBufferAllocPool {
280 public:
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 
348 private:
349     typedef GrBufferAllocPool INHERITED;
350 };
351 
352 #endif
353