• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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