Line data Source code
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 :
14 0 : GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
15 0 : fFlags = 0;
16 0 : if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
17 0 : fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
18 0 : fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
19 0 : int i = 0;
20 0 : for (auto& fp : paint.fColorFragmentProcessors) {
21 0 : fFragmentProcessors[i++] = fp.release();
22 : }
23 0 : for (auto& fp : paint.fCoverageFragmentProcessors) {
24 0 : fFragmentProcessors[i++] = fp.release();
25 : }
26 0 : if (paint.usesDistanceVectorField()) {
27 0 : fFlags |= kUseDistanceVectorField_Flag;
28 : }
29 : } else {
30 0 : SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
31 0 : fColorFragmentProcessorCnt = 0;
32 : }
33 0 : if (paint.getDisableOutputConversionToSRGB()) {
34 0 : fFlags |= kDisableOutputConversionToSRGB_Flag;
35 : }
36 0 : if (paint.getAllowSRGBInputs()) {
37 0 : fFlags |= kAllowSRGBInputs_Flag;
38 : }
39 0 : }
40 :
41 0 : GrProcessorSet::~GrProcessorSet() {
42 0 : for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
43 0 : if (this->isFinalized()) {
44 0 : fFragmentProcessors[i]->completedExecution();
45 : } else {
46 0 : fFragmentProcessors[i]->unref();
47 : }
48 : }
49 0 : if (this->isFinalized() && this->xferProcessor()) {
50 0 : this->xferProcessor()->unref();
51 : }
52 0 : }
53 :
54 0 : bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
55 0 : SkASSERT(this->isFinalized());
56 0 : SkASSERT(that.isFinalized());
57 0 : int fpCount = this->numFragmentProcessors();
58 0 : if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
59 0 : fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
60 0 : return false;
61 : }
62 :
63 0 : for (int i = 0; i < fpCount; ++i) {
64 0 : int a = i + fFragmentProcessorOffset;
65 0 : int b = i + that.fFragmentProcessorOffset;
66 0 : if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
67 0 : return false;
68 : }
69 : }
70 : // Most of the time both of these are null
71 0 : if (!this->xferProcessor() && !that.xferProcessor()) {
72 0 : return true;
73 : }
74 0 : const GrXferProcessor& thisXP = this->xferProcessor()
75 0 : ? *this->xferProcessor()
76 0 : : GrPorterDuffXPFactory::SimpleSrcOverXP();
77 0 : const GrXferProcessor& thatXP = that.xferProcessor()
78 0 : ? *that.xferProcessor()
79 0 : : GrPorterDuffXPFactory::SimpleSrcOverXP();
80 0 : return thisXP.isEqual(thatXP);
81 : }
82 :
83 0 : GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
84 : const GrProcessorAnalysisCoverage coverageInput,
85 : const GrAppliedClip* clip, bool isMixedSamples,
86 : const GrCaps& caps, GrColor* overrideInputColor) {
87 0 : SkASSERT(!this->isFinalized());
88 0 : SkASSERT(!fFragmentProcessorOffset);
89 :
90 0 : GrProcessorSet::Analysis analysis;
91 :
92 0 : const GrFragmentProcessor* clipFP = clip ? clip->clipCoverageFragmentProcessor() : nullptr;
93 0 : GrColorFragmentProcessorAnalysis colorAnalysis(colorInput);
94 0 : analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
95 :
96 0 : const GrFragmentProcessor* const* fps = fFragmentProcessors.get() + fFragmentProcessorOffset;
97 0 : colorAnalysis.analyzeProcessors(fps, fColorFragmentProcessorCnt);
98 0 : analysis.fCompatibleWithCoverageAsAlpha &=
99 0 : colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
100 0 : fps += fColorFragmentProcessorCnt;
101 0 : int n = this->numCoverageFragmentProcessors();
102 0 : bool hasCoverageFP = n > 0;
103 0 : bool coverageUsesLocalCoords = false;
104 0 : for (int i = 0; i < n; ++i) {
105 0 : if (!fps[i]->compatibleWithCoverageAsAlpha()) {
106 0 : analysis.fCompatibleWithCoverageAsAlpha = false;
107 : // Other than tests that exercise atypical behavior we expect all coverage FPs to be
108 : // compatible with the coverage-as-alpha optimization.
109 0 : GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
110 : }
111 0 : coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
112 : }
113 :
114 0 : if (clipFP) {
115 0 : analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
116 0 : coverageUsesLocalCoords |= clipFP->usesLocalCoords();
117 0 : hasCoverageFP = true;
118 : }
119 0 : int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
120 0 : analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
121 : colorFPsToEliminate ? Analysis::kOverridden_InputColorType
122 : : Analysis::kOriginal_InputColorType);
123 :
124 : GrProcessorAnalysisCoverage outputCoverage;
125 0 : if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
126 0 : outputCoverage = GrProcessorAnalysisCoverage::kLCD;
127 0 : } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
128 0 : outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
129 : } else {
130 0 : outputCoverage = GrProcessorAnalysisCoverage::kNone;
131 : }
132 :
133 0 : GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
134 0 : this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps);
135 0 : if (!this->numCoverageFragmentProcessors() &&
136 : GrProcessorAnalysisCoverage::kNone == coverageInput) {
137 0 : analysis.fCanCombineOverlappedStencilAndCover = SkToBool(
138 : props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
139 : } else {
140 : // If we have non-clipping coverage processors we don't try to merge stencil steps as its
141 : // unclear whether it will be correct. We don't expect this to happen in practice.
142 0 : analysis.fCanCombineOverlappedStencilAndCover = false;
143 : }
144 0 : analysis.fRequiresDstTexture =
145 0 : SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
146 0 : analysis.fCompatibleWithCoverageAsAlpha &=
147 0 : SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
148 0 : analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
149 : props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
150 0 : if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
151 0 : colorFPsToEliminate = this->numColorFragmentProcessors();
152 0 : analysis.fInputColorType =
153 : static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
154 0 : analysis.fUsesLocalCoords = coverageUsesLocalCoords;
155 : } else {
156 0 : analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
157 : }
158 0 : for (int i = 0; i < colorFPsToEliminate; ++i) {
159 0 : fFragmentProcessors[i]->unref();
160 0 : fFragmentProcessors[i] = nullptr;
161 : }
162 0 : for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
163 0 : fFragmentProcessors[i]->addPendingExecution();
164 0 : fFragmentProcessors[i]->unref();
165 : }
166 0 : fFragmentProcessorOffset = colorFPsToEliminate;
167 0 : fColorFragmentProcessorCnt -= colorFPsToEliminate;
168 :
169 0 : auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
170 0 : outputCoverage, isMixedSamples, caps);
171 0 : fXP.fProcessor = xp.release();
172 :
173 0 : fFlags |= kFinalized_Flag;
174 0 : analysis.fIsInitialized = true;
175 0 : return analysis;
176 : }
|