|
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 |
|
15 class GrGeometryBuffer; |
|
16 class 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 */ |
|
30 class GrBufferAllocPool : public SkNoncopyable { |
|
31 public: |
|
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 |
|
63 protected: |
|
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 */ |
|
69 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 |
|
98 /** |
|
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 |
|
145 private: |
|
146 |
|
147 // The GrGpu must be able to clear the ref of pools it creates as members |
|
148 friend class GrGpu; |
|
149 void releaseGpuRef(); |
|
150 |
|
151 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); |
|
159 #ifdef SK_DEBUG |
|
160 void validate(bool unusedBlockAllowed = false) const; |
|
161 #endif |
|
162 |
|
163 size_t fBytesInUse; |
|
164 |
|
165 GrGpu* fGpu; |
|
166 bool fGpuIsReffed; |
|
167 bool fFrequentResetHint; |
|
168 SkTDArray<GrGeometryBuffer*> fPreallocBuffers; |
|
169 size_t fMinBlockSize; |
|
170 BufferType fBufferType; |
|
171 |
|
172 SkTArray<BufferBlock> fBlocks; |
|
173 int fPreallocBuffersInUse; |
|
174 // We attempt to cycle through the preallocated buffers rather than |
|
175 // always starting from the first. |
|
176 int fPreallocBufferStartIdx; |
|
177 SkAutoMalloc fCpuData; |
|
178 void* fBufferPtr; |
|
179 }; |
|
180 |
|
181 class GrVertexBuffer; |
|
182 |
|
183 /** |
|
184 * A GrBufferAllocPool of vertex buffers |
|
185 */ |
|
186 class GrVertexBufferAllocPool : public GrBufferAllocPool { |
|
187 public: |
|
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 * |
|
220 * @param vertexSize specifies size of a vertex to allocate space for |
|
221 * @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 */ |
|
228 void* makeSpace(size_t vertexSize, |
|
229 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 */ |
|
236 bool appendVertices(size_t vertexSize, |
|
237 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 * |
|
249 * @param the size of a vertex to compute space for. |
|
250 * @return the number of vertices that would fit in the current buffer. |
|
251 */ |
|
252 int currentBufferVertices(size_t vertexSize) const; |
|
253 |
|
254 /** |
|
255 * Gets the number of vertices that can fit in a preallocated vertex buffer. |
|
256 * Zero if no preallocated buffers. |
|
257 * |
|
258 * @param the size of a vertex to compute space for. |
|
259 * |
|
260 * @return number of vertices that fit in one of the preallocated vertex |
|
261 * buffers. |
|
262 */ |
|
263 int preallocatedBufferVertices(size_t vertexSize) const; |
|
264 |
|
265 private: |
|
266 typedef GrBufferAllocPool INHERITED; |
|
267 }; |
|
268 |
|
269 class GrIndexBuffer; |
|
270 |
|
271 /** |
|
272 * A GrBufferAllocPool of index buffers |
|
273 */ |
|
274 class GrIndexBufferAllocPool : public GrBufferAllocPool { |
|
275 public: |
|
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 |
|
343 private: |
|
344 typedef GrBufferAllocPool INHERITED; |
|
345 }; |
|
346 |
|
347 #endif |