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