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/core/SkBlendModePriv.h" |
9 | #include "src/gpu/GrAppliedClip.h" |
10 | #include "src/gpu/GrCaps.h" |
11 | #include "src/gpu/GrProcessorSet.h" |
12 | #include "src/gpu/GrUserStencilSettings.h" |
13 | #include "src/gpu/GrXferProcessor.h" |
14 | #include "src/gpu/effects/GrPorterDuffXferProcessor.h" |
15 | |
16 | const GrProcessorSet& GrProcessorSet::EmptySet() { |
17 | static GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty); |
18 | return gEmpty; |
19 | } |
20 | |
21 | GrProcessorSet GrProcessorSet::MakeEmptySet() { |
22 | return GrProcessorSet(GrProcessorSet::Empty::kEmpty); |
23 | } |
24 | |
25 | GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) { |
26 | fFlags = 0; |
27 | if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) { |
28 | fColorFragmentProcessorCnt = paint.numColorFragmentProcessors(); |
29 | fFragmentProcessors.reset(paint.numTotalFragmentProcessors()); |
30 | int i = 0; |
31 | for (auto& fp : paint.fColorFragmentProcessors) { |
32 | SkASSERT(fp.get()); |
33 | fFragmentProcessors[i++] = std::move(fp); |
34 | } |
35 | for (auto& fp : paint.fCoverageFragmentProcessors) { |
36 | SkASSERT(fp.get()); |
37 | fFragmentProcessors[i++] = std::move(fp); |
38 | } |
39 | } else { |
40 | SkDebugf("Insane number of color fragment processors in paint. Dropping all processors." ); |
41 | fColorFragmentProcessorCnt = 0; |
42 | } |
43 | SkDEBUGCODE(paint.fAlive = false;) |
44 | } |
45 | |
46 | GrProcessorSet::GrProcessorSet(SkBlendMode mode) |
47 | : fXP(SkBlendMode_AsXPFactory(mode)) |
48 | , fColorFragmentProcessorCnt(0) |
49 | , fFragmentProcessorOffset(0) |
50 | , fFlags(0) {} |
51 | |
52 | GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP) |
53 | : fFragmentProcessors(1) |
54 | , fXP((const GrXPFactory*)nullptr) |
55 | , fColorFragmentProcessorCnt(1) |
56 | , fFragmentProcessorOffset(0) |
57 | , fFlags(0) { |
58 | SkASSERT(colorFP); |
59 | fFragmentProcessors[0] = std::move(colorFP); |
60 | } |
61 | |
62 | GrProcessorSet::GrProcessorSet(GrProcessorSet&& that) |
63 | : fXP(std::move(that.fXP)) |
64 | , fColorFragmentProcessorCnt(that.fColorFragmentProcessorCnt) |
65 | , fFragmentProcessorOffset(0) |
66 | , fFlags(that.fFlags) { |
67 | fFragmentProcessors.reset(that.fFragmentProcessors.count() - that.fFragmentProcessorOffset); |
68 | for (int i = 0; i < fFragmentProcessors.count(); ++i) { |
69 | fFragmentProcessors[i] = |
70 | std::move(that.fFragmentProcessors[i + that.fFragmentProcessorOffset]); |
71 | } |
72 | that.fColorFragmentProcessorCnt = 0; |
73 | that.fFragmentProcessors.reset(0); |
74 | } |
75 | |
76 | GrProcessorSet::~GrProcessorSet() { |
77 | if (this->isFinalized() && this->xferProcessor()) { |
78 | this->xferProcessor()->unref(); |
79 | } |
80 | } |
81 | |
82 | #ifdef SK_DEBUG |
83 | SkString dump_fragment_processor_tree(const GrFragmentProcessor* fp, int indentCnt) { |
84 | SkString result; |
85 | SkString indentString; |
86 | for (int i = 0; i < indentCnt; ++i) { |
87 | indentString.append(" " ); |
88 | } |
89 | result.appendf("%s%s %s \n" , indentString.c_str(), fp->name(), fp->dumpInfo().c_str()); |
90 | if (fp->numChildProcessors()) { |
91 | for (int i = 0; i < fp->numChildProcessors(); ++i) { |
92 | result += dump_fragment_processor_tree(&fp->childProcessor(i), indentCnt + 1); |
93 | } |
94 | } |
95 | return result; |
96 | } |
97 | |
98 | SkString GrProcessorSet::dumpProcessors() const { |
99 | SkString result; |
100 | if (this->numFragmentProcessors()) { |
101 | if (this->numColorFragmentProcessors()) { |
102 | result.append("Color Fragment Processors:\n" ); |
103 | for (int i = 0; i < this->numColorFragmentProcessors(); ++i) { |
104 | result += dump_fragment_processor_tree(this->colorFragmentProcessor(i), 1); |
105 | } |
106 | } else { |
107 | result.append("No color fragment processors.\n" ); |
108 | } |
109 | if (this->numCoverageFragmentProcessors()) { |
110 | result.append("Coverage Fragment Processors:\n" ); |
111 | for (int i = 0; i < this->numColorFragmentProcessors(); ++i) { |
112 | result += dump_fragment_processor_tree(this->coverageFragmentProcessor(i), 1); |
113 | } |
114 | } else { |
115 | result.append("No coverage fragment processors.\n" ); |
116 | } |
117 | } else { |
118 | result.append("No color or coverage fragment processors.\n" ); |
119 | } |
120 | if (this->isFinalized()) { |
121 | result.append("Xfer Processor: " ); |
122 | if (this->xferProcessor()) { |
123 | result.appendf("%s\n" , this->xferProcessor()->name()); |
124 | } else { |
125 | result.append("SrcOver\n" ); |
126 | } |
127 | } else { |
128 | result.append("XP Factory dumping not implemented.\n" ); |
129 | } |
130 | return result; |
131 | } |
132 | #endif |
133 | |
134 | bool GrProcessorSet::operator==(const GrProcessorSet& that) const { |
135 | SkASSERT(this->isFinalized()); |
136 | SkASSERT(that.isFinalized()); |
137 | int fpCount = this->numFragmentProcessors(); |
138 | if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() || |
139 | fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) { |
140 | return false; |
141 | } |
142 | |
143 | for (int i = 0; i < fpCount; ++i) { |
144 | int a = i + fFragmentProcessorOffset; |
145 | int b = i + that.fFragmentProcessorOffset; |
146 | if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) { |
147 | return false; |
148 | } |
149 | } |
150 | // Most of the time both of these are null |
151 | if (!this->xferProcessor() && !that.xferProcessor()) { |
152 | return true; |
153 | } |
154 | const GrXferProcessor& thisXP = this->xferProcessor() |
155 | ? *this->xferProcessor() |
156 | : GrPorterDuffXPFactory::SimpleSrcOverXP(); |
157 | const GrXferProcessor& thatXP = that.xferProcessor() |
158 | ? *that.xferProcessor() |
159 | : GrPorterDuffXPFactory::SimpleSrcOverXP(); |
160 | return thisXP.isEqual(thatXP); |
161 | } |
162 | |
163 | GrProcessorSet::Analysis GrProcessorSet::finalize( |
164 | const GrProcessorAnalysisColor& colorInput, const GrProcessorAnalysisCoverage coverageInput, |
165 | const GrAppliedClip* clip, const GrUserStencilSettings* userStencil, |
166 | bool hasMixedSampledCoverage, const GrCaps& caps, GrClampType clampType, |
167 | SkPMColor4f* overrideInputColor) { |
168 | SkASSERT(!this->isFinalized()); |
169 | SkASSERT(!fFragmentProcessorOffset); |
170 | |
171 | GrProcessorSet::Analysis analysis; |
172 | analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput; |
173 | |
174 | const std::unique_ptr<GrFragmentProcessor>* fps = |
175 | fFragmentProcessors.get() + fFragmentProcessorOffset; |
176 | GrColorFragmentProcessorAnalysis colorAnalysis(colorInput, fps, fColorFragmentProcessorCnt); |
177 | fps += fColorFragmentProcessorCnt; |
178 | int n = this->numCoverageFragmentProcessors(); |
179 | bool hasCoverageFP = n > 0; |
180 | bool coverageUsesLocalCoords = false; |
181 | for (int i = 0; i < n; ++i) { |
182 | if (!fps[i]->compatibleWithCoverageAsAlpha()) { |
183 | analysis.fCompatibleWithCoverageAsAlpha = false; |
184 | } |
185 | coverageUsesLocalCoords |= fps[i]->usesLocalCoords(); |
186 | } |
187 | if (clip) { |
188 | hasCoverageFP = hasCoverageFP || clip->numClipCoverageFragmentProcessors(); |
189 | for (int i = 0; i < clip->numClipCoverageFragmentProcessors(); ++i) { |
190 | const GrFragmentProcessor* clipFP = clip->clipCoverageFragmentProcessor(i); |
191 | analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha(); |
192 | coverageUsesLocalCoords |= clipFP->usesLocalCoords(); |
193 | } |
194 | } |
195 | int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor); |
196 | analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>( |
197 | colorFPsToEliminate ? Analysis::kOverridden_InputColorType |
198 | : Analysis::kOriginal_InputColorType); |
199 | |
200 | GrProcessorAnalysisCoverage outputCoverage; |
201 | if (GrProcessorAnalysisCoverage::kLCD == coverageInput) { |
202 | outputCoverage = GrProcessorAnalysisCoverage::kLCD; |
203 | } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) { |
204 | outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel; |
205 | } else { |
206 | outputCoverage = GrProcessorAnalysisCoverage::kNone; |
207 | } |
208 | |
209 | GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties( |
210 | this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps, clampType); |
211 | if (!this->numCoverageFragmentProcessors() && |
212 | GrProcessorAnalysisCoverage::kNone == coverageInput) { |
213 | } |
214 | analysis.fRequiresDstTexture = |
215 | SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture); |
216 | analysis.fCompatibleWithCoverageAsAlpha &= |
217 | SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithCoverageAsAlpha); |
218 | analysis.fRequiresNonOverlappingDraws = SkToBool( |
219 | props & GrXPFactory::AnalysisProperties::kRequiresNonOverlappingDraws); |
220 | if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) { |
221 | colorFPsToEliminate = this->numColorFragmentProcessors(); |
222 | analysis.fInputColorType = |
223 | static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType); |
224 | analysis.fUsesLocalCoords = coverageUsesLocalCoords; |
225 | } else { |
226 | analysis.fCompatibleWithCoverageAsAlpha &= |
227 | colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha(); |
228 | analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords(); |
229 | } |
230 | for (int i = 0; i < colorFPsToEliminate; ++i) { |
231 | fFragmentProcessors[i].reset(nullptr); |
232 | } |
233 | fFragmentProcessorOffset = colorFPsToEliminate; |
234 | fColorFragmentProcessorCnt -= colorFPsToEliminate; |
235 | analysis.fHasColorFragmentProcessor = (fColorFragmentProcessorCnt != 0); |
236 | |
237 | auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(), |
238 | outputCoverage, hasMixedSampledCoverage, caps, |
239 | clampType); |
240 | fXP.fProcessor = xp.release(); |
241 | |
242 | fFlags |= kFinalized_Flag; |
243 | analysis.fIsInitialized = true; |
244 | #ifdef SK_DEBUG |
245 | bool hasXferBarrier = |
246 | fXP.fProcessor && |
247 | GrXferBarrierType::kNone_GrXferBarrierType != fXP.fProcessor->xferBarrierType(caps); |
248 | bool needsNonOverlappingDraws = analysis.fRequiresDstTexture || hasXferBarrier; |
249 | SkASSERT(analysis.fRequiresNonOverlappingDraws == needsNonOverlappingDraws); |
250 | #endif |
251 | return analysis; |
252 | } |
253 | |
254 | void GrProcessorSet::visitProxies(const GrOp::VisitProxyFunc& func) const { |
255 | for (auto [sampler, fp] : GrFragmentProcessor::ProcessorSetTextureSamplerRange(*this)) { |
256 | bool mipped = (GrSamplerState::Filter::kMipMap == sampler.samplerState().filter()); |
257 | func(sampler.view().proxy(), GrMipMapped(mipped)); |
258 | } |
259 | } |
260 | |