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 "GrTypesPriv.h" 12 #include "SkNoncopyable.h" 13 #include "SkTArray.h" 14 #include "SkTDArray.h" 15 #include "SkTypes.h" 16 17 class GrBuffer; 18 class GrGpu; 19 20 /** 21 * A pool of geometry buffers tied to a GrGpu. 22 * 23 * The pool allows a client to make space for geometry and then put back excess 24 * space if it over allocated. When a client is ready to draw from the pool 25 * it calls unmap on the pool ensure buffers are ready for drawing. The pool 26 * can be reset after drawing is completed to recycle space. 27 * 28 * At creation time a minimum per-buffer size can be specified. Additionally, 29 * a number of buffers to preallocate can be specified. These will 30 * be allocated at the min size and kept around until the pool is destroyed. 31 */ 32 class GrBufferAllocPool : SkNoncopyable { 33 public: 34 static constexpr size_t kDefaultBufferSize = 1 << 15; 35 36 /** 37 * Ensures all buffers are unmapped and have all data written to them. 38 * Call before drawing using buffers from the pool. 39 */ 40 void unmap(); 41 42 /** 43 * Invalidates all the data in the pool, unrefs non-preallocated buffers. 44 */ 45 void reset(); 46 47 /** 48 * Frees data from makeSpaces in LIFO order. 49 */ 50 void putBack(size_t bytes); 51 52 protected: 53 /** 54 * Constructor 55 * 56 * @param gpu The GrGpu used to create the buffers. 57 * @param bufferType The type of buffers to create. 58 * @param initialBuffer If non-null this should be a kDefaultBufferSize byte allocation. 59 * This parameter can be used to avoid malloc/free when all 60 * usages can be satisfied with default-sized buffers. 61 */ 62 GrBufferAllocPool(GrGpu* gpu, GrBufferType bufferType, void* initialBuffer); 63 64 virtual ~GrBufferAllocPool(); 65 66 /** 67 * Returns a block of memory to hold data. A buffer designated to hold the 68 * data is given to the caller. The buffer may or may not be locked. The 69 * returned ptr remains valid until any of the following: 70 * *makeSpace is called again. 71 * *unmap is called. 72 * *reset is called. 73 * *this object is destroyed. 74 * 75 * Once unmap on the pool is called the data is guaranteed to be in the 76 * buffer at the offset indicated by offset. Until that time it may be 77 * in temporary storage and/or the buffer may be locked. 78 * 79 * @param size the amount of data to make space for 80 * @param alignment alignment constraint from start of buffer 81 * @param buffer returns the buffer that will hold the data. 82 * @param offset returns the offset into buffer of the data. 83 * @return pointer to where the client should write the data. 84 */ 85 void* makeSpace(size_t size, size_t alignment, sk_sp<const GrBuffer>* buffer, size_t* offset); 86 87 /** 88 * Returns a block of memory to hold data. A buffer designated to hold the 89 * data is given to the caller. The buffer may or may not be locked. The 90 * returned ptr remains valid until any of the following: 91 * *makeSpace is called again. 92 * *unmap is called. 93 * *reset is called. 94 * *this object is destroyed. 95 * 96 * Once unmap on the pool is called the data is guaranteed to be in the 97 * buffer at the offset indicated by offset. Until that time it may be 98 * in temporary storage and/or the buffer may be locked. 99 * 100 * The caller requests a minimum number of bytes, but the block may be (much) 101 * larger. Assuming that a new block must be allocated, it will be fallbackSize bytes. 102 * The actual block size is returned in actualSize. 103 * 104 * @param minSize the minimum amount of data to make space for 105 * @param fallbackSize the amount of data to make space for if a new block is needed 106 * @param alignment alignment constraint from start of buffer 107 * @param buffer returns the buffer that will hold the data. 108 * @param offset returns the offset into buffer of the data. 109 * @param actualSize returns the capacity of the block 110 * @return pointer to where the client should write the data. 111 */ 112 void* makeSpaceAtLeast(size_t minSize, 113 size_t fallbackSize, 114 size_t alignment, 115 sk_sp<const GrBuffer>* buffer, 116 size_t* offset, 117 size_t* actualSize); 118 119 sk_sp<GrBuffer> getBuffer(size_t size); 120 121 private: 122 struct BufferBlock { 123 size_t fBytesFree; 124 sk_sp<GrBuffer> fBuffer; 125 }; 126 127 bool createBlock(size_t requestSize); 128 void destroyBlock(); 129 void deleteBlocks(); 130 void flushCpuData(const BufferBlock& block, size_t flushSize); 131 void* resetCpuData(size_t newSize); 132 #ifdef SK_DEBUG 133 void validate(bool unusedBlockAllowed = false) const; 134 #endif 135 size_t fBytesInUse = 0; 136 137 SkTArray<BufferBlock> fBlocks; 138 GrGpu* fGpu; 139 GrBufferType fBufferType; 140 void* fInitialCpuData = nullptr; 141 void* fCpuData = nullptr; 142 size_t fCpuDataSize = 0; 143 void* fBufferPtr = nullptr; 144 }; 145 146 /** 147 * A GrBufferAllocPool of vertex buffers 148 */ 149 class GrVertexBufferAllocPool : public GrBufferAllocPool { 150 public: 151 /** 152 * Constructor 153 * 154 * @param gpu The GrGpu used to create the vertex buffers. 155 * @param initialBuffer If non-null this should be a kDefaultBufferSize byte allocation. 156 * This parameter can be used to avoid malloc/free when all 157 * usages can be satisfied with default-sized buffers. 158 */ 159 GrVertexBufferAllocPool(GrGpu* gpu, void* initialBuffer); 160 161 /** 162 * Returns a block of memory to hold vertices. A buffer designated to hold 163 * the vertices given to the caller. The buffer may or may not be locked. 164 * The returned ptr remains valid until any of the following: 165 * *makeSpace is called again. 166 * *unmap is called. 167 * *reset is called. 168 * *this object is destroyed. 169 * 170 * Once unmap on the pool is called the vertices are guaranteed to be in 171 * the buffer at the offset indicated by startVertex. Until that time they 172 * may be in temporary storage and/or the buffer may be locked. 173 * 174 * @param vertexSize specifies size of a vertex to allocate space for 175 * @param vertexCount number of vertices to allocate space for 176 * @param buffer returns the vertex buffer that will hold the 177 * vertices. 178 * @param startVertex returns the offset into buffer of the first vertex. 179 * In units of the size of a vertex from layout param. 180 * @return pointer to first vertex. 181 */ 182 void* makeSpace(size_t vertexSize, 183 int vertexCount, 184 sk_sp<const GrBuffer>* buffer, 185 int* startVertex); 186 187 /** 188 * Returns a block of memory to hold vertices. A buffer designated to hold 189 * the vertices given to the caller. The buffer may or may not be locked. 190 * The returned ptr remains valid until any of the following: 191 * *makeSpace is called again. 192 * *unmap is called. 193 * *reset is called. 194 * *this object is destroyed. 195 * 196 * Once unmap on the pool is called the vertices are guaranteed to be in 197 * the buffer at the offset indicated by startVertex. Until that time they 198 * may be in temporary storage and/or the buffer may be locked. 199 * 200 * The caller requests a minimum number of vertices, but the block may be (much) 201 * larger. Assuming that a new block must be allocated, it will be sized to hold 202 * fallbackVertexCount vertices. The actual block size (in vertices) is returned in 203 * actualVertexCount. 204 * 205 * @param vertexSize specifies size of a vertex to allocate space for 206 * @param minVertexCount minimum number of vertices to allocate space for 207 * @param fallbackVertexCount number of vertices to allocate space for if a new block is needed 208 * @param buffer returns the vertex buffer that will hold the vertices. 209 * @param startVertex returns the offset into buffer of the first vertex. 210 * In units of the size of a vertex from layout param. 211 * @param actualVertexCount returns the capacity of the block (in vertices) 212 * @return pointer to first vertex. 213 */ 214 void* makeSpaceAtLeast(size_t vertexSize, 215 int minVertexCount, 216 int fallbackVertexCount, 217 sk_sp<const GrBuffer>* buffer, 218 int* startVertex, 219 int* actualVertexCount); 220 221 private: 222 typedef GrBufferAllocPool INHERITED; 223 }; 224 225 /** 226 * A GrBufferAllocPool of index buffers 227 */ 228 class GrIndexBufferAllocPool : public GrBufferAllocPool { 229 public: 230 /** 231 * Constructor 232 * 233 * @param gpu The GrGpu used to create the index buffers. 234 * @param initialBuffer If non-null this should be a kDefaultBufferSize byte allocation. 235 * This parameter can be used to avoid malloc/free when all 236 * usages can be satisfied with default-sized buffers. 237 */ 238 GrIndexBufferAllocPool(GrGpu* gpu, void* initialBuffer); 239 240 /** 241 * Returns a block of memory to hold indices. A buffer designated to hold 242 * the indices is given to the caller. The buffer may or may not be locked. 243 * The returned ptr remains valid until any of the following: 244 * *makeSpace is called again. 245 * *unmap is called. 246 * *reset is called. 247 * *this object is destroyed. 248 * 249 * Once unmap on the pool is called the indices are guaranteed to be in the 250 * buffer at the offset indicated by startIndex. Until that time they may be 251 * in temporary storage and/or the buffer may be locked. 252 * 253 * @param indexCount number of indices to allocate space for 254 * @param buffer returns the index buffer that will hold the indices. 255 * @param startIndex returns the offset into buffer of the first index. 256 * @return pointer to first index. 257 */ 258 void* makeSpace(int indexCount, sk_sp<const GrBuffer>* buffer, int* startIndex); 259 260 /** 261 * Returns a block of memory to hold indices. A buffer designated to hold 262 * the indices is given to the caller. The buffer may or may not be locked. 263 * The returned ptr remains valid until any of the following: 264 * *makeSpace is called again. 265 * *unmap is called. 266 * *reset is called. 267 * *this object is destroyed. 268 * 269 * Once unmap on the pool is called the indices are guaranteed to be in the 270 * buffer at the offset indicated by startIndex. Until that time they may be 271 * in temporary storage and/or the buffer may be locked. 272 * 273 * The caller requests a minimum number of indices, but the block may be (much) 274 * larger. Assuming that a new block must be allocated, it will be sized to hold 275 * fallbackIndexCount indices. The actual block size (in indices) is returned in 276 * actualIndexCount. 277 * 278 * @param minIndexCount minimum number of indices to allocate space for 279 * @param fallbackIndexCount number of indices to allocate space for if a new block is needed 280 * @param buffer returns the index buffer that will hold the indices. 281 * @param startIndex returns the offset into buffer of the first index. 282 * @param actualIndexCount returns the capacity of the block (in indices) 283 * @return pointer to first index. 284 */ 285 void* makeSpaceAtLeast(int minIndexCount, 286 int fallbackIndexCount, 287 sk_sp<const GrBuffer>* buffer, 288 int* startIndex, 289 int* actualIndexCount); 290 291 private: 292 typedef GrBufferAllocPool INHERITED; 293 }; 294 295 #endif 296