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 "include/core/SkString.h"
12 #include "include/private/SkColorData.h"
13 #include "include/private/base/SkAssert.h"
14 #include "include/private/base/SkDebug.h"
15 #include "include/private/base/SkMacros.h"
16 #include "include/private/gpu/ganesh/GrTypesPriv.h"
17 #include "src/gpu/ganesh/GrCaps.h"
18 #include "src/gpu/ganesh/GrPaint.h"
19 #include "src/gpu/ganesh/GrPipeline.h"
20 #include "src/gpu/ganesh/GrProcessorSet.h"
21 #include "src/gpu/ganesh/GrUserStencilSettings.h"
22 #include "src/gpu/ganesh/ops/GrDrawOp.h"
23 #include "src/gpu/ganesh/ops/GrOp.h"
24
25 #include <cstdint>
26 #include <new>
27 #include <utility>
28
29 class GrAppliedClip;
30 class GrDstProxyView;
31 class GrGeometryProcessor;
32 class GrOpFlushState;
33 class GrProcessorAnalysisColor;
34 class GrProgramInfo;
35 class GrRecordingContext;
36 class GrSurfaceProxyView;
37 class SkArenaAlloc;
38 enum class GrProcessorAnalysisCoverage;
39 enum class GrXferBarrierFlags;
40 namespace skgpu {
41 class Swizzle;
42 }
43 struct SkRect;
44
45 /**
46 * This class can be used to help implement simple mesh draw ops. It reduces the amount of
47 * boilerplate code to type and also provides a mechanism for optionally allocating space for a
48 * GrProcessorSet based on a GrPaint. It is intended to be used by ops that construct a single
49 * GrPipeline for a uniform primitive color and a GrPaint.
50 */
51 class GrSimpleMeshDrawOpHelper {
52 public:
53 /**
54 * This can be used by a Op class to perform allocation and initialization such that a
55 * GrProcessorSet (if required) is allocated as part of the the same allocation that as
56 * the Op instance. It requires that Op implements a constructor of the form:
57 * Op(ProcessorSet*, GrColor, OpArgs...).
58 */
59 template <typename Op, typename... OpArgs>
60 static GrOp::Owner FactoryHelper(GrRecordingContext*, GrPaint&&, OpArgs&&...);
61
62 // Here we allow callers to specify a subset of the GrPipeline::InputFlags upon creation.
63 enum class InputFlags : uint8_t {
64 kNone = 0,
65 kSnapVerticesToPixelCenters = (uint8_t)GrPipeline::InputFlags::kSnapVerticesToPixelCenters,
66 kConservativeRaster = (uint8_t)GrPipeline::InputFlags::kConservativeRaster,
67 };
68 SK_DECL_BITFIELD_CLASS_OPS_FRIENDS(InputFlags);
69
70 GrSimpleMeshDrawOpHelper(GrProcessorSet*, GrAAType, InputFlags = InputFlags::kNone);
71 ~GrSimpleMeshDrawOpHelper();
72
73 GrSimpleMeshDrawOpHelper() = delete;
74 GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete;
75 GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete;
76
77 GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const;
78
79 // ignoreAAType should be set to true if the op already knows the AA settings are acceptible
80 bool isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps&, const SkRect& thisBounds,
81 const SkRect& thatBounds, bool ignoreAAType = false) const;
82
83 /**
84 * Finalizes the processor set and determines whether the destination must be provided
85 * to the fragment shader as a texture for blending.
86 *
87 * @param geometryCoverage Describes the coverage output of the op's geometry processor
88 * @param geometryColor An in/out param. As input this informs processor analysis about the
89 * color the op expects to output from its geometry processor. As output
90 * this may be set to a known color in which case the op must output this
91 * color from its geometry processor instead.
92 */
finalizeProcessors(const GrCaps & caps,const GrAppliedClip * clip,GrClampType clampType,GrProcessorAnalysisCoverage geometryCoverage,GrProcessorAnalysisColor * geometryColor)93 GrProcessorSet::Analysis finalizeProcessors(const GrCaps& caps, const GrAppliedClip* clip,
94 GrClampType clampType,
95 GrProcessorAnalysisCoverage geometryCoverage,
96 GrProcessorAnalysisColor* geometryColor) {
97 return this->finalizeProcessors(caps, clip, &GrUserStencilSettings::kUnused, clampType,
98 geometryCoverage, geometryColor);
99 }
100
101 /**
102 * Version of above that can be used by ops that have a constant color geometry processor
103 * output. The op passes this color as 'geometryColor' and after return if 'geometryColor' has
104 * changed the op must override its geometry processor color output with the new color.
105 */
106 GrProcessorSet::Analysis finalizeProcessors(const GrCaps&, const GrAppliedClip*, GrClampType,
107 GrProcessorAnalysisCoverage geometryCoverage,
108 SkPMColor4f* geometryColor, bool* wideColor);
109
isTrivial()110 bool isTrivial() const {
111 return fProcessors == nullptr;
112 }
113
usesLocalCoords()114 bool usesLocalCoords() const {
115 SkASSERT(fDidAnalysis);
116 return fUsesLocalCoords;
117 }
118
compatibleWithCoverageAsAlpha()119 bool compatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
120
visitProxies(const GrVisitProxyFunc & func)121 void visitProxies(const GrVisitProxyFunc& func) const {
122 if (fProcessors) {
123 fProcessors->visitProxies(func);
124 }
125 }
126
127 #if defined(GPU_TEST_UTILS)
128 SkString dumpInfo() const;
129 #endif
aaType()130 GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
131
setAAType(GrAAType aaType)132 void setAAType(GrAAType aaType) {
133 fAAType = static_cast<unsigned>(aaType);
134 }
135
136 static const GrPipeline* CreatePipeline(const GrCaps*,
137 SkArenaAlloc*,
138 skgpu::Swizzle writeViewSwizzle,
139 GrAppliedClip&&,
140 const GrDstProxyView&,
141 GrProcessorSet&&,
142 GrPipeline::InputFlags pipelineFlags);
143
144 static const GrPipeline* CreatePipeline(GrOpFlushState*,
145 GrProcessorSet&&,
146 GrPipeline::InputFlags pipelineFlags);
147
148 const GrPipeline* createPipeline(GrOpFlushState* flushState);
149
150 const GrPipeline* createPipeline(const GrCaps*,
151 SkArenaAlloc*,
152 skgpu::Swizzle writeViewSwizzle,
153 GrAppliedClip&&,
154 const GrDstProxyView&);
155
156 static GrProgramInfo* CreateProgramInfo(const GrCaps*,
157 SkArenaAlloc*,
158 const GrPipeline*,
159 const GrSurfaceProxyView& writeView,
160 bool usesMSAASurface,
161 GrGeometryProcessor*,
162 GrPrimitiveType,
163 GrXferBarrierFlags renderPassXferBarriers,
164 GrLoadOp colorLoadOp,
165 const GrUserStencilSettings*
166 = &GrUserStencilSettings::kUnused);
167
168 // Create a programInfo with the following properties:
169 // its primitive processor uses no textures
170 // it has no dynamic state besides the scissor clip
171 static GrProgramInfo* CreateProgramInfo(const GrCaps*,
172 SkArenaAlloc*,
173 const GrSurfaceProxyView& writeView,
174 bool usesMSAASurface,
175 GrAppliedClip&&,
176 const GrDstProxyView&,
177 GrGeometryProcessor*,
178 GrProcessorSet&&,
179 GrPrimitiveType,
180 GrXferBarrierFlags renderPassXferBarriers,
181 GrLoadOp colorLoadOp,
182 GrPipeline::InputFlags pipelineFlags
183 = GrPipeline::InputFlags::kNone,
184 const GrUserStencilSettings*
185 = &GrUserStencilSettings::kUnused);
186
187 GrProgramInfo* createProgramInfo(const GrCaps*,
188 SkArenaAlloc*,
189 const GrSurfaceProxyView& writeView,
190 bool usesMSAASurface,
191 GrAppliedClip&&,
192 const GrDstProxyView&,
193 GrGeometryProcessor*,
194 GrPrimitiveType,
195 GrXferBarrierFlags renderPassXferBarriers,
196 GrLoadOp colorLoadOp);
197
detachProcessorSet()198 GrProcessorSet detachProcessorSet() {
199 return fProcessors ? std::move(*fProcessors) : GrProcessorSet::MakeEmptySet();
200 }
201
pipelineFlags()202 GrPipeline::InputFlags pipelineFlags() const { return fPipelineFlags; }
203
204 protected:
205 GrProcessorSet::Analysis finalizeProcessors(const GrCaps& caps, const GrAppliedClip*,
206 const GrUserStencilSettings*, GrClampType,
207 GrProcessorAnalysisCoverage geometryCoverage,
208 GrProcessorAnalysisColor* geometryColor);
209
210 GrProcessorSet* fProcessors;
211 GrPipeline::InputFlags fPipelineFlags;
212 unsigned fAAType : 2;
213 unsigned fUsesLocalCoords : 1;
214 unsigned fCompatibleWithCoverageAsAlpha : 1;
215 SkDEBUGCODE(unsigned fMadePipeline : 1;)
216 SkDEBUGCODE(unsigned fDidAnalysis : 1;)
217 };
218
219 template<typename Op, typename... Args>
MakeWithProcessorSet(GrRecordingContext * context,const SkPMColor4f & color,GrPaint && paint,Args &&...args)220 GrOp::Owner GrOp::MakeWithProcessorSet(
221 GrRecordingContext* context, const SkPMColor4f& color,
222 GrPaint&& paint, Args&&... args) {
223 char* bytes = (char*)::operator new(sizeof(Op) + sizeof(GrProcessorSet));
224 char* setMem = bytes + sizeof(Op);
225 GrProcessorSet* processorSet = new (setMem) GrProcessorSet{std::move(paint)};
226 return Owner{new (bytes) Op(processorSet, color, std::forward<Args>(args)...)};
227 }
228
229 template <typename Op, typename... OpArgs>
FactoryHelper(GrRecordingContext * context,GrPaint && paint,OpArgs &&...opArgs)230 GrOp::Owner GrSimpleMeshDrawOpHelper::FactoryHelper(GrRecordingContext* context,
231 GrPaint&& paint,
232 OpArgs&& ... opArgs) {
233 auto color = paint.getColor4f();
234 if (paint.isTrivial()) {
235 return GrOp::Make<Op>(context, nullptr, color, std::forward<OpArgs>(opArgs)...);
236 } else {
237 return GrOp::MakeWithProcessorSet<Op>(
238 context, color, std::move(paint), std::forward<OpArgs>(opArgs)...);
239 }
240 }
241
242 SK_MAKE_BITFIELD_CLASS_OPS(GrSimpleMeshDrawOpHelper::InputFlags)
243
244 #endif
245