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/ganesh/GrAppliedClip.h"
10 #include "src/gpu/ganesh/GrCaps.h"
11 #include "src/gpu/ganesh/GrProcessorSet.h"
12 #include "src/gpu/ganesh/GrUserStencilSettings.h"
13 #include "src/gpu/ganesh/GrXferProcessor.h"
14 #include "src/gpu/ganesh/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 fColorFragmentProcessor = std::move(paint.fColorFragmentProcessor);
27 fCoverageFragmentProcessor = std::move(paint.fCoverageFragmentProcessor);
28
29 SkDEBUGCODE(paint.fAlive = false;)
30 }
31
GrProcessorSet(SkBlendMode mode)32 GrProcessorSet::GrProcessorSet(SkBlendMode mode) : fXP(SkBlendMode_AsXPFactory(mode)) {}
33
GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)34 GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)
35 : fXP((const GrXPFactory*)nullptr) {
36 SkASSERT(colorFP);
37 fColorFragmentProcessor = std::move(colorFP);
38 }
39
GrProcessorSet(GrProcessorSet && that)40 GrProcessorSet::GrProcessorSet(GrProcessorSet&& that)
41 : fColorFragmentProcessor(std::move(that.fColorFragmentProcessor))
42 , fCoverageFragmentProcessor(std::move(that.fCoverageFragmentProcessor))
43 , fXP(std::move(that.fXP))
44 , fFlags(that.fFlags) {}
45
~GrProcessorSet()46 GrProcessorSet::~GrProcessorSet() {
47 if (this->isFinalized() && this->xferProcessor()) {
48 this->xferProcessor()->unref();
49 }
50 }
51
52 #if GR_TEST_UTILS
dumpProcessors() const53 SkString GrProcessorSet::dumpProcessors() const {
54 SkString result;
55 if (this->hasColorFragmentProcessor()) {
56 result.append("Color Fragment Processor:\n");
57 result += this->colorFragmentProcessor()->dumpTreeInfo();
58 } else {
59 result.append("No color fragment processor.\n");
60 }
61 if (this->hasCoverageFragmentProcessor()) {
62 result.append("Coverage Fragment Processor:\n");
63 result += this->coverageFragmentProcessor()->dumpTreeInfo();
64 } else {
65 result.append("No coverage fragment processors.\n");
66 }
67 if (this->isFinalized()) {
68 result.append("Xfer Processor: ");
69 if (this->xferProcessor()) {
70 result.appendf("%s\n", this->xferProcessor()->name());
71 } else {
72 result.append("SrcOver\n");
73 }
74 } else {
75 result.append("XP Factory dumping not implemented.\n");
76 }
77 return result;
78 }
79 #endif
80
operator ==(const GrProcessorSet & that) const81 bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
82 SkASSERT(this->isFinalized());
83 SkASSERT(that.isFinalized());
84 if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) ||
85 this->hasColorFragmentProcessor() != that.hasColorFragmentProcessor() ||
86 this->hasCoverageFragmentProcessor() != that.hasCoverageFragmentProcessor()) {
87 return false;
88 }
89
90 if (this->hasColorFragmentProcessor()) {
91 if (!colorFragmentProcessor()->isEqual(*that.colorFragmentProcessor())) {
92 return false;
93 }
94 }
95
96 if (this->hasCoverageFragmentProcessor()) {
97 if (!coverageFragmentProcessor()->isEqual(*that.coverageFragmentProcessor())) {
98 return false;
99 }
100 }
101
102 // Most of the time both of these are null
103 if (!this->xferProcessor() && !that.xferProcessor()) {
104 return true;
105 }
106 const GrXferProcessor& thisXP = this->xferProcessor()
107 ? *this->xferProcessor()
108 : GrPorterDuffXPFactory::SimpleSrcOverXP();
109 const GrXferProcessor& thatXP = that.xferProcessor()
110 ? *that.xferProcessor()
111 : GrPorterDuffXPFactory::SimpleSrcOverXP();
112 return thisXP.isEqual(thatXP);
113 }
114
finalize(const GrProcessorAnalysisColor & colorInput,const GrProcessorAnalysisCoverage coverageInput,const GrAppliedClip * clip,const GrUserStencilSettings * userStencil,const GrCaps & caps,GrClampType clampType,SkPMColor4f * overrideInputColor)115 GrProcessorSet::Analysis GrProcessorSet::finalize(
116 const GrProcessorAnalysisColor& colorInput, const GrProcessorAnalysisCoverage coverageInput,
117 const GrAppliedClip* clip, const GrUserStencilSettings* userStencil,
118 const GrCaps& caps, GrClampType clampType, SkPMColor4f* overrideInputColor) {
119 SkASSERT(!this->isFinalized());
120
121 GrProcessorSet::Analysis analysis;
122 analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
123
124 GrColorFragmentProcessorAnalysis colorAnalysis(colorInput, &fColorFragmentProcessor,
125 this->hasColorFragmentProcessor() ? 1 : 0);
126 bool hasCoverageFP = this->hasCoverageFragmentProcessor();
127 bool coverageUsesLocalCoords = false;
128 if (hasCoverageFP) {
129 if (!fCoverageFragmentProcessor->compatibleWithCoverageAsAlpha()) {
130 analysis.fCompatibleWithCoverageAsAlpha = false;
131 }
132 coverageUsesLocalCoords |= fCoverageFragmentProcessor->usesSampleCoords();
133 }
134 if (clip && clip->hasCoverageFragmentProcessor()) {
135 hasCoverageFP = true;
136 const GrFragmentProcessor* clipFP = clip->coverageFragmentProcessor();
137 analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
138 coverageUsesLocalCoords |= clipFP->usesSampleCoords();
139 }
140 int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
141 analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
142 colorFPsToEliminate ? Analysis::kOverridden_InputColorType
143 : Analysis::kOriginal_InputColorType);
144
145 GrProcessorAnalysisCoverage outputCoverage;
146 if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
147 outputCoverage = GrProcessorAnalysisCoverage::kLCD;
148 } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
149 outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
150 } else {
151 outputCoverage = GrProcessorAnalysisCoverage::kNone;
152 }
153
154 GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
155 this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps, clampType);
156 analysis.fRequiresDstTexture = (props & GrXPFactory::AnalysisProperties::kRequiresDstTexture) ||
157 colorAnalysis.requiresDstTexture(caps);
158 analysis.fCompatibleWithCoverageAsAlpha &=
159 SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithCoverageAsAlpha);
160 analysis.fRequiresNonOverlappingDraws =
161 (props & GrXPFactory::AnalysisProperties::kRequiresNonOverlappingDraws) ||
162 analysis.fRequiresDstTexture;
163 analysis.fUsesNonCoherentHWBlending =
164 SkToBool(props & GrXPFactory::AnalysisProperties::kUsesNonCoherentHWBlending);
165 analysis.fUnaffectedByDstValue =
166 SkToBool(props & GrXPFactory::AnalysisProperties::kUnaffectedByDstValue);
167 if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
168 colorFPsToEliminate = this->hasColorFragmentProcessor() ? 1 : 0;
169 analysis.fInputColorType =
170 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
171 analysis.fUsesLocalCoords = coverageUsesLocalCoords;
172 } else {
173 analysis.fCompatibleWithCoverageAsAlpha &=
174 colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
175 analysis.fUsesLocalCoords = coverageUsesLocalCoords || colorAnalysis.usesLocalCoords();
176 }
177 if (colorFPsToEliminate) {
178 SkASSERT(colorFPsToEliminate == 1);
179 fColorFragmentProcessor = nullptr;
180 }
181 analysis.fHasColorFragmentProcessor = this->hasColorFragmentProcessor();
182
183 auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
184 outputCoverage, caps, clampType);
185 fXP.fProcessor = xp.release();
186
187 fFlags |= kFinalized_Flag;
188 analysis.fIsInitialized = true;
189 #ifdef SK_DEBUG
190 bool hasXferBarrier =
191 fXP.fProcessor &&
192 GrXferBarrierType::kNone_GrXferBarrierType != fXP.fProcessor->xferBarrierType(caps);
193 bool needsNonOverlappingDraws = analysis.fRequiresDstTexture || hasXferBarrier;
194 SkASSERT(analysis.fRequiresNonOverlappingDraws == needsNonOverlappingDraws);
195 #endif
196 return analysis;
197 }
198
visitProxies(const GrVisitProxyFunc & func) const199 void GrProcessorSet::visitProxies(const GrVisitProxyFunc& func) const {
200 if (this->hasColorFragmentProcessor()) {
201 fColorFragmentProcessor->visitProxies(func);
202 }
203 if (this->hasCoverageFragmentProcessor()) {
204 fCoverageFragmentProcessor->visitProxies(func);
205 }
206 }
207