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