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