1
2/*
3 * Copyright 2011 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 GrInOrderDrawBuffer_DEFINED
12#define GrInOrderDrawBuffer_DEFINED
13
14#include "GrDrawTarget.h"
15#include "GrAllocPool.h"
16#include "GrAllocator.h"
17#include "GrPath.h"
18
19#include "SkClipStack.h"
20#include "SkStrokeRec.h"
21#include "SkTemplates.h"
22
23class GrGpu;
24class GrIndexBufferAllocPool;
25class GrVertexBufferAllocPool;
26
27/**
28 * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up draws for eventual
29 * playback into a GrGpu. In theory one draw buffer could playback into another. When index or
30 * vertex buffers are used as geometry sources it is the callers the draw buffer only holds
31 * references to the buffers. It is the callers responsibility to ensure that the data is still
32 * valid when the draw buffer is played back into a GrGpu. Similarly, it is the caller's
33 * responsibility to ensure that all referenced textures, buffers, and render-targets are associated
34 * in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to
35 * store geometry.
36 */
37class GrInOrderDrawBuffer : public GrDrawTarget {
38public:
39
40    /**
41     * Creates a GrInOrderDrawBuffer
42     *
43     * @param gpu        the gpu object that this draw buffer flushes to.
44     * @param vertexPool pool where vertices for queued draws will be saved when
45     *                   the vertex source is either reserved or array.
46     * @param indexPool  pool where indices for queued draws will be saved when
47     *                   the index source is either reserved or array.
48     */
49    GrInOrderDrawBuffer(GrGpu* gpu,
50                        GrVertexBufferAllocPool* vertexPool,
51                        GrIndexBufferAllocPool* indexPool);
52
53    virtual ~GrInOrderDrawBuffer();
54
55    /**
56     * Empties the draw buffer of any queued up draws. This must not be called while inside an
57     * unbalanced pushGeometrySource(). The current draw state and clip are preserved.
58     */
59    void reset();
60
61    /**
62     * This plays the queued up draws to its GrGpu target. It also resets this object (i.e. flushing
63     * is destructive). This buffer must not have an active reserved vertex or index source. Any
64     * reserved geometry on the target will be finalized because it's geometry source will be pushed
65     * before flushing and popped afterwards.
66     */
67    void flush();
68
69    // overrides from GrDrawTarget
70    virtual bool geometryHints(int* vertexCount,
71                               int* indexCount) const SK_OVERRIDE;
72    virtual void clear(const SkIRect* rect,
73                       GrColor color,
74                       GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
75
76    virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE;
77
78
79protected:
80    virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE;
81
82private:
83    enum Cmd {
84        kDraw_Cmd           = 1,
85        kStencilPath_Cmd    = 2,
86        kSetState_Cmd       = 3,
87        kSetClip_Cmd        = 4,
88        kClear_Cmd          = 5,
89        kCopySurface_Cmd    = 6,
90    };
91
92    class DrawRecord : public DrawInfo {
93    public:
94        DrawRecord(const DrawInfo& info) : DrawInfo(info) {}
95        const GrVertexBuffer*   fVertexBuffer;
96        const GrIndexBuffer*    fIndexBuffer;
97    };
98
99    struct StencilPath : GrNoncopyable {
100        StencilPath();
101
102        SkAutoTUnref<const GrPath>  fPath;
103        SkStrokeRec                 fStroke;
104        SkPath::FillType            fFill;
105    };
106
107    struct Clear  : GrNoncopyable {
108        Clear() : fRenderTarget(NULL) {}
109        ~Clear() { GrSafeUnref(fRenderTarget); }
110
111        SkIRect         fRect;
112        GrColor         fColor;
113        GrRenderTarget* fRenderTarget;
114    };
115
116    struct CopySurface  : GrNoncopyable {
117        SkAutoTUnref<GrSurface> fDst;
118        SkAutoTUnref<GrSurface> fSrc;
119        SkIRect                 fSrcRect;
120        SkIPoint                fDstPoint;
121    };
122
123    // overrides from GrDrawTarget
124    virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
125    virtual void onDrawRect(const SkRect& rect,
126                            const SkMatrix* matrix,
127                            const SkRect* localRect,
128                            const SkMatrix* localMatrix) SK_OVERRIDE;
129    virtual void onStencilPath(const GrPath*, const SkStrokeRec& stroke, SkPath::FillType) SK_OVERRIDE;
130    virtual bool onReserveVertexSpace(size_t vertexSize,
131                                      int vertexCount,
132                                      void** vertices) SK_OVERRIDE;
133    virtual bool onReserveIndexSpace(int indexCount,
134                                     void** indices) SK_OVERRIDE;
135    virtual void releaseReservedVertexSpace() SK_OVERRIDE;
136    virtual void releaseReservedIndexSpace() SK_OVERRIDE;
137    virtual void onSetVertexSourceToArray(const void* vertexArray,
138                                          int vertexCount) SK_OVERRIDE;
139    virtual void onSetIndexSourceToArray(const void* indexArray,
140                                         int indexCount) SK_OVERRIDE;
141    virtual void releaseVertexArray() SK_OVERRIDE;
142    virtual void releaseIndexArray() SK_OVERRIDE;
143    virtual void geometrySourceWillPush() SK_OVERRIDE;
144    virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE;
145    virtual void willReserveVertexAndIndexSpace(int vertexCount,
146                                                int indexCount) SK_OVERRIDE;
147    virtual bool onCopySurface(GrSurface* dst,
148                               GrSurface* src,
149                               const SkIRect& srcRect,
150                               const SkIPoint& dstPoint)  SK_OVERRIDE;
151    virtual bool onCanCopySurface(GrSurface* dst,
152                                  GrSurface* src,
153                                  const SkIRect& srcRect,
154                                  const SkIPoint& dstPoint) SK_OVERRIDE;
155
156    bool quickInsideClip(const SkRect& devBounds);
157
158    // Attempts to concat instances from info onto the previous draw. info must represent an
159    // instanced draw. The caller must have already recorded a new draw state and clip if necessary.
160    int concatInstancedDraw(const DrawInfo& info);
161
162    // we lazily record state and clip changes in order to skip clips and states that have no
163    // effect.
164    bool needsNewState() const;
165    bool needsNewClip() const;
166
167    // these functions record a command
168    void            recordState();
169    void            recordClip();
170    DrawRecord*     recordDraw(const DrawInfo&);
171    StencilPath*    recordStencilPath();
172    Clear*          recordClear();
173    CopySurface*    recordCopySurface();
174
175    // TODO: Use a single allocator for commands and records
176    enum {
177        kCmdPreallocCnt          = 32,
178        kDrawPreallocCnt         = 8,
179        kStencilPathPreallocCnt  = 8,
180        kStatePreallocCnt        = 8,
181        kClipPreallocCnt         = 8,
182        kClearPreallocCnt        = 4,
183        kGeoPoolStatePreAllocCnt = 4,
184        kCopySurfacePreallocCnt  = 4,
185    };
186
187    SkSTArray<kCmdPreallocCnt, uint8_t, true>                          fCmds;
188    GrSTAllocator<kDrawPreallocCnt, DrawRecord>                        fDraws;
189    GrSTAllocator<kStatePreallocCnt, StencilPath>                      fStencilPaths;
190    GrSTAllocator<kStatePreallocCnt, GrDrawState::DeferredState>       fStates;
191    GrSTAllocator<kClearPreallocCnt, Clear>                            fClears;
192    GrSTAllocator<kCopySurfacePreallocCnt, CopySurface>                fCopySurfaces;
193    GrSTAllocator<kClipPreallocCnt, SkClipStack>                       fClips;
194    GrSTAllocator<kClipPreallocCnt, SkIPoint>                          fClipOrigins;
195
196    GrDrawTarget*                   fDstGpu;
197
198    bool                            fClipSet;
199
200    enum ClipProxyState {
201        kUnknown_ClipProxyState,
202        kValid_ClipProxyState,
203        kInvalid_ClipProxyState
204    };
205    ClipProxyState                  fClipProxyState;
206    SkRect                          fClipProxy;
207
208    GrVertexBufferAllocPool&        fVertexPool;
209
210    GrIndexBufferAllocPool&         fIndexPool;
211
212    struct GeometryPoolState {
213        const GrVertexBuffer*           fPoolVertexBuffer;
214        int                             fPoolStartVertex;
215        const GrIndexBuffer*            fPoolIndexBuffer;
216        int                             fPoolStartIndex;
217        // caller may conservatively over reserve vertices / indices.
218        // we release unused space back to allocator if possible
219        // can only do this if there isn't an intervening pushGeometrySource()
220        size_t                          fUsedPoolVertexBytes;
221        size_t                          fUsedPoolIndexBytes;
222    };
223    SkSTArray<kGeoPoolStatePreAllocCnt, GeometryPoolState> fGeoPoolStateStack;
224
225    bool                            fFlushing;
226
227    typedef GrDrawTarget INHERITED;
228};
229
230#endif
231