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 "GrUserStencilSettings.h"
12 #include "GrXferProcessor.h"
13 #include "SkBlendModePriv.h"
14 #include "effects/GrPorterDuffXferProcessor.h"
15 
EmptySet()16 const GrProcessorSet& GrProcessorSet::EmptySet() {
17     static GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty);
18     return gEmpty;
19 }
20 
MakeEmptySet()21 GrProcessorSet GrProcessorSet::MakeEmptySet() {
22     return GrProcessorSet(GrProcessorSet::Empty::kEmpty);
23 }
24 
GrProcessorSet(GrPaint && paint)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 
GrProcessorSet(SkBlendMode mode)46 GrProcessorSet::GrProcessorSet(SkBlendMode mode)
47         : fXP(SkBlendMode_AsXPFactory(mode))
48         , fColorFragmentProcessorCnt(0)
49         , fFragmentProcessorOffset(0)
50         , fFlags(0) {}
51 
GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)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 
GrProcessorSet(GrProcessorSet && that)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 
~GrProcessorSet()76 GrProcessorSet::~GrProcessorSet() {
77     if (this->isFinalized() && this->xferProcessor()) {
78         this->xferProcessor()->unref();
79     }
80 }
81 
82 #ifdef SK_DEBUG
dump_fragment_processor_tree(const GrFragmentProcessor * fp,int indentCnt)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 
dumpProcessors() const98 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 
operator ==(const GrProcessorSet & that) const134 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 
finalize(const GrProcessorAnalysisColor & colorInput,const GrProcessorAnalysisCoverage coverageInput,const GrAppliedClip * clip,const GrUserStencilSettings * userStencil,GrFSAAType fsaaType,const GrCaps & caps,GrClampType clampType,SkPMColor4f * overrideInputColor)163 GrProcessorSet::Analysis GrProcessorSet::finalize(
164         const GrProcessorAnalysisColor& colorInput, const GrProcessorAnalysisCoverage coverageInput,
165         const GrAppliedClip* clip, const GrUserStencilSettings* userStencil, GrFSAAType fsaaType,
166         const GrCaps& caps, GrClampType clampType, 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, clampType);
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     analysis.fHasColorFragmentProcessor = (fColorFragmentProcessorCnt != 0);
239 
240     bool hasMixedSampledCoverage = (GrFSAAType::kMixedSamples == fsaaType)
241             && !userStencil->testAlwaysPasses((clip) ? clip->hasStencilClip() : false);
242     auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
243                                              outputCoverage, hasMixedSampledCoverage, caps,
244                                              clampType);
245     fXP.fProcessor = xp.release();
246 
247     fFlags |= kFinalized_Flag;
248     analysis.fIsInitialized = true;
249 #ifdef SK_DEBUG
250     bool hasXferBarrier =
251             fXP.fProcessor &&
252             GrXferBarrierType::kNone_GrXferBarrierType != fXP.fProcessor->xferBarrierType(caps);
253     bool needsNonOverlappingDraws = analysis.fRequiresDstTexture || hasXferBarrier;
254     SkASSERT(analysis.fRequiresNonOverlappingDraws == needsNonOverlappingDraws);
255 #endif
256     return analysis;
257 }
258