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