Home | History | Annotate | Download | only in gpu
      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 
     23 class GrGpu;
     24 class GrIndexBufferAllocPool;
     25 class 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  */
     37 class GrInOrderDrawBuffer : public GrDrawTarget {
     38 public:
     39 
     40     /**
     41      * Creates a GrInOrderDrawBuffer
     42      *
     43      * @param gpu        the gpu object where this will be played back
     44      *                   (possible indirectly). GrResources used with the draw
     45      *                   buffer are created by this gpu object.
     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(const 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 another 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      * @return false if the playback trivially drew nothing because nothing was recorded.
     70      *
     71      * @param target    the target to receive the playback
     72      */
     73     bool flushTo(GrDrawTarget* target);
     74 
     75     /**
     76      * This function allows the draw buffer to automatically flush itself to another target. This
     77      * means the buffer may internally call this->flushTo(target) when it is safe to do so.
     78      *
     79      * When the auto flush target is set to NULL (as it initially is) the draw buffer will never
     80      * automatically flush itself.
     81      */
     82     void setAutoFlushTarget(GrDrawTarget* target);
     83 
     84     // overrides from GrDrawTarget
     85     virtual bool geometryHints(size_t vertexSize,
     86                                int* vertexCount,
     87                                int* indexCount) const SK_OVERRIDE;
     88     virtual void clear(const GrIRect* rect,
     89                        GrColor color,
     90                        GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
     91     virtual void drawRect(const GrRect& rect,
     92                           const SkMatrix* matrix,
     93                           const GrRect* srcRects[],
     94                           const SkMatrix* srcMatrices[]) SK_OVERRIDE;
     95 
     96 protected:
     97     virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE;
     98 
     99 private:
    100     enum Cmd {
    101         kDraw_Cmd           = 1,
    102         kStencilPath_Cmd    = 2,
    103         kSetState_Cmd       = 3,
    104         kSetClip_Cmd        = 4,
    105         kClear_Cmd          = 5,
    106     };
    107 
    108     class DrawRecord : public DrawInfo {
    109     public:
    110         DrawRecord(const DrawInfo& info) : DrawInfo(info) {}
    111         GrVertexLayout          fVertexLayout;
    112         const GrVertexBuffer*   fVertexBuffer;
    113         const GrIndexBuffer*    fIndexBuffer;
    114     };
    115 
    116     struct StencilPath {
    117         StencilPath();
    118 
    119         SkAutoTUnref<const GrPath>  fPath;
    120         SkStrokeRec                 fStroke;
    121         SkPath::FillType            fFill;
    122     };
    123 
    124     struct Clear {
    125         Clear() : fRenderTarget(NULL) {}
    126         ~Clear() { GrSafeUnref(fRenderTarget); }
    127 
    128         GrIRect         fRect;
    129         GrColor         fColor;
    130         GrRenderTarget* fRenderTarget;
    131     };
    132 
    133     // overrides from GrDrawTarget
    134     virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
    135     virtual void onStencilPath(const GrPath*, const SkStrokeRec& stroke, SkPath::FillType) SK_OVERRIDE;
    136     virtual bool onReserveVertexSpace(size_t vertexSize,
    137                                       int vertexCount,
    138                                       void** vertices) SK_OVERRIDE;
    139     virtual bool onReserveIndexSpace(int indexCount,
    140                                      void** indices) SK_OVERRIDE;
    141     virtual void releaseReservedVertexSpace() SK_OVERRIDE;
    142     virtual void releaseReservedIndexSpace() SK_OVERRIDE;
    143     virtual void onSetVertexSourceToArray(const void* vertexArray,
    144                                           int vertexCount) SK_OVERRIDE;
    145     virtual void onSetIndexSourceToArray(const void* indexArray,
    146                                          int indexCount) SK_OVERRIDE;
    147     virtual void releaseVertexArray() SK_OVERRIDE;
    148     virtual void releaseIndexArray() SK_OVERRIDE;
    149     virtual void geometrySourceWillPush() SK_OVERRIDE;
    150     virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE;
    151     virtual void willReserveVertexAndIndexSpace(size_t vertexSize,
    152                                                 int vertexCount,
    153                                                 int indexCount) SK_OVERRIDE;
    154     bool quickInsideClip(const SkRect& devBounds);
    155 
    156     // Attempts to concat instances from info onto the previous draw. info must represent an
    157     // instanced draw. The caller must have already recorded a new draw state and clip if necessary.
    158     int concatInstancedDraw(const DrawInfo& info);
    159 
    160     // we lazily record state and clip changes in order to skip clips and states that have no
    161     // effect.
    162     bool needsNewState() const;
    163     bool needsNewClip() const;
    164 
    165     // these functions record a command
    166     void            recordState();
    167     void            recordClip();
    168     DrawRecord*     recordDraw(const DrawInfo&);
    169     StencilPath*    recordStencilPath();
    170     Clear*          recordClear();
    171 
    172     enum {
    173         kCmdPreallocCnt          = 32,
    174         kDrawPreallocCnt         = 8,
    175         kStencilPathPreallocCnt  = 8,
    176         kStatePreallocCnt        = 8,
    177         kClipPreallocCnt         = 8,
    178         kClearPreallocCnt        = 4,
    179         kGeoPoolStatePreAllocCnt = 4,
    180     };
    181 
    182     SkAutoTUnref<const GrGpu> fGpu;
    183 
    184     SkSTArray<kCmdPreallocCnt, uint8_t, true>                          fCmds;
    185     GrSTAllocator<kDrawPreallocCnt, DrawRecord>                        fDraws;
    186     GrSTAllocator<kStatePreallocCnt, StencilPath>                      fStencilPaths;
    187     GrSTAllocator<kStatePreallocCnt, GrDrawState::DeferredState>       fStates;
    188     GrSTAllocator<kClearPreallocCnt, Clear>                            fClears;
    189 
    190     GrSTAllocator<kClipPreallocCnt, SkClipStack>        fClips;
    191     GrSTAllocator<kClipPreallocCnt, SkIPoint>           fClipOrigins;
    192 
    193     GrDrawTarget*                   fAutoFlushTarget;
    194 
    195     bool                            fClipSet;
    196 
    197     enum ClipProxyState {
    198         kUnknown_ClipProxyState,
    199         kValid_ClipProxyState,
    200         kInvalid_ClipProxyState
    201     };
    202     ClipProxyState                  fClipProxyState;
    203     SkRect                          fClipProxy;
    204 
    205     GrVertexBufferAllocPool&        fVertexPool;
    206 
    207     GrIndexBufferAllocPool&         fIndexPool;
    208 
    209     struct GeometryPoolState {
    210         const GrVertexBuffer*           fPoolVertexBuffer;
    211         int                             fPoolStartVertex;
    212         const GrIndexBuffer*            fPoolIndexBuffer;
    213         int                             fPoolStartIndex;
    214         // caller may conservatively over reserve vertices / indices.
    215         // we release unused space back to allocator if possible
    216         // can only do this if there isn't an intervening pushGeometrySource()
    217         size_t                          fUsedPoolVertexBytes;
    218         size_t                          fUsedPoolIndexBytes;
    219     };
    220     SkSTArray<kGeoPoolStatePreAllocCnt, GeometryPoolState> fGeoPoolStateStack;
    221 
    222     bool                            fFlushing;
    223 
    224     typedef GrDrawTarget INHERITED;
    225 };
    226 
    227 #endif
    228