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