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