• 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 "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