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