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