GrProcessorSet.cpp revision 5f970fe6bed7a40ba95365bfe3220f18699a9176
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 "GrProcessorSet.h"
9#include "GrAppliedClip.h"
10#include "GrCaps.h"
11#include "GrXferProcessor.h"
12#include "effects/GrPorterDuffXferProcessor.h"
13
14const GrProcessorSet& GrProcessorSet::EmptySet() {
15    static const GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty);
16    return gEmpty;
17}
18
19GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
20    fFlags = 0;
21    if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
22        fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
23        fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
24        int i = 0;
25        for (auto& fp : paint.fColorFragmentProcessors) {
26            SkASSERT(fp.get());
27            fFragmentProcessors[i++] = fp.release();
28        }
29        for (auto& fp : paint.fCoverageFragmentProcessors) {
30            SkASSERT(fp.get());
31            fFragmentProcessors[i++] = fp.release();
32        }
33    } else {
34        SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
35        fColorFragmentProcessorCnt = 0;
36    }
37}
38
39GrProcessorSet::~GrProcessorSet() {
40    for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
41        if (this->isFinalized()) {
42            fFragmentProcessors[i]->completedExecution();
43        } else {
44            fFragmentProcessors[i]->unref();
45        }
46    }
47    if (this->isFinalized() && this->xferProcessor()) {
48        this->xferProcessor()->unref();
49    }
50}
51
52SkString dump_fragment_processor_tree(const GrFragmentProcessor* fp, int indentCnt) {
53    SkString result;
54    SkString indentString;
55    for (int i = 0; i < indentCnt; ++i) {
56        indentString.append("    ");
57    }
58    result.appendf("%s%s %s \n", indentString.c_str(), fp->name(), fp->dumpInfo().c_str());
59    if (fp->numChildProcessors()) {
60        for (int i = 0; i < fp->numChildProcessors(); ++i) {
61            result += dump_fragment_processor_tree(&fp->childProcessor(i), indentCnt + 1);
62        }
63    }
64    return result;
65}
66
67SkString GrProcessorSet::dumpProcessors() const {
68    SkString result;
69    if (this->numFragmentProcessors()) {
70        if (this->numColorFragmentProcessors()) {
71            result.append("Color Fragment Processors:\n");
72            for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
73                result += dump_fragment_processor_tree(this->colorFragmentProcessor(i), 1);
74            }
75        } else {
76            result.append("No color fragment processors.\n");
77        }
78        if (this->numCoverageFragmentProcessors()) {
79            result.append("Coverage Fragment Processors:\n");
80            for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
81                result += dump_fragment_processor_tree(this->coverageFragmentProcessor(i), 1);
82            }
83        } else {
84            result.append("No coverage fragment processors.\n");
85        }
86    } else {
87        result.append("No color or coverage fragment processors.\n");
88    }
89    if (this->isFinalized()) {
90        result.append("Xfer Processor: ");
91        if (this->xferProcessor()) {
92            result.appendf("%s\n", this->xferProcessor()->name());
93        } else {
94            result.append("SrcOver\n");
95        }
96    } else {
97        result.append("XP Factory dumping not implemented.\n");
98    }
99    return result;
100}
101
102bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
103    SkASSERT(this->isFinalized());
104    SkASSERT(that.isFinalized());
105    int fpCount = this->numFragmentProcessors();
106    if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
107        fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
108        return false;
109    }
110
111    for (int i = 0; i < fpCount; ++i) {
112        int a = i + fFragmentProcessorOffset;
113        int b = i + that.fFragmentProcessorOffset;
114        if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
115            return false;
116        }
117    }
118    // Most of the time both of these are null
119    if (!this->xferProcessor() && !that.xferProcessor()) {
120        return true;
121    }
122    const GrXferProcessor& thisXP = this->xferProcessor()
123                                            ? *this->xferProcessor()
124                                            : GrPorterDuffXPFactory::SimpleSrcOverXP();
125    const GrXferProcessor& thatXP = that.xferProcessor()
126                                            ? *that.xferProcessor()
127                                            : GrPorterDuffXPFactory::SimpleSrcOverXP();
128    return thisXP.isEqual(thatXP);
129}
130
131GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
132                                                  const GrProcessorAnalysisCoverage coverageInput,
133                                                  const GrAppliedClip* clip, bool isMixedSamples,
134                                                  const GrCaps& caps, GrColor* overrideInputColor) {
135    SkASSERT(!this->isFinalized());
136    SkASSERT(!fFragmentProcessorOffset);
137
138    GrProcessorSet::Analysis analysis;
139
140    const GrFragmentProcessor* clipFP = clip ? clip->clipCoverageFragmentProcessor() : nullptr;
141    GrColorFragmentProcessorAnalysis colorAnalysis(colorInput);
142    analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
143
144    const GrFragmentProcessor* const* fps = fFragmentProcessors.get() + fFragmentProcessorOffset;
145    colorAnalysis.analyzeProcessors(fps, fColorFragmentProcessorCnt);
146    analysis.fCompatibleWithCoverageAsAlpha &=
147            colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
148    fps += fColorFragmentProcessorCnt;
149    int n = this->numCoverageFragmentProcessors();
150    bool hasCoverageFP = n > 0;
151    bool coverageUsesLocalCoords = false;
152    for (int i = 0; i < n; ++i) {
153        if (!fps[i]->compatibleWithCoverageAsAlpha()) {
154            analysis.fCompatibleWithCoverageAsAlpha = false;
155            // Other than tests that exercise atypical behavior we expect all coverage FPs to be
156            // compatible with the coverage-as-alpha optimization.
157            GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
158        }
159        coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
160    }
161
162    if (clipFP) {
163        analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
164        coverageUsesLocalCoords |= clipFP->usesLocalCoords();
165        hasCoverageFP = true;
166    }
167    int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
168    analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
169            colorFPsToEliminate ? Analysis::kOverridden_InputColorType
170                                : Analysis::kOriginal_InputColorType);
171
172    GrProcessorAnalysisCoverage outputCoverage;
173    if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
174        outputCoverage = GrProcessorAnalysisCoverage::kLCD;
175    } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
176        outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
177    } else {
178        outputCoverage = GrProcessorAnalysisCoverage::kNone;
179    }
180
181    GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
182            this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps);
183    if (!this->numCoverageFragmentProcessors() &&
184        GrProcessorAnalysisCoverage::kNone == coverageInput) {
185        analysis.fCanCombineOverlappedStencilAndCover = SkToBool(
186                props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
187    } else {
188        // If we have non-clipping coverage processors we don't try to merge stencil steps as its
189        // unclear whether it will be correct. We don't expect this to happen in practice.
190        analysis.fCanCombineOverlappedStencilAndCover = false;
191    }
192    analysis.fRequiresDstTexture =
193            SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
194    analysis.fCompatibleWithCoverageAsAlpha &=
195            SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
196    analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
197            props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
198    if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
199        colorFPsToEliminate = this->numColorFragmentProcessors();
200        analysis.fInputColorType =
201                static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
202        analysis.fUsesLocalCoords = coverageUsesLocalCoords;
203    } else {
204        analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
205    }
206    for (int i = 0; i < colorFPsToEliminate; ++i) {
207        fFragmentProcessors[i]->unref();
208        fFragmentProcessors[i] = nullptr;
209    }
210    for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
211        fFragmentProcessors[i]->addPendingExecution();
212        fFragmentProcessors[i]->unref();
213    }
214    fFragmentProcessorOffset = colorFPsToEliminate;
215    fColorFragmentProcessorCnt -= colorFPsToEliminate;
216
217    auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
218                                             outputCoverage, isMixedSamples, caps);
219    fXP.fProcessor = xp.release();
220
221    fFlags |= kFinalized_Flag;
222    analysis.fIsInitialized = true;
223    return analysis;
224}
225