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 26 class GrGeometryBuffer; 27 class 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 */ 41 class GrBufferAllocPool : GrNoncopyable { 42 43 public: 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 */ getGpu()73 GrGpu* getGpu() { return fGpu; } 74 75 protected: 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 */ preallocatedBufferSize()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 157 private: 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 189 class GrVertexBuffer; 190 191 /** 192 * A GrBufferAllocPool of vertex buffers 193 */ 194 class GrVertexBufferAllocPool : public GrBufferAllocPool { 195 public: 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 273 private: 274 typedef GrBufferAllocPool INHERITED; 275 }; 276 277 class GrIndexBuffer; 278 279 /** 280 * A GrBufferAllocPool of index buffers 281 */ 282 class GrIndexBufferAllocPool : public GrBufferAllocPool { 283 public: 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 351 private: 352 typedef GrBufferAllocPool INHERITED; 353 }; 354 355 #endif 356