diff options
author | 2015-03-03 09:28:16 -0800 | |
---|---|---|
committer | 2015-03-03 09:28:16 -0800 | |
commit | dad7794dcbf205a6d0f3c5c44e251897f5256f09 (patch) | |
tree | 3d2d2b06949e4a2b918dbf6d88e3c699f79f538f /src/gpu/GrInOrderDrawBuffer.h | |
parent | 47ef4d5d934bba86848aa238efab21f54a160c1a (diff) |
Split command holding object (GrTargetCommands) out of GrInOrderDrawBuffer
This is still a bit odd in that the IoDB and TargetCommands are annoyingly interwoven. This should improve a bit when batching is everywhere.
Joshua - I think you're lead on this.
Review URL: https://codereview.chromium.org/973853002
Diffstat (limited to 'src/gpu/GrInOrderDrawBuffer.h')
-rw-r--r-- | src/gpu/GrInOrderDrawBuffer.h | 304 |
1 files changed, 195 insertions, 109 deletions
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h index 5a525fdfa2..1100d95a9c 100644 --- a/src/gpu/GrInOrderDrawBuffer.h +++ b/src/gpu/GrInOrderDrawBuffer.h @@ -17,88 +17,21 @@ #include "GrPath.h" #include "GrTRecorder.h" -/** - * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up draws for eventual - * playback into a GrGpu. In theory one draw buffer could playback into another. When index or - * vertex buffers are used as geometry sources it is the callers the draw buffer only holds - * references to the buffers. It is the callers responsibility to ensure that the data is still - * valid when the draw buffer is played back into a GrGpu. Similarly, it is the caller's - * responsibility to ensure that all referenced textures, buffers, and render-targets are associated - * in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to - * store geometry. - */ -class GrInOrderDrawBuffer : public GrFlushToGpuDrawTarget { -public: - - /** - * Creates a GrInOrderDrawBuffer - * - * @param gpu the gpu object that this draw buffer flushes to. - * @param vertexPool pool where vertices for queued draws will be saved when - * the vertex source is either reserved or array. - * @param indexPool pool where indices for queued draws will be saved when - * the index source is either reserved or array. - */ - GrInOrderDrawBuffer(GrGpu* gpu, - GrVertexBufferAllocPool* vertexPool, - GrIndexBufferAllocPool* indexPool); - - ~GrInOrderDrawBuffer() SK_OVERRIDE; - - // tracking for draws - DrawToken getCurrentDrawToken() SK_OVERRIDE { return DrawToken(this, fDrawID); } - - void clearStencilClip(const SkIRect& rect, - bool insideClip, - GrRenderTarget* renderTarget) SK_OVERRIDE; +class GrInOrderDrawBuffer; - void discard(GrRenderTarget*) SK_OVERRIDE; - -protected: - void willReserveVertexAndIndexSpace(int vertexCount, - size_t vertexStride, - int indexCount); - - void appendIndicesAndTransforms(const void* indexValues, PathIndexType indexType, - const float* transformValues, PathTransformType transformType, - int count, char** indicesLocation, float** xformsLocation) { - int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType); - *indicesLocation = (char*) fPathIndexBuffer.alloc(count * indexBytes, - SkChunkAlloc::kThrow_AllocFailType); - SkASSERT(SkIsAlign4((uintptr_t)*indicesLocation)); - memcpy(*indicesLocation, reinterpret_cast<const char*>(indexValues), count * indexBytes); - - const int xformBytes = GrPathRendering::PathTransformSize(transformType) * sizeof(float); - *xformsLocation = NULL; - - if (0 != xformBytes) { - *xformsLocation = (float*) fPathTransformBuffer.alloc(count * xformBytes, - SkChunkAlloc::kThrow_AllocFailType); - SkASSERT(SkIsAlign4((uintptr_t)*xformsLocation)); - memcpy(*xformsLocation, transformValues, count * xformBytes); - } - } - - bool canConcatToIndexBuffer(const GrIndexBuffer** ib) { - const GrDrawTarget::GeometrySrcState& geomSrc = this->getGeomSrc(); - - // we only attempt to concat when reserved verts are used with a client-specified - // index buffer. To make this work with client-specified VBs we'd need to know if the VB - // was updated between draws. - if (kReserved_GeometrySrcType != geomSrc.fVertexSrc || - kBuffer_GeometrySrcType != geomSrc.fIndexSrc) { - return false; - } +class GrTargetCommands : ::SkNoncopyable { + struct SetState; - *ib = geomSrc.fIndexBuffer; - return true; +public: + GrTargetCommands(GrGpu* gpu, + GrVertexBufferAllocPool* vertexPool, + GrIndexBufferAllocPool* indexPool) + : fCmdBuffer(kCmdBufferInitialSizeInBytes) + , fPrevState(NULL) + , fBatchTarget(gpu, vertexPool, indexPool) + , fDrawBatch(NULL) { } -private: - typedef GrGpu::DrawArgs DrawArgs; - - struct SetState; - struct Cmd : ::SkNoncopyable { enum { kDraw_Cmd = 1, @@ -128,12 +61,89 @@ private: uint8_t fType; }; + void reset(); + void flush(GrInOrderDrawBuffer*); + + Cmd* recordClearStencilClip(GrInOrderDrawBuffer*, + const SkIRect& rect, + bool insideClip, + GrRenderTarget* renderTarget); + + Cmd* recordDiscard(GrInOrderDrawBuffer*, GrRenderTarget*); + + Cmd* recordDraw(GrInOrderDrawBuffer*, + const GrGeometryProcessor*, + const GrDrawTarget::DrawInfo&, + const GrDrawTarget::PipelineInfo&); + Cmd* recordDrawBatch(GrInOrderDrawBuffer*, + GrBatch*, + const GrDrawTarget::PipelineInfo&); + void recordDrawRect(GrInOrderDrawBuffer*, + GrPipelineBuilder*, + GrColor, + const SkMatrix& viewMatrix, + const SkRect& rect, + const SkRect* localRect, + const SkMatrix* localMatrix); + Cmd* recordStencilPath(GrInOrderDrawBuffer*, + const GrPipelineBuilder&, + const GrPathProcessor*, + const GrPath*, + const GrScissorState&, + const GrStencilSettings&); + Cmd* recordDrawPath(GrInOrderDrawBuffer*, + const GrPathProcessor*, + const GrPath*, + const GrStencilSettings&, + const GrDrawTarget::PipelineInfo&); + Cmd* recordDrawPaths(GrInOrderDrawBuffer*, + const GrPathProcessor*, + const GrPathRange*, + const void*, + GrDrawTarget::PathIndexType, + const float transformValues[], + GrDrawTarget::PathTransformType , + int, + const GrStencilSettings&, + const GrDrawTarget::PipelineInfo&); + Cmd* recordClear(GrInOrderDrawBuffer*, + const SkIRect* rect, + GrColor, + bool canIgnoreRect, + GrRenderTarget*); + Cmd* recordCopySurface(GrInOrderDrawBuffer*, + GrSurface* dst, + GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint); + +protected: + void willReserveVertexAndIndexSpace(int vertexCount, + size_t vertexStride, + int indexCount); + +private: + friend class GrInOrderDrawBuffer; + + typedef GrGpu::DrawArgs DrawArgs; + + // Attempts to concat instances from info onto the previous draw. info must represent an + // instanced draw. The caller must have already recorded a new draw state and clip if necessary. + int concatInstancedDraw(GrInOrderDrawBuffer*, const GrDrawTarget::DrawInfo&); + + bool SK_WARN_UNUSED_RESULT setupPipelineAndShouldDraw(GrInOrderDrawBuffer*, + const GrPrimitiveProcessor*, + const GrDrawTarget::PipelineInfo&); + bool SK_WARN_UNUSED_RESULT setupPipelineAndShouldDraw(GrInOrderDrawBuffer*, + GrBatch*, + const GrDrawTarget::PipelineInfo&); + struct Draw : public Cmd { - Draw(const DrawInfo& info) : Cmd(kDraw_Cmd), fInfo(info) {} + Draw(const GrDrawTarget::DrawInfo& info) : Cmd(kDraw_Cmd), fInfo(info) {} void execute(GrGpu*, const SetState*) SK_OVERRIDE; - DrawInfo fInfo; + GrDrawTarget::DrawInfo fInfo; }; struct StencilPath : public Cmd { @@ -175,12 +185,12 @@ private: void execute(GrGpu*, const SetState*) SK_OVERRIDE; - char* fIndices; - PathIndexType fIndexType; - float* fTransforms; - PathTransformType fTransformType; - int fCount; - GrStencilSettings fStencilSettings; + char* fIndices; + GrDrawTarget::PathIndexType fIndexType; + float* fTransforms; + GrDrawTarget::PathTransformType fTransformType; + int fCount; + GrStencilSettings fStencilSettings; private: GrPendingIOResource<const GrPathRange, kRead_GrIOType> fPathRange; @@ -276,8 +286,103 @@ private: GrBatchTarget* fBatchTarget; }; - typedef void* TCmdAlign; // This wouldn't be enough align if a command used long double. - typedef GrTRecorder<Cmd, TCmdAlign> CmdBuffer; + static const int kCmdBufferInitialSizeInBytes = 8 * 1024; + + typedef void* TCmdAlign; // This wouldn't be enough align if a command used long double. + typedef GrTRecorder<Cmd, TCmdAlign> CmdBuffer; + + CmdBuffer fCmdBuffer; + SetState* fPrevState; + GrBatchTarget fBatchTarget; + // TODO hack until batch is everywhere + GrTargetCommands::DrawBatch* fDrawBatch; + + // This will go away when everything uses batch. However, in the short term anything which + // might be put into the GrInOrderDrawBuffer needs to make sure it closes the last batch + void closeBatch(); +}; + +/** + * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up draws for eventual + * playback into a GrGpu. In theory one draw buffer could playback into another. When index or + * vertex buffers are used as geometry sources it is the callers the draw buffer only holds + * references to the buffers. It is the callers responsibility to ensure that the data is still + * valid when the draw buffer is played back into a GrGpu. Similarly, it is the caller's + * responsibility to ensure that all referenced textures, buffers, and render-targets are associated + * in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to + * store geometry. + */ +class GrInOrderDrawBuffer : public GrFlushToGpuDrawTarget { +public: + + /** + * Creates a GrInOrderDrawBuffer + * + * @param gpu the gpu object that this draw buffer flushes to. + * @param vertexPool pool where vertices for queued draws will be saved when + * the vertex source is either reserved or array. + * @param indexPool pool where indices for queued draws will be saved when + * the index source is either reserved or array. + */ + GrInOrderDrawBuffer(GrGpu* gpu, + GrVertexBufferAllocPool* vertexPool, + GrIndexBufferAllocPool* indexPool); + + ~GrInOrderDrawBuffer() SK_OVERRIDE; + + // tracking for draws + DrawToken getCurrentDrawToken() SK_OVERRIDE { return DrawToken(this, fDrawID); } + + void clearStencilClip(const SkIRect& rect, + bool insideClip, + GrRenderTarget* renderTarget) SK_OVERRIDE; + + void discard(GrRenderTarget*) SK_OVERRIDE; + +protected: + void willReserveVertexAndIndexSpace(int vertexCount, + size_t vertexStride, + int indexCount) SK_OVERRIDE; + + void appendIndicesAndTransforms(const void* indexValues, PathIndexType indexType, + const float* transformValues, PathTransformType transformType, + int count, char** indicesLocation, float** xformsLocation) { + int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType); + *indicesLocation = (char*) fPathIndexBuffer.alloc(count * indexBytes, + SkChunkAlloc::kThrow_AllocFailType); + SkASSERT(SkIsAlign4((uintptr_t)*indicesLocation)); + memcpy(*indicesLocation, reinterpret_cast<const char*>(indexValues), count * indexBytes); + + const int xformBytes = GrPathRendering::PathTransformSize(transformType) * sizeof(float); + *xformsLocation = NULL; + + if (0 != xformBytes) { + *xformsLocation = (float*) fPathTransformBuffer.alloc(count * xformBytes, + SkChunkAlloc::kThrow_AllocFailType); + SkASSERT(SkIsAlign4((uintptr_t)*xformsLocation)); + memcpy(*xformsLocation, transformValues, count * xformBytes); + } + } + + bool canConcatToIndexBuffer(const GrIndexBuffer** ib) { + const GrDrawTarget::GeometrySrcState& geomSrc = this->getGeomSrc(); + + // we only attempt to concat when reserved verts are used with a client-specified + // index buffer. To make this work with client-specified VBs we'd need to know if the VB + // was updated between draws. + if (kReserved_GeometrySrcType != geomSrc.fVertexSrc || + kBuffer_GeometrySrcType != geomSrc.fIndexSrc) { + return false; + } + + *ib = geomSrc.fIndexBuffer; + return true; + } + +private: + friend class GrTargetCommands; + + typedef GrGpu::DrawArgs DrawArgs; void onReset() SK_OVERRIDE; void onFlush() SK_OVERRIDE; @@ -323,46 +428,27 @@ private: // instanced draw. The caller must have already recorded a new draw state and clip if necessary. int concatInstancedDraw(const DrawInfo&); - // Determines whether the current draw operation requires a new GrPipeline and if so - // records it. If the draw can be skipped false is returned and no new GrPipeline is - // recorded. - // TODO delete the primproc variant when we have batches everywhere - bool SK_WARN_UNUSED_RESULT setupPipelineAndShouldDraw(const GrPrimitiveProcessor*, - const PipelineInfo&); - bool SK_WARN_UNUSED_RESULT setupPipelineAndShouldDraw(GrBatch*, const PipelineInfo&); - // We lazily record clip changes in order to skip clips that have no effect. void recordClipIfNecessary(); // Records any trace markers for a command - void recordTraceMarkersIfNecessary(Cmd*); + void recordTraceMarkersIfNecessary(GrTargetCommands::Cmd*); SkString getCmdString(int index) const { SkASSERT(index < fGpuCmdMarkers.count()); return fGpuCmdMarkers[index].toString(); } bool isIssued(uint32_t drawID) SK_OVERRIDE { return drawID != fDrawID; } - GrBatchTarget* getBatchTarget() { return &fBatchTarget; } - // TODO: Use a single allocator for commands and records enum { - kCmdBufferInitialSizeInBytes = 8 * 1024, kPathIdxBufferMinReserve = 2 * 64, // 64 uint16_t's kPathXformBufferMinReserve = 2 * 64, // 64 two-float transforms }; - CmdBuffer fCmdBuffer; - SetState* fPrevState; + GrTargetCommands fCommands; SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers; SkChunkAlloc fPathIndexBuffer; SkChunkAlloc fPathTransformBuffer; uint32_t fDrawID; - GrBatchTarget fBatchTarget; - // TODO hack until batch is everywhere - DrawBatch* fDrawBatch; - - // This will go away when everything uses batch. However, in the short term anything which - // might be put into the GrInOrderDrawBuffer needs to make sure it closes the last batch - inline void closeBatch(); typedef GrFlushToGpuDrawTarget INHERITED; }; |