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 "src/core/SkBlendModePriv.h"
9 #include "src/gpu/GrAppliedClip.h"
10 #include "src/gpu/GrCaps.h"
11 #include "src/gpu/GrProcessorSet.h"
12 #include "src/gpu/GrUserStencilSettings.h"
13 #include "src/gpu/GrXferProcessor.h"
14 #include "src/gpu/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,bool hasMixedSampledCoverage,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,
166         bool hasMixedSampledCoverage, const GrCaps& caps, GrClampType clampType,
167         SkPMColor4f* overrideInputColor) {
168     SkASSERT(!this->isFinalized());
169     SkASSERT(!fFragmentProcessorOffset);
170 
171     GrProcessorSet::Analysis analysis;
172     analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
173 
174     const std::unique_ptr<const GrFragmentProcessor>* fps =
175             fFragmentProcessors.get() + fFragmentProcessorOffset;
176     GrColorFragmentProcessorAnalysis colorAnalysis(
177             colorInput, unique_ptr_address_as_pointer_address(fps), fColorFragmentProcessorCnt);
178     fps += fColorFragmentProcessorCnt;
179     int n = this->numCoverageFragmentProcessors();
180     bool hasCoverageFP = n > 0;
181     bool coverageUsesLocalCoords = false;
182     for (int i = 0; i < n; ++i) {
183         if (!fps[i]->compatibleWithCoverageAsAlpha()) {
184             analysis.fCompatibleWithCoverageAsAlpha = false;
185         }
186         coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
187     }
188     if (clip) {
189         hasCoverageFP = hasCoverageFP || clip->numClipCoverageFragmentProcessors();
190         for (int i = 0; i < clip->numClipCoverageFragmentProcessors(); ++i) {
191             const GrFragmentProcessor* clipFP = clip->clipCoverageFragmentProcessor(i);
192             analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
193             coverageUsesLocalCoords |= clipFP->usesLocalCoords();
194         }
195     }
196     int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
197     analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
198             colorFPsToEliminate ? Analysis::kOverridden_InputColorType
199                                 : Analysis::kOriginal_InputColorType);
200 
201     GrProcessorAnalysisCoverage outputCoverage;
202     if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
203         outputCoverage = GrProcessorAnalysisCoverage::kLCD;
204     } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
205         outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
206     } else {
207         outputCoverage = GrProcessorAnalysisCoverage::kNone;
208     }
209 
210     GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
211             this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps, clampType);
212     if (!this->numCoverageFragmentProcessors() &&
213         GrProcessorAnalysisCoverage::kNone == coverageInput) {
214     }
215     analysis.fRequiresDstTexture =
216             SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
217     analysis.fCompatibleWithCoverageAsAlpha &=
218             SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithCoverageAsAlpha);
219     analysis.fRequiresNonOverlappingDraws = SkToBool(
220             props & GrXPFactory::AnalysisProperties::kRequiresNonOverlappingDraws);
221     if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
222         colorFPsToEliminate = this->numColorFragmentProcessors();
223         analysis.fInputColorType =
224                 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
225         analysis.fUsesLocalCoords = coverageUsesLocalCoords;
226     } else {
227         analysis.fCompatibleWithCoverageAsAlpha &=
228             colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
229         analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
230     }
231     for (int i = 0; i < colorFPsToEliminate; ++i) {
232         fFragmentProcessors[i].reset(nullptr);
233     }
234     fFragmentProcessorOffset = colorFPsToEliminate;
235     fColorFragmentProcessorCnt -= colorFPsToEliminate;
236     analysis.fHasColorFragmentProcessor = (fColorFragmentProcessorCnt != 0);
237 
238     auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
239                                              outputCoverage, hasMixedSampledCoverage, caps,
240                                              clampType);
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