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 #include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
9
10 #include "src/gpu/GrAppliedClip.h"
11 #include "src/gpu/GrProcessorSet.h"
12 #include "src/gpu/GrProgramInfo.h"
13 #include "src/gpu/GrUserStencilSettings.h"
14 #include "src/gpu/SkGr.h"
15 #include "src/gpu/geometry/GrRect.h"
16
GrSimpleMeshDrawOpHelper(GrProcessorSet * processorSet,GrAAType aaType,InputFlags inputFlags)17 GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(GrProcessorSet* processorSet,
18 GrAAType aaType,
19 InputFlags inputFlags)
20 : fProcessors(processorSet)
21 , fPipelineFlags((GrPipeline::InputFlags)inputFlags)
22 , fAAType((int)aaType)
23 , fUsesLocalCoords(false)
24 , fCompatibleWithCoverageAsAlpha(false) {
25 SkDEBUGCODE(fDidAnalysis = false);
26 SkDEBUGCODE(fMadePipeline = false);
27 }
28
~GrSimpleMeshDrawOpHelper()29 GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() {
30 if (fProcessors) {
31 fProcessors->~GrProcessorSet();
32 }
33 }
34
fixedFunctionFlags() const35 GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const {
36 return GrAATypeIsHW(this->aaType()) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA
37 : GrDrawOp::FixedFunctionFlags::kNone;
38 }
39
isCompatible(const GrSimpleMeshDrawOpHelper & that,const GrCaps & caps,const SkRect & thisBounds,const SkRect & thatBounds,bool ignoreAAType) const40 bool GrSimpleMeshDrawOpHelper::isCompatible(const GrSimpleMeshDrawOpHelper& that,
41 const GrCaps& caps, const SkRect& thisBounds,
42 const SkRect& thatBounds, bool ignoreAAType) const {
43 if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) {
44 return false;
45 }
46 if (fProcessors) {
47 if (*fProcessors != *that.fProcessors) {
48 return false;
49 }
50 }
51
52 #ifdef SK_DEBUG
53 if (ignoreAAType) {
54 // If we're ignoring AA it should be bc we already know they are the same or that
55 // the are different but are compatible (i.e., one is AA and the other is None)
56 SkASSERT(fAAType == that.fAAType ||
57 GrMeshDrawOp::CanUpgradeAAOnMerge(this->aaType(), that.aaType()));
58 }
59 #endif
60
61 bool result = fPipelineFlags == that.fPipelineFlags &&
62 (ignoreAAType || fAAType == that.fAAType);
63 SkASSERT(!result || fCompatibleWithCoverageAsAlpha == that.fCompatibleWithCoverageAsAlpha);
64 SkASSERT(!result || fUsesLocalCoords == that.fUsesLocalCoords);
65 return result;
66 }
67
finalizeProcessors(const GrCaps & caps,const GrAppliedClip * clip,GrClampType clampType,GrProcessorAnalysisCoverage geometryCoverage,SkPMColor4f * geometryColor,bool * wideColor)68 GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors(
69 const GrCaps& caps, const GrAppliedClip* clip, GrClampType clampType,
70 GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor, bool* wideColor) {
71 GrProcessorAnalysisColor color = *geometryColor;
72 auto result = this->finalizeProcessors(caps, clip, clampType, geometryCoverage, &color);
73 color.isConstant(geometryColor);
74 if (wideColor) {
75 *wideColor = !geometryColor->fitsInBytes();
76 }
77 return result;
78 }
79
finalizeProcessors(const GrCaps & caps,const GrAppliedClip * clip,const GrUserStencilSettings * userStencil,GrClampType clampType,GrProcessorAnalysisCoverage geometryCoverage,GrProcessorAnalysisColor * geometryColor)80 GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors(
81 const GrCaps& caps, const GrAppliedClip* clip, const GrUserStencilSettings* userStencil,
82 GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage,
83 GrProcessorAnalysisColor* geometryColor) {
84 SkDEBUGCODE(fDidAnalysis = true);
85 GrProcessorSet::Analysis analysis;
86 if (fProcessors) {
87 GrProcessorAnalysisCoverage coverage = geometryCoverage;
88 if (GrProcessorAnalysisCoverage::kNone == coverage) {
89 coverage = (clip && clip->hasCoverageFragmentProcessor())
90 ? GrProcessorAnalysisCoverage::kSingleChannel
91 : GrProcessorAnalysisCoverage::kNone;
92 }
93 SkPMColor4f overrideColor;
94 analysis = fProcessors->finalize(*geometryColor, coverage, clip, userStencil, caps,
95 clampType, &overrideColor);
96 if (analysis.inputColorIsOverridden()) {
97 *geometryColor = overrideColor;
98 }
99 } else {
100 analysis = GrProcessorSet::EmptySetAnalysis();
101 }
102 fUsesLocalCoords = analysis.usesLocalCoords();
103 fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha();
104 return analysis;
105 }
106
CreatePipeline(const GrCaps * caps,SkArenaAlloc * arena,GrSwizzle writeViewSwizzle,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView,GrProcessorSet && processorSet,GrPipeline::InputFlags pipelineFlags)107 const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(
108 const GrCaps* caps,
109 SkArenaAlloc* arena,
110 GrSwizzle writeViewSwizzle,
111 GrAppliedClip&& appliedClip,
112 const GrDstProxyView& dstProxyView,
113 GrProcessorSet&& processorSet,
114 GrPipeline::InputFlags pipelineFlags) {
115 GrPipeline::InitArgs pipelineArgs;
116
117 pipelineArgs.fInputFlags = pipelineFlags;
118 pipelineArgs.fCaps = caps;
119 pipelineArgs.fDstProxyView = dstProxyView;
120 pipelineArgs.fWriteSwizzle = writeViewSwizzle;
121
122 return arena->make<GrPipeline>(pipelineArgs,
123 std::move(processorSet),
124 std::move(appliedClip));
125 }
126
CreatePipeline(GrOpFlushState * flushState,GrProcessorSet && processorSet,GrPipeline::InputFlags pipelineFlags)127 const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(
128 GrOpFlushState* flushState,
129 GrProcessorSet&& processorSet,
130 GrPipeline::InputFlags pipelineFlags) {
131 return CreatePipeline(&flushState->caps(),
132 flushState->allocator(),
133 flushState->writeView().swizzle(),
134 flushState->detachAppliedClip(),
135 flushState->dstProxyView(),
136 std::move(processorSet),
137 pipelineFlags);
138 }
139
createPipeline(GrOpFlushState * flushState)140 const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(GrOpFlushState* flushState) {
141 return CreatePipeline(&flushState->caps(),
142 flushState->allocator(),
143 flushState->writeView().swizzle(),
144 flushState->detachAppliedClip(),
145 flushState->dstProxyView(),
146 this->detachProcessorSet(),
147 this->pipelineFlags());
148 }
149
createPipeline(const GrCaps * caps,SkArenaAlloc * arena,GrSwizzle writeViewSwizzle,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView)150 const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(
151 const GrCaps* caps,
152 SkArenaAlloc* arena,
153 GrSwizzle writeViewSwizzle,
154 GrAppliedClip&& appliedClip,
155 const GrDstProxyView& dstProxyView) {
156 return GrSimpleMeshDrawOpHelper::CreatePipeline(caps,
157 arena,
158 writeViewSwizzle,
159 std::move(appliedClip),
160 dstProxyView,
161 this->detachProcessorSet(),
162 this->pipelineFlags());
163 }
164
CreateProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView,GrGeometryProcessor * geometryProcessor,GrProcessorSet && processorSet,GrPrimitiveType primitiveType,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp,GrPipeline::InputFlags pipelineFlags,const GrUserStencilSettings * stencilSettings)165 GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(
166 const GrCaps* caps,
167 SkArenaAlloc* arena,
168 const GrSurfaceProxyView& writeView,
169 bool usesMSAASurface,
170 GrAppliedClip&& appliedClip,
171 const GrDstProxyView& dstProxyView,
172 GrGeometryProcessor* geometryProcessor,
173 GrProcessorSet&& processorSet,
174 GrPrimitiveType primitiveType,
175 GrXferBarrierFlags renderPassXferBarriers,
176 GrLoadOp colorLoadOp,
177 GrPipeline::InputFlags pipelineFlags,
178 const GrUserStencilSettings* stencilSettings) {
179 auto pipeline = CreatePipeline(caps,
180 arena,
181 writeView.swizzle(),
182 std::move(appliedClip),
183 dstProxyView,
184 std::move(processorSet),
185 pipelineFlags);
186
187 return CreateProgramInfo(caps, arena, pipeline, writeView, usesMSAASurface, geometryProcessor,
188 primitiveType, renderPassXferBarriers, colorLoadOp, stencilSettings);
189 }
190
CreateProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrPipeline * pipeline,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrGeometryProcessor * geometryProcessor,GrPrimitiveType primitiveType,GrXferBarrierFlags xferBarrierFlags,GrLoadOp colorLoadOp,const GrUserStencilSettings * stencilSettings)191 GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(const GrCaps* caps,
192 SkArenaAlloc* arena,
193 const GrPipeline* pipeline,
194 const GrSurfaceProxyView& writeView,
195 bool usesMSAASurface,
196 GrGeometryProcessor* geometryProcessor,
197 GrPrimitiveType primitiveType,
198 GrXferBarrierFlags xferBarrierFlags,
199 GrLoadOp colorLoadOp,
200 const GrUserStencilSettings* stencilSettings) {
201 auto tmp = arena->make<GrProgramInfo>(*caps,
202 writeView,
203 usesMSAASurface,
204 pipeline,
205 stencilSettings,
206 geometryProcessor,
207 primitiveType,
208 0,
209 xferBarrierFlags,
210 colorLoadOp);
211 return tmp;
212 }
213
createProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView,GrGeometryProcessor * gp,GrPrimitiveType primType,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)214 GrProgramInfo* GrSimpleMeshDrawOpHelper::createProgramInfo(
215 const GrCaps* caps,
216 SkArenaAlloc* arena,
217 const GrSurfaceProxyView& writeView,
218 bool usesMSAASurface,
219 GrAppliedClip&& appliedClip,
220 const GrDstProxyView& dstProxyView,
221 GrGeometryProcessor* gp,
222 GrPrimitiveType primType,
223 GrXferBarrierFlags renderPassXferBarriers,
224 GrLoadOp colorLoadOp) {
225 return CreateProgramInfo(caps,
226 arena,
227 writeView,
228 usesMSAASurface,
229 std::move(appliedClip),
230 dstProxyView,
231 gp,
232 this->detachProcessorSet(),
233 primType,
234 renderPassXferBarriers,
235 colorLoadOp,
236 this->pipelineFlags());
237 }
238
239 #if GR_TEST_UTILS
dump_pipeline_flags(GrPipeline::InputFlags flags,SkString * result)240 static void dump_pipeline_flags(GrPipeline::InputFlags flags, SkString* result) {
241 if (GrPipeline::InputFlags::kNone != flags) {
242 if (flags & GrPipeline::InputFlags::kSnapVerticesToPixelCenters) {
243 result->append("Snap vertices to pixel center.\n");
244 }
245 if (flags & GrPipeline::InputFlags::kWireframe) {
246 result->append("Wireframe enabled.\n");
247 }
248 if (flags & GrPipeline::InputFlags::kConservativeRaster) {
249 result->append("Conservative raster enabled.\n");
250 }
251 return;
252 }
253 result->append("No pipeline flags\n");
254 }
255
dumpInfo() const256 SkString GrSimpleMeshDrawOpHelper::dumpInfo() const {
257 const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
258 SkString result = processors.dumpProcessors();
259 result.append("AA Type: ");
260 switch (this->aaType()) {
261 case GrAAType::kNone:
262 result.append(" none\n");
263 break;
264 case GrAAType::kCoverage:
265 result.append(" coverage\n");
266 break;
267 case GrAAType::kMSAA:
268 result.append(" msaa\n");
269 break;
270 }
271 dump_pipeline_flags(fPipelineFlags, &result);
272 return result;
273 }
274 #endif
275