2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrInOrderDrawBuffer_DEFINED
9 #define GrInOrderDrawBuffer_DEFINED
11 #include "GrDrawTarget.h"
12 #include "GrAllocPool.h"
13 #include "GrAllocator.h"
14 #include "GrIndexBuffer.h"
15 #include "GrRenderTarget.h"
17 #include "GrPathRange.h"
18 #include "GrSurface.h"
19 #include "GrTRecorder.h"
20 #include "GrVertexBuffer.h"
22 #include "SkClipStack.h"
23 #include "SkTemplates.h"
27 class GrIndexBufferAllocPool;
28 class GrVertexBufferAllocPool;
31 * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up draws for eventual
32 * playback into a GrGpu. In theory one draw buffer could playback into another. When index or
33 * vertex buffers are used as geometry sources it is the callers the draw buffer only holds
34 * references to the buffers. It is the callers responsibility to ensure that the data is still
35 * valid when the draw buffer is played back into a GrGpu. Similarly, it is the caller's
36 * responsibility to ensure that all referenced textures, buffers, and render-targets are associated
37 * in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to
40 class GrInOrderDrawBuffer : public GrClipTarget {
44 * Creates a GrInOrderDrawBuffer
46 * @param gpu the gpu object that this draw buffer flushes to.
47 * @param vertexPool pool where vertices for queued draws will be saved when
48 * the vertex source is either reserved or array.
49 * @param indexPool pool where indices for queued draws will be saved when
50 * the index source is either reserved or array.
52 GrInOrderDrawBuffer(GrGpu* gpu,
53 GrVertexBufferAllocPool* vertexPool,
54 GrIndexBufferAllocPool* indexPool);
56 virtual ~GrInOrderDrawBuffer();
59 * Empties the draw buffer of any queued up draws. This must not be called while inside an
60 * unbalanced pushGeometrySource(). The current draw state and clip are preserved.
65 * This plays the queued up draws to its GrGpu target. It also resets this object (i.e. flushing
66 * is destructive). This buffer must not have an active reserved vertex or index source. Any
67 * reserved geometry on the target will be finalized because it's geometry source will be pushed
68 * before flushing and popped afterwards.
73 virtual DrawToken getCurrentDrawToken() { return DrawToken(this, fDrawID); }
75 // overrides from GrDrawTarget
76 virtual bool geometryHints(int* vertexCount,
77 int* indexCount) const SK_OVERRIDE;
79 virtual bool copySurface(GrSurface* dst,
81 const SkIRect& srcRect,
82 const SkIPoint& dstPoint) SK_OVERRIDE;
84 virtual bool canCopySurface(GrSurface* dst,
86 const SkIRect& srcRect,
87 const SkIPoint& dstPoint) SK_OVERRIDE;
89 virtual void clearStencilClip(const SkIRect& rect,
91 GrRenderTarget* renderTarget) SK_OVERRIDE;
93 virtual void discard(GrRenderTarget*) SK_OVERRIDE;
95 virtual void initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) SK_OVERRIDE;
98 virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE;
103 kStencilPath_Cmd = 2,
107 kCopySurface_Cmd = 6,
112 struct Cmd : ::SkNoncopyable {
113 Cmd(uint8_t type) : fType(type) {}
116 virtual void execute(GrClipTarget*) = 0;
121 struct Draw : public Cmd {
122 Draw(const DrawInfo& info, const GrVertexBuffer* vb, const GrIndexBuffer* ib)
126 , fIndexBuffer(ib) {}
128 const GrVertexBuffer* vertexBuffer() const { return fVertexBuffer.get(); }
129 const GrIndexBuffer* indexBuffer() const { return fIndexBuffer.get(); }
131 virtual void execute(GrClipTarget*);
136 GrPendingIOResource<const GrVertexBuffer, kRead_GrIOType> fVertexBuffer;
137 GrPendingIOResource<const GrIndexBuffer, kRead_GrIOType> fIndexBuffer;
140 struct StencilPath : public Cmd {
141 StencilPath(const GrPath* path) : Cmd(kStencilPath_Cmd), fPath(path) {}
143 const GrPath* path() const { return fPath.get(); }
145 virtual void execute(GrClipTarget*);
147 GrPathRendering::FillType fFill;
150 GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
153 struct DrawPath : public Cmd {
154 DrawPath(const GrPath* path) : Cmd(kDrawPath_Cmd), fPath(path) {}
156 const GrPath* path() const { return fPath.get(); }
158 virtual void execute(GrClipTarget*);
160 GrPathRendering::FillType fFill;
161 GrDeviceCoordTexture fDstCopy;
164 GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
167 struct DrawPaths : public Cmd {
168 DrawPaths(const GrPathRange* pathRange) : Cmd(kDrawPaths_Cmd), fPathRange(pathRange) {}
170 const GrPathRange* pathRange() const { return fPathRange.get(); }
171 uint32_t* indices() { return reinterpret_cast<uint32_t*>(CmdBuffer::GetDataForItem(this)); }
172 float* transforms() { return reinterpret_cast<float*>(&this->indices()[fCount]); }
174 virtual void execute(GrClipTarget*);
177 PathTransformType fTransformsType;
178 GrPathRendering::FillType fFill;
179 GrDeviceCoordTexture fDstCopy;
182 GrPendingIOResource<const GrPathRange, kRead_GrIOType> fPathRange;
185 // This is also used to record a discard by setting the color to GrColor_ILLEGAL
186 struct Clear : public Cmd {
187 Clear(GrRenderTarget* rt) : Cmd(kClear_Cmd), fRenderTarget(rt) {}
189 GrRenderTarget* renderTarget() const { return fRenderTarget.get(); }
191 virtual void execute(GrClipTarget*);
198 GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
201 // This command is ONLY used by the clip mask manager to clear the stencil clip bits
202 struct ClearStencilClip : public Cmd {
203 ClearStencilClip(GrRenderTarget* rt) : Cmd(kClear_Cmd), fRenderTarget(rt) {}
205 GrRenderTarget* renderTarget() const { return fRenderTarget.get(); }
207 virtual void execute(GrClipTarget*);
213 GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
216 struct CopySurface : public Cmd {
217 CopySurface(GrSurface* dst, GrSurface* src) : Cmd(kCopySurface_Cmd), fDst(dst), fSrc(src) {}
219 GrSurface* dst() const { return fDst.get(); }
220 GrSurface* src() const { return fSrc.get(); }
222 virtual void execute(GrClipTarget*);
228 GrPendingIOResource<GrSurface, kWrite_GrIOType> fDst;
229 GrPendingIOResource<GrSurface, kRead_GrIOType> fSrc;
232 struct SetState : public Cmd {
233 SetState(const GrDrawState& state) : Cmd(kSetState_Cmd), fState(state) {}
235 virtual void execute(GrClipTarget*);
240 struct SetClip : public Cmd {
241 SetClip(const GrClipData* clipData)
243 fStackStorage(*clipData->fClipStack) {
244 fClipData.fClipStack = &fStackStorage;
245 fClipData.fOrigin = clipData->fOrigin;
248 virtual void execute(GrClipTarget*);
250 GrClipData fClipData;
253 SkClipStack fStackStorage;
256 typedef void* TCmdAlign; // This wouldn't be enough align if a command used long double.
257 typedef GrTRecorder<Cmd, TCmdAlign> CmdBuffer;
259 // overrides from GrDrawTarget
260 virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
261 virtual void onDrawRect(const SkRect& rect,
262 const SkRect* localRect,
263 const SkMatrix* localMatrix) SK_OVERRIDE;
265 virtual void onStencilPath(const GrPath*, GrPathRendering::FillType) SK_OVERRIDE;
266 virtual void onDrawPath(const GrPath*, GrPathRendering::FillType,
267 const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
268 virtual void onDrawPaths(const GrPathRange*,
269 const uint32_t indices[], int count,
270 const float transforms[], PathTransformType,
271 GrPathRendering::FillType, const GrDeviceCoordTexture*) SK_OVERRIDE;
272 virtual void onClear(const SkIRect* rect,
275 GrRenderTarget* renderTarget) SK_OVERRIDE;
277 virtual bool onReserveVertexSpace(size_t vertexSize,
279 void** vertices) SK_OVERRIDE;
280 virtual bool onReserveIndexSpace(int indexCount,
281 void** indices) SK_OVERRIDE;
282 virtual void releaseReservedVertexSpace() SK_OVERRIDE;
283 virtual void releaseReservedIndexSpace() SK_OVERRIDE;
284 virtual void geometrySourceWillPush() SK_OVERRIDE;
285 virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE;
286 virtual void willReserveVertexAndIndexSpace(int vertexCount,
287 int indexCount) SK_OVERRIDE;
289 bool quickInsideClip(const SkRect& devBounds);
291 virtual void didAddGpuTraceMarker() SK_OVERRIDE {}
292 virtual void didRemoveGpuTraceMarker() SK_OVERRIDE {}
294 // Attempts to concat instances from info onto the previous draw. info must represent an
295 // instanced draw. The caller must have already recorded a new draw state and clip if necessary.
296 int concatInstancedDraw(const DrawInfo& info);
298 // Determines whether the current draw operation requieres a new drawstate and if so records it.
299 void recordStateIfNecessary();
300 // We lazily record clip changes in order to skip clips that have no effect.
301 void recordClipIfNecessary();
302 // Records any trace markers for a command after adding it to the buffer.
303 void recordTraceMarkersIfNecessary();
305 virtual bool isIssued(uint32_t drawID) { return drawID != fDrawID; }
307 // TODO: Use a single allocator for commands and records
309 kCmdBufferInitialSizeInBytes = 64 * 1024,
310 kGeoPoolStatePreAllocCnt = 4,
313 CmdBuffer fCmdBuffer;
314 GrDrawState* fLastState;
315 GrClipData* fLastClip;
317 SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers;
318 GrClipTarget* fDstGpu;
321 enum ClipProxyState {
322 kUnknown_ClipProxyState,
323 kValid_ClipProxyState,
324 kInvalid_ClipProxyState
327 ClipProxyState fClipProxyState;
329 GrVertexBufferAllocPool& fVertexPool;
330 GrIndexBufferAllocPool& fIndexPool;
332 struct GeometryPoolState {
333 const GrVertexBuffer* fPoolVertexBuffer;
334 int fPoolStartVertex;
335 const GrIndexBuffer* fPoolIndexBuffer;
337 // caller may conservatively over reserve vertices / indices.
338 // we release unused space back to allocator if possible
339 // can only do this if there isn't an intervening pushGeometrySource()
340 size_t fUsedPoolVertexBytes;
341 size_t fUsedPoolIndexBytes;
344 typedef SkSTArray<kGeoPoolStatePreAllocCnt, GeometryPoolState> GeoPoolStateStack;
346 GeoPoolStateStack fGeoPoolStateStack;
350 typedef GrClipTarget INHERITED;