/* * 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 GrTargetCommands_DEFINED #define GrTargetCommands_DEFINED #include "GrDrawTarget.h" #include "GrPath.h" #include "GrPendingProgramElement.h" #include "GrPrimitiveProcessor.h" #include "GrRenderTarget.h" #include "GrTRecorder.h" #include "batches/GrBatch.h" #include "SkRect.h" class GrResourceProvider; class GrBatchFlushState; // TODO: Convert all commands into GrBatch and remove this class. class GrTargetCommands : ::SkNoncopyable { public: GrTargetCommands() : fCmdBuffer(kCmdBufferInitialSizeInBytes), fLastFlushToken(0) {} class Cmd : ::SkNoncopyable { public: enum CmdType { kDrawPath_CmdType = 2, kDrawPaths_CmdType = 3, kDrawBatch_CmdType = 4, }; Cmd(CmdType type) : fType(type) #if GR_BATCH_SPEW , fUniqueID(GenID(&gUniqueID)) #endif {} virtual ~Cmd() {} virtual void execute(GrBatchFlushState*) = 0; CmdType type() const { return fType; } GrBATCH_SPEW(uint32_t uniqueID() const { return fUniqueID;} ) private: // TODO move this to a common header so it can be shared with GrBatch static uint32_t GenID(int32_t* idCounter) { uint32_t id = static_cast(sk_atomic_inc(idCounter)) + 1; if (!id) { SkFAIL("This should never wrap\n"); } return id; } CmdType fType; GrBATCH_SPEW(uint32_t fUniqueID); GrBATCH_SPEW(static int32_t gUniqueID;) }; void reset(); void flush(GrGpu*, GrResourceProvider*); private: friend class GrCommandBuilder; friend class GrBufferedDrawTarget; // This goes away when State becomes just a pipeline friend class GrReorderCommandBuilder; typedef GrGpu::DrawArgs DrawArgs; // TODO: This can be just a pipeline once paths are in batch, and it should live elsewhere struct StateForPathDraw : public SkNVRefCnt { // TODO get rid of the prim proc parameter when we use batch everywhere StateForPathDraw(const GrPrimitiveProcessor* primProc = NULL) : fPrimitiveProcessor(primProc) , fCompiled(false) {} ~StateForPathDraw() { reinterpret_cast(fPipeline.get())->~GrPipeline(); } // This function is only for getting the location in memory where we will create our // pipeline object. void* pipelineLocation() { return fPipeline.get(); } const GrPipeline* getPipeline() const { return reinterpret_cast(fPipeline.get()); } GrRenderTarget* getRenderTarget() const { return this->getPipeline()->getRenderTarget(); } const GrXferProcessor* getXferProcessor() const { return this->getPipeline()->getXferProcessor(); } void operator delete(void* p) {} void* operator new(size_t) { SkFAIL("All States are created by placement new."); return sk_malloc_throw(0); } void* operator new(size_t, void* p) { return p; } void operator delete(void* target, void* placement) { ::operator delete(target, placement); } typedef GrPendingProgramElement ProgramPrimitiveProcessor; ProgramPrimitiveProcessor fPrimitiveProcessor; SkAlignedSStorage fPipeline; GrProgramDesc fDesc; GrBatchTracker fBatchTracker; bool fCompiled; }; // TODO remove this when State is just a pipeline friend SkNVRefCnt; struct DrawPath : public Cmd { DrawPath(StateForPathDraw* state, const GrPath* path) : Cmd(kDrawPath_CmdType) , fState(SkRef(state)) , fPath(path) {} const GrPath* path() const { return fPath.get(); } void execute(GrBatchFlushState*) override; SkAutoTUnref fState; GrStencilSettings fStencilSettings; private: GrPendingIOResource fPath; }; struct DrawPaths : public Cmd { DrawPaths(StateForPathDraw* state, const GrPathRange* pathRange) : Cmd(kDrawPaths_CmdType) , fState(SkRef(state)) , fPathRange(pathRange) {} const GrPathRange* pathRange() const { return fPathRange.get(); } void execute(GrBatchFlushState*) override; SkAutoTUnref fState; char* fIndices; GrDrawTarget::PathIndexType fIndexType; float* fTransforms; GrDrawTarget::PathTransformType fTransformType; int fCount; GrStencilSettings fStencilSettings; private: GrPendingIOResource fPathRange; }; struct DrawBatch : public Cmd { DrawBatch(GrBatch* batch) : Cmd(kDrawBatch_CmdType) , fBatch(SkRef(batch)){ SkASSERT(!batch->isUsed()); } GrBatch* batch() { return fBatch; } void execute(GrBatchFlushState*) override; private: SkAutoTUnref fBatch; }; static const int kCmdBufferInitialSizeInBytes = 8 * 1024; typedef void* TCmdAlign; // This wouldn't be enough align if a command used long double. typedef GrTRecorder CmdBuffer; CmdBuffer* cmdBuffer() { return &fCmdBuffer; } CmdBuffer fCmdBuffer; GrBatchToken fLastFlushToken; }; #endif