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