diff options
author | 2016-12-07 17:06:19 -0500 | |
---|---|---|
committer | 2016-12-07 23:36:31 +0000 | |
commit | 742e31de1599f3902810aecdf2e2e3eed3b40a09 (patch) | |
tree | bbac738ec7cecce88712ad2df993933c8888305e /src/gpu/GrOpFlushState.h | |
parent | 42521e891081a7a85db4390a457074054649f194 (diff) |
Rename GrBatchFlushState to GrOpFlushState
Change-Id: I1a8052c61d7624929caf45ba44e2a465cd0dc1c2
Reviewed-on: https://skia-review.googlesource.com/5649
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Diffstat (limited to 'src/gpu/GrOpFlushState.h')
-rw-r--r-- | src/gpu/GrOpFlushState.h | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h new file mode 100644 index 0000000000..9b8baffcb2 --- /dev/null +++ b/src/gpu/GrOpFlushState.h @@ -0,0 +1,211 @@ +/* + * 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 "GrGpu.h" +#include "batches/GrMeshDrawOp.h" + +class GrGpuCommandBuffer; +class GrResourceProvider; + +/** Tracks the state across all the GrOps (really just the GrDrawOps) in a GrOpList flush. */ +class GrOpFlushState { +public: + GrOpFlushState(GrGpu*, GrResourceProvider*); + + ~GrOpFlushState() { this->reset(); } + + /** Inserts an upload to be executed after all ops in the flush prepared their draws but before + the draws are executed to the backend 3D API. */ + void addASAPUpload(GrDrawOp::DeferredUploadFn&& upload) { + fAsapUploads.emplace_back(std::move(upload)); + } + + const GrCaps& caps() const { return *fGpu->caps(); } + GrResourceProvider* resourceProvider() const { return fResourceProvider; } + + /** Has the token been flushed to the backend 3D API. */ + bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const { + return token.fSequenceNumber <= fLastFlushedToken.fSequenceNumber; + } + + /** Issue a token to an operation that is being enqueued. */ + GrDrawOpUploadToken issueDrawToken() { + return GrDrawOpUploadToken(++fLastIssuedToken.fSequenceNumber); + } + + /** Call every time a draw that was issued a token is flushed */ + void flushToken() { ++fLastFlushedToken.fSequenceNumber; } + + /** Gets the next draw token that will be issued. */ + GrDrawOpUploadToken nextDrawToken() const { + return GrDrawOpUploadToken(fLastIssuedToken.fSequenceNumber + 1); + } + + /** The last token flushed to all the way to the backend API. */ + GrDrawOpUploadToken nextTokenToFlush() const { + return GrDrawOpUploadToken(fLastFlushedToken.fSequenceNumber + 1); + } + + void* makeVertexSpace(size_t vertexSize, int vertexCount, + const GrBuffer** buffer, int* startVertex); + uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex); + + /** This is called after each op has a chance to prepare its draws and before the draws are + issued. */ + void preIssueDraws() { + fVertexPool.unmap(); + fIndexPool.unmap(); + int uploadCount = fAsapUploads.count(); + + for (int i = 0; i < uploadCount; i++) { + this->doUpload(fAsapUploads[i]); + } + fAsapUploads.reset(); + } + + void doUpload(GrDrawOp::DeferredUploadFn& upload) { + GrDrawOp::WritePixelsFn wp = [this] (GrSurface* surface, + int left, int top, int width, int height, + GrPixelConfig config, const void* buffer, + size_t rowBytes) -> bool { + return this->fGpu->writePixels(surface, left, top, width, height, config, buffer, + rowBytes); + }; + upload(wp); + } + + void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); } + + void putBackVertexSpace(size_t sizeInBytes) { fVertexPool.putBack(sizeInBytes); } + + GrGpuCommandBuffer* commandBuffer() { return fCommandBuffer; } + void setCommandBuffer(GrGpuCommandBuffer* buffer) { fCommandBuffer = buffer; } + + GrGpu* gpu() { return fGpu; } + + void reset() { + fVertexPool.reset(); + fIndexPool.reset(); + } + +private: + + GrGpu* fGpu; + + GrResourceProvider* fResourceProvider; + + GrGpuCommandBuffer* fCommandBuffer; + + GrVertexBufferAllocPool fVertexPool; + GrIndexBufferAllocPool fIndexPool; + + SkSTArray<4, GrDrawOp::DeferredUploadFn> fAsapUploads; + + GrDrawOpUploadToken fLastIssuedToken; + + GrDrawOpUploadToken fLastFlushedToken; +}; + +/** + * A word about uploads and tokens: Ops should usually schedule their uploads to occur at the + * begining of a frame whenever possible. These are called ASAP uploads. Of course, this requires + * that there are no draws that have yet to be flushed that rely on the old texture contents. In + * that case the ASAP upload would happen prior to the previous draw causing the draw to read the + * new (wrong) texture data. In that case they should schedule an inline upload. + * + * Ops, in conjunction with helpers such as GrBatchAtlas, can use the token system to know + * what the most recent draw was that referenced a resource (or portion of a resource). Each draw + * is assigned a token. A resource (or portion) can be tagged with the most recent draw's + * token. The target provides a facility for testing whether the draw corresponding to the token + * has been flushed. If it has not been flushed then the op must perform an inline upload instead. + * When scheduling an inline upload the op provides the token of the draw that the upload must occur + * before. The upload will then occur between the draw that requires the new data but after the + * token that requires the old data. + * + * TODO: Currently the token/upload interface is spread over GrDrawOp, GrMeshDrawOp, + * GrDrawOp::Target, and GrMeshDrawOp::Target. However, the interface at the GrDrawOp level is not + * complete and isn't useful. We should push it down to GrMeshDrawOp until it is required at the + * GrDrawOp level. + */ + +/** + * GrDrawOp instances use this object to allocate space for their geometry and to issue the draws + * that render their op. + */ +class GrDrawOp::Target { +public: + Target(GrOpFlushState* state, GrDrawOp* op) : fState(state), fOp(op) {} + + /** Returns the token of the draw that this upload will occur before. */ + GrDrawOpUploadToken addInlineUpload(DeferredUploadFn&& upload) { + fOp->fInlineUploads.emplace_back(std::move(upload), fState->nextDrawToken()); + return fOp->fInlineUploads.back().fUploadBeforeToken; + } + + /** Returns the token of the draw that this upload will occur before. Since ASAP uploads + are done first during a flush, this will be the first token since the most recent + flush. */ + GrDrawOpUploadToken addAsapUpload(DeferredUploadFn&& upload) { + fState->addASAPUpload(std::move(upload)); + return fState->nextTokenToFlush(); + } + + bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const { + return fState->hasDrawBeenFlushed(token); + } + + /** Gets the next draw token that will be issued by this target. This can be used by an op + to record that the next draw it issues will use a resource (e.g. texture) while preparing + that draw. */ + GrDrawOpUploadToken nextDrawToken() const { return fState->nextDrawToken(); } + + const GrCaps& caps() const { return fState->caps(); } + + GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); } + +protected: + GrDrawOp* op() { return fOp; } + GrOpFlushState* state() { return fState; } + +private: + GrOpFlushState* fState; + GrDrawOp* fOp; +}; + +/** Extension of GrDrawOp::Target for use by GrMeshDrawOp. Adds the ability to create vertex + draws. */ +class GrMeshDrawOp::Target : public GrDrawOp::Target { +public: + Target(GrOpFlushState* state, GrMeshDrawOp* op) : INHERITED(state, op) {} + + void draw(const GrGeometryProcessor* gp, const GrMesh& mesh); + + void* makeVertexSpace(size_t vertexSize, int vertexCount, + const GrBuffer** buffer, int* startVertex) { + return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex); + } + + uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) { + return this->state()->makeIndexSpace(indexCount, buffer, startIndex); + } + + /** Helpers for ops which over-allocate and then return data to the pool. */ + void putBackIndices(int indices) { this->state()->putBackIndices(indices); } + void putBackVertices(int vertices, size_t vertexStride) { + this->state()->putBackVertexSpace(vertices * vertexStride); + } + +private: + GrMeshDrawOp* meshDrawOp() { return static_cast<GrMeshDrawOp*>(this->op()); } + typedef GrDrawOp::Target INHERITED; +}; + +#endif |