1 /*
2  * 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.
6  */
7 
8 #ifndef GrBufferAllocPool_DEFINED
9 #define GrBufferAllocPool_DEFINED
10 
11 #include "SkTArray.h"
12 #include "SkTDArray.h"
13 #include "SkTypes.h"
14 #include "GrTypesPriv.h"
15 
16 class GrBuffer;
17 class GrGpu;
18 
19 /**
20  * A pool of geometry buffers tied to a GrGpu.
21  *
22  * The pool allows a client to make space for geometry and then put back excess
23  * space if it over allocated. When a client is ready to draw from the pool
24  * it calls unmap on the pool ensure buffers are ready for drawing. The pool
25  * can be reset after drawing is completed to recycle space.
26  *
27  * At creation time a minimum per-buffer size can be specified. Additionally,
28  * a number of buffers to preallocate can be specified. These will
29  * be allocated at the min size and kept around until the pool is destroyed.
30  */
31 class GrBufferAllocPool : SkNoncopyable {
32 public:
33     /**
34      * Ensures all buffers are unmapped and have all data written to them.
35      * Call before drawing using buffers from the pool.
36      */
37     void unmap();
38 
39     /**
40      *  Invalidates all the data in the pool, unrefs non-preallocated buffers.
41      */
42     void reset();
43 
44     /**
45      * Frees data from makeSpaces in LIFO order.
46      */
47     void putBack(size_t bytes);
48 
49 protected:
50     /**
51      * Constructor
52      *
53      * @param gpu                   The GrGpu used to create the buffers.
54      * @param bufferType            The type of buffers to create.
55      * @param bufferSize            The minimum size of created buffers.
56      *                              This value will be clamped to some
57      *                              reasonable minimum.
58      */
59      GrBufferAllocPool(GrGpu* gpu,
60                        GrBufferType bufferType,
61                        size_t   bufferSize = 0);
62 
63      virtual ~GrBufferAllocPool();
64 
65     /**
66      * Returns a block of memory to hold data. A buffer designated to hold the
67      * data is given to the caller. The buffer may or may not be locked. The
68      * returned ptr remains valid until any of the following:
69      *      *makeSpace is called again.
70      *      *unmap is called.
71      *      *reset is called.
72      *      *this object is destroyed.
73      *
74      * Once unmap on the pool is called the data is guaranteed to be in the
75      * buffer at the offset indicated by offset. Until that time it may be
76      * in temporary storage and/or the buffer may be locked.
77      *
78      * @param size         the amount of data to make space for
79      * @param alignment    alignment constraint from start of buffer
80      * @param buffer       returns the buffer that will hold the data.
81      * @param offset       returns the offset into buffer of the data.
82      * @return pointer to where the client should write the data.
83      */
84     void* makeSpace(size_t size,
85                     size_t alignment,
86                     const GrBuffer** buffer,
87                     size_t* offset);
88 
89     GrBuffer* getBuffer(size_t size);
90 
91 private:
92     struct BufferBlock {
93         size_t      fBytesFree;
94         GrBuffer*   fBuffer;
95     };
96 
97     bool createBlock(size_t requestSize);
98     void destroyBlock();
99     void deleteBlocks();
100     void flushCpuData(const BufferBlock& block, size_t flushSize);
101     void* resetCpuData(size_t newSize);
102 #ifdef SK_DEBUG
103     void validate(bool unusedBlockAllowed = false) const;
104 #endif
105     size_t                          fBytesInUse;
106 
107     GrGpu*                          fGpu;
108     size_t                          fMinBlockSize;
109     GrBufferType                    fBufferType;
110 
111     SkTArray<BufferBlock>           fBlocks;
112     void*                           fCpuData;
113     void*                           fBufferPtr;
114     size_t                          fBufferMapThreshold;
115 };
116 
117 /**
118  * A GrBufferAllocPool of vertex buffers
119  */
120 class GrVertexBufferAllocPool : public GrBufferAllocPool {
121 public:
122     /**
123      * Constructor
124      *
125      * @param gpu                   The GrGpu used to create the vertex buffers.
126      */
127     GrVertexBufferAllocPool(GrGpu* gpu);
128 
129     /**
130      * Returns a block of memory to hold vertices. A buffer designated to hold
131      * the vertices given to the caller. The buffer may or may not be locked.
132      * The returned ptr remains valid until any of the following:
133      *      *makeSpace is called again.
134      *      *unmap is called.
135      *      *reset is called.
136      *      *this object is destroyed.
137      *
138      * Once unmap on the pool is called the vertices are guaranteed to be in
139      * the buffer at the offset indicated by startVertex. Until that time they
140      * may be in temporary storage and/or the buffer may be locked.
141      *
142      * @param vertexSize   specifies size of a vertex to allocate space for
143      * @param vertexCount  number of vertices to allocate space for
144      * @param buffer       returns the vertex buffer that will hold the
145      *                     vertices.
146      * @param startVertex  returns the offset into buffer of the first vertex.
147      *                     In units of the size of a vertex from layout param.
148      * @return pointer to first vertex.
149      */
150     void* makeSpace(size_t vertexSize,
151                     int vertexCount,
152                     const GrBuffer** buffer,
153                     int* startVertex);
154 
155 private:
156     typedef GrBufferAllocPool INHERITED;
157 };
158 
159 /**
160  * A GrBufferAllocPool of index buffers
161  */
162 class GrIndexBufferAllocPool : public GrBufferAllocPool {
163 public:
164     /**
165      * Constructor
166      *
167      * @param gpu                   The GrGpu used to create the index buffers.
168      */
169     GrIndexBufferAllocPool(GrGpu* gpu);
170 
171     /**
172      * Returns a block of memory to hold indices. A buffer designated to hold
173      * the indices is given to the caller. The buffer may or may not be locked.
174      * The returned ptr remains valid until any of the following:
175      *      *makeSpace is called again.
176      *      *unmap is called.
177      *      *reset is called.
178      *      *this object is destroyed.
179      *
180      * Once unmap on the pool is called the indices are guaranteed to be in the
181      * buffer at the offset indicated by startIndex. Until that time they may be
182      * in temporary storage and/or the buffer may be locked.
183      *
184      * @param indexCount   number of indices to allocate space for
185      * @param buffer       returns the index buffer that will hold the indices.
186      * @param startIndex   returns the offset into buffer of the first index.
187      * @return pointer to first index.
188      */
189     void* makeSpace(int indexCount,
190                     const GrBuffer** buffer,
191                     int* startIndex);
192 
193 private:
194     typedef GrBufferAllocPool INHERITED;
195 };
196 
197 #endif
198