aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrOpFlushState.h
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2016-12-07 17:06:19 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-12-07 23:36:31 +0000
commit742e31de1599f3902810aecdf2e2e3eed3b40a09 (patch)
treebbac738ec7cecce88712ad2df993933c8888305e /src/gpu/GrOpFlushState.h
parent42521e891081a7a85db4390a457074054649f194 (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.h211
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