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 | fColorFragmentProcessor = std::move(paint.fColorFragmentProcessor); |
27 | fCoverageFragmentProcessor = std::move(paint.fCoverageFragmentProcessor); |
28 | |
29 | SkDEBUGCODE(paint.fAlive = false;) |
30 | } |
31 | |
32 | GrProcessorSet::GrProcessorSet(SkBlendMode mode) : fXP(SkBlendMode_AsXPFactory(mode)) {} |
33 | |
34 | GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP) |
35 | : fXP((const GrXPFactory*)nullptr) { |
36 | SkASSERT(colorFP); |
37 | fColorFragmentProcessor = std::move(colorFP); |
38 | } |
39 | |
40 | GrProcessorSet::GrProcessorSet(GrProcessorSet&& that) |
41 | : fColorFragmentProcessor(std::move(that.fColorFragmentProcessor)) |
42 | , fCoverageFragmentProcessor(std::move(that.fCoverageFragmentProcessor)) |
43 | , fXP(std::move(that.fXP)) |
44 | , fFlags(that.fFlags) {} |
45 | |
46 | GrProcessorSet::~GrProcessorSet() { |
47 | if (this->isFinalized() && this->xferProcessor()) { |
48 | this->xferProcessor()->unref(); |
49 | } |
50 | } |
51 | |
52 | #if GR_TEST_UTILS |
53 | SkString GrProcessorSet::dumpProcessors() const { |
54 | SkString result; |
55 | if (this->hasColorFragmentProcessor()) { |
56 | result.append("Color Fragment Processor:\n" ); |
57 | result += this->colorFragmentProcessor()->dumpTreeInfo(); |
58 | } else { |
59 | result.append("No color fragment processor.\n" ); |
60 | } |
61 | if (this->hasCoverageFragmentProcessor()) { |
62 | result.append("Coverage Fragment Processor:\n" ); |
63 | result += this->coverageFragmentProcessor()->dumpTreeInfo(); |
64 | } else { |
65 | result.append("No coverage fragment processors.\n" ); |
66 | } |
67 | if (this->isFinalized()) { |
68 | result.append("Xfer Processor: " ); |
69 | if (this->xferProcessor()) { |
70 | result.appendf("%s\n" , this->xferProcessor()->name()); |
71 | } else { |
72 | result.append("SrcOver\n" ); |
73 | } |
74 | } else { |
75 | result.append("XP Factory dumping not implemented.\n" ); |
76 | } |
77 | return result; |
78 | } |
79 | #endif |
80 | |
81 | bool GrProcessorSet::operator==(const GrProcessorSet& that) const { |
82 | SkASSERT(this->isFinalized()); |
83 | SkASSERT(that.isFinalized()); |
84 | if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || |
85 | this->hasColorFragmentProcessor() != that.hasColorFragmentProcessor() || |
86 | this->hasCoverageFragmentProcessor() != that.hasCoverageFragmentProcessor()) { |
87 | return false; |
88 | } |
89 | |
90 | if (this->hasColorFragmentProcessor()) { |
91 | if (!colorFragmentProcessor()->isEqual(*that.colorFragmentProcessor())) { |
92 | return false; |
93 | } |
94 | } |
95 | |
96 | if (this->hasCoverageFragmentProcessor()) { |
97 | if (!coverageFragmentProcessor()->isEqual(*that.coverageFragmentProcessor())) { |
98 | return false; |
99 | } |
100 | } |
101 | |
102 | // Most of the time both of these are null |
103 | if (!this->xferProcessor() && !that.xferProcessor()) { |
104 | return true; |
105 | } |
106 | const GrXferProcessor& thisXP = this->xferProcessor() |
107 | ? *this->xferProcessor() |
108 | : GrPorterDuffXPFactory::SimpleSrcOverXP(); |
109 | const GrXferProcessor& thatXP = that.xferProcessor() |
110 | ? *that.xferProcessor() |
111 | : GrPorterDuffXPFactory::SimpleSrcOverXP(); |
112 | return thisXP.isEqual(thatXP); |
113 | } |
114 | |
115 | GrProcessorSet::Analysis GrProcessorSet::finalize( |
116 | const GrProcessorAnalysisColor& colorInput, const GrProcessorAnalysisCoverage coverageInput, |
117 | const GrAppliedClip* clip, const GrUserStencilSettings* userStencil, |
118 | bool hasMixedSampledCoverage, const GrCaps& caps, GrClampType clampType, |
119 | SkPMColor4f* overrideInputColor) { |
120 | SkASSERT(!this->isFinalized()); |
121 | |
122 | GrProcessorSet::Analysis analysis; |
123 | analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput; |
124 | |
125 | GrColorFragmentProcessorAnalysis colorAnalysis(colorInput, &fColorFragmentProcessor, |
126 | this->hasColorFragmentProcessor() ? 1 : 0); |
127 | bool hasCoverageFP = this->hasCoverageFragmentProcessor(); |
128 | bool coverageUsesLocalCoords = false; |
129 | if (hasCoverageFP) { |
130 | if (!fCoverageFragmentProcessor->compatibleWithCoverageAsAlpha()) { |
131 | analysis.fCompatibleWithCoverageAsAlpha = false; |
132 | } |
133 | coverageUsesLocalCoords |= fCoverageFragmentProcessor->usesVaryingCoords(); |
134 | } |
135 | if (clip && clip->hasCoverageFragmentProcessor()) { |
136 | hasCoverageFP = true; |
137 | const GrFragmentProcessor* clipFP = clip->coverageFragmentProcessor(); |
138 | analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha(); |
139 | coverageUsesLocalCoords |= clipFP->usesVaryingCoords(); |
140 | } |
141 | int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor); |
142 | analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>( |
143 | colorFPsToEliminate ? Analysis::kOverridden_InputColorType |
144 | : Analysis::kOriginal_InputColorType); |
145 | |
146 | GrProcessorAnalysisCoverage outputCoverage; |
147 | if (GrProcessorAnalysisCoverage::kLCD == coverageInput) { |
148 | outputCoverage = GrProcessorAnalysisCoverage::kLCD; |
149 | } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) { |
150 | outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel; |
151 | } else { |
152 | outputCoverage = GrProcessorAnalysisCoverage::kNone; |
153 | } |
154 | |
155 | GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties( |
156 | this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps, clampType); |
157 | analysis.fRequiresDstTexture = |
158 | SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture); |
159 | analysis.fCompatibleWithCoverageAsAlpha &= |
160 | SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithCoverageAsAlpha); |
161 | analysis.fRequiresNonOverlappingDraws = |
162 | SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresNonOverlappingDraws); |
163 | if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) { |
164 | colorFPsToEliminate = this->hasColorFragmentProcessor() ? 1 : 0; |
165 | analysis.fInputColorType = |
166 | static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType); |
167 | analysis.fUsesLocalCoords = coverageUsesLocalCoords; |
168 | } else { |
169 | analysis.fCompatibleWithCoverageAsAlpha &= |
170 | colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha(); |
171 | analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords(); |
172 | } |
173 | if (colorFPsToEliminate) { |
174 | SkASSERT(colorFPsToEliminate == 1); |
175 | fColorFragmentProcessor = nullptr; |
176 | } |
177 | analysis.fHasColorFragmentProcessor = this->hasColorFragmentProcessor(); |
178 | |
179 | auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(), |
180 | outputCoverage, hasMixedSampledCoverage, caps, |
181 | clampType); |
182 | fXP.fProcessor = xp.release(); |
183 | |
184 | fFlags |= kFinalized_Flag; |
185 | analysis.fIsInitialized = true; |
186 | #ifdef SK_DEBUG |
187 | bool hasXferBarrier = |
188 | fXP.fProcessor && |
189 | GrXferBarrierType::kNone_GrXferBarrierType != fXP.fProcessor->xferBarrierType(caps); |
190 | bool needsNonOverlappingDraws = analysis.fRequiresDstTexture || hasXferBarrier; |
191 | SkASSERT(analysis.fRequiresNonOverlappingDraws == needsNonOverlappingDraws); |
192 | #endif |
193 | return analysis; |
194 | } |
195 | |
196 | void GrProcessorSet::visitProxies(const GrOp::VisitProxyFunc& func) const { |
197 | if (this->hasColorFragmentProcessor()) { |
198 | fColorFragmentProcessor->visitProxies(func); |
199 | } |
200 | if (this->hasCoverageFragmentProcessor()) { |
201 | fCoverageFragmentProcessor->visitProxies(func); |
202 | } |
203 | } |
204 | |