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