xref: /third_party/skia/src/gpu/GrProcessorSet.cpp (revision cb93a386)
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/GrAppliedClip.h"
10#include "src/gpu/GrCaps.h"
11#include "src/gpu/GrProcessorSet.h"
12#include "src/gpu/GrUserStencilSettings.h"
13#include "src/gpu/GrXferProcessor.h"
14#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
15
16const GrProcessorSet& GrProcessorSet::EmptySet() {
17    static GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty);
18    return gEmpty;
19}
20
21GrProcessorSet GrProcessorSet::MakeEmptySet() {
22    return GrProcessorSet(GrProcessorSet::Empty::kEmpty);
23}
24
25GrProcessorSet::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
32GrProcessorSet::GrProcessorSet(SkBlendMode mode) : fXP(SkBlendMode_AsXPFactory(mode)) {}
33
34GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)
35        : fXP((const GrXPFactory*)nullptr) {
36    SkASSERT(colorFP);
37    fColorFragmentProcessor = std::move(colorFP);
38}
39
40GrProcessorSet::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
46GrProcessorSet::~GrProcessorSet() {
47    if (this->isFinalized() && this->xferProcessor()) {
48        this->xferProcessor()->unref();
49    }
50}
51
52#if GR_TEST_UTILS
53SkString 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
81bool 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
115GrProcessorSet::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
199void 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