| /* | |
| * Copyright 2017 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef GrSimpleMeshDrawOpHelper_DEFINED | |
| #define GrSimpleMeshDrawOpHelper_DEFINED | |
| #include "GrContext.h" | |
| #include "GrContextPriv.h" | |
| #include "GrMemoryPool.h" // only here bc of the templated FactoryHelper | |
| #include "GrMeshDrawOp.h" | |
| #include "GrOpFlushState.h" | |
| #include "GrPipeline.h" | |
| #include <new> | |
| struct SkRect; | |
| /** | |
| * This class can be used to help implement simple mesh draw ops. It reduces the amount of | |
| * boilerplate code to type and also provides a mechanism for optionally allocating space for a | |
| * GrProcessorSet based on a GrPaint. It is intended to be used by ops that construct a single | |
| * GrPipeline for a uniform primitive color and a GrPaint. | |
| */ | |
| class GrSimpleMeshDrawOpHelper { | |
| public: | |
| struct MakeArgs; | |
| /** | |
| * This can be used by a Op class to perform allocation and initialization such that a | |
| * GrProcessorSet (if required) is allocated as part of the the same allocation that as | |
| * the Op instance. It requires that Op implements a constructor of the form: | |
| * Op(MakeArgs, GrColor, OpArgs...) | |
| * which is public or made accessible via 'friend'. | |
| */ | |
| template <typename Op, typename... OpArgs> | |
| static std::unique_ptr<GrDrawOp> FactoryHelper(GrContext*, GrPaint&& paint, OpArgs... opArgs); | |
| enum class Flags : uint32_t { | |
| kNone = 0x0, | |
| kSnapVerticesToPixelCenters = 0x1, | |
| }; | |
| GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags); | |
| GrSimpleMeshDrawOpHelper(const MakeArgs&, GrAAType, Flags = Flags::kNone); | |
| ~GrSimpleMeshDrawOpHelper(); | |
| GrSimpleMeshDrawOpHelper() = delete; | |
| GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete; | |
| GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete; | |
| GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const; | |
| bool isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps&, const SkRect& thisBounds, | |
| const SkRect& thatBounds) const; | |
| /** | |
| * Finalizes the processor set and determines whether the destination must be provided | |
| * to the fragment shader as a texture for blending. | |
| * | |
| * @param geometryCoverage Describes the coverage output of the op's geometry processor | |
| * @param geometryColor An in/out param. As input this informs processor analysis about the | |
| * color the op expects to output from its geometry processor. As output | |
| * this may be set to a known color in which case the op must output this | |
| * color from its geometry processor instead. | |
| */ | |
| GrDrawOp::RequiresDstTexture xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip, | |
| GrProcessorAnalysisCoverage geometryCoverage, | |
| GrProcessorAnalysisColor* geometryColor); | |
| /** | |
| * Version of above that can be used by ops that have a constant color geometry processor | |
| * output. The op passes this color as 'geometryColor' and after return if 'geometryColor' has | |
| * changed the op must override its geometry processor color output with the new color. | |
| */ | |
| GrDrawOp::RequiresDstTexture xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*, | |
| GrProcessorAnalysisCoverage geometryCoverage, | |
| GrColor* geometryColor); | |
| bool usesLocalCoords() const { | |
| SkASSERT(fDidAnalysis); | |
| return fUsesLocalCoords; | |
| } | |
| bool compatibleWithAlphaAsCoverage() const { return fCompatibleWithAlphaAsCoveage; } | |
| using PipelineAndFixedDynamicState = GrOpFlushState::PipelineAndFixedDynamicState; | |
| /** Makes a pipeline that consumes the processor set and the op's applied clip. */ | |
| PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target* target, | |
| int numPrimitiveProcessorTextures = 0) { | |
| return this->internalMakePipeline(target, this->pipelineInitArgs(target), | |
| numPrimitiveProcessorTextures); | |
| } | |
| struct MakeArgs { | |
| private: | |
| MakeArgs() = default; | |
| GrProcessorSet* fProcessorSet; | |
| friend class GrSimpleMeshDrawOpHelper; | |
| }; | |
| void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) const { | |
| if (fProcessors) { | |
| fProcessors->visitProxies(func); | |
| } | |
| } | |
| SkString dumpInfo() const; | |
| protected: | |
| GrAAType aaType() const { return static_cast<GrAAType>(fAAType); } | |
| uint32_t pipelineFlags() const { return fPipelineFlags; } | |
| GrPipeline::InitArgs pipelineInitArgs(GrMeshDrawOp::Target* target) const; | |
| PipelineAndFixedDynamicState internalMakePipeline(GrMeshDrawOp::Target*, | |
| const GrPipeline::InitArgs&, | |
| int numPrimitiveProcessorTextures); | |
| private: | |
| GrProcessorSet* fProcessors; | |
| unsigned fPipelineFlags : 8; | |
| unsigned fAAType : 2; | |
| unsigned fRequiresDstTexture : 1; | |
| unsigned fUsesLocalCoords : 1; | |
| unsigned fCompatibleWithAlphaAsCoveage : 1; | |
| SkDEBUGCODE(unsigned fMadePipeline : 1;) | |
| SkDEBUGCODE(unsigned fDidAnalysis : 1;) | |
| }; | |
| /** | |
| * This class extends GrSimpleMeshDrawOpHelper to support an optional GrUserStencilSettings. This | |
| * uses private inheritance because it non-virtually overrides methods in the base class and should | |
| * never be used with a GrSimpleMeshDrawOpHelper pointer or reference. | |
| */ | |
| class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper { | |
| public: | |
| using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs; | |
| using Flags = GrSimpleMeshDrawOpHelper::Flags; | |
| using PipelineAndFixedDynamicState = GrOpFlushState::PipelineAndFixedDynamicState; | |
| using GrSimpleMeshDrawOpHelper::visitProxies; | |
| // using declarations can't be templated, so this is a pass through function instead. | |
| template <typename Op, typename... OpArgs> | |
| static std::unique_ptr<GrDrawOp> FactoryHelper(GrContext* context, GrPaint&& paint, | |
| OpArgs... opArgs) { | |
| return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>( | |
| context, std::move(paint), std::forward<OpArgs>(opArgs)...); | |
| } | |
| GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs&, GrAAType, const GrUserStencilSettings*, | |
| Flags = Flags::kNone); | |
| GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const; | |
| using GrSimpleMeshDrawOpHelper::xpRequiresDstTexture; | |
| using GrSimpleMeshDrawOpHelper::usesLocalCoords; | |
| using GrSimpleMeshDrawOpHelper::compatibleWithAlphaAsCoverage; | |
| bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps&, | |
| const SkRect& thisBounds, const SkRect& thatBounds) const; | |
| PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target*, | |
| int numPrimitiveProcessorTextures = 0); | |
| SkString dumpInfo() const; | |
| private: | |
| const GrUserStencilSettings* fStencilSettings; | |
| typedef GrSimpleMeshDrawOpHelper INHERITED; | |
| }; | |
| template <typename Op, typename... OpArgs> | |
| std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrContext* context, | |
| GrPaint&& paint, | |
| OpArgs... opArgs) { | |
| GrOpMemoryPool* pool = context->contextPriv().opMemoryPool(); | |
| MakeArgs makeArgs; | |
| GrColor color = paint.getColor(); | |
| if (paint.isTrivial()) { | |
| makeArgs.fProcessorSet = nullptr; | |
| return pool->allocate<Op>(makeArgs, color, std::forward<OpArgs>(opArgs)...); | |
| } else { | |
| char* mem = (char*) pool->allocate(sizeof(Op) + sizeof(GrProcessorSet)); | |
| char* setMem = mem + sizeof(Op); | |
| makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint)); | |
| return std::unique_ptr<GrDrawOp>(new (mem) Op(makeArgs, color, | |
| std::forward<OpArgs>(opArgs)...)); | |
| } | |
| } | |
| GR_MAKE_BITFIELD_CLASS_OPS(GrSimpleMeshDrawOpHelper::Flags) | |
| #endif |