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