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