1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrBufferAllocPool.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,347 @@ 1.4 +/* 1.5 + * Copyright 2010 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#ifndef GrBufferAllocPool_DEFINED 1.12 +#define GrBufferAllocPool_DEFINED 1.13 + 1.14 +#include "SkTArray.h" 1.15 +#include "SkTDArray.h" 1.16 +#include "SkTypes.h" 1.17 + 1.18 +class GrGeometryBuffer; 1.19 +class GrGpu; 1.20 + 1.21 +/** 1.22 + * A pool of geometry buffers tied to a GrGpu. 1.23 + * 1.24 + * The pool allows a client to make space for geometry and then put back excess 1.25 + * space if it over allocated. When a client is ready to draw from the pool 1.26 + * it calls unlock on the pool ensure buffers are ready for drawing. The pool 1.27 + * can be reset after drawing is completed to recycle space. 1.28 + * 1.29 + * At creation time a minimum per-buffer size can be specified. Additionally, 1.30 + * a number of buffers to preallocate can be specified. These will 1.31 + * be allocated at the min size and kept around until the pool is destroyed. 1.32 + */ 1.33 +class GrBufferAllocPool : public SkNoncopyable { 1.34 +public: 1.35 + /** 1.36 + * Ensures all buffers are unlocked and have all data written to them. 1.37 + * Call before drawing using buffers from the pool. 1.38 + */ 1.39 + void unlock(); 1.40 + 1.41 + /** 1.42 + * Invalidates all the data in the pool, unrefs non-preallocated buffers. 1.43 + */ 1.44 + void reset(); 1.45 + 1.46 + /** 1.47 + * Gets the number of preallocated buffers that are yet to be used. 1.48 + */ 1.49 + int preallocatedBuffersRemaining() const; 1.50 + 1.51 + /** 1.52 + * gets the number of preallocated buffers 1.53 + */ 1.54 + int preallocatedBufferCount() const; 1.55 + 1.56 + /** 1.57 + * Frees data from makeSpaces in LIFO order. 1.58 + */ 1.59 + void putBack(size_t bytes); 1.60 + 1.61 + /** 1.62 + * Gets the GrGpu that this pool is associated with. 1.63 + */ 1.64 + GrGpu* getGpu() { return fGpu; } 1.65 + 1.66 +protected: 1.67 + /** 1.68 + * Used to determine what type of buffers to create. We could make the 1.69 + * createBuffer a virtual except that we want to use it in the cons for 1.70 + * pre-allocated buffers. 1.71 + */ 1.72 + enum BufferType { 1.73 + kVertex_BufferType, 1.74 + kIndex_BufferType, 1.75 + }; 1.76 + 1.77 + /** 1.78 + * Constructor 1.79 + * 1.80 + * @param gpu The GrGpu used to create the buffers. 1.81 + * @param bufferType The type of buffers to create. 1.82 + * @param frequentResetHint A hint that indicates that the pool 1.83 + * should expect frequent unlock() calls 1.84 + * (as opposed to many makeSpace / acquires 1.85 + * between resets). 1.86 + * @param bufferSize The minimum size of created buffers. 1.87 + * This value will be clamped to some 1.88 + * reasonable minimum. 1.89 + * @param preallocBufferCnt The pool will allocate this number of 1.90 + * buffers at bufferSize and keep them until it 1.91 + * is destroyed. 1.92 + */ 1.93 + GrBufferAllocPool(GrGpu* gpu, 1.94 + BufferType bufferType, 1.95 + bool frequentResetHint, 1.96 + size_t bufferSize = 0, 1.97 + int preallocBufferCnt = 0); 1.98 + 1.99 + virtual ~GrBufferAllocPool(); 1.100 + 1.101 + /** 1.102 + * Gets the size of the preallocated buffers. 1.103 + * 1.104 + * @return the size of preallocated buffers. 1.105 + */ 1.106 + size_t preallocatedBufferSize() const { 1.107 + return fPreallocBuffers.count() ? fMinBlockSize : 0; 1.108 + } 1.109 + 1.110 + /** 1.111 + * Returns a block of memory to hold data. A buffer designated to hold the 1.112 + * data is given to the caller. The buffer may or may not be locked. The 1.113 + * returned ptr remains valid until any of the following: 1.114 + * *makeSpace is called again. 1.115 + * *unlock is called. 1.116 + * *reset is called. 1.117 + * *this object is destroyed. 1.118 + * 1.119 + * Once unlock on the pool is called the data is guaranteed to be in the 1.120 + * buffer at the offset indicated by offset. Until that time it may be 1.121 + * in temporary storage and/or the buffer may be locked. 1.122 + * 1.123 + * @param size the amount of data to make space for 1.124 + * @param alignment alignment constraint from start of buffer 1.125 + * @param buffer returns the buffer that will hold the data. 1.126 + * @param offset returns the offset into buffer of the data. 1.127 + * @return pointer to where the client should write the data. 1.128 + */ 1.129 + void* makeSpace(size_t size, 1.130 + size_t alignment, 1.131 + const GrGeometryBuffer** buffer, 1.132 + size_t* offset); 1.133 + 1.134 + /** 1.135 + * Gets the number of items of a size that can be added to the current 1.136 + * buffer without spilling to another buffer. If the pool has been reset, or 1.137 + * the previous makeSpace completely exhausted a buffer then the returned 1.138 + * size will be the size of the next available preallocated buffer, or zero 1.139 + * if no preallocated buffer remains available. It is assumed that items 1.140 + * should be itemSize-aligned from the start of a buffer. 1.141 + * 1.142 + * @return the number of items that would fit in the current buffer. 1.143 + */ 1.144 + int currentBufferItems(size_t itemSize) const; 1.145 + 1.146 + GrGeometryBuffer* createBuffer(size_t size); 1.147 + 1.148 +private: 1.149 + 1.150 + // The GrGpu must be able to clear the ref of pools it creates as members 1.151 + friend class GrGpu; 1.152 + void releaseGpuRef(); 1.153 + 1.154 + struct BufferBlock { 1.155 + size_t fBytesFree; 1.156 + GrGeometryBuffer* fBuffer; 1.157 + }; 1.158 + 1.159 + bool createBlock(size_t requestSize); 1.160 + void destroyBlock(); 1.161 + void flushCpuData(GrGeometryBuffer* buffer, size_t flushSize); 1.162 +#ifdef SK_DEBUG 1.163 + void validate(bool unusedBlockAllowed = false) const; 1.164 +#endif 1.165 + 1.166 + size_t fBytesInUse; 1.167 + 1.168 + GrGpu* fGpu; 1.169 + bool fGpuIsReffed; 1.170 + bool fFrequentResetHint; 1.171 + SkTDArray<GrGeometryBuffer*> fPreallocBuffers; 1.172 + size_t fMinBlockSize; 1.173 + BufferType fBufferType; 1.174 + 1.175 + SkTArray<BufferBlock> fBlocks; 1.176 + int fPreallocBuffersInUse; 1.177 + // We attempt to cycle through the preallocated buffers rather than 1.178 + // always starting from the first. 1.179 + int fPreallocBufferStartIdx; 1.180 + SkAutoMalloc fCpuData; 1.181 + void* fBufferPtr; 1.182 +}; 1.183 + 1.184 +class GrVertexBuffer; 1.185 + 1.186 +/** 1.187 + * A GrBufferAllocPool of vertex buffers 1.188 + */ 1.189 +class GrVertexBufferAllocPool : public GrBufferAllocPool { 1.190 +public: 1.191 + /** 1.192 + * Constructor 1.193 + * 1.194 + * @param gpu The GrGpu used to create the vertex buffers. 1.195 + * @param frequentResetHint A hint that indicates that the pool 1.196 + * should expect frequent unlock() calls 1.197 + * (as opposed to many makeSpace / acquires 1.198 + * between resets). 1.199 + * @param bufferSize The minimum size of created VBs This value 1.200 + * will be clamped to some reasonable minimum. 1.201 + * @param preallocBufferCnt The pool will allocate this number of VBs at 1.202 + * bufferSize and keep them until it is 1.203 + * destroyed. 1.204 + */ 1.205 + GrVertexBufferAllocPool(GrGpu* gpu, 1.206 + bool frequentResetHint, 1.207 + size_t bufferSize = 0, 1.208 + int preallocBufferCnt = 0); 1.209 + 1.210 + /** 1.211 + * Returns a block of memory to hold vertices. A buffer designated to hold 1.212 + * the vertices given to the caller. The buffer may or may not be locked. 1.213 + * The returned ptr remains valid until any of the following: 1.214 + * *makeSpace is called again. 1.215 + * *unlock is called. 1.216 + * *reset is called. 1.217 + * *this object is destroyed. 1.218 + * 1.219 + * Once unlock on the pool is called the vertices are guaranteed to be in 1.220 + * the buffer at the offset indicated by startVertex. Until that time they 1.221 + * may be in temporary storage and/or the buffer may be locked. 1.222 + * 1.223 + * @param vertexSize specifies size of a vertex to allocate space for 1.224 + * @param vertexCount number of vertices to allocate space for 1.225 + * @param buffer returns the vertex buffer that will hold the 1.226 + * vertices. 1.227 + * @param startVertex returns the offset into buffer of the first vertex. 1.228 + * In units of the size of a vertex from layout param. 1.229 + * @return pointer to first vertex. 1.230 + */ 1.231 + void* makeSpace(size_t vertexSize, 1.232 + int vertexCount, 1.233 + const GrVertexBuffer** buffer, 1.234 + int* startVertex); 1.235 + 1.236 + /** 1.237 + * Shortcut to make space and then write verts into the made space. 1.238 + */ 1.239 + bool appendVertices(size_t vertexSize, 1.240 + int vertexCount, 1.241 + const void* vertices, 1.242 + const GrVertexBuffer** buffer, 1.243 + int* startVertex); 1.244 + 1.245 + /** 1.246 + * Gets the number of vertices that can be added to the current VB without 1.247 + * spilling to another VB. If the pool has been reset, or the previous 1.248 + * makeSpace completely exhausted a VB then the returned number of vertices 1.249 + * would fit in the next available preallocated buffer. If any makeSpace 1.250 + * would force a new VB to be created the return value will be zero. 1.251 + * 1.252 + * @param the size of a vertex to compute space for. 1.253 + * @return the number of vertices that would fit in the current buffer. 1.254 + */ 1.255 + int currentBufferVertices(size_t vertexSize) const; 1.256 + 1.257 + /** 1.258 + * Gets the number of vertices that can fit in a preallocated vertex buffer. 1.259 + * Zero if no preallocated buffers. 1.260 + * 1.261 + * @param the size of a vertex to compute space for. 1.262 + * 1.263 + * @return number of vertices that fit in one of the preallocated vertex 1.264 + * buffers. 1.265 + */ 1.266 + int preallocatedBufferVertices(size_t vertexSize) const; 1.267 + 1.268 +private: 1.269 + typedef GrBufferAllocPool INHERITED; 1.270 +}; 1.271 + 1.272 +class GrIndexBuffer; 1.273 + 1.274 +/** 1.275 + * A GrBufferAllocPool of index buffers 1.276 + */ 1.277 +class GrIndexBufferAllocPool : public GrBufferAllocPool { 1.278 +public: 1.279 + /** 1.280 + * Constructor 1.281 + * 1.282 + * @param gpu The GrGpu used to create the index buffers. 1.283 + * @param frequentResetHint A hint that indicates that the pool 1.284 + * should expect frequent unlock() calls 1.285 + * (as opposed to many makeSpace / acquires 1.286 + * between resets). 1.287 + * @param bufferSize The minimum size of created IBs This value 1.288 + * will be clamped to some reasonable minimum. 1.289 + * @param preallocBufferCnt The pool will allocate this number of VBs at 1.290 + * bufferSize and keep them until it is 1.291 + * destroyed. 1.292 + */ 1.293 + GrIndexBufferAllocPool(GrGpu* gpu, 1.294 + bool frequentResetHint, 1.295 + size_t bufferSize = 0, 1.296 + int preallocBufferCnt = 0); 1.297 + 1.298 + /** 1.299 + * Returns a block of memory to hold indices. A buffer designated to hold 1.300 + * the indices is given to the caller. The buffer may or may not be locked. 1.301 + * The returned ptr remains valid until any of the following: 1.302 + * *makeSpace is called again. 1.303 + * *unlock is called. 1.304 + * *reset is called. 1.305 + * *this object is destroyed. 1.306 + * 1.307 + * Once unlock on the pool is called the indices are guaranteed to be in the 1.308 + * buffer at the offset indicated by startIndex. Until that time they may be 1.309 + * in temporary storage and/or the buffer may be locked. 1.310 + * 1.311 + * @param indexCount number of indices to allocate space for 1.312 + * @param buffer returns the index buffer that will hold the indices. 1.313 + * @param startIndex returns the offset into buffer of the first index. 1.314 + * @return pointer to first index. 1.315 + */ 1.316 + void* makeSpace(int indexCount, 1.317 + const GrIndexBuffer** buffer, 1.318 + int* startIndex); 1.319 + 1.320 + /** 1.321 + * Shortcut to make space and then write indices into the made space. 1.322 + */ 1.323 + bool appendIndices(int indexCount, 1.324 + const void* indices, 1.325 + const GrIndexBuffer** buffer, 1.326 + int* startIndex); 1.327 + 1.328 + /** 1.329 + * Gets the number of indices that can be added to the current IB without 1.330 + * spilling to another IB. If the pool has been reset, or the previous 1.331 + * makeSpace completely exhausted a IB then the returned number of indices 1.332 + * would fit in the next available preallocated buffer. If any makeSpace 1.333 + * would force a new IB to be created the return value will be zero. 1.334 + */ 1.335 + int currentBufferIndices() const; 1.336 + 1.337 + /** 1.338 + * Gets the number of indices that can fit in a preallocated index buffer. 1.339 + * Zero if no preallocated buffers. 1.340 + * 1.341 + * @return number of indices that fit in one of the preallocated index 1.342 + * buffers. 1.343 + */ 1.344 + int preallocatedBufferIndices() const; 1.345 + 1.346 +private: 1.347 + typedef GrBufferAllocPool INHERITED; 1.348 +}; 1.349 + 1.350 +#endif