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