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 "GrProcessorSet.h"
9 #include "GrAppliedClip.h"
10 #include "GrCaps.h"
11 #include "GrXferProcessor.h"
12 #include "SkBlendModePriv.h"
13 #include "effects/GrPorterDuffXferProcessor.h"
14
EmptySet()15 const GrProcessorSet& GrProcessorSet::EmptySet() {
16 static GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty);
17 return gEmpty;
18 }
19
MakeEmptySet()20 GrProcessorSet GrProcessorSet::MakeEmptySet() {
21 return GrProcessorSet(GrProcessorSet::Empty::kEmpty);
22 }
23
GrProcessorSet(GrPaint && paint)24 GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
25 fFlags = 0;
26 if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
27 fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
28 fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
29 int i = 0;
30 for (auto& fp : paint.fColorFragmentProcessors) {
31 SkASSERT(fp.get());
32 fFragmentProcessors[i++] = std::move(fp);
33 }
34 for (auto& fp : paint.fCoverageFragmentProcessors) {
35 SkASSERT(fp.get());
36 fFragmentProcessors[i++] = std::move(fp);
37 }
38 } else {
39 SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
40 fColorFragmentProcessorCnt = 0;
41 }
42 }
43
GrProcessorSet(SkBlendMode mode)44 GrProcessorSet::GrProcessorSet(SkBlendMode mode)
45 : fXP(SkBlendMode_AsXPFactory(mode))
46 , fColorFragmentProcessorCnt(0)
47 , fFragmentProcessorOffset(0)
48 , fFlags(0) {}
49
GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)50 GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)
51 : fFragmentProcessors(1)
52 , fXP((const GrXPFactory*)nullptr)
53 , fColorFragmentProcessorCnt(1)
54 , fFragmentProcessorOffset(0)
55 , fFlags(0) {
56 SkASSERT(colorFP);
57 fFragmentProcessors[0] = std::move(colorFP);
58 }
59
GrProcessorSet(GrProcessorSet && that)60 GrProcessorSet::GrProcessorSet(GrProcessorSet&& that)
61 : fXP(std::move(that.fXP))
62 , fColorFragmentProcessorCnt(that.fColorFragmentProcessorCnt)
63 , fFragmentProcessorOffset(0)
64 , fFlags(that.fFlags) {
65 fFragmentProcessors.reset(that.fFragmentProcessors.count() - that.fFragmentProcessorOffset);
66 for (int i = 0; i < fFragmentProcessors.count(); ++i) {
67 fFragmentProcessors[i] =
68 std::move(that.fFragmentProcessors[i + that.fFragmentProcessorOffset]);
69 }
70 that.fColorFragmentProcessorCnt = 0;
71 that.fFragmentProcessors.reset(0);
72 }
73
~GrProcessorSet()74 GrProcessorSet::~GrProcessorSet() {
75 if (this->isFinalized() && this->xferProcessor()) {
76 this->xferProcessor()->unref();
77 }
78 }
79
dump_fragment_processor_tree(const GrFragmentProcessor * fp,int indentCnt)80 SkString dump_fragment_processor_tree(const GrFragmentProcessor* fp, int indentCnt) {
81 SkString result;
82 SkString indentString;
83 for (int i = 0; i < indentCnt; ++i) {
84 indentString.append(" ");
85 }
86 result.appendf("%s%s %s \n", indentString.c_str(), fp->name(), fp->dumpInfo().c_str());
87 if (fp->numChildProcessors()) {
88 for (int i = 0; i < fp->numChildProcessors(); ++i) {
89 result += dump_fragment_processor_tree(&fp->childProcessor(i), indentCnt + 1);
90 }
91 }
92 return result;
93 }
94
dumpProcessors() const95 SkString GrProcessorSet::dumpProcessors() const {
96 SkString result;
97 if (this->numFragmentProcessors()) {
98 if (this->numColorFragmentProcessors()) {
99 result.append("Color Fragment Processors:\n");
100 for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
101 result += dump_fragment_processor_tree(this->colorFragmentProcessor(i), 1);
102 }
103 } else {
104 result.append("No color fragment processors.\n");
105 }
106 if (this->numCoverageFragmentProcessors()) {
107 result.append("Coverage Fragment Processors:\n");
108 for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
109 result += dump_fragment_processor_tree(this->coverageFragmentProcessor(i), 1);
110 }
111 } else {
112 result.append("No coverage fragment processors.\n");
113 }
114 } else {
115 result.append("No color or coverage fragment processors.\n");
116 }
117 if (this->isFinalized()) {
118 result.append("Xfer Processor: ");
119 if (this->xferProcessor()) {
120 result.appendf("%s\n", this->xferProcessor()->name());
121 } else {
122 result.append("SrcOver\n");
123 }
124 } else {
125 result.append("XP Factory dumping not implemented.\n");
126 }
127 return result;
128 }
129
operator ==(const GrProcessorSet & that) const130 bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
131 SkASSERT(this->isFinalized());
132 SkASSERT(that.isFinalized());
133 int fpCount = this->numFragmentProcessors();
134 if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
135 fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
136 return false;
137 }
138
139 for (int i = 0; i < fpCount; ++i) {
140 int a = i + fFragmentProcessorOffset;
141 int b = i + that.fFragmentProcessorOffset;
142 if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
143 return false;
144 }
145 }
146 // Most of the time both of these are null
147 if (!this->xferProcessor() && !that.xferProcessor()) {
148 return true;
149 }
150 const GrXferProcessor& thisXP = this->xferProcessor()
151 ? *this->xferProcessor()
152 : GrPorterDuffXPFactory::SimpleSrcOverXP();
153 const GrXferProcessor& thatXP = that.xferProcessor()
154 ? *that.xferProcessor()
155 : GrPorterDuffXPFactory::SimpleSrcOverXP();
156 return thisXP.isEqual(thatXP);
157 }
158
finalize(const GrProcessorAnalysisColor & colorInput,const GrProcessorAnalysisCoverage coverageInput,const GrAppliedClip * clip,bool isMixedSamples,const GrCaps & caps,GrPixelConfigIsClamped dstIsClamped,GrColor * overrideInputColor)159 GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
160 const GrProcessorAnalysisCoverage coverageInput,
161 const GrAppliedClip* clip, bool isMixedSamples,
162 const GrCaps& caps,
163 GrPixelConfigIsClamped dstIsClamped,
164 GrColor* overrideInputColor) {
165 SkASSERT(!this->isFinalized());
166 SkASSERT(!fFragmentProcessorOffset);
167
168 GrProcessorSet::Analysis analysis;
169 analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
170
171 const std::unique_ptr<const GrFragmentProcessor>* fps =
172 fFragmentProcessors.get() + fFragmentProcessorOffset;
173 GrColorFragmentProcessorAnalysis colorAnalysis(
174 colorInput, unique_ptr_address_as_pointer_address(fps), fColorFragmentProcessorCnt);
175 analysis.fCompatibleWithCoverageAsAlpha &=
176 colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
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, dstIsClamped);
211 if (!this->numCoverageFragmentProcessors() &&
212 GrProcessorAnalysisCoverage::kNone == coverageInput) {
213 analysis.fCanCombineOverlappedStencilAndCover = SkToBool(
214 props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
215 } else {
216 // If we have non-clipping coverage processors we don't try to merge stencil steps as its
217 // unclear whether it will be correct. We don't expect this to happen in practice.
218 analysis.fCanCombineOverlappedStencilAndCover = false;
219 }
220 analysis.fRequiresDstTexture =
221 SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
222 analysis.fCompatibleWithCoverageAsAlpha &=
223 SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
224 analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
225 props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
226 if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
227 colorFPsToEliminate = this->numColorFragmentProcessors();
228 analysis.fInputColorType =
229 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
230 analysis.fUsesLocalCoords = coverageUsesLocalCoords;
231 } else {
232 analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
233 }
234 for (int i = 0; i < colorFPsToEliminate; ++i) {
235 fFragmentProcessors[i].reset(nullptr);
236 }
237 for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
238 fFragmentProcessors[i]->markPendingExecution();
239 }
240 fFragmentProcessorOffset = colorFPsToEliminate;
241 fColorFragmentProcessorCnt -= colorFPsToEliminate;
242
243 auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
244 outputCoverage, isMixedSamples, caps, dstIsClamped);
245 fXP.fProcessor = xp.release();
246
247 fFlags |= kFinalized_Flag;
248 analysis.fIsInitialized = true;
249 return analysis;
250 }
251