blob: b20098aac759f4b04c869ead2d8e2cfc1b2e35c9 [file] [log] [blame]
/*
* 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 GrOpFlushState_DEFINED
#define GrOpFlushState_DEFINED
#include <utility>
#include "GrAppliedClip.h"
#include "GrBufferAllocPool.h"
#include "GrDeferredUpload.h"
#include "SkArenaAlloc.h"
#include "ops/GrMeshDrawOp.h"
class GrGpu;
class GrGpuCommandBuffer;
class GrGpuRTCommandBuffer;
class GrResourceProvider;
/** Tracks the state across all the GrOps (really just the GrDrawOps) in a GrOpList flush. */
class GrOpFlushState final : public GrDeferredUploadTarget, public GrMeshDrawOp::Target {
public:
GrOpFlushState(GrGpu*, GrResourceProvider*);
~GrOpFlushState() final { this->reset(); }
/** This is called after each op has a chance to prepare its draws and before the draws are
executed. */
void preExecuteDraws();
void doUpload(GrDeferredTextureUploadFn&);
/** Called as ops are executed. Must be called in the same order as the ops were prepared. */
void executeDrawsAndUploadsForMeshDrawOp(uint32_t opID, const SkRect& opBounds);
GrGpuCommandBuffer* commandBuffer() { return fCommandBuffer; }
// Helper function used by Ops that are only called via RenderTargetOpLists
GrGpuRTCommandBuffer* rtCommandBuffer();
void setCommandBuffer(GrGpuCommandBuffer* buffer) { fCommandBuffer = buffer; }
GrGpu* gpu() { return fGpu; }
void reset();
/** Additional data required on a per-op basis when executing GrOps. */
struct OpArgs {
GrRenderTarget* renderTarget() const { return fProxy->priv().peekRenderTarget(); }
GrOp* fOp;
// TODO: do we still need the dst proxy here?
GrRenderTargetProxy* fProxy;
GrAppliedClip* fAppliedClip;
GrXferProcessor::DstProxy fDstProxy;
};
void setOpArgs(OpArgs* opArgs) { fOpArgs = opArgs; }
const OpArgs& drawOpArgs() const {
SkASSERT(fOpArgs);
SkASSERT(fOpArgs->fOp);
return *fOpArgs;
}
/** Overrides of GrDeferredUploadTarget. */
GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) final;
GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&&) final;
/** Overrides of GrMeshDrawOp::Target. */
void draw(const GrGeometryProcessor*, const GrPipeline*, const GrMesh&) final;
void* makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer**,
int* startVertex) final;
uint16_t* makeIndexSpace(int indexCount, const GrBuffer**, int* startIndex) final;
void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, int fallbackVertexCount,
const GrBuffer**, int* startVertex, int* actualVertexCount) final;
uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount, const GrBuffer**,
int* startIndex, int* actualIndexCount) final;
void putBackIndices(int indexCount) final;
void putBackVertices(int vertices, size_t vertexStride) final;
GrRenderTargetProxy* proxy() const final { return fOpArgs->fProxy; }
GrAppliedClip detachAppliedClip() final;
const GrXferProcessor::DstProxy& dstProxy() const final { return fOpArgs->fDstProxy; }
GrDeferredUploadTarget* deferredUploadTarget() final { return this; }
const GrCaps& caps() const final;
GrResourceProvider* resourceProvider() const final { return fResourceProvider; }
private:
/** GrMeshDrawOp::Target override. */
SkArenaAlloc* pipelineArena() override { return &fArena; }
struct InlineUpload {
InlineUpload(GrDeferredTextureUploadFn&& upload, GrDeferredUploadToken token)
: fUpload(std::move(upload)), fUploadBeforeToken(token) {}
GrDeferredTextureUploadFn fUpload;
GrDeferredUploadToken fUploadBeforeToken;
};
// A set of contiguous draws that share a draw token, geometry processor, and pipeline. The
// meshes for the draw are stored in the fMeshes array. The reason for coalescing meshes
// that share a geometry processor into a Draw is that it allows the Gpu object to setup
// the shared state once and then issue draws for each mesh.
struct Draw {
int fMeshCnt = 0;
GrPendingProgramElement<const GrGeometryProcessor> fGeometryProcessor;
const GrPipeline* fPipeline;
uint32_t fOpID;
};
/**
* A singly linked list of Ts stored in a SkArenaAlloc. The arena rather than the list owns
* the elements. This supports forward iteration and range based for loops.
*/
template <typename T>
class List {
private:
struct Node;
public:
List() = default;
void reset() { fHead = fTail = nullptr; }
template <typename... Args>
T& append(SkArenaAlloc* arena, Args... args);
class Iter {
public:
Iter() = default;
Iter& operator++();
T& operator*() const { return fCurr->fT; }
T* operator->() const { return &fCurr->fT; }
bool operator==(const Iter& that) const { return fCurr == that.fCurr; }
bool operator!=(const Iter& that) const { return !(*this == that); }
private:
friend class List;
explicit Iter(Node* node) : fCurr(node) {}
Node* fCurr = nullptr;
};
Iter begin() { return Iter(fHead); }
Iter end() { return Iter(); }
Iter tail() { return Iter(fTail); }
private:
struct Node {
template <typename... Args>
Node(Args... args) : fT(std::forward<Args>(args)...) {}
T fT;
Node* fNext = nullptr;
};
Node* fHead = nullptr;
Node* fTail = nullptr;
};
// Storage for ops' pipelines, draws, and inline uploads.
SkArenaAlloc fArena{sizeof(GrPipeline) * 100};
// Store vertex and index data on behalf of ops that are flushed.
GrVertexBufferAllocPool fVertexPool;
GrIndexBufferAllocPool fIndexPool;
// Data stored on behalf of the ops being flushed.
List<GrDeferredTextureUploadFn> fAsapUploads;
List<InlineUpload> fInlineUploads;
List<Draw> fDraws;
// TODO: These should go in the arena. However, GrGpuCommandBuffer and other classes currently
// accept contiguous arrays of meshes.
SkSTArray<16, GrMesh> fMeshes;
// All draws we store have an implicit draw token. This is the draw token for the first draw
// in fDraws.
GrDeferredUploadToken fBaseDrawToken = GrDeferredUploadToken::AlreadyFlushedToken();
// Info about the op that is currently preparing or executing using the flush state or null if
// an op is not currently preparing of executing.
OpArgs* fOpArgs = nullptr;
GrGpu* fGpu;
GrResourceProvider* fResourceProvider;
GrGpuCommandBuffer* fCommandBuffer = nullptr;
// Variables that are used to track where we are in lists as ops are executed
List<Draw>::Iter fCurrDraw;
int fCurrMesh;
List<InlineUpload>::Iter fCurrUpload;
};
#endif