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