blob: 03b9b1a96d566ba932502aa96f977958b29b09ec [file] [log] [blame]
Brian Salomon6d4b65e2017-05-03 17:06:09 -04001/*
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 "GrAppliedClip.h"
12#include "GrOpFlushState.h"
13#include "GrPipeline.h"
14#include "GrProcessorSet.h"
Brian Salomona4677b52017-05-04 12:39:56 -040015#include "GrRect.h"
Brian Salomon6d4b65e2017-05-03 17:06:09 -040016#include "GrUserStencilSettings.h"
17
18/**
19 * This class can be used to help implement simple mesh draw ops. It reduces the amount of
20 * boilerplate code to type and also provides a mechanism for optionally allocating space for a
21 * GrProcessorSet based on a GrPaint. It is intended to be used by ops that construct a single
22 * GrPipeline for a uniform primitive color and a GrPaint.
23 */
24class GrSimpleMeshDrawOpHelper {
25public:
26 struct MakeArgs;
27
28 /**
29 * This can be used by a Op class to perform allocation and initialization such that a
30 * GrProcessorSet (if required) is allocated at the same time as the Op instance. It requires
31 * that Op implements a constructor of the form:
32 * Op(MakeArgs, GrColor, OpArgs...)
33 * which is public or made accessible via 'friend'.
34 */
35 template <typename Op, typename... OpArgs>
36 static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs);
37
38 GrSimpleMeshDrawOpHelper(const MakeArgs& args, GrAAType aaType,
39 GrUserStencilSettings* stencilSettings = nullptr)
40 : fProcessors(args.fProcessorSet)
41 , fPipelineFlags(args.fSRGBFlags)
Brian Salomona4677b52017-05-04 12:39:56 -040042 , fAAType((int)aaType)
43 , fRequiresDstTexture(false) {
Brian Salomon6d4b65e2017-05-03 17:06:09 -040044 SkASSERT(!stencilSettings);
45 if (GrAATypeIsHW(aaType)) {
46 fPipelineFlags |= GrPipeline::kHWAntialias_Flag;
47 }
48 }
49
50 ~GrSimpleMeshDrawOpHelper() {
51 if (fProcessors) {
52 fProcessors->~GrProcessorSet();
53 }
54 }
55
56 GrSimpleMeshDrawOpHelper() = delete;
57 GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete;
58 GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete;
59
60 GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const {
61 return GrAATypeIsHW((this->aaType())) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA
62 : GrDrawOp::FixedFunctionFlags::kNone;
63 }
64
Brian Salomona4677b52017-05-04 12:39:56 -040065 bool isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps& caps,
66 const SkRect& aBounds, const SkRect& bBounds) const {
Brian Salomon6d4b65e2017-05-03 17:06:09 -040067 if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) {
68 return false;
69 }
Brian Salomona4677b52017-05-04 12:39:56 -040070 if (fProcessors) {
71 if (*fProcessors != *that.fProcessors) {
72 return false;
73 }
74 if (fRequiresDstTexture || (fProcessors->xferProcessor() &&
75 fProcessors->xferProcessor()->xferBarrierType(caps))) {
76 if (GrRectsTouchOrOverlap(aBounds, bBounds)) {
77 return false;
78 }
79 }
Brian Salomon6d4b65e2017-05-03 17:06:09 -040080 }
81 return fPipelineFlags == that.fPipelineFlags && fAAType == that.fAAType;
82 }
83
84 bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip,
85 GrProcessorAnalysisCoverage geometryCoverage, GrColor* color) {
86 if (fProcessors) {
87 GrProcessorAnalysisCoverage coverage = geometryCoverage;
88 if (GrProcessorAnalysisCoverage::kNone == coverage) {
89 coverage = clip->clipCoverageFragmentProcessor()
90 ? GrProcessorAnalysisCoverage::kSingleChannel
91 : GrProcessorAnalysisCoverage::kNone;
92 }
93 bool isMixedSamples = this->aaType() == GrAAType::kMixedSamples;
94 GrProcessorSet::Analysis analysis =
95 fProcessors->finalize(*color, coverage, clip, isMixedSamples, caps, color);
Brian Salomona4677b52017-05-04 12:39:56 -040096 fRequiresDstTexture = analysis.requiresDstTexture();
Brian Salomon6d4b65e2017-05-03 17:06:09 -040097 return analysis.requiresDstTexture();
98 } else {
99 return GrProcessorSet::EmptySetAnalysis().requiresDstTexture();
100 }
101 }
102
103 GrPipeline* makePipeline(GrMeshDrawOp::Target* target) const {
104 return target->allocPipeline(this->pipelineInitArgs(target));
105 }
106
107 struct MakeArgs {
108 private:
109 MakeArgs() = default;
110
111 GrProcessorSet* fProcessorSet;
112 uint32_t fSRGBFlags;
113
114 friend class GrSimpleMeshDrawOpHelper;
115 };
116
117protected:
118 GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
119 uint32_t pipelineFlags() const { return fPipelineFlags; }
120 const GrProcessorSet& processors() const {
121 return fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
122 }
123
124 GrPipeline::InitArgs pipelineInitArgs(GrMeshDrawOp::Target* target) const {
125 GrPipeline::InitArgs args;
126 args.fFlags = this->pipelineFlags();
127 args.fProcessors = &this->processors();
128 args.fRenderTarget = target->renderTarget();
129 args.fAppliedClip = target->clip();
130 args.fDstTexture = target->dstTexture();
131 args.fCaps = &target->caps();
132 return args;
133 }
134
135private:
136 GrProcessorSet* fProcessors;
137 unsigned fPipelineFlags : 8;
138 unsigned fAAType : 2;
Brian Salomona4677b52017-05-04 12:39:56 -0400139 unsigned fRequiresDstTexture : 1;
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400140};
141
142/**
143 * This class extends GrSimpleMeshDrawOpHelper to support an optional GrUserStencilSettings. This
144 * uses private inheritance because it non-virtually overrides methods in the base class and should
145 * never be used with a GrSimpleMeshDrawOpHelper pointer or reference.
146 */
147class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper {
148public:
149 using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs;
150
151 // using declarations can't be templated, so this is a pass through function instead.
152 template <typename Op, typename... OpArgs>
153 static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs) {
154 return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>(
155 std::move(paint), std::forward<OpArgs>(opArgs)...);
156 }
157
158 GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs& args, GrAAType aaType,
159 const GrUserStencilSettings* stencilSettings)
160 : INHERITED(args, aaType)
161 , fStencilSettings(stencilSettings ? stencilSettings
162 : &GrUserStencilSettings::kUnused) {}
163
164 GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const {
165 GrDrawOp::FixedFunctionFlags flags = INHERITED::fixedFunctionFlags();
166 if (fStencilSettings != &GrUserStencilSettings::kUnused) {
167 flags |= GrDrawOp::FixedFunctionFlags::kUsesStencil;
168 }
169 return flags;
170 }
171
172 using GrSimpleMeshDrawOpHelper::xpRequiresDstTexture;
173
Brian Salomona4677b52017-05-04 12:39:56 -0400174 bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps& caps,
175 const SkRect& aBounds, const SkRect& bBounds) const {
176 return INHERITED::isCompatible(that, caps, aBounds, bBounds) &&
177 fStencilSettings == that.fStencilSettings;
Brian Salomon6d4b65e2017-05-03 17:06:09 -0400178 }
179
180 GrPipeline* makePipeline(GrMeshDrawOp::Target* target) const {
181 auto args = INHERITED::pipelineInitArgs(target);
182 args.fUserStencil = fStencilSettings;
183 return target->allocPipeline(args);
184 }
185
186private:
187 const GrUserStencilSettings* fStencilSettings;
188 typedef GrSimpleMeshDrawOpHelper INHERITED;
189};
190
191template <typename Op, typename... OpArgs>
192std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrPaint&& paint,
193 OpArgs... opArgs) {
194 MakeArgs makeArgs;
195 makeArgs.fSRGBFlags = GrPipeline::SRGBFlagsFromPaint(paint);
196 GrColor color = paint.getColor();
197 if (paint.isTrivial()) {
198 makeArgs.fProcessorSet = nullptr;
199 return std::unique_ptr<GrDrawOp>(new Op(makeArgs, color, std::forward<OpArgs>(opArgs)...));
200 } else {
201 char* mem = (char*)GrOp::operator new(sizeof(Op) + sizeof(GrProcessorSet));
202 char* setMem = mem + sizeof(Op);
203 makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint));
204 return std::unique_ptr<GrDrawOp>(
205 new (mem) Op(makeArgs, color, std::forward<OpArgs>(opArgs)...));
206 }
207}
208
209#endif