blob: b8a0aef92cc520701ef65c0789a70d95b04eb61d [file] [log] [blame]
Brian Salomon92ce5942017-01-18 11:01:10 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#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"
Brian Salomon92ce5942017-01-18 11:01:10 -050015
Brian Salomon292bf7a2017-05-17 09:43:55 -040016const GrProcessorSet& GrProcessorSet::EmptySet() {
Brian Salomon91326c32017-08-09 16:02:19 -040017 static GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty);
Brian Salomon292bf7a2017-05-17 09:43:55 -040018 return gEmpty;
19}
Brian Salomon6d4b65e2017-05-03 17:06:09 -040020
Brian Salomon91326c32017-08-09 16:02:19 -040021GrProcessorSet GrProcessorSet::MakeEmptySet() {
22 return GrProcessorSet(GrProcessorSet::Empty::kEmpty);
23}
24
Brian Salomon48d1b4c2017-04-08 07:38:53 -040025GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
Brian Salomonf87e2b92017-01-19 11:31:50 -050026 fFlags = 0;
Brian Salomon8d2f90b2017-03-13 09:11:58 -040027 if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
28 fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
29 fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
30 int i = 0;
31 for (auto& fp : paint.fColorFragmentProcessors) {
Brian Salomon5f970fe2017-06-16 17:30:59 -040032 SkASSERT(fp.get());
Brian Salomonaff329b2017-08-11 09:40:37 -040033 fFragmentProcessors[i++] = std::move(fp);
Brian Salomon8d2f90b2017-03-13 09:11:58 -040034 }
35 for (auto& fp : paint.fCoverageFragmentProcessors) {
Brian Salomon5f970fe2017-06-16 17:30:59 -040036 SkASSERT(fp.get());
Brian Salomonaff329b2017-08-11 09:40:37 -040037 fFragmentProcessors[i++] = std::move(fp);
Brian Salomon8d2f90b2017-03-13 09:11:58 -040038 }
Brian Salomon8d2f90b2017-03-13 09:11:58 -040039 } else {
40 SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
41 fColorFragmentProcessorCnt = 0;
Brian Salomonf87e2b92017-01-19 11:31:50 -050042 }
Mike Klein16885072018-12-11 09:54:31 -050043 SkDEBUGCODE(paint.fAlive = false;)
Brian Salomon92ce5942017-01-18 11:01:10 -050044}
Brian Salomon5298dc82017-02-22 11:52:03 -050045
Brian Salomon477d0ef2017-07-14 10:12:26 -040046GrProcessorSet::GrProcessorSet(SkBlendMode mode)
47 : fXP(SkBlendMode_AsXPFactory(mode))
48 , fColorFragmentProcessorCnt(0)
49 , fFragmentProcessorOffset(0)
50 , fFlags(0) {}
51
Brian Salomonaff329b2017-08-11 09:40:37 -040052GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)
Brian Salomon82ddc942017-07-14 12:00:13 -040053 : fFragmentProcessors(1)
54 , fXP((const GrXPFactory*)nullptr)
55 , fColorFragmentProcessorCnt(1)
56 , fFragmentProcessorOffset(0)
57 , fFlags(0) {
58 SkASSERT(colorFP);
Brian Salomonaff329b2017-08-11 09:40:37 -040059 fFragmentProcessors[0] = std::move(colorFP);
Brian Salomon82ddc942017-07-14 12:00:13 -040060}
61
Brian Salomon91326c32017-08-09 16:02:19 -040062GrProcessorSet::GrProcessorSet(GrProcessorSet&& that)
63 : fXP(std::move(that.fXP))
64 , fColorFragmentProcessorCnt(that.fColorFragmentProcessorCnt)
65 , fFragmentProcessorOffset(0)
66 , fFlags(that.fFlags) {
67 fFragmentProcessors.reset(that.fFragmentProcessors.count() - that.fFragmentProcessorOffset);
68 for (int i = 0; i < fFragmentProcessors.count(); ++i) {
Brian Salomonaff329b2017-08-11 09:40:37 -040069 fFragmentProcessors[i] =
70 std::move(that.fFragmentProcessors[i + that.fFragmentProcessorOffset]);
Brian Salomon91326c32017-08-09 16:02:19 -040071 }
Brian Salomon91326c32017-08-09 16:02:19 -040072 that.fFragmentProcessors.reset(0);
Robert Phillips9977ab92020-06-19 15:01:47 -040073 that.fColorFragmentProcessorCnt = 0;
74 that.fFragmentProcessorOffset = 0;
Brian Salomon91326c32017-08-09 16:02:19 -040075}
76
Brian Salomon54d212e2017-03-21 14:22:38 -040077GrProcessorSet::~GrProcessorSet() {
Brian Salomon48d1b4c2017-04-08 07:38:53 -040078 if (this->isFinalized() && this->xferProcessor()) {
Brian Salomond61c9d92017-04-10 10:54:25 -040079 this->xferProcessor()->unref();
Brian Salomon54d212e2017-03-21 14:22:38 -040080 }
81}
82
Brian Osman9a390ac2018-11-12 09:47:48 -050083#ifdef SK_DEBUG
Brian Salomon82dfd3d2017-06-14 12:30:35 -040084SkString dump_fragment_processor_tree(const GrFragmentProcessor* fp, int indentCnt) {
85 SkString result;
86 SkString indentString;
87 for (int i = 0; i < indentCnt; ++i) {
88 indentString.append(" ");
89 }
90 result.appendf("%s%s %s \n", indentString.c_str(), fp->name(), fp->dumpInfo().c_str());
91 if (fp->numChildProcessors()) {
92 for (int i = 0; i < fp->numChildProcessors(); ++i) {
93 result += dump_fragment_processor_tree(&fp->childProcessor(i), indentCnt + 1);
94 }
95 }
96 return result;
97}
98
99SkString GrProcessorSet::dumpProcessors() const {
100 SkString result;
101 if (this->numFragmentProcessors()) {
102 if (this->numColorFragmentProcessors()) {
103 result.append("Color Fragment Processors:\n");
104 for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
105 result += dump_fragment_processor_tree(this->colorFragmentProcessor(i), 1);
106 }
107 } else {
108 result.append("No color fragment processors.\n");
109 }
110 if (this->numCoverageFragmentProcessors()) {
111 result.append("Coverage Fragment Processors:\n");
112 for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
113 result += dump_fragment_processor_tree(this->coverageFragmentProcessor(i), 1);
114 }
115 } else {
116 result.append("No coverage fragment processors.\n");
117 }
118 } else {
119 result.append("No color or coverage fragment processors.\n");
120 }
121 if (this->isFinalized()) {
122 result.append("Xfer Processor: ");
123 if (this->xferProcessor()) {
124 result.appendf("%s\n", this->xferProcessor()->name());
125 } else {
126 result.append("SrcOver\n");
127 }
128 } else {
Derek Sollenberger08c06292019-01-24 16:30:28 +0000129 result.append("XP Factory dumping not implemented.\n");
Brian Salomon82dfd3d2017-06-14 12:30:35 -0400130 }
131 return result;
132}
Brian Osman9a390ac2018-11-12 09:47:48 -0500133#endif
Brian Salomon82dfd3d2017-06-14 12:30:35 -0400134
Brian Salomon54d212e2017-03-21 14:22:38 -0400135bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400136 SkASSERT(this->isFinalized());
137 SkASSERT(that.isFinalized());
Brian Salomon70288c02017-03-24 12:27:17 -0400138 int fpCount = this->numFragmentProcessors();
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400139 if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
Brian Salomon54d212e2017-03-21 14:22:38 -0400140 fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
141 return false;
142 }
Brian Salomon70288c02017-03-24 12:27:17 -0400143
144 for (int i = 0; i < fpCount; ++i) {
145 int a = i + fFragmentProcessorOffset;
146 int b = i + that.fFragmentProcessorOffset;
147 if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400148 return false;
149 }
150 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400151 // Most of the time both of these are null
152 if (!this->xferProcessor() && !that.xferProcessor()) {
153 return true;
Brian Salomon54d212e2017-03-21 14:22:38 -0400154 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400155 const GrXferProcessor& thisXP = this->xferProcessor()
156 ? *this->xferProcessor()
157 : GrPorterDuffXPFactory::SimpleSrcOverXP();
158 const GrXferProcessor& thatXP = that.xferProcessor()
159 ? *that.xferProcessor()
160 : GrPorterDuffXPFactory::SimpleSrcOverXP();
161 return thisXP.isEqual(thatXP);
Brian Salomon54d212e2017-03-21 14:22:38 -0400162}
163
Chris Daltonb8fff0d2019-03-05 10:11:58 -0700164GrProcessorSet::Analysis GrProcessorSet::finalize(
165 const GrProcessorAnalysisColor& colorInput, const GrProcessorAnalysisCoverage coverageInput,
Chris Dalton6ce447a2019-06-23 18:07:38 -0600166 const GrAppliedClip* clip, const GrUserStencilSettings* userStencil,
167 bool hasMixedSampledCoverage, const GrCaps& caps, GrClampType clampType,
168 SkPMColor4f* overrideInputColor) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400169 SkASSERT(!this->isFinalized());
170 SkASSERT(!fFragmentProcessorOffset);
Brian Salomon5298dc82017-02-22 11:52:03 -0500171
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400172 GrProcessorSet::Analysis analysis;
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400173 analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
174
Brian Salomon64f42062020-02-14 10:42:45 -0500175 const std::unique_ptr<GrFragmentProcessor>* fps =
Brian Salomonaff329b2017-08-11 09:40:37 -0400176 fFragmentProcessors.get() + fFragmentProcessorOffset;
Brian Salomon64f42062020-02-14 10:42:45 -0500177 GrColorFragmentProcessorAnalysis colorAnalysis(colorInput, fps, fColorFragmentProcessorCnt);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400178 fps += fColorFragmentProcessorCnt;
179 int n = this->numCoverageFragmentProcessors();
Brian Salomon5298dc82017-02-22 11:52:03 -0500180 bool hasCoverageFP = n > 0;
Brian Salomon31853842017-03-28 16:32:05 -0400181 bool coverageUsesLocalCoords = false;
Brian Salomonbfafcba2017-03-02 08:49:19 -0500182 for (int i = 0; i < n; ++i) {
Brian Salomon5298dc82017-02-22 11:52:03 -0500183 if (!fps[i]->compatibleWithCoverageAsAlpha()) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400184 analysis.fCompatibleWithCoverageAsAlpha = false;
Brian Salomon5298dc82017-02-22 11:52:03 -0500185 }
Brian Salomon31853842017-03-28 16:32:05 -0400186 coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500187 }
Chris Dalton69824002017-10-31 00:37:52 -0600188 if (clip) {
189 hasCoverageFP = hasCoverageFP || clip->numClipCoverageFragmentProcessors();
190 for (int i = 0; i < clip->numClipCoverageFragmentProcessors(); ++i) {
191 const GrFragmentProcessor* clipFP = clip->clipCoverageFragmentProcessor(i);
192 analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
193 coverageUsesLocalCoords |= clipFP->usesLocalCoords();
194 }
Brian Salomon5298dc82017-02-22 11:52:03 -0500195 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400196 int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
197 analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
198 colorFPsToEliminate ? Analysis::kOverridden_InputColorType
199 : Analysis::kOriginal_InputColorType);
Brian Salomon5298dc82017-02-22 11:52:03 -0500200
Brian Salomona811b122017-03-30 08:21:32 -0400201 GrProcessorAnalysisCoverage outputCoverage;
202 if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
203 outputCoverage = GrProcessorAnalysisCoverage::kLCD;
204 } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
205 outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
Brian Salomon5298dc82017-02-22 11:52:03 -0500206 } else {
Brian Salomona811b122017-03-30 08:21:32 -0400207 outputCoverage = GrProcessorAnalysisCoverage::kNone;
Brian Salomon31853842017-03-28 16:32:05 -0400208 }
Brian Salomon31853842017-03-28 16:32:05 -0400209
210 GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
Brian Osman5ced0bf2019-03-15 10:15:29 -0400211 this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps, clampType);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400212 if (!this->numCoverageFragmentProcessors() &&
Brian Salomona811b122017-03-30 08:21:32 -0400213 GrProcessorAnalysisCoverage::kNone == coverageInput) {
Brian Salomon31853842017-03-28 16:32:05 -0400214 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400215 analysis.fRequiresDstTexture =
216 SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
217 analysis.fCompatibleWithCoverageAsAlpha &=
Brian Osman605c6d52019-03-15 12:10:35 -0400218 SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithCoverageAsAlpha);
Chris Dalton945ee652019-01-23 09:10:36 -0700219 analysis.fRequiresNonOverlappingDraws = SkToBool(
220 props & GrXPFactory::AnalysisProperties::kRequiresNonOverlappingDraws);
Brian Salomon31853842017-03-28 16:32:05 -0400221 if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400222 colorFPsToEliminate = this->numColorFragmentProcessors();
223 analysis.fInputColorType =
224 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
225 analysis.fUsesLocalCoords = coverageUsesLocalCoords;
Brian Salomon31853842017-03-28 16:32:05 -0400226 } else {
Michael Ludwig0cb2fde2019-05-28 13:14:41 -0400227 analysis.fCompatibleWithCoverageAsAlpha &=
228 colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400229 analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500230 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400231 for (int i = 0; i < colorFPsToEliminate; ++i) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400232 fFragmentProcessors[i].reset(nullptr);
Brian Salomon5dac9b32017-04-08 02:53:30 +0000233 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400234 fFragmentProcessorOffset = colorFPsToEliminate;
235 fColorFragmentProcessorCnt -= colorFPsToEliminate;
Brian Salomon41f9c3c2019-03-25 11:06:12 -0400236 analysis.fHasColorFragmentProcessor = (fColorFragmentProcessorCnt != 0);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400237
238 auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
Brian Osman5ced0bf2019-03-15 10:15:29 -0400239 outputCoverage, hasMixedSampledCoverage, caps,
240 clampType);
Brian Salomond61c9d92017-04-10 10:54:25 -0400241 fXP.fProcessor = xp.release();
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400242
Brian Salomond61c9d92017-04-10 10:54:25 -0400243 fFlags |= kFinalized_Flag;
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400244 analysis.fIsInitialized = true;
Chris Dalton945ee652019-01-23 09:10:36 -0700245#ifdef SK_DEBUG
246 bool hasXferBarrier =
247 fXP.fProcessor &&
248 GrXferBarrierType::kNone_GrXferBarrierType != fXP.fProcessor->xferBarrierType(caps);
249 bool needsNonOverlappingDraws = analysis.fRequiresDstTexture || hasXferBarrier;
250 SkASSERT(analysis.fRequiresNonOverlappingDraws == needsNonOverlappingDraws);
251#endif
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400252 return analysis;
Brian Salomon70288c02017-03-24 12:27:17 -0400253}
Brian Salomonc241b582019-11-27 08:57:17 -0500254
255void GrProcessorSet::visitProxies(const GrOp::VisitProxyFunc& func) const {
256 for (auto [sampler, fp] : GrFragmentProcessor::ProcessorSetTextureSamplerRange(*this)) {
257 bool mipped = (GrSamplerState::Filter::kMipMap == sampler.samplerState().filter());
Robert Phillipsbd99c0c2019-12-12 13:26:58 +0000258 func(sampler.view().proxy(), GrMipMapped(mipped));
Brian Salomonc241b582019-11-27 08:57:17 -0500259 }
260}