1/*
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 {
42
43public:
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     */
81    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
110    /**
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
159    // The GrGpu must be able to clear the ref of pools it creates as members
160    friend class GrGpu;
161    void releaseGpuRef();
162
163    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
172    void validate() const;
173#endif
174
175    GrGpu*                          fGpu;
176    bool                            fGpuIsReffed;
177    bool                            fFrequentResetHint;
178    GrTDArray<GrGeometryBuffer*>    fPreallocBuffers;
179    size_t                          fMinBlockSize;
180    BufferType                      fBufferType;
181
182    GrTArray<BufferBlock>           fBlocks;
183    int                             fPreallocBuffersInUse;
184    int                             fFirstPreallocBuffer;
185    GrAutoMalloc                    fCpuData;
186    void*                       	fBufferPtr;
187};
188
189class GrVertexBuffer;
190
191/**
192 * A GrBufferAllocPool of vertex buffers
193 */
194class GrVertexBufferAllocPool : public GrBufferAllocPool {
195public:
196    /**
197     * Constructor
198     *
199     * @param gpu                   The GrGpu used to create the vertex buffers.
200     * @param frequentResetHint     A hint that indicates that the pool
201     *                              should expect frequent unlock() calls
202     *                              (as opposed to many makeSpace / acquires
203     *                              between resets).
204     * @param bufferSize            The minimum size of created VBs This value
205     *                              will be clamped to some reasonable minimum.
206     * @param preallocBufferCnt     The pool will allocate this number of VBs at
207     *                              bufferSize and keep them until it is
208     *                              destroyed.
209     */
210    GrVertexBufferAllocPool(GrGpu* gpu,
211                            bool frequentResetHint,
212                            size_t bufferSize = 0,
213                            int preallocBufferCnt = 0);
214
215    /**
216     * Returns a block of memory to hold vertices. A buffer designated to hold
217     * the vertices given to the caller. The buffer may or may not be locked.
218     * The returned ptr remains valid until any of the following:
219     *      *makeSpace is called again.
220     *      *unlock is called.
221     *      *reset is called.
222     *      *this object is destroyed.
223     *
224     * Once unlock on the pool is called the vertices are guaranteed to be in
225     * the buffer at the offset indicated by startVertex. Until that time they
226     * may be in temporary storage and/or the buffer may be locked.
227     *
228     * @param layout       specifies type of vertices to allocate space for
229     * @param vertexCount  number of vertices to allocate space for
230     * @param buffer       returns the vertex buffer that will hold the
231     *                     vertices.
232     * @param startVertex  returns the offset into buffer of the first vertex.
233     *                     In units of the size of a vertex from layout param.
234     * @return pointer to first vertex.
235     */
236    void* makeSpace(GrVertexLayout layout,
237                    int vertexCount,
238                    const GrVertexBuffer** buffer,
239                    int* startVertex);
240
241    /**
242     * Shortcut to make space and then write verts into the made space.
243     */
244    bool appendVertices(GrVertexLayout layout,
245                        int vertexCount,
246                        const void* vertices,
247                        const GrVertexBuffer** buffer,
248                        int* startVertex);
249
250    /**
251     * Gets the number of vertices that can be added to the current VB without
252     * spilling to another VB. If the pool has been reset, or the previous
253     * makeSpace completely exhausted a VB then the returned number of vertices
254     * would fit in the next available preallocated buffer. If any makeSpace
255     * would force a new VB to be created the return value will be zero.
256     *
257     * @param   the format of vertices to compute space for.
258     * @return the number of vertices that would fit in the current buffer.
259     */
260    int currentBufferVertices(GrVertexLayout layout) const;
261
262    /**
263     * Gets the number of vertices that can fit in a  preallocated vertex buffer.
264     * Zero if no preallocated buffers.
265     *
266     * @param   the format of vertices to compute space for.
267     *
268     * @return number of vertices that fit in one of the preallocated vertex
269     *         buffers.
270     */
271    int preallocatedBufferVertices(GrVertexLayout layout) const;
272
273private:
274    typedef GrBufferAllocPool INHERITED;
275};
276
277class GrIndexBuffer;
278
279/**
280 * A GrBufferAllocPool of index buffers
281 */
282class GrIndexBufferAllocPool : public GrBufferAllocPool {
283public:
284    /**
285     * Constructor
286     *
287     * @param gpu                   The GrGpu used to create the index buffers.
288     * @param frequentResetHint     A hint that indicates that the pool
289     *                              should expect frequent unlock() calls
290     *                              (as opposed to many makeSpace / acquires
291     *                              between resets).
292     * @param bufferSize            The minimum size of created IBs This value
293     *                              will be clamped to some reasonable minimum.
294     * @param preallocBufferCnt     The pool will allocate this number of VBs at
295     *                              bufferSize and keep them until it is
296     *                              destroyed.
297     */
298    GrIndexBufferAllocPool(GrGpu* gpu,
299                           bool frequentResetHint,
300                           size_t bufferSize = 0,
301                           int preallocBufferCnt = 0);
302
303    /**
304     * Returns a block of memory to hold indices. A buffer designated to hold
305     * the indices is given to the caller. The buffer may or may not be locked.
306     * The returned ptr remains valid until any of the following:
307     *      *makeSpace is called again.
308     *      *unlock is called.
309     *      *reset is called.
310     *      *this object is destroyed.
311     *
312     * Once unlock on the pool is called the indices are guaranteed to be in the
313     * buffer at the offset indicated by startIndex. Until that time they may be
314     * in temporary storage and/or the buffer may be locked.
315     *
316     * @param indexCount   number of indices to allocate space for
317     * @param buffer       returns the index buffer that will hold the indices.
318     * @param startIndex   returns the offset into buffer of the first index.
319     * @return pointer to first index.
320     */
321    void* makeSpace(int indexCount,
322                    const GrIndexBuffer** buffer,
323                    int* startIndex);
324
325    /**
326     * Shortcut to make space and then write indices into the made space.
327     */
328    bool appendIndices(int indexCount,
329                       const void* indices,
330                       const GrIndexBuffer** buffer,
331                       int* startIndex);
332
333    /**
334     * Gets the number of indices that can be added to the current IB without
335     * spilling to another IB. If the pool has been reset, or the previous
336     * makeSpace completely exhausted a IB then the returned number of indices
337     * would fit in the next available preallocated buffer. If any makeSpace
338     * would force a new IB to be created the return value will be zero.
339     */
340    int currentBufferIndices() const;
341
342    /**
343     * Gets the number of indices that can fit in a preallocated index buffer.
344     * Zero if no preallocated buffers.
345     *
346     * @return number of indices that fit in one of the preallocated index
347     *         buffers.
348     */
349    int preallocatedBufferIndices() const;
350
351private:
352    typedef GrBufferAllocPool INHERITED;
353};
354
355#endif
356