/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef gr_instanced_InstancedRendering_DEFINED #define gr_instanced_InstancedRendering_DEFINED #include "GrGpu.h" #include "instanced/InstancedOp.h" #include "instanced/InstancedRenderingTypes.h" #include "SkTInternalLList.h" class GrResourceProvider; namespace gr_instanced { class InstancedOp; class InstanceProcessor; /** * Instanced Rendering occurs through the interaction of four class: * InstancedOp * OpAllocator * InstancedRendering * InstanceProcessor * * The InstancedOp is a GrDrawOp but is more of a proxy than normal operations. It accumulates a * LL of Draw objects that are allocated all together by the OpAllocator. * * There is only one OpAllocator which encapsulates the creation of InstancedOps and the pool * of memory used for their Draw objects. * * The InstancedRendering class tracks a list of InstancedOps that will all be drawn during * the same flush. There is currently one per opList. The nature of instanced * rendering allows these ops to combine well and render efficiently. * During a flush, it assembles the accumulated draw data into a single vertex and texel * buffer per opList, and its subclasses draw the ops using backend-specific instanced * rendering APIs. * * InstanceProcessors implement the shaders required for instance rendering. */ class InstancedRendering : public SkNoncopyable { public: virtual ~InstancedRendering() { SkASSERT(State::kRecordingDraws == fState); } GrGpu* gpu() const { return fGpu.get(); } /** * Compiles all recorded draws into GPU buffers and allows the client to begin flushing the * ops created by this class. */ void beginFlush(GrResourceProvider*); void draw(const GrPipeline& pipeline, OpInfo info, const InstancedOp* baseOp); /** * Called once the ops created previously by this class have all been released. Allows the * client to begin recording draws again. */ void endFlush(); enum class ResetType : bool { kDestroy, kAbandon }; /** * Resets all GPU resources, including those that are held long term. They will be lazily * reinitialized if the class begins to be used again. */ void resetGpuResources(ResetType); void addOp(InstancedOp* op) { fTrackedOps.addToTail(op); } void removeOp(InstancedOp* op) { fTrackedOps.remove(op); } int addOpParams(InstancedOp* op); #ifdef SK_DEBUG bool isFlushing() const { return InstancedRendering::State::kFlushing == fState; } #endif protected: typedef SkTInternalLList OpList; InstancedRendering(GrGpu* gpu); const OpList& trackedOps() const { return fTrackedOps; } const GrBuffer* vertexBuffer() const { SkASSERT(fVertexBuffer); return fVertexBuffer.get(); } const GrBuffer* indexBuffer() const { SkASSERT(fIndexBuffer); return fIndexBuffer.get(); } virtual void onBeginFlush(GrResourceProvider*) = 0; virtual void onDraw(const GrPipeline&, const InstanceProcessor&, const InstancedOp*) = 0; virtual void onEndFlush() = 0; virtual void onResetGpuResources(ResetType) = 0; private: #ifdef SK_DEBUG enum class State : bool { kRecordingDraws, kFlushing }; #endif const sk_sp fGpu; SkDEBUGCODE(State fState;) SkSTArray<1024, ParamsTexel, true> fParams; OpList fTrackedOps; sk_sp fVertexBuffer; sk_sp fIndexBuffer; sk_sp fParamsBuffer; }; } #endif