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