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 | |
16 | GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(const MakeArgs& args, |
17 | GrAAType aaType, |
18 | InputFlags inputFlags) |
19 | : fProcessors(args.fProcessorSet) |
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 | |
31 | GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() { |
32 | if (fProcessors) { |
33 | fProcessors->~GrProcessorSet(); |
34 | } |
35 | } |
36 | |
37 | GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const { |
38 | return GrAATypeIsHW(this->aaType()) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA |
39 | : GrDrawOp::FixedFunctionFlags::kNone; |
40 | } |
41 | |
42 | 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 | |
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 | |
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->numClipCoverageFragmentProcessors() |
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 | |
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 | const GrUserStencilSettings* stencilSettings) { |
120 | GrPipeline::InitArgs pipelineArgs; |
121 | |
122 | pipelineArgs.fInputFlags = pipelineFlags; |
123 | pipelineArgs.fUserStencil = stencilSettings; |
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 | |
133 | const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline( |
134 | GrOpFlushState* flushState, |
135 | GrProcessorSet&& processorSet, |
136 | GrPipeline::InputFlags pipelineFlags, |
137 | const GrUserStencilSettings* stencilSettings) { |
138 | return CreatePipeline(&flushState->caps(), |
139 | flushState->allocator(), |
140 | flushState->writeView()->swizzle(), |
141 | flushState->detachAppliedClip(), |
142 | flushState->dstProxyView(), |
143 | std::move(processorSet), |
144 | pipelineFlags, |
145 | stencilSettings); |
146 | } |
147 | |
148 | const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(GrOpFlushState* flushState) { |
149 | return CreatePipeline(&flushState->caps(), |
150 | flushState->allocator(), |
151 | flushState->writeView()->swizzle(), |
152 | flushState->detachAppliedClip(), |
153 | flushState->dstProxyView(), |
154 | this->detachProcessorSet(), |
155 | this->pipelineFlags()); |
156 | } |
157 | |
158 | GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo( |
159 | const GrCaps* caps, |
160 | SkArenaAlloc* arena, |
161 | const GrSurfaceProxyView* writeView, |
162 | GrAppliedClip&& appliedClip, |
163 | const GrXferProcessor::DstProxyView& dstProxyView, |
164 | GrGeometryProcessor* geometryProcessor, |
165 | GrProcessorSet&& processorSet, |
166 | GrPrimitiveType primitiveType, |
167 | GrPipeline::InputFlags pipelineFlags, |
168 | const GrUserStencilSettings* stencilSettings) { |
169 | auto pipeline = CreatePipeline(caps, |
170 | arena, |
171 | writeView->swizzle(), |
172 | std::move(appliedClip), |
173 | dstProxyView, |
174 | std::move(processorSet), |
175 | pipelineFlags, |
176 | stencilSettings); |
177 | |
178 | return CreateProgramInfo(arena, pipeline, writeView, geometryProcessor, primitiveType); |
179 | } |
180 | |
181 | GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(SkArenaAlloc* arena, |
182 | const GrPipeline* pipeline, |
183 | const GrSurfaceProxyView* writeView, |
184 | GrGeometryProcessor* geometryProcessor, |
185 | GrPrimitiveType primitiveType) { |
186 | GrRenderTargetProxy* outputProxy = writeView->asRenderTargetProxy(); |
187 | |
188 | auto tmp = arena->make<GrProgramInfo>(outputProxy->numSamples(), |
189 | outputProxy->numStencilSamples(), |
190 | outputProxy->backendFormat(), |
191 | writeView->origin(), |
192 | pipeline, |
193 | geometryProcessor, |
194 | primitiveType); |
195 | return tmp; |
196 | } |
197 | |
198 | GrProgramInfo* GrSimpleMeshDrawOpHelper::createProgramInfo( |
199 | const GrCaps* caps, |
200 | SkArenaAlloc* arena, |
201 | const GrSurfaceProxyView* writeView, |
202 | GrAppliedClip&& appliedClip, |
203 | const GrXferProcessor::DstProxyView& dstProxyView, |
204 | GrGeometryProcessor* gp, |
205 | GrPrimitiveType primType) { |
206 | return CreateProgramInfo(caps, |
207 | arena, |
208 | writeView, |
209 | std::move(appliedClip), |
210 | dstProxyView, |
211 | gp, |
212 | this->detachProcessorSet(), |
213 | primType, |
214 | this->pipelineFlags()); |
215 | } |
216 | |
217 | #ifdef SK_DEBUG |
218 | static void dump_pipeline_flags(GrPipeline::InputFlags flags, SkString* result) { |
219 | if (GrPipeline::InputFlags::kNone != flags) { |
220 | if (flags & GrPipeline::InputFlags::kSnapVerticesToPixelCenters) { |
221 | result->append("Snap vertices to pixel center.\n" ); |
222 | } |
223 | if (flags & GrPipeline::InputFlags::kHWAntialias) { |
224 | result->append("HW Antialiasing enabled.\n" ); |
225 | } |
226 | return; |
227 | } |
228 | result->append("No pipeline flags\n" ); |
229 | } |
230 | |
231 | SkString GrSimpleMeshDrawOpHelper::dumpInfo() const { |
232 | const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet(); |
233 | SkString result = processors.dumpProcessors(); |
234 | result.append("AA Type: " ); |
235 | switch (this->aaType()) { |
236 | case GrAAType::kNone: |
237 | result.append(" none\n" ); |
238 | break; |
239 | case GrAAType::kCoverage: |
240 | result.append(" coverage\n" ); |
241 | break; |
242 | case GrAAType::kMSAA: |
243 | result.append(" msaa\n" ); |
244 | break; |
245 | } |
246 | dump_pipeline_flags(fPipelineFlags, &result); |
247 | return result; |
248 | } |
249 | #endif |
250 | |