/* * 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 "GrBatch.h" #include "GrBatchTarget.h" #include "GrDrawTarget.h" #include "GrGpu.h" #include "GrPath.h" #include "GrPendingProgramElement.h" #include "GrRenderTarget.h" #include "GrTRecorder.h" #include "SkRect.h" #include "SkTypes.h" class GrInOrderDrawBuffer; class GrTargetCommands : ::SkNoncopyable { public: GrTargetCommands(GrGpu* gpu) : fCmdBuffer(kCmdBufferInitialSizeInBytes) , fBatchTarget(gpu) { } class Cmd : ::SkNoncopyable { public: enum CmdType { kStencilPath_CmdType = 1, kSetState_CmdType = 2, kClear_CmdType = 3, kClearStencil_CmdType = 4, kCopySurface_CmdType = 5, kDrawPath_CmdType = 6, kDrawPaths_CmdType = 7, kDrawBatch_CmdType = 8, kXferBarrier_CmdType = 9, }; Cmd(CmdType type) : fMarkerID(-1), fType(type) {} virtual ~Cmd() {} virtual void execute(GrGpu*) = 0; CmdType type() const { return fType; } // trace markers bool isTraced() const { return -1 != fMarkerID; } void setMarkerID(int markerID) { SkASSERT(-1 == fMarkerID); fMarkerID = markerID; } int markerID() const { return fMarkerID; } private: int fMarkerID; CmdType fType; }; void reset(); void flush(GrInOrderDrawBuffer*); private: friend class GrCommandBuilder; friend class GrInOrderDrawBuffer; // This goes away when State becomes just a pipeline friend class GrReorderCommandBuilder; typedef GrGpu::DrawArgs DrawArgs; void recordXferBarrierIfNecessary(const GrPipeline&, GrInOrderDrawBuffer*); // TODO: This can be just a pipeline once paths are in batch, and it should live elsewhere struct State : public SkNVRefCnt { // TODO get rid of the prim proc parameter when we use batch everywhere State(const GrPrimitiveProcessor* primProc = NULL) : fPrimitiveProcessor(primProc) , fCompiled(false) {} ~State() { reinterpret_cast(fPipeline.get())->~GrPipeline(); } // This function is only for getting the location in memory where we will create our // pipeline object. GrPipeline* pipelineLocation() { return reinterpret_cast(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 StencilPath : public Cmd { StencilPath(const GrPath* path, GrRenderTarget* rt) : Cmd(kStencilPath_CmdType) , fRenderTarget(rt) , fPath(path) {} const GrPath* path() const { return fPath.get(); } void execute(GrGpu*) override; SkMatrix fViewMatrix; bool fUseHWAA; GrStencilSettings fStencil; GrScissorState fScissor; private: GrPendingIOResource fRenderTarget; GrPendingIOResource fPath; }; struct DrawPath : public Cmd { DrawPath(State* state, const GrPath* path) : Cmd(kDrawPath_CmdType) , fState(SkRef(state)) , fPath(path) {} const GrPath* path() const { return fPath.get(); } void execute(GrGpu*) override; SkAutoTUnref fState; GrStencilSettings fStencilSettings; private: GrPendingIOResource fPath; }; struct DrawPaths : public Cmd { DrawPaths(State* state, const GrPathRange* pathRange) : Cmd(kDrawPaths_CmdType) , fState(SkRef(state)) , fPathRange(pathRange) {} const GrPathRange* pathRange() const { return fPathRange.get(); } void execute(GrGpu*) override; SkAutoTUnref fState; char* fIndices; GrDrawTarget::PathIndexType fIndexType; float* fTransforms; GrDrawTarget::PathTransformType fTransformType; int fCount; GrStencilSettings fStencilSettings; private: GrPendingIOResource fPathRange; }; // This is also used to record a discard by setting the color to GrColor_ILLEGAL struct Clear : public Cmd { Clear(GrRenderTarget* rt) : Cmd(kClear_CmdType), fRenderTarget(rt) {} GrRenderTarget* renderTarget() const { return fRenderTarget.get(); } void execute(GrGpu*) override; SkIRect fRect; GrColor fColor; bool fCanIgnoreRect; private: GrPendingIOResource fRenderTarget; }; // This command is ONLY used by the clip mask manager to clear the stencil clip bits struct ClearStencilClip : public Cmd { ClearStencilClip(GrRenderTarget* rt) : Cmd(kClearStencil_CmdType), fRenderTarget(rt) {} GrRenderTarget* renderTarget() const { return fRenderTarget.get(); } void execute(GrGpu*) override; SkIRect fRect; bool fInsideClip; private: GrPendingIOResource fRenderTarget; }; struct CopySurface : public Cmd { CopySurface(GrSurface* dst, GrSurface* src) : Cmd(kCopySurface_CmdType) , fDst(dst) , fSrc(src) { } GrSurface* dst() const { return fDst.get(); } GrSurface* src() const { return fSrc.get(); } void execute(GrGpu*) override; SkIPoint fDstPoint; SkIRect fSrcRect; private: GrPendingIOResource fDst; GrPendingIOResource fSrc; }; struct DrawBatch : public Cmd { DrawBatch(State* state, GrBatch* batch, GrBatchTarget* batchTarget) : Cmd(kDrawBatch_CmdType) , fState(SkRef(state)) , fBatch(SkRef(batch)) , fBatchTarget(batchTarget) { SkASSERT(!batch->isUsed()); } void execute(GrGpu*) override; SkAutoTUnref fState; SkAutoTUnref fBatch; private: GrBatchTarget* fBatchTarget; }; struct XferBarrier : public Cmd { XferBarrier(GrRenderTarget* rt) : Cmd(kXferBarrier_CmdType) , fRenderTarget(rt) { } void execute(GrGpu*) override; GrXferBarrierType fBarrierType; private: GrPendingIOResource fRenderTarget; }; 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; } GrBatchTarget* batchTarget() { return &fBatchTarget; } CmdBuffer fCmdBuffer; GrBatchTarget fBatchTarget; }; #endif