1 /*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #ifndef GrSimpleMeshDrawOpHelper_DEFINED
9 #define GrSimpleMeshDrawOpHelper_DEFINED
10
11 #include "GrContext.h"
12 #include "GrContextPriv.h"
13 #include "GrMemoryPool.h" // only here bc of the templated FactoryHelper
14 #include "GrMeshDrawOp.h"
15 #include "GrOpFlushState.h"
16 #include "GrPipeline.h"
17 #include <new>
18
19 struct SkRect;
20
21 /**
22 * This class can be used to help implement simple mesh draw ops. It reduces the amount of
23 * boilerplate code to type and also provides a mechanism for optionally allocating space for a
24 * GrProcessorSet based on a GrPaint. It is intended to be used by ops that construct a single
25 * GrPipeline for a uniform primitive color and a GrPaint.
26 */
27 class GrSimpleMeshDrawOpHelper {
28 public:
29 struct MakeArgs;
30
31 /**
32 * This can be used by a Op class to perform allocation and initialization such that a
33 * GrProcessorSet (if required) is allocated as part of the the same allocation that as
34 * the Op instance. It requires that Op implements a constructor of the form:
35 * Op(MakeArgs, GrColor, OpArgs...)
36 * which is public or made accessible via 'friend'.
37 */
38 template <typename Op, typename... OpArgs>
39 static std::unique_ptr<GrDrawOp> FactoryHelper(GrContext*, GrPaint&& paint, OpArgs... opArgs);
40
41 enum class Flags : uint32_t {
42 kNone = 0x0,
43 kSnapVerticesToPixelCenters = 0x1,
44 };
45 GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags);
46
47 GrSimpleMeshDrawOpHelper(const MakeArgs&, GrAAType, Flags = Flags::kNone);
48 ~GrSimpleMeshDrawOpHelper();
49
50 GrSimpleMeshDrawOpHelper() = delete;
51 GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete;
52 GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete;
53
54 GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const;
55
56 // noneAACompatibleWithCoverage should be set to true if the op can properly render a non-AA
57 // primitive merged into a coverage-based op.
58 bool isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps&, const SkRect& thisBounds,
59 const SkRect& thatBounds, bool noneAACompatibleWithCoverage = false) const;
60
61 /**
62 * Finalizes the processor set and determines whether the destination must be provided
63 * to the fragment shader as a texture for blending.
64 *
65 * @param geometryCoverage Describes the coverage output of the op's geometry processor
66 * @param geometryColor An in/out param. As input this informs processor analysis about the
67 * color the op expects to output from its geometry processor. As output
68 * this may be set to a known color in which case the op must output this
69 * color from its geometry processor instead.
70 */
71 GrProcessorSet::Analysis finalizeProcessors(const GrCaps& caps, const GrAppliedClip*,
72 GrProcessorAnalysisCoverage geometryCoverage,
73 GrProcessorAnalysisColor* geometryColor);
74
75 /**
76 * Version of above that can be used by ops that have a constant color geometry processor
77 * output. The op passes this color as 'geometryColor' and after return if 'geometryColor' has
78 * changed the op must override its geometry processor color output with the new color.
79 */
80 GrProcessorSet::Analysis finalizeProcessors(const GrCaps&, const GrAppliedClip*,
81 GrProcessorAnalysisCoverage geometryCoverage,
82 SkPMColor4f* geometryColor);
83
isTrivial()84 bool isTrivial() const {
85 return fProcessors == nullptr;
86 }
87
usesLocalCoords()88 bool usesLocalCoords() const {
89 SkASSERT(fDidAnalysis);
90 return fUsesLocalCoords;
91 }
92
compatibleWithAlphaAsCoverage()93 bool compatibleWithAlphaAsCoverage() const { return fCompatibleWithAlphaAsCoveage; }
94
95 using PipelineAndFixedDynamicState = GrOpFlushState::PipelineAndFixedDynamicState;
96 /** Makes a pipeline that consumes the processor set and the op's applied clip. */
97 PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target* target,
98 int numPrimitiveProcessorTextures = 0) {
99 return this->internalMakePipeline(target, this->pipelineInitArgs(target),
100 numPrimitiveProcessorTextures);
101 }
102
103 struct MakeArgs {
104 private:
105 MakeArgs() = default;
106
107 GrProcessorSet* fProcessorSet;
108
109 friend class GrSimpleMeshDrawOpHelper;
110 };
111
visitProxies(const std::function<void (GrSurfaceProxy *)> & func)112 void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) const {
113 if (fProcessors) {
114 fProcessors->visitProxies(func);
115 }
116 }
117
118 #ifdef SK_DEBUG
119 SkString dumpInfo() const;
120 #endif
aaType()121 GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
122
setAAType(GrAAType aaType)123 void setAAType(GrAAType aaType) {
124 fAAType = static_cast<unsigned>(aaType);
125 }
126
127 protected:
pipelineFlags()128 uint32_t pipelineFlags() const { return fPipelineFlags; }
129
130 GrPipeline::InitArgs pipelineInitArgs(GrMeshDrawOp::Target* target) const;
131
132 PipelineAndFixedDynamicState internalMakePipeline(GrMeshDrawOp::Target*,
133 const GrPipeline::InitArgs&,
134 int numPrimitiveProcessorTextures);
135
136 private:
137 GrProcessorSet* fProcessors;
138 unsigned fPipelineFlags : 8;
139 unsigned fAAType : 2;
140 unsigned fUsesLocalCoords : 1;
141 unsigned fCompatibleWithAlphaAsCoveage : 1;
142 SkDEBUGCODE(unsigned fMadePipeline : 1;)
143 SkDEBUGCODE(unsigned fDidAnalysis : 1;)
144 };
145
146 /**
147 * This class extends GrSimpleMeshDrawOpHelper to support an optional GrUserStencilSettings. This
148 * uses private inheritance because it non-virtually overrides methods in the base class and should
149 * never be used with a GrSimpleMeshDrawOpHelper pointer or reference.
150 */
151 class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper {
152 public:
153 using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs;
154 using Flags = GrSimpleMeshDrawOpHelper::Flags;
155 using PipelineAndFixedDynamicState = GrOpFlushState::PipelineAndFixedDynamicState;
156
157 using GrSimpleMeshDrawOpHelper::visitProxies;
158
159 // using declarations can't be templated, so this is a pass through function instead.
160 template <typename Op, typename... OpArgs>
FactoryHelper(GrContext * context,GrPaint && paint,OpArgs...opArgs)161 static std::unique_ptr<GrDrawOp> FactoryHelper(GrContext* context, GrPaint&& paint,
162 OpArgs... opArgs) {
163 return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>(
164 context, std::move(paint), std::forward<OpArgs>(opArgs)...);
165 }
166
167 GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs&, GrAAType, const GrUserStencilSettings*,
168 Flags = Flags::kNone);
169
170 GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const;
171
172 using GrSimpleMeshDrawOpHelper::aaType;
173 using GrSimpleMeshDrawOpHelper::setAAType;
174 using GrSimpleMeshDrawOpHelper::isTrivial;
175 using GrSimpleMeshDrawOpHelper::finalizeProcessors;
176 using GrSimpleMeshDrawOpHelper::usesLocalCoords;
177 using GrSimpleMeshDrawOpHelper::compatibleWithAlphaAsCoverage;
178
179 bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps&,
180 const SkRect& thisBounds, const SkRect& thatBounds,
181 bool noneAACompatibleWithCoverage = false) const;
182
183 PipelineAndFixedDynamicState makePipeline(GrMeshDrawOp::Target*,
184 int numPrimitiveProcessorTextures = 0);
185
186 #ifdef SK_DEBUG
187 SkString dumpInfo() const;
188 #endif
189
190 private:
191 const GrUserStencilSettings* fStencilSettings;
192 typedef GrSimpleMeshDrawOpHelper INHERITED;
193 };
194
195 template <typename Op, typename... OpArgs>
FactoryHelper(GrContext * context,GrPaint && paint,OpArgs...opArgs)196 std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrContext* context,
197 GrPaint&& paint,
198 OpArgs... opArgs) {
199 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
200
201 MakeArgs makeArgs;
202
203 if (paint.isTrivial()) {
204 makeArgs.fProcessorSet = nullptr;
205 return pool->allocate<Op>(makeArgs, paint.getColor4f(), std::forward<OpArgs>(opArgs)...);
206 } else {
207 char* mem = (char*) pool->allocate(sizeof(Op) + sizeof(GrProcessorSet));
208 char* setMem = mem + sizeof(Op);
209 auto color = paint.getColor4f();
210 makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint));
211 return std::unique_ptr<GrDrawOp>(new (mem) Op(makeArgs, color,
212 std::forward<OpArgs>(opArgs)...));
213 }
214 }
215
216 GR_MAKE_BITFIELD_CLASS_OPS(GrSimpleMeshDrawOpHelper::Flags)
217
218 #endif
219