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