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 15class GrGeometryBuffer; 16class 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 unmap 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 */ 30class GrBufferAllocPool : SkNoncopyable { 31public: 32 /** 33 * Ensures all buffers are unmapped and have all data written to them. 34 * Call before drawing using buffers from the pool. 35 */ 36 void unmap(); 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 63protected: 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 unmap() 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 * *unmap is called. 113 * *reset is called. 114 * *this object is destroyed. 115 * 116 * Once unmap 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 145private: 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(const BufferBlock& block, 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 181class GrVertexBuffer; 182 183/** 184 * A GrBufferAllocPool of vertex buffers 185 */ 186class GrVertexBufferAllocPool : public GrBufferAllocPool { 187public: 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 unmap() 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 * *unmap is called. 213 * *reset is called. 214 * *this object is destroyed. 215 * 216 * Once unmap 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 265private: 266 typedef GrBufferAllocPool INHERITED; 267}; 268 269class GrIndexBuffer; 270 271/** 272 * A GrBufferAllocPool of index buffers 273 */ 274class GrIndexBufferAllocPool : public GrBufferAllocPool { 275public: 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 unmap() 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 * *unmap is called. 301 * *reset is called. 302 * *this object is destroyed. 303 * 304 * Once unmap 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 343private: 344 typedef GrBufferAllocPool INHERITED; 345}; 346 347#endif 348