Home | History | Annotate | Download | only in gpu
      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      */
     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      */
    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