| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrBatchBuffer_DEFINED |
| #define GrBatchBuffer_DEFINED |
| |
| #include "GrBufferAllocPool.h" |
| #include "GrPendingProgramElement.h" |
| #include "GrPipeline.h" |
| #include "GrGpu.h" |
| #include "GrTRecorder.h" |
| |
| /* |
| * GrBatch instances use this object to allocate space for their geometry and to issue the draws |
| * that render their batch. |
| */ |
| |
| class GrIndexBufferAllocPool; |
| class GrVertexBufferAllocPool; |
| |
| class GrBatchTarget : public SkNoncopyable { |
| public: |
| GrBatchTarget(GrGpu* gpu, |
| GrVertexBufferAllocPool* vpool, |
| GrIndexBufferAllocPool* ipool) |
| : fGpu(gpu) |
| , fVertexPool(vpool) |
| , fIndexPool(ipool) |
| , fFlushBuffer(kFlushBufferInitialSizeInBytes) |
| , fIter(fFlushBuffer) |
| , fNumberOfDraws(0) {} |
| |
| typedef GrDrawTarget::DrawInfo DrawInfo; |
| void initDraw(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline) { |
| GrNEW_APPEND_TO_RECORDER(fFlushBuffer, BufferedFlush, (primProc, pipeline)); |
| fNumberOfDraws++; |
| } |
| |
| void draw(const GrDrawTarget::DrawInfo& draw) { |
| fFlushBuffer.back().fDraws.push_back(draw); |
| } |
| |
| // TODO this is temporary until batch is everywhere |
| //void flush(); |
| void resetNumberOfDraws() { fNumberOfDraws = 0; } |
| int numberOfDraws() const { return fNumberOfDraws; } |
| void preFlush() { fIter = FlushBuffer::Iter(fFlushBuffer); } |
| void flushNext(int n) { |
| for (; n > 0; n--) { |
| SkDEBUGCODE(bool verify =) fIter.next(); |
| SkASSERT(verify); |
| GrProgramDesc desc; |
| BufferedFlush* bf = fIter.get(); |
| const GrPipeline* pipeline = bf->fPipeline; |
| const GrPrimitiveProcessor* primProc = bf->fPrimitiveProcessor.get(); |
| fGpu->buildProgramDesc(&desc, *primProc, *pipeline, bf->fBatchTracker); |
| |
| GrGpu::DrawArgs args(primProc, pipeline, &desc, &bf->fBatchTracker); |
| |
| int drawCount = bf->fDraws.count(); |
| const SkSTArray<1, DrawInfo, true>& draws = bf->fDraws; |
| for (int i = 0; i < drawCount; i++) { |
| fGpu->draw(args, draws[i]); |
| } |
| } |
| } |
| void postFlush() { SkASSERT(!fIter.next()); fFlushBuffer.reset(); } |
| |
| // TODO This goes away when everything uses batch |
| GrBatchTracker* currentBatchTracker() { |
| SkASSERT(!fFlushBuffer.empty()); |
| return &fFlushBuffer.back().fBatchTracker; |
| } |
| |
| const GrDrawTargetCaps& caps() const { return *fGpu->caps(); } |
| |
| GrVertexBufferAllocPool* vertexPool() { return fVertexPool; } |
| GrIndexBufferAllocPool* indexPool() { return fIndexPool; } |
| |
| const GrIndexBuffer* quadIndexBuffer() const { return fGpu->getQuadIndexBuffer(); } |
| |
| // A helper for draws which overallocate and then return data to the pool |
| void putBackIndices(size_t indices) { fIndexPool->putBack(indices * sizeof(uint16_t)); } |
| |
| void putBackVertices(size_t vertices, size_t vertexStride) { |
| fVertexPool->putBack(vertices * vertexStride); |
| } |
| |
| private: |
| GrGpu* fGpu; |
| GrVertexBufferAllocPool* fVertexPool; |
| GrIndexBufferAllocPool* fIndexPool; |
| |
| typedef void* TBufferAlign; // This wouldn't be enough align if a command used long double. |
| |
| struct BufferedFlush { |
| BufferedFlush(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline) |
| : fPrimitiveProcessor(primProc) |
| , fPipeline(pipeline) {} |
| typedef GrPendingProgramElement<const GrPrimitiveProcessor> ProgramPrimitiveProcessor; |
| ProgramPrimitiveProcessor fPrimitiveProcessor; |
| const GrPipeline* fPipeline; |
| GrBatchTracker fBatchTracker; |
| SkSTArray<1, DrawInfo, true> fDraws; |
| }; |
| |
| enum { |
| kFlushBufferInitialSizeInBytes = 8 * sizeof(BufferedFlush), |
| }; |
| |
| typedef GrTRecorder<BufferedFlush, TBufferAlign> FlushBuffer; |
| |
| FlushBuffer fFlushBuffer; |
| // TODO this is temporary |
| FlushBuffer::Iter fIter; |
| int fNumberOfDraws; |
| }; |
| |
| #endif |