aboutsummaryrefslogtreecommitdiffhomepage
path: root/gpu/include/GrInOrderDrawBuffer.h
blob: d59eb96b08f3ee762fc9c4f6e66752b80dfca40e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */


#ifndef GrInOrderDrawBuffer_DEFINED
#define GrInOrderDrawBuffer_DEFINED

#include "GrDrawTarget.h"
#include "GrAllocPool.h"
#include "GrAllocator.h"
#include "GrClip.h"

class GrVertexBufferAllocPool;
class GrIndexBufferAllocPool;

/**
 * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up
 * draws for eventual playback into a GrGpu. In theory one draw buffer could
 * playback into another. When index or vertex buffers are used as geometry
 * sources it is the callers the draw buffer only holds references to the
 * buffers. It is the callers responsibility to ensure that the data is still
 * valid when the draw buffer is played back into a GrGpu. Similarly, it is the
 * caller's responsibility to ensure that all referenced textures, buffers,
 * and rendertargets are associated in the GrGpu object that the buffer is
 * played back into. The buffer requires VB and IB pools to store geometry.
 */

class GrInOrderDrawBuffer : public GrDrawTarget {
public:

    /**
     * Creates a GrInOrderDrawBuffer
     *
     * @param vertexPool pool where vertices for queued draws will be saved when
     *                   the vertex source is either reserved or array.
     * @param indexPool  pool where indices for queued draws will be saved when
     *                   the index source is either reserved or array.
     */
    GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool,
                        GrIndexBufferAllocPool* indexPool);

    virtual ~GrInOrderDrawBuffer();

    /**
     * Copies the draw state and clip from target to this draw buffer.
     *
     * @param target    the target whose clip and state should be copied.
     */
    void initializeDrawStateAndClip(const GrDrawTarget& target);

    /**
     * Provides the buffer with an index buffer that can be used for quad rendering.
     * The buffer may be able to batch consecutive drawRects if this is provided.
     * @param indexBuffer   index buffer with quad indices.
     */
    void setQuadIndexBuffer(const GrIndexBuffer* indexBuffer);

    /**
     * Empties the draw buffer of any queued up draws.
     */
    void reset();

    /**
     * plays the queued up draws to another target. Does not empty this buffer so
     * that it can be played back multiple times.
     * @param target    the target to receive the playback
     */
    void playback(GrDrawTarget* target);
    
    // overrides from GrDrawTarget
    virtual void drawIndexed(GrPrimitiveType primitiveType,
                             int startVertex,
                             int startIndex,
                             int vertexCount,
                             int indexCount);
    virtual void drawNonIndexed(GrPrimitiveType primitiveType,
                                int startVertex,
                                int vertexCount);

    virtual void drawRect(const GrRect& rect, 
                          const GrMatrix* matrix = NULL,
                          int stageEnableMask = 0,
                          const GrRect* srcRects[] = NULL,
                          const GrMatrix* srcMatrices[] = NULL);

    virtual bool geometryHints(GrVertexLayout vertexLayout,
                               int* vertexCount,
                               int* indexCount) const;

private:

    struct Draw {
        GrPrimitiveType         fPrimitiveType;
        int                     fStartVertex;
        int                     fStartIndex;
        int                     fVertexCount;
        int                     fIndexCount;
        bool                    fStateChanged;
        bool                    fClipChanged;
        GrVertexLayout          fVertexLayout;
        const GrVertexBuffer*   fVertexBuffer;
        const GrIndexBuffer*    fIndexBuffer;
    };

    virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout,
                                       void**         vertices,
                                       void**         indices);
    virtual void releaseGeometryHelper();
    virtual void clipWillBeSet(const GrClip& newClip);

    virtual void setVertexSourceToArrayHelper(const void* vertexArray,
                                              int vertexCount);

    virtual void setIndexSourceToArrayHelper(const void* indexArray,
                                             int indexCount);

    bool needsNewState() const;
    bool needsNewClip() const;

    void pushState();
    void pushClip();

    GrTAllocator<Draw>              fDraws;
    // HACK: We currently do not hold refs on RTs in the saved draw states.
    // The reason is that in the GL implementation when a GrTexture is destroyed
    // that has an associated RT the RT is destroyed regardless of its ref count.
    // We need a third object that holds the shared GL ids and persists until
    // both reach ref count 0. (skia issue 122)
    GrTAllocator<SavedDrawState>    fStates;

    GrTAllocator<GrClip>            fClips;
    bool                            fClipSet;

    GrVertexLayout                  fLastRectVertexLayout;
    const GrIndexBuffer*            fQuadIndexBuffer;
    int                             fMaxQuads;
    int                             fCurrQuad;

    GrVertexBufferAllocPool&        fVertexPool;
    const GrVertexBuffer*           fCurrPoolVertexBuffer;
    int                             fCurrPoolStartVertex;

    GrIndexBufferAllocPool&         fIndexPool;
    const GrIndexBuffer*            fCurrPoolIndexBuffer;
    int                             fCurrPoolStartIndex;

    // caller may conservatively over reserve vertices / indices.
    // we release unused space back to allocator if possible
    size_t                          fReservedVertexBytes;
    size_t                          fReservedIndexBytes;
    size_t                          fUsedReservedVertexBytes;
    size_t                          fUsedReservedIndexBytes;

    static const uint32_t           STATES_BLOCK_SIZE = 8;
    static const uint32_t           DRAWS_BLOCK_SIZE  = 8;
    static const uint32_t           CLIPS_BLOCK_SIZE  = 8;
    static const uint32_t           VERTEX_BLOCK_SIZE = 1 << 12;
    static const uint32_t           INDEX_BLOCK_SIZE  = 1 << 10;
    int8_t                          fDrawsStorage[sizeof(Draw) *
                                                  DRAWS_BLOCK_SIZE];
    int8_t                          fStatesStorage[sizeof(SavedDrawState) *
                                                   STATES_BLOCK_SIZE];
    int8_t                          fClipsStorage[sizeof(GrClip) *
                                                  CLIPS_BLOCK_SIZE];
    typedef GrDrawTarget INHERITED;
};

#endif