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/ganesh/ops/GrSimpleMeshDrawOpHelper.h"
9
10 #include "src/gpu/ganesh/GrAppliedClip.h"
11 #include "src/gpu/ganesh/GrProcessorSet.h"
12 #include "src/gpu/ganesh/GrProgramInfo.h"
13 #include "src/gpu/ganesh/GrUserStencilSettings.h"
14 #include "src/gpu/ganesh/SkGr.h"
15 #include "src/gpu/ganesh/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,skgpu::Swizzle writeViewSwizzle,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView,GrProcessorSet && processorSet,GrPipeline::InputFlags pipelineFlags)107 const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(const GrCaps* caps,
108 SkArenaAlloc* arena,
109 skgpu::Swizzle writeViewSwizzle,
110 GrAppliedClip&& appliedClip,
111 const GrDstProxyView& dstProxyView,
112 GrProcessorSet&& processorSet,
113 GrPipeline::InputFlags pipelineFlags) {
114 GrPipeline::InitArgs pipelineArgs;
115
116 pipelineArgs.fInputFlags = pipelineFlags;
117 pipelineArgs.fCaps = caps;
118 pipelineArgs.fDstProxyView = dstProxyView;
119 pipelineArgs.fWriteSwizzle = writeViewSwizzle;
120
121 return arena->make<GrPipeline>(pipelineArgs,
122 std::move(processorSet),
123 std::move(appliedClip));
124 }
125
CreatePipeline(GrOpFlushState * flushState,GrProcessorSet && processorSet,GrPipeline::InputFlags pipelineFlags)126 const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(GrOpFlushState* flushState,
127 GrProcessorSet&& processorSet,
128 GrPipeline::InputFlags pipelineFlags) {
129 return CreatePipeline(&flushState->caps(),
130 flushState->allocator(),
131 flushState->writeView().swizzle(),
132 flushState->detachAppliedClip(),
133 flushState->dstProxyView(),
134 std::move(processorSet),
135 pipelineFlags);
136 }
137
createPipeline(GrOpFlushState * flushState)138 const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(GrOpFlushState* flushState) {
139 return CreatePipeline(&flushState->caps(),
140 flushState->allocator(),
141 flushState->writeView().swizzle(),
142 flushState->detachAppliedClip(),
143 flushState->dstProxyView(),
144 this->detachProcessorSet(),
145 this->pipelineFlags());
146 }
147
createPipeline(const GrCaps * caps,SkArenaAlloc * arena,skgpu::Swizzle writeViewSwizzle,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView)148 const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(const GrCaps* caps,
149 SkArenaAlloc* arena,
150 skgpu::Swizzle writeViewSwizzle,
151 GrAppliedClip&& appliedClip,
152 const GrDstProxyView& dstProxyView) {
153 return GrSimpleMeshDrawOpHelper::CreatePipeline(caps,
154 arena,
155 writeViewSwizzle,
156 std::move(appliedClip),
157 dstProxyView,
158 this->detachProcessorSet(),
159 this->pipelineFlags());
160 }
161
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)162 GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(
163 const GrCaps* caps,
164 SkArenaAlloc* arena,
165 const GrSurfaceProxyView& writeView,
166 bool usesMSAASurface,
167 GrAppliedClip&& appliedClip,
168 const GrDstProxyView& dstProxyView,
169 GrGeometryProcessor* geometryProcessor,
170 GrProcessorSet&& processorSet,
171 GrPrimitiveType primitiveType,
172 GrXferBarrierFlags renderPassXferBarriers,
173 GrLoadOp colorLoadOp,
174 GrPipeline::InputFlags pipelineFlags,
175 const GrUserStencilSettings* stencilSettings) {
176 auto pipeline = CreatePipeline(caps,
177 arena,
178 writeView.swizzle(),
179 std::move(appliedClip),
180 dstProxyView,
181 std::move(processorSet),
182 pipelineFlags);
183
184 return CreateProgramInfo(caps, arena, pipeline, writeView, usesMSAASurface, geometryProcessor,
185 primitiveType, renderPassXferBarriers, colorLoadOp, stencilSettings);
186 }
187
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)188 GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(const GrCaps* caps,
189 SkArenaAlloc* arena,
190 const GrPipeline* pipeline,
191 const GrSurfaceProxyView& writeView,
192 bool usesMSAASurface,
193 GrGeometryProcessor* geometryProcessor,
194 GrPrimitiveType primitiveType,
195 GrXferBarrierFlags xferBarrierFlags,
196 GrLoadOp colorLoadOp,
197 const GrUserStencilSettings* stencilSettings) {
198 auto tmp = arena->make<GrProgramInfo>(*caps,
199 writeView,
200 usesMSAASurface,
201 pipeline,
202 stencilSettings,
203 geometryProcessor,
204 primitiveType,
205 xferBarrierFlags,
206 colorLoadOp);
207 return tmp;
208 }
209
createProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView,GrGeometryProcessor * gp,GrPrimitiveType primType,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)210 GrProgramInfo* GrSimpleMeshDrawOpHelper::createProgramInfo(
211 const GrCaps* caps,
212 SkArenaAlloc* arena,
213 const GrSurfaceProxyView& writeView,
214 bool usesMSAASurface,
215 GrAppliedClip&& appliedClip,
216 const GrDstProxyView& dstProxyView,
217 GrGeometryProcessor* gp,
218 GrPrimitiveType primType,
219 GrXferBarrierFlags renderPassXferBarriers,
220 GrLoadOp colorLoadOp) {
221 return CreateProgramInfo(caps,
222 arena,
223 writeView,
224 usesMSAASurface,
225 std::move(appliedClip),
226 dstProxyView,
227 gp,
228 this->detachProcessorSet(),
229 primType,
230 renderPassXferBarriers,
231 colorLoadOp,
232 this->pipelineFlags());
233 }
234
235 #if defined(GR_TEST_UTILS)
dump_pipeline_flags(GrPipeline::InputFlags flags,SkString * result)236 static void dump_pipeline_flags(GrPipeline::InputFlags flags, SkString* result) {
237 if (GrPipeline::InputFlags::kNone != flags) {
238 if (flags & GrPipeline::InputFlags::kSnapVerticesToPixelCenters) {
239 result->append("Snap vertices to pixel center.\n");
240 }
241 if (flags & GrPipeline::InputFlags::kWireframe) {
242 result->append("Wireframe enabled.\n");
243 }
244 if (flags & GrPipeline::InputFlags::kConservativeRaster) {
245 result->append("Conservative raster enabled.\n");
246 }
247 return;
248 }
249 result->append("No pipeline flags\n");
250 }
251
dumpInfo() const252 SkString GrSimpleMeshDrawOpHelper::dumpInfo() const {
253 const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
254 SkString result = processors.dumpProcessors();
255 result.append("AA Type: ");
256 switch (this->aaType()) {
257 case GrAAType::kNone:
258 result.append(" none\n");
259 break;
260 case GrAAType::kCoverage:
261 result.append(" coverage\n");
262 break;
263 case GrAAType::kMSAA:
264 result.append(" msaa\n");
265 break;
266 }
267 dump_pipeline_flags(fPipelineFlags, &result);
268 return result;
269 }
270 #endif
271