michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef GrInOrderDrawBuffer_DEFINED michael@0: #define GrInOrderDrawBuffer_DEFINED michael@0: michael@0: #include "GrDrawTarget.h" michael@0: #include "GrAllocPool.h" michael@0: #include "GrAllocator.h" michael@0: #include "GrPath.h" michael@0: michael@0: #include "SkClipStack.h" michael@0: #include "SkTemplates.h" michael@0: #include "SkTypes.h" michael@0: michael@0: class GrGpu; michael@0: class GrIndexBufferAllocPool; michael@0: class GrVertexBufferAllocPool; michael@0: michael@0: /** michael@0: * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up draws for eventual michael@0: * playback into a GrGpu. In theory one draw buffer could playback into another. When index or michael@0: * vertex buffers are used as geometry sources it is the callers the draw buffer only holds michael@0: * references to the buffers. It is the callers responsibility to ensure that the data is still michael@0: * valid when the draw buffer is played back into a GrGpu. Similarly, it is the caller's michael@0: * responsibility to ensure that all referenced textures, buffers, and render-targets are associated michael@0: * in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to michael@0: * store geometry. michael@0: */ michael@0: class GrInOrderDrawBuffer : public GrDrawTarget { michael@0: public: michael@0: michael@0: /** michael@0: * Creates a GrInOrderDrawBuffer michael@0: * michael@0: * @param gpu the gpu object that this draw buffer flushes to. michael@0: * @param vertexPool pool where vertices for queued draws will be saved when michael@0: * the vertex source is either reserved or array. michael@0: * @param indexPool pool where indices for queued draws will be saved when michael@0: * the index source is either reserved or array. michael@0: */ michael@0: GrInOrderDrawBuffer(GrGpu* gpu, michael@0: GrVertexBufferAllocPool* vertexPool, michael@0: GrIndexBufferAllocPool* indexPool); michael@0: michael@0: virtual ~GrInOrderDrawBuffer(); michael@0: michael@0: /** michael@0: * Empties the draw buffer of any queued up draws. This must not be called while inside an michael@0: * unbalanced pushGeometrySource(). The current draw state and clip are preserved. michael@0: */ michael@0: void reset(); michael@0: michael@0: /** michael@0: * This plays the queued up draws to its GrGpu target. It also resets this object (i.e. flushing michael@0: * is destructive). This buffer must not have an active reserved vertex or index source. Any michael@0: * reserved geometry on the target will be finalized because it's geometry source will be pushed michael@0: * before flushing and popped afterwards. michael@0: */ michael@0: void flush(); michael@0: michael@0: // tracking for draws michael@0: virtual DrawToken getCurrentDrawToken() { return DrawToken(this, fDrawID); } michael@0: michael@0: // overrides from GrDrawTarget michael@0: virtual bool geometryHints(int* vertexCount, michael@0: int* indexCount) const SK_OVERRIDE; michael@0: virtual void clear(const SkIRect* rect, michael@0: GrColor color, michael@0: bool canIgnoreRect, michael@0: GrRenderTarget* renderTarget = NULL) SK_OVERRIDE; michael@0: michael@0: virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE; michael@0: michael@0: protected: michael@0: virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE; michael@0: michael@0: private: michael@0: enum Cmd { michael@0: kDraw_Cmd = 1, michael@0: kStencilPath_Cmd = 2, michael@0: kSetState_Cmd = 3, michael@0: kSetClip_Cmd = 4, michael@0: kClear_Cmd = 5, michael@0: kCopySurface_Cmd = 6, michael@0: kDrawPath_Cmd = 7, michael@0: }; michael@0: michael@0: class DrawRecord : public DrawInfo { michael@0: public: michael@0: DrawRecord(const DrawInfo& info) : DrawInfo(info) {} michael@0: const GrVertexBuffer* fVertexBuffer; michael@0: const GrIndexBuffer* fIndexBuffer; michael@0: }; michael@0: michael@0: struct StencilPath : public ::SkNoncopyable { michael@0: StencilPath(); michael@0: michael@0: SkAutoTUnref fPath; michael@0: SkPath::FillType fFill; michael@0: }; michael@0: michael@0: struct DrawPath : public ::SkNoncopyable { michael@0: DrawPath(); michael@0: michael@0: SkAutoTUnref fPath; michael@0: SkPath::FillType fFill; michael@0: GrDeviceCoordTexture fDstCopy; michael@0: }; michael@0: michael@0: struct Clear : public ::SkNoncopyable { michael@0: Clear() : fRenderTarget(NULL) {} michael@0: ~Clear() { SkSafeUnref(fRenderTarget); } michael@0: michael@0: SkIRect fRect; michael@0: GrColor fColor; michael@0: bool fCanIgnoreRect; michael@0: GrRenderTarget* fRenderTarget; michael@0: }; michael@0: michael@0: struct CopySurface : public ::SkNoncopyable { michael@0: SkAutoTUnref fDst; michael@0: SkAutoTUnref fSrc; michael@0: SkIRect fSrcRect; michael@0: SkIPoint fDstPoint; michael@0: }; michael@0: michael@0: // overrides from GrDrawTarget michael@0: virtual void onDraw(const DrawInfo&) SK_OVERRIDE; michael@0: virtual void onDrawRect(const SkRect& rect, michael@0: const SkMatrix* matrix, michael@0: const SkRect* localRect, michael@0: const SkMatrix* localMatrix) SK_OVERRIDE; michael@0: michael@0: virtual void onStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE; michael@0: virtual void onDrawPath(const GrPath*, SkPath::FillType, michael@0: const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE; michael@0: michael@0: virtual bool onReserveVertexSpace(size_t vertexSize, michael@0: int vertexCount, michael@0: void** vertices) SK_OVERRIDE; michael@0: virtual bool onReserveIndexSpace(int indexCount, michael@0: void** indices) SK_OVERRIDE; michael@0: virtual void releaseReservedVertexSpace() SK_OVERRIDE; michael@0: virtual void releaseReservedIndexSpace() SK_OVERRIDE; michael@0: virtual void onSetVertexSourceToArray(const void* vertexArray, michael@0: int vertexCount) SK_OVERRIDE; michael@0: virtual void onSetIndexSourceToArray(const void* indexArray, michael@0: int indexCount) SK_OVERRIDE; michael@0: virtual void releaseVertexArray() SK_OVERRIDE; michael@0: virtual void releaseIndexArray() SK_OVERRIDE; michael@0: virtual void geometrySourceWillPush() SK_OVERRIDE; michael@0: virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE; michael@0: virtual void willReserveVertexAndIndexSpace(int vertexCount, michael@0: int indexCount) SK_OVERRIDE; michael@0: virtual bool onCopySurface(GrSurface* dst, michael@0: GrSurface* src, michael@0: const SkIRect& srcRect, michael@0: const SkIPoint& dstPoint) SK_OVERRIDE; michael@0: virtual bool onCanCopySurface(GrSurface* dst, michael@0: GrSurface* src, michael@0: const SkIRect& srcRect, michael@0: const SkIPoint& dstPoint) SK_OVERRIDE; michael@0: michael@0: bool quickInsideClip(const SkRect& devBounds); michael@0: michael@0: virtual void onInstantGpuTraceEvent(const char* marker) SK_OVERRIDE; michael@0: virtual void onPushGpuTraceEvent(const char* marker) SK_OVERRIDE; michael@0: virtual void onPopGpuTraceEvent() SK_OVERRIDE; michael@0: michael@0: michael@0: // Attempts to concat instances from info onto the previous draw. info must represent an michael@0: // instanced draw. The caller must have already recorded a new draw state and clip if necessary. michael@0: int concatInstancedDraw(const DrawInfo& info); michael@0: michael@0: // we lazily record state and clip changes in order to skip clips and states that have no michael@0: // effect. michael@0: bool needsNewState() const; michael@0: bool needsNewClip() const; michael@0: michael@0: // these functions record a command michael@0: void recordState(); michael@0: void recordClip(); michael@0: DrawRecord* recordDraw(const DrawInfo&); michael@0: StencilPath* recordStencilPath(); michael@0: DrawPath* recordDrawPath(); michael@0: Clear* recordClear(); michael@0: CopySurface* recordCopySurface(); michael@0: michael@0: // TODO: Use a single allocator for commands and records michael@0: enum { michael@0: kCmdPreallocCnt = 32, michael@0: kDrawPreallocCnt = 8, michael@0: kStencilPathPreallocCnt = 8, michael@0: kDrawPathPreallocCnt = 8, michael@0: kStatePreallocCnt = 8, michael@0: kClipPreallocCnt = 8, michael@0: kClearPreallocCnt = 4, michael@0: kGeoPoolStatePreAllocCnt = 4, michael@0: kCopySurfacePreallocCnt = 4, michael@0: }; michael@0: michael@0: SkSTArray fCmds; michael@0: GrSTAllocator fDraws; michael@0: GrSTAllocator fStencilPaths; michael@0: GrSTAllocator fDrawPaths; michael@0: GrSTAllocator fStates; michael@0: GrSTAllocator fClears; michael@0: GrSTAllocator fCopySurfaces; michael@0: GrSTAllocator fClips; michael@0: GrSTAllocator fClipOrigins; michael@0: michael@0: GrDrawTarget* fDstGpu; michael@0: michael@0: bool fClipSet; michael@0: michael@0: enum ClipProxyState { michael@0: kUnknown_ClipProxyState, michael@0: kValid_ClipProxyState, michael@0: kInvalid_ClipProxyState michael@0: }; michael@0: ClipProxyState fClipProxyState; michael@0: SkRect fClipProxy; michael@0: michael@0: GrVertexBufferAllocPool& fVertexPool; michael@0: michael@0: GrIndexBufferAllocPool& fIndexPool; michael@0: michael@0: struct GeometryPoolState { michael@0: const GrVertexBuffer* fPoolVertexBuffer; michael@0: int fPoolStartVertex; michael@0: const GrIndexBuffer* fPoolIndexBuffer; michael@0: int fPoolStartIndex; michael@0: // caller may conservatively over reserve vertices / indices. michael@0: // we release unused space back to allocator if possible michael@0: // can only do this if there isn't an intervening pushGeometrySource() michael@0: size_t fUsedPoolVertexBytes; michael@0: size_t fUsedPoolIndexBytes; michael@0: }; michael@0: SkSTArray fGeoPoolStateStack; michael@0: michael@0: virtual bool isIssued(uint32_t drawID) { return drawID != fDrawID; } michael@0: michael@0: bool fFlushing; michael@0: uint32_t fDrawID; michael@0: michael@0: typedef GrDrawTarget INHERITED; michael@0: }; michael@0: michael@0: #endif