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/private/GrRecordingContext.h" |
12 | #include "src/gpu/GrMemoryPool.h" |
13 | #include "src/gpu/GrOpFlushState.h" |
14 | #include "src/gpu/GrPipeline.h" |
15 | #include "src/gpu/GrRecordingContextPriv.h" |
16 | #include "src/gpu/ops/GrMeshDrawOp.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(GrRecordingContext*, GrPaint&&, OpArgs...); |
40 | |
41 | // Here we allow callers to specify a subset of the GrPipeline::InputFlags upon creation. |
42 | enum class InputFlags : uint8_t { |
43 | kNone = 0, |
44 | kSnapVerticesToPixelCenters = (uint8_t)GrPipeline::InputFlags::kSnapVerticesToPixelCenters, |
45 | kConservativeRaster = (uint8_t)GrPipeline::InputFlags::kConservativeRaster, |
46 | }; |
47 | GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(InputFlags); |
48 | |
49 | GrSimpleMeshDrawOpHelper(const MakeArgs&, GrAAType, InputFlags = InputFlags::kNone); |
50 | ~GrSimpleMeshDrawOpHelper(); |
51 | |
52 | GrSimpleMeshDrawOpHelper() = delete; |
53 | GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete; |
54 | GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete; |
55 | |
56 | GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const; |
57 | |
58 | // ignoreAAType should be set to true if the op already knows the AA settings are acceptible |
59 | bool isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps&, const SkRect& thisBounds, |
60 | const SkRect& thatBounds, bool ignoreAAType = false) const; |
61 | |
62 | /** |
63 | * Finalizes the processor set and determines whether the destination must be provided |
64 | * to the fragment shader as a texture for blending. |
65 | * |
66 | * @param geometryCoverage Describes the coverage output of the op's geometry processor |
67 | * @param geometryColor An in/out param. As input this informs processor analysis about the |
68 | * color the op expects to output from its geometry processor. As output |
69 | * this may be set to a known color in which case the op must output this |
70 | * color from its geometry processor instead. |
71 | */ |
72 | GrProcessorSet::Analysis finalizeProcessors( |
73 | const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage, |
74 | GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, |
75 | GrProcessorAnalysisColor* geometryColor) { |
76 | return this->finalizeProcessors( |
77 | caps, clip, &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, clampType, |
78 | geometryCoverage, geometryColor); |
79 | } |
80 | |
81 | /** |
82 | * Version of above that can be used by ops that have a constant color geometry processor |
83 | * output. The op passes this color as 'geometryColor' and after return if 'geometryColor' has |
84 | * changed the op must override its geometry processor color output with the new color. |
85 | */ |
86 | GrProcessorSet::Analysis finalizeProcessors( |
87 | const GrCaps&, const GrAppliedClip*, bool hasMixedSampledCoverage, GrClampType, |
88 | GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor, |
89 | bool* wideColor); |
90 | |
91 | bool isTrivial() const { |
92 | return fProcessors == nullptr; |
93 | } |
94 | |
95 | bool usesLocalCoords() const { |
96 | SkASSERT(fDidAnalysis); |
97 | return fUsesLocalCoords; |
98 | } |
99 | |
100 | bool compatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; } |
101 | |
102 | struct MakeArgs { |
103 | private: |
104 | MakeArgs() = default; |
105 | |
106 | GrProcessorSet* fProcessorSet; |
107 | |
108 | friend class GrSimpleMeshDrawOpHelper; |
109 | }; |
110 | |
111 | void visitProxies(const GrOp::VisitProxyFunc& func) const { |
112 | if (fProcessors) { |
113 | fProcessors->visitProxies(func); |
114 | } |
115 | } |
116 | |
117 | #ifdef SK_DEBUG |
118 | SkString dumpInfo() const; |
119 | #endif |
120 | GrAAType aaType() const { return static_cast<GrAAType>(fAAType); } |
121 | |
122 | void setAAType(GrAAType aaType) { |
123 | fAAType = static_cast<unsigned>(aaType); |
124 | } |
125 | |
126 | static const GrPipeline* CreatePipeline( |
127 | const GrCaps*, |
128 | SkArenaAlloc*, |
129 | GrSwizzle writeViewSwizzle, |
130 | GrAppliedClip&&, |
131 | const GrXferProcessor::DstProxyView&, |
132 | GrProcessorSet&&, |
133 | GrPipeline::InputFlags pipelineFlags, |
134 | const GrUserStencilSettings* = &GrUserStencilSettings::kUnused); |
135 | static const GrPipeline* CreatePipeline( |
136 | GrOpFlushState*, |
137 | GrProcessorSet&&, |
138 | GrPipeline::InputFlags pipelineFlags, |
139 | const GrUserStencilSettings* = &GrUserStencilSettings::kUnused); |
140 | |
141 | const GrPipeline* createPipeline(GrOpFlushState* flushState); |
142 | |
143 | static GrProgramInfo* CreateProgramInfo(SkArenaAlloc*, |
144 | const GrPipeline*, |
145 | const GrSurfaceProxyView* writeView, |
146 | GrGeometryProcessor*, |
147 | GrPrimitiveType); |
148 | |
149 | // Create a programInfo with the following properties: |
150 | // its primitive processor uses no textures |
151 | // it has no dynamic state besides the scissor clip |
152 | static GrProgramInfo* CreateProgramInfo(const GrCaps*, |
153 | SkArenaAlloc*, |
154 | const GrSurfaceProxyView* writeView, |
155 | GrAppliedClip&&, |
156 | const GrXferProcessor::DstProxyView&, |
157 | GrGeometryProcessor*, |
158 | GrProcessorSet&&, |
159 | GrPrimitiveType, |
160 | GrPipeline::InputFlags pipelineFlags |
161 | = GrPipeline::InputFlags::kNone, |
162 | const GrUserStencilSettings* |
163 | = &GrUserStencilSettings::kUnused); |
164 | |
165 | GrProgramInfo* createProgramInfo(const GrCaps*, |
166 | SkArenaAlloc*, |
167 | const GrSurfaceProxyView* writeView, |
168 | GrAppliedClip&&, |
169 | const GrXferProcessor::DstProxyView&, |
170 | GrGeometryProcessor*, |
171 | GrPrimitiveType); |
172 | |
173 | GrProcessorSet detachProcessorSet() { |
174 | return fProcessors ? std::move(*fProcessors) : GrProcessorSet::MakeEmptySet(); |
175 | } |
176 | |
177 | GrPipeline::InputFlags pipelineFlags() const { return fPipelineFlags; } |
178 | |
179 | protected: |
180 | GrProcessorSet::Analysis finalizeProcessors( |
181 | const GrCaps& caps, const GrAppliedClip*, const GrUserStencilSettings*, |
182 | bool hasMixedSampledCoverage, GrClampType, GrProcessorAnalysisCoverage geometryCoverage, |
183 | GrProcessorAnalysisColor* geometryColor); |
184 | |
185 | GrProcessorSet* fProcessors; |
186 | GrPipeline::InputFlags fPipelineFlags; |
187 | unsigned fAAType : 2; |
188 | unsigned fUsesLocalCoords : 1; |
189 | unsigned fCompatibleWithCoverageAsAlpha : 1; |
190 | SkDEBUGCODE(unsigned fMadePipeline : 1;) |
191 | SkDEBUGCODE(unsigned fDidAnalysis : 1;) |
192 | }; |
193 | |
194 | template <typename Op, typename... OpArgs> |
195 | std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrRecordingContext* context, |
196 | GrPaint&& paint, |
197 | OpArgs... opArgs) { |
198 | GrOpMemoryPool* pool = context->priv().opMemoryPool(); |
199 | |
200 | MakeArgs makeArgs; |
201 | |
202 | if (paint.isTrivial()) { |
203 | makeArgs.fProcessorSet = nullptr; |
204 | return pool->allocate<Op>(makeArgs, paint.getColor4f(), std::forward<OpArgs>(opArgs)...); |
205 | } else { |
206 | char* mem = (char*) pool->allocate(sizeof(Op) + sizeof(GrProcessorSet)); |
207 | char* setMem = mem + sizeof(Op); |
208 | auto color = paint.getColor4f(); |
209 | makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint)); |
210 | return std::unique_ptr<GrDrawOp>(new (mem) Op(makeArgs, color, |
211 | std::forward<OpArgs>(opArgs)...)); |
212 | } |
213 | } |
214 | |
215 | GR_MAKE_BITFIELD_CLASS_OPS(GrSimpleMeshDrawOpHelper::InputFlags) |
216 | |
217 | #endif |
218 | |