blob: 7694806659cc6da554aa8fc7f8a4e4ec96addc96 [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
8#include "GrProcessorSet.h"
Brian Salomon5298dc82017-02-22 11:52:03 -05009#include "GrAppliedClip.h"
10#include "GrCaps.h"
Brian Salomon31853842017-03-28 16:32:05 -040011#include "GrXferProcessor.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040012#include "SkBlendModePriv.h"
Brian Salomon48d1b4c2017-04-08 07:38:53 -040013#include "effects/GrPorterDuffXferProcessor.h"
Brian Salomon92ce5942017-01-18 11:01:10 -050014
Brian Salomon292bf7a2017-05-17 09:43:55 -040015const GrProcessorSet& GrProcessorSet::EmptySet() {
Brian Salomon91326c32017-08-09 16:02:19 -040016 static GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty);
Brian Salomon292bf7a2017-05-17 09:43:55 -040017 return gEmpty;
18}
Brian Salomon6d4b65e2017-05-03 17:06:09 -040019
Brian Salomon91326c32017-08-09 16:02:19 -040020GrProcessorSet GrProcessorSet::MakeEmptySet() {
21 return GrProcessorSet(GrProcessorSet::Empty::kEmpty);
22}
23
Brian Salomon48d1b4c2017-04-08 07:38:53 -040024GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
Brian Salomonf87e2b92017-01-19 11:31:50 -050025 fFlags = 0;
Brian Salomon8d2f90b2017-03-13 09:11:58 -040026 if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
27 fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
28 fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
29 int i = 0;
30 for (auto& fp : paint.fColorFragmentProcessors) {
Brian Salomon5f970fe2017-06-16 17:30:59 -040031 SkASSERT(fp.get());
Brian Salomonaff329b2017-08-11 09:40:37 -040032 fFragmentProcessors[i++] = std::move(fp);
Brian Salomon8d2f90b2017-03-13 09:11:58 -040033 }
34 for (auto& fp : paint.fCoverageFragmentProcessors) {
Brian Salomon5f970fe2017-06-16 17:30:59 -040035 SkASSERT(fp.get());
Brian Salomonaff329b2017-08-11 09:40:37 -040036 fFragmentProcessors[i++] = std::move(fp);
Brian Salomon8d2f90b2017-03-13 09:11:58 -040037 }
Brian Salomon8d2f90b2017-03-13 09:11:58 -040038 } else {
39 SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
40 fColorFragmentProcessorCnt = 0;
Brian Salomonf87e2b92017-01-19 11:31:50 -050041 }
Brian Salomon92ce5942017-01-18 11:01:10 -050042}
Brian Salomon5298dc82017-02-22 11:52:03 -050043
Brian Salomon477d0ef2017-07-14 10:12:26 -040044GrProcessorSet::GrProcessorSet(SkBlendMode mode)
45 : fXP(SkBlendMode_AsXPFactory(mode))
46 , fColorFragmentProcessorCnt(0)
47 , fFragmentProcessorOffset(0)
48 , fFlags(0) {}
49
Brian Salomonaff329b2017-08-11 09:40:37 -040050GrProcessorSet::GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP)
Brian Salomon82ddc942017-07-14 12:00:13 -040051 : fFragmentProcessors(1)
52 , fXP((const GrXPFactory*)nullptr)
53 , fColorFragmentProcessorCnt(1)
54 , fFragmentProcessorOffset(0)
55 , fFlags(0) {
56 SkASSERT(colorFP);
Brian Salomonaff329b2017-08-11 09:40:37 -040057 fFragmentProcessors[0] = std::move(colorFP);
Brian Salomon82ddc942017-07-14 12:00:13 -040058}
59
Brian Salomon91326c32017-08-09 16:02:19 -040060GrProcessorSet::GrProcessorSet(GrProcessorSet&& that)
61 : fXP(std::move(that.fXP))
62 , fColorFragmentProcessorCnt(that.fColorFragmentProcessorCnt)
63 , fFragmentProcessorOffset(0)
64 , fFlags(that.fFlags) {
65 fFragmentProcessors.reset(that.fFragmentProcessors.count() - that.fFragmentProcessorOffset);
66 for (int i = 0; i < fFragmentProcessors.count(); ++i) {
Brian Salomonaff329b2017-08-11 09:40:37 -040067 fFragmentProcessors[i] =
68 std::move(that.fFragmentProcessors[i + that.fFragmentProcessorOffset]);
Brian Salomon91326c32017-08-09 16:02:19 -040069 }
70 that.fColorFragmentProcessorCnt = 0;
71 that.fFragmentProcessors.reset(0);
72}
73
Brian Salomon54d212e2017-03-21 14:22:38 -040074GrProcessorSet::~GrProcessorSet() {
Brian Salomon48d1b4c2017-04-08 07:38:53 -040075 if (this->isFinalized() && this->xferProcessor()) {
Brian Salomond61c9d92017-04-10 10:54:25 -040076 this->xferProcessor()->unref();
Brian Salomon54d212e2017-03-21 14:22:38 -040077 }
78}
79
Brian Salomon82dfd3d2017-06-14 12:30:35 -040080SkString dump_fragment_processor_tree(const GrFragmentProcessor* fp, int indentCnt) {
81 SkString result;
82 SkString indentString;
83 for (int i = 0; i < indentCnt; ++i) {
84 indentString.append(" ");
85 }
86 result.appendf("%s%s %s \n", indentString.c_str(), fp->name(), fp->dumpInfo().c_str());
87 if (fp->numChildProcessors()) {
88 for (int i = 0; i < fp->numChildProcessors(); ++i) {
89 result += dump_fragment_processor_tree(&fp->childProcessor(i), indentCnt + 1);
90 }
91 }
92 return result;
93}
94
95SkString GrProcessorSet::dumpProcessors() const {
96 SkString result;
97 if (this->numFragmentProcessors()) {
98 if (this->numColorFragmentProcessors()) {
99 result.append("Color Fragment Processors:\n");
100 for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
101 result += dump_fragment_processor_tree(this->colorFragmentProcessor(i), 1);
102 }
103 } else {
104 result.append("No color fragment processors.\n");
105 }
106 if (this->numCoverageFragmentProcessors()) {
107 result.append("Coverage Fragment Processors:\n");
108 for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
109 result += dump_fragment_processor_tree(this->coverageFragmentProcessor(i), 1);
110 }
111 } else {
112 result.append("No coverage fragment processors.\n");
113 }
114 } else {
115 result.append("No color or coverage fragment processors.\n");
116 }
117 if (this->isFinalized()) {
118 result.append("Xfer Processor: ");
119 if (this->xferProcessor()) {
120 result.appendf("%s\n", this->xferProcessor()->name());
121 } else {
122 result.append("SrcOver\n");
123 }
124 } else {
125 result.append("XP Factory dumping not implemented.\n");
126 }
127 return result;
128}
129
Brian Salomon54d212e2017-03-21 14:22:38 -0400130bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400131 SkASSERT(this->isFinalized());
132 SkASSERT(that.isFinalized());
Brian Salomon70288c02017-03-24 12:27:17 -0400133 int fpCount = this->numFragmentProcessors();
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400134 if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
Brian Salomon54d212e2017-03-21 14:22:38 -0400135 fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
136 return false;
137 }
Brian Salomon70288c02017-03-24 12:27:17 -0400138
139 for (int i = 0; i < fpCount; ++i) {
140 int a = i + fFragmentProcessorOffset;
141 int b = i + that.fFragmentProcessorOffset;
142 if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400143 return false;
144 }
145 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400146 // Most of the time both of these are null
147 if (!this->xferProcessor() && !that.xferProcessor()) {
148 return true;
Brian Salomon54d212e2017-03-21 14:22:38 -0400149 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400150 const GrXferProcessor& thisXP = this->xferProcessor()
151 ? *this->xferProcessor()
152 : GrPorterDuffXPFactory::SimpleSrcOverXP();
153 const GrXferProcessor& thatXP = that.xferProcessor()
154 ? *that.xferProcessor()
155 : GrPorterDuffXPFactory::SimpleSrcOverXP();
156 return thisXP.isEqual(thatXP);
Brian Salomon54d212e2017-03-21 14:22:38 -0400157}
158
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400159GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
160 const GrProcessorAnalysisCoverage coverageInput,
161 const GrAppliedClip* clip, bool isMixedSamples,
Brian Osman9a725dd2017-09-20 09:53:22 -0400162 const GrCaps& caps,
163 GrPixelConfigIsClamped dstIsClamped,
164 GrColor* overrideInputColor) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400165 SkASSERT(!this->isFinalized());
166 SkASSERT(!fFragmentProcessorOffset);
Brian Salomon5298dc82017-02-22 11:52:03 -0500167
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400168 GrProcessorSet::Analysis analysis;
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400169 analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
170
Brian Salomon650ced02017-07-20 16:46:46 -0400171 const GrFragmentProcessor* clipFP = clip ? clip->clipCoverageFragmentProcessor() : nullptr;
Brian Salomonaff329b2017-08-11 09:40:37 -0400172 const std::unique_ptr<const GrFragmentProcessor>* fps =
173 fFragmentProcessors.get() + fFragmentProcessorOffset;
174 GrColorFragmentProcessorAnalysis colorAnalysis(
175 colorInput, unique_ptr_address_as_pointer_address(fps), fColorFragmentProcessorCnt);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400176 analysis.fCompatibleWithCoverageAsAlpha &=
177 colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
178 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 // Other than tests that exercise atypical behavior we expect all coverage FPs to be
186 // compatible with the coverage-as-alpha optimization.
187 GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
Brian Salomon5298dc82017-02-22 11:52:03 -0500188 }
Brian Salomon31853842017-03-28 16:32:05 -0400189 coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500190 }
191
192 if (clipFP) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400193 analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
Brian Salomon31853842017-03-28 16:32:05 -0400194 coverageUsesLocalCoords |= clipFP->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500195 hasCoverageFP = true;
196 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400197 int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
198 analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
199 colorFPsToEliminate ? Analysis::kOverridden_InputColorType
200 : Analysis::kOriginal_InputColorType);
Brian Salomon5298dc82017-02-22 11:52:03 -0500201
Brian Salomona811b122017-03-30 08:21:32 -0400202 GrProcessorAnalysisCoverage outputCoverage;
203 if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
204 outputCoverage = GrProcessorAnalysisCoverage::kLCD;
205 } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
206 outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
Brian Salomon5298dc82017-02-22 11:52:03 -0500207 } else {
Brian Salomona811b122017-03-30 08:21:32 -0400208 outputCoverage = GrProcessorAnalysisCoverage::kNone;
Brian Salomon31853842017-03-28 16:32:05 -0400209 }
Brian Salomon31853842017-03-28 16:32:05 -0400210
211 GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
Brian Osman9a725dd2017-09-20 09:53:22 -0400212 this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps, dstIsClamped);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400213 if (!this->numCoverageFragmentProcessors() &&
Brian Salomona811b122017-03-30 08:21:32 -0400214 GrProcessorAnalysisCoverage::kNone == coverageInput) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400215 analysis.fCanCombineOverlappedStencilAndCover = SkToBool(
Brian Salomon31853842017-03-28 16:32:05 -0400216 props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
217 } else {
218 // If we have non-clipping coverage processors we don't try to merge stencil steps as its
219 // unclear whether it will be correct. We don't expect this to happen in practice.
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400220 analysis.fCanCombineOverlappedStencilAndCover = false;
Brian Salomon31853842017-03-28 16:32:05 -0400221 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400222 analysis.fRequiresDstTexture =
223 SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
224 analysis.fCompatibleWithCoverageAsAlpha &=
Brian Salomon31853842017-03-28 16:32:05 -0400225 SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400226 analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
Brian Salomon4fc77402017-03-30 16:48:26 -0400227 props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
Brian Salomon31853842017-03-28 16:32:05 -0400228 if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400229 colorFPsToEliminate = this->numColorFragmentProcessors();
230 analysis.fInputColorType =
231 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
232 analysis.fUsesLocalCoords = coverageUsesLocalCoords;
Brian Salomon31853842017-03-28 16:32:05 -0400233 } else {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400234 analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500235 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400236 for (int i = 0; i < colorFPsToEliminate; ++i) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400237 fFragmentProcessors[i].reset(nullptr);
Brian Salomon5dac9b32017-04-08 02:53:30 +0000238 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400239 for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400240 fFragmentProcessors[i]->markPendingExecution();
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400241 }
242 fFragmentProcessorOffset = colorFPsToEliminate;
243 fColorFragmentProcessorCnt -= colorFPsToEliminate;
244
245 auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
Brian Osman9a725dd2017-09-20 09:53:22 -0400246 outputCoverage, isMixedSamples, caps, dstIsClamped);
Brian Salomond61c9d92017-04-10 10:54:25 -0400247 fXP.fProcessor = xp.release();
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400248
Brian Salomond61c9d92017-04-10 10:54:25 -0400249 fFlags |= kFinalized_Flag;
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400250 analysis.fIsInitialized = true;
251 return analysis;
Brian Salomon70288c02017-03-24 12:27:17 -0400252}