| /* | |
| * Copyright 2010 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef GrBufferAllocPool_DEFINED | |
| #define GrBufferAllocPool_DEFINED | |
| #include "SkTArray.h" | |
| #include "SkTDArray.h" | |
| #include "SkTypes.h" | |
| class GrGeometryBuffer; | |
| class GrGpu; | |
| /** | |
| * A pool of geometry buffers tied to a GrGpu. | |
| * | |
| * The pool allows a client to make space for geometry and then put back excess | |
| * space if it over allocated. When a client is ready to draw from the pool | |
| * it calls unmap on the pool ensure buffers are ready for drawing. The pool | |
| * can be reset after drawing is completed to recycle space. | |
| * | |
| * At creation time a minimum per-buffer size can be specified. Additionally, | |
| * a number of buffers to preallocate can be specified. These will | |
| * be allocated at the min size and kept around until the pool is destroyed. | |
| */ | |
| class GrBufferAllocPool : SkNoncopyable { | |
| public: | |
| /** | |
| * Ensures all buffers are unmapped and have all data written to them. | |
| * Call before drawing using buffers from the pool. | |
| */ | |
| void unmap(); | |
| /** | |
| * Invalidates all the data in the pool, unrefs non-preallocated buffers. | |
| */ | |
| void reset(); | |
| /** | |
| * Gets the number of preallocated buffers that are yet to be used. | |
| */ | |
| int preallocatedBuffersRemaining() const; | |
| /** | |
| * gets the number of preallocated buffers | |
| */ | |
| int preallocatedBufferCount() const; | |
| /** | |
| * Frees data from makeSpaces in LIFO order. | |
| */ | |
| void putBack(size_t bytes); | |
| /** | |
| * Gets the GrGpu that this pool is associated with. | |
| */ | |
| GrGpu* getGpu() { return fGpu; } | |
| protected: | |
| /** | |
| * Used to determine what type of buffers to create. We could make the | |
| * createBuffer a virtual except that we want to use it in the cons for | |
| * pre-allocated buffers. | |
| */ | |
| enum BufferType { | |
| kVertex_BufferType, | |
| kIndex_BufferType, | |
| }; | |
| /** | |
| * Constructor | |
| * | |
| * @param gpu The GrGpu used to create the buffers. | |
| * @param bufferType The type of buffers to create. | |
| * @param frequentResetHint A hint that indicates that the pool | |
| * should expect frequent unmap() calls | |
| * (as opposed to many makeSpace / acquires | |
| * between resets). | |
| * @param bufferSize The minimum size of created buffers. | |
| * This value will be clamped to some | |
| * reasonable minimum. | |
| * @param preallocBufferCnt The pool will allocate this number of | |
| * buffers at bufferSize and keep them until it | |
| * is destroyed. | |
| */ | |
| GrBufferAllocPool(GrGpu* gpu, | |
| BufferType bufferType, | |
| bool frequentResetHint, | |
| size_t bufferSize = 0, | |
| int preallocBufferCnt = 0); | |
| virtual ~GrBufferAllocPool(); | |
| /** | |
| * Gets the size of the preallocated buffers. | |
| * | |
| * @return the size of preallocated buffers. | |
| */ | |
| size_t preallocatedBufferSize() const { | |
| return fPreallocBuffers.count() ? fMinBlockSize : 0; | |
| } | |
| /** | |
| * Returns a block of memory to hold data. A buffer designated to hold the | |
| * data is given to the caller. The buffer may or may not be locked. The | |
| * returned ptr remains valid until any of the following: | |
| * *makeSpace is called again. | |
| * *unmap is called. | |
| * *reset is called. | |
| * *this object is destroyed. | |
| * | |
| * Once unmap on the pool is called the data is guaranteed to be in the | |
| * buffer at the offset indicated by offset. Until that time it may be | |
| * in temporary storage and/or the buffer may be locked. | |
| * | |
| * @param size the amount of data to make space for | |
| * @param alignment alignment constraint from start of buffer | |
| * @param buffer returns the buffer that will hold the data. | |
| * @param offset returns the offset into buffer of the data. | |
| * @return pointer to where the client should write the data. | |
| */ | |
| void* makeSpace(size_t size, | |
| size_t alignment, | |
| const GrGeometryBuffer** buffer, | |
| size_t* offset); | |
| /** | |
| * Gets the number of items of a size that can be added to the current | |
| * buffer without spilling to another buffer. If the pool has been reset, or | |
| * the previous makeSpace completely exhausted a buffer then the returned | |
| * size will be the size of the next available preallocated buffer, or zero | |
| * if no preallocated buffer remains available. It is assumed that items | |
| * should be itemSize-aligned from the start of a buffer. | |
| * | |
| * @return the number of items that would fit in the current buffer. | |
| */ | |
| int currentBufferItems(size_t itemSize) const; | |
| GrGeometryBuffer* createBuffer(size_t size); | |
| private: | |
| // The GrGpu must be able to clear the ref of pools it creates as members | |
| friend class GrGpu; | |
| void releaseGpuRef(); | |
| struct BufferBlock { | |
| size_t fBytesFree; | |
| GrGeometryBuffer* fBuffer; | |
| }; | |
| bool createBlock(size_t requestSize); | |
| void destroyBlock(); | |
| void flushCpuData(const BufferBlock& block, size_t flushSize); | |
| #ifdef SK_DEBUG | |
| void validate(bool unusedBlockAllowed = false) const; | |
| #endif | |
| size_t fBytesInUse; | |
| GrGpu* fGpu; | |
| bool fGpuIsReffed; | |
| bool fFrequentResetHint; | |
| SkTDArray<GrGeometryBuffer*> fPreallocBuffers; | |
| size_t fMinBlockSize; | |
| BufferType fBufferType; | |
| SkTArray<BufferBlock> fBlocks; | |
| int fPreallocBuffersInUse; | |
| // We attempt to cycle through the preallocated buffers rather than | |
| // always starting from the first. | |
| int fPreallocBufferStartIdx; | |
| SkAutoMalloc fCpuData; | |
| void* fBufferPtr; | |
| }; | |
| class GrVertexBuffer; | |
| /** | |
| * A GrBufferAllocPool of vertex buffers | |
| */ | |
| class GrVertexBufferAllocPool : public GrBufferAllocPool { | |
| public: | |
| /** | |
| * Constructor | |
| * | |
| * @param gpu The GrGpu used to create the vertex buffers. | |
| * @param frequentResetHint A hint that indicates that the pool | |
| * should expect frequent unmap() calls | |
| * (as opposed to many makeSpace / acquires | |
| * between resets). | |
| * @param bufferSize The minimum size of created VBs This value | |
| * will be clamped to some reasonable minimum. | |
| * @param preallocBufferCnt The pool will allocate this number of VBs at | |
| * bufferSize and keep them until it is | |
| * destroyed. | |
| */ | |
| GrVertexBufferAllocPool(GrGpu* gpu, | |
| bool frequentResetHint, | |
| size_t bufferSize = 0, | |
| int preallocBufferCnt = 0); | |
| /** | |
| * Returns a block of memory to hold vertices. A buffer designated to hold | |
| * the vertices given to the caller. The buffer may or may not be locked. | |
| * The returned ptr remains valid until any of the following: | |
| * *makeSpace is called again. | |
| * *unmap is called. | |
| * *reset is called. | |
| * *this object is destroyed. | |
| * | |
| * Once unmap on the pool is called the vertices are guaranteed to be in | |
| * the buffer at the offset indicated by startVertex. Until that time they | |
| * may be in temporary storage and/or the buffer may be locked. | |
| * | |
| * @param vertexSize specifies size of a vertex to allocate space for | |
| * @param vertexCount number of vertices to allocate space for | |
| * @param buffer returns the vertex buffer that will hold the | |
| * vertices. | |
| * @param startVertex returns the offset into buffer of the first vertex. | |
| * In units of the size of a vertex from layout param. | |
| * @return pointer to first vertex. | |
| */ | |
| void* makeSpace(size_t vertexSize, | |
| int vertexCount, | |
| const GrVertexBuffer** buffer, | |
| int* startVertex); | |
| /** | |
| * Gets the number of vertices that can be added to the current VB without | |
| * spilling to another VB. If the pool has been reset, or the previous | |
| * makeSpace completely exhausted a VB then the returned number of vertices | |
| * would fit in the next available preallocated buffer. If any makeSpace | |
| * would force a new VB to be created the return value will be zero. | |
| * | |
| * @param the size of a vertex to compute space for. | |
| * @return the number of vertices that would fit in the current buffer. | |
| */ | |
| int currentBufferVertices(size_t vertexSize) const; | |
| /** | |
| * Gets the number of vertices that can fit in a preallocated vertex buffer. | |
| * Zero if no preallocated buffers. | |
| * | |
| * @param the size of a vertex to compute space for. | |
| * | |
| * @return number of vertices that fit in one of the preallocated vertex | |
| * buffers. | |
| */ | |
| int preallocatedBufferVertices(size_t vertexSize) const; | |
| private: | |
| typedef GrBufferAllocPool INHERITED; | |
| }; | |
| class GrIndexBuffer; | |
| /** | |
| * A GrBufferAllocPool of index buffers | |
| */ | |
| class GrIndexBufferAllocPool : public GrBufferAllocPool { | |
| public: | |
| /** | |
| * Constructor | |
| * | |
| * @param gpu The GrGpu used to create the index buffers. | |
| * @param frequentResetHint A hint that indicates that the pool | |
| * should expect frequent unmap() calls | |
| * (as opposed to many makeSpace / acquires | |
| * between resets). | |
| * @param bufferSize The minimum size of created IBs This value | |
| * will be clamped to some reasonable minimum. | |
| * @param preallocBufferCnt The pool will allocate this number of VBs at | |
| * bufferSize and keep them until it is | |
| * destroyed. | |
| */ | |
| GrIndexBufferAllocPool(GrGpu* gpu, | |
| bool frequentResetHint, | |
| size_t bufferSize = 0, | |
| int preallocBufferCnt = 0); | |
| /** | |
| * Returns a block of memory to hold indices. A buffer designated to hold | |
| * the indices is given to the caller. The buffer may or may not be locked. | |
| * The returned ptr remains valid until any of the following: | |
| * *makeSpace is called again. | |
| * *unmap is called. | |
| * *reset is called. | |
| * *this object is destroyed. | |
| * | |
| * Once unmap on the pool is called the indices are guaranteed to be in the | |
| * buffer at the offset indicated by startIndex. Until that time they may be | |
| * in temporary storage and/or the buffer may be locked. | |
| * | |
| * @param indexCount number of indices to allocate space for | |
| * @param buffer returns the index buffer that will hold the indices. | |
| * @param startIndex returns the offset into buffer of the first index. | |
| * @return pointer to first index. | |
| */ | |
| void* makeSpace(int indexCount, | |
| const GrIndexBuffer** buffer, | |
| int* startIndex); | |
| /** | |
| * Gets the number of indices that can be added to the current IB without | |
| * spilling to another IB. If the pool has been reset, or the previous | |
| * makeSpace completely exhausted a IB then the returned number of indices | |
| * would fit in the next available preallocated buffer. If any makeSpace | |
| * would force a new IB to be created the return value will be zero. | |
| */ | |
| int currentBufferIndices() const; | |
| /** | |
| * Gets the number of indices that can fit in a preallocated index buffer. | |
| * Zero if no preallocated buffers. | |
| * | |
| * @return number of indices that fit in one of the preallocated index | |
| * buffers. | |
| */ | |
| int preallocatedBufferIndices() const; | |
| private: | |
| typedef GrBufferAllocPool INHERITED; | |
| }; | |
| #endif |