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 "SkTArray.h"
12#include "SkTDArray.h"
13#include "SkTypes.h"
14
15class GrGeometryBuffer;
16class GrGpu;
17
18/**
19 * A pool of geometry buffers tied to a GrGpu.
20 *
21 * The pool allows a client to make space for geometry and then put back excess
22 * space if it over allocated. When a client is ready to draw from the pool
23 * it calls unmap on the pool ensure buffers are ready for drawing. The pool
24 * can be reset after drawing is completed to recycle space.
25 *
26 * At creation time a minimum per-buffer size can be specified. Additionally,
27 * a number of buffers to preallocate can be specified. These will
28 * be allocated at the min size and kept around until the pool is destroyed.
29 */
30class GrBufferAllocPool : SkNoncopyable {
31public:
32    /**
33     * Ensures all buffers are unmapped and have all data written to them.
34     * Call before drawing using buffers from the pool.
35     */
36    void unmap();
37
38    /**
39     *  Invalidates all the data in the pool, unrefs non-preallocated buffers.
40     */
41    void reset();
42
43    /**
44     * Frees data from makeSpaces in LIFO order.
45     */
46    void putBack(size_t bytes);
47
48protected:
49    /**
50     * Used to determine what type of buffers to create. We could make the
51     * createBuffer a virtual except that we want to use it in the cons for
52     * pre-allocated buffers.
53     */
54    enum BufferType {
55        kVertex_BufferType,
56        kIndex_BufferType,
57    };
58
59    /**
60     * Constructor
61     *
62     * @param gpu                   The GrGpu used to create the buffers.
63     * @param bufferType            The type of buffers to create.
64     * @param bufferSize            The minimum size of created buffers.
65     *                              This value will be clamped to some
66     *                              reasonable minimum.
67     */
68     GrBufferAllocPool(GrGpu* gpu,
69                       BufferType bufferType,
70                       size_t   bufferSize = 0);
71
72     virtual ~GrBufferAllocPool();
73
74    /**
75     * Returns a block of memory to hold data. A buffer designated to hold the
76     * data is given to the caller. The buffer may or may not be locked. The
77     * returned ptr remains valid until any of the following:
78     *      *makeSpace is called again.
79     *      *unmap is called.
80     *      *reset is called.
81     *      *this object is destroyed.
82     *
83     * Once unmap on the pool is called the data is guaranteed to be in the
84     * buffer at the offset indicated by offset. Until that time it may be
85     * in temporary storage and/or the buffer may be locked.
86     *
87     * @param size         the amount of data to make space for
88     * @param alignment    alignment constraint from start of buffer
89     * @param buffer       returns the buffer that will hold the data.
90     * @param offset       returns the offset into buffer of the data.
91     * @return pointer to where the client should write the data.
92     */
93    void* makeSpace(size_t size,
94                    size_t alignment,
95                    const GrGeometryBuffer** buffer,
96                    size_t* offset);
97
98    GrGeometryBuffer* getBuffer(size_t size);
99
100private:
101    struct BufferBlock {
102        size_t              fBytesFree;
103        GrGeometryBuffer*   fBuffer;
104    };
105
106    bool createBlock(size_t requestSize);
107    void destroyBlock();
108    void deleteBlocks();
109    void flushCpuData(const BufferBlock& block, size_t flushSize);
110    void* resetCpuData(size_t newSize);
111#ifdef SK_DEBUG
112    void validate(bool unusedBlockAllowed = false) const;
113#endif
114    size_t                          fBytesInUse;
115
116    GrGpu*                          fGpu;
117    size_t                          fMinBlockSize;
118    BufferType                      fBufferType;
119
120    SkTArray<BufferBlock>           fBlocks;
121    void*                           fCpuData;
122    void*                           fBufferPtr;
123    size_t                          fGeometryBufferMapThreshold;
124};
125
126class GrVertexBuffer;
127
128/**
129 * A GrBufferAllocPool of vertex buffers
130 */
131class GrVertexBufferAllocPool : public GrBufferAllocPool {
132public:
133    /**
134     * Constructor
135     *
136     * @param gpu                   The GrGpu used to create the vertex buffers.
137     */
138    GrVertexBufferAllocPool(GrGpu* gpu);
139
140    /**
141     * Returns a block of memory to hold vertices. A buffer designated to hold
142     * the vertices given to the caller. The buffer may or may not be locked.
143     * The returned ptr remains valid until any of the following:
144     *      *makeSpace is called again.
145     *      *unmap is called.
146     *      *reset is called.
147     *      *this object is destroyed.
148     *
149     * Once unmap on the pool is called the vertices are guaranteed to be in
150     * the buffer at the offset indicated by startVertex. Until that time they
151     * may be in temporary storage and/or the buffer may be locked.
152     *
153     * @param vertexSize   specifies size of a vertex to allocate space for
154     * @param vertexCount  number of vertices to allocate space for
155     * @param buffer       returns the vertex buffer that will hold the
156     *                     vertices.
157     * @param startVertex  returns the offset into buffer of the first vertex.
158     *                     In units of the size of a vertex from layout param.
159     * @return pointer to first vertex.
160     */
161    void* makeSpace(size_t vertexSize,
162                    int vertexCount,
163                    const GrVertexBuffer** buffer,
164                    int* startVertex);
165
166private:
167    typedef GrBufferAllocPool INHERITED;
168};
169
170class GrIndexBuffer;
171
172/**
173 * A GrBufferAllocPool of index buffers
174 */
175class GrIndexBufferAllocPool : public GrBufferAllocPool {
176public:
177    /**
178     * Constructor
179     *
180     * @param gpu                   The GrGpu used to create the index buffers.
181     */
182    GrIndexBufferAllocPool(GrGpu* gpu);
183
184    /**
185     * Returns a block of memory to hold indices. A buffer designated to hold
186     * the indices is given to the caller. The buffer may or may not be locked.
187     * The returned ptr remains valid until any of the following:
188     *      *makeSpace is called again.
189     *      *unmap is called.
190     *      *reset is called.
191     *      *this object is destroyed.
192     *
193     * Once unmap on the pool is called the indices are guaranteed to be in the
194     * buffer at the offset indicated by startIndex. Until that time they may be
195     * in temporary storage and/or the buffer may be locked.
196     *
197     * @param indexCount   number of indices to allocate space for
198     * @param buffer       returns the index buffer that will hold the indices.
199     * @param startIndex   returns the offset into buffer of the first index.
200     * @return pointer to first index.
201     */
202    void* makeSpace(int indexCount,
203                    const GrIndexBuffer** buffer,
204                    int* startIndex);
205
206private:
207    typedef GrBufferAllocPool INHERITED;
208};
209
210#endif
211