blob: e073679d449d69dc0e7880acd8bc916d0c66a13b [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 Salomon48d1b4c2017-04-08 07:38:53 -040012#include "effects/GrPorterDuffXferProcessor.h"
Brian Salomon92ce5942017-01-18 11:01:10 -050013
Brian Salomon292bf7a2017-05-17 09:43:55 -040014const GrProcessorSet& GrProcessorSet::EmptySet() {
15 static const GrProcessorSet gEmpty(GrProcessorSet::Empty::kEmpty);
16 return gEmpty;
17}
Brian Salomon6d4b65e2017-05-03 17:06:09 -040018
Brian Salomon48d1b4c2017-04-08 07:38:53 -040019GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
Brian Salomonf87e2b92017-01-19 11:31:50 -050020 fFlags = 0;
Brian Salomon8d2f90b2017-03-13 09:11:58 -040021 if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
22 fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
23 fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
24 int i = 0;
25 for (auto& fp : paint.fColorFragmentProcessors) {
26 fFragmentProcessors[i++] = fp.release();
27 }
28 for (auto& fp : paint.fCoverageFragmentProcessors) {
29 fFragmentProcessors[i++] = fp.release();
30 }
Brian Salomon8d2f90b2017-03-13 09:11:58 -040031 } else {
32 SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
33 fColorFragmentProcessorCnt = 0;
Brian Salomonf87e2b92017-01-19 11:31:50 -050034 }
Brian Salomon92ce5942017-01-18 11:01:10 -050035}
Brian Salomon5298dc82017-02-22 11:52:03 -050036
Brian Salomon54d212e2017-03-21 14:22:38 -040037GrProcessorSet::~GrProcessorSet() {
Brian Salomon70288c02017-03-24 12:27:17 -040038 for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -040039 if (this->isFinalized()) {
Brian Salomon70288c02017-03-24 12:27:17 -040040 fFragmentProcessors[i]->completedExecution();
41 } else {
42 fFragmentProcessors[i]->unref();
Brian Salomon54d212e2017-03-21 14:22:38 -040043 }
44 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -040045 if (this->isFinalized() && this->xferProcessor()) {
Brian Salomond61c9d92017-04-10 10:54:25 -040046 this->xferProcessor()->unref();
Brian Salomon54d212e2017-03-21 14:22:38 -040047 }
48}
49
Brian Salomon82dfd3d2017-06-14 12:30:35 -040050SkString dump_fragment_processor_tree(const GrFragmentProcessor* fp, int indentCnt) {
51 SkString result;
52 SkString indentString;
53 for (int i = 0; i < indentCnt; ++i) {
54 indentString.append(" ");
55 }
56 result.appendf("%s%s %s \n", indentString.c_str(), fp->name(), fp->dumpInfo().c_str());
57 if (fp->numChildProcessors()) {
58 for (int i = 0; i < fp->numChildProcessors(); ++i) {
59 result += dump_fragment_processor_tree(&fp->childProcessor(i), indentCnt + 1);
60 }
61 }
62 return result;
63}
64
65SkString GrProcessorSet::dumpProcessors() const {
66 SkString result;
67 if (this->numFragmentProcessors()) {
68 if (this->numColorFragmentProcessors()) {
69 result.append("Color Fragment Processors:\n");
70 for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
71 result += dump_fragment_processor_tree(this->colorFragmentProcessor(i), 1);
72 }
73 } else {
74 result.append("No color fragment processors.\n");
75 }
76 if (this->numCoverageFragmentProcessors()) {
77 result.append("Coverage Fragment Processors:\n");
78 for (int i = 0; i < this->numColorFragmentProcessors(); ++i) {
79 result += dump_fragment_processor_tree(this->coverageFragmentProcessor(i), 1);
80 }
81 } else {
82 result.append("No coverage fragment processors.\n");
83 }
84 } else {
85 result.append("No color or coverage fragment processors.\n");
86 }
87 if (this->isFinalized()) {
88 result.append("Xfer Processor: ");
89 if (this->xferProcessor()) {
90 result.appendf("%s\n", this->xferProcessor()->name());
91 } else {
92 result.append("SrcOver\n");
93 }
94 } else {
95 result.append("XP Factory dumping not implemented.\n");
96 }
97 return result;
98}
99
Brian Salomon54d212e2017-03-21 14:22:38 -0400100bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400101 SkASSERT(this->isFinalized());
102 SkASSERT(that.isFinalized());
Brian Salomon70288c02017-03-24 12:27:17 -0400103 int fpCount = this->numFragmentProcessors();
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400104 if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
Brian Salomon54d212e2017-03-21 14:22:38 -0400105 fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
106 return false;
107 }
Brian Salomon70288c02017-03-24 12:27:17 -0400108
109 for (int i = 0; i < fpCount; ++i) {
110 int a = i + fFragmentProcessorOffset;
111 int b = i + that.fFragmentProcessorOffset;
112 if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400113 return false;
114 }
115 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400116 // Most of the time both of these are null
117 if (!this->xferProcessor() && !that.xferProcessor()) {
118 return true;
Brian Salomon54d212e2017-03-21 14:22:38 -0400119 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400120 const GrXferProcessor& thisXP = this->xferProcessor()
121 ? *this->xferProcessor()
122 : GrPorterDuffXPFactory::SimpleSrcOverXP();
123 const GrXferProcessor& thatXP = that.xferProcessor()
124 ? *that.xferProcessor()
125 : GrPorterDuffXPFactory::SimpleSrcOverXP();
126 return thisXP.isEqual(thatXP);
Brian Salomon54d212e2017-03-21 14:22:38 -0400127}
128
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400129GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
130 const GrProcessorAnalysisCoverage coverageInput,
131 const GrAppliedClip* clip, bool isMixedSamples,
132 const GrCaps& caps, GrColor* overrideInputColor) {
133 SkASSERT(!this->isFinalized());
134 SkASSERT(!fFragmentProcessorOffset);
Brian Salomon5298dc82017-02-22 11:52:03 -0500135
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400136 GrProcessorSet::Analysis analysis;
Brian Salomon5298dc82017-02-22 11:52:03 -0500137
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400138 const GrFragmentProcessor* clipFP = clip ? clip->clipCoverageFragmentProcessor() : nullptr;
139 GrColorFragmentProcessorAnalysis colorAnalysis(colorInput);
140 analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
141
142 const GrFragmentProcessor* const* fps = fFragmentProcessors.get() + fFragmentProcessorOffset;
143 colorAnalysis.analyzeProcessors(fps, fColorFragmentProcessorCnt);
144 analysis.fCompatibleWithCoverageAsAlpha &=
145 colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
146 fps += fColorFragmentProcessorCnt;
147 int n = this->numCoverageFragmentProcessors();
Brian Salomon5298dc82017-02-22 11:52:03 -0500148 bool hasCoverageFP = n > 0;
Brian Salomon31853842017-03-28 16:32:05 -0400149 bool coverageUsesLocalCoords = false;
Brian Salomonbfafcba2017-03-02 08:49:19 -0500150 for (int i = 0; i < n; ++i) {
Brian Salomon5298dc82017-02-22 11:52:03 -0500151 if (!fps[i]->compatibleWithCoverageAsAlpha()) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400152 analysis.fCompatibleWithCoverageAsAlpha = false;
Brian Salomon5298dc82017-02-22 11:52:03 -0500153 // Other than tests that exercise atypical behavior we expect all coverage FPs to be
154 // compatible with the coverage-as-alpha optimization.
155 GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
Brian Salomon5298dc82017-02-22 11:52:03 -0500156 }
Brian Salomon31853842017-03-28 16:32:05 -0400157 coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500158 }
159
160 if (clipFP) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400161 analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
Brian Salomon31853842017-03-28 16:32:05 -0400162 coverageUsesLocalCoords |= clipFP->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500163 hasCoverageFP = true;
164 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400165 int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
166 analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
167 colorFPsToEliminate ? Analysis::kOverridden_InputColorType
168 : Analysis::kOriginal_InputColorType);
Brian Salomon5298dc82017-02-22 11:52:03 -0500169
Brian Salomona811b122017-03-30 08:21:32 -0400170 GrProcessorAnalysisCoverage outputCoverage;
171 if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
172 outputCoverage = GrProcessorAnalysisCoverage::kLCD;
173 } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
174 outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
Brian Salomon5298dc82017-02-22 11:52:03 -0500175 } else {
Brian Salomona811b122017-03-30 08:21:32 -0400176 outputCoverage = GrProcessorAnalysisCoverage::kNone;
Brian Salomon31853842017-03-28 16:32:05 -0400177 }
Brian Salomon31853842017-03-28 16:32:05 -0400178
179 GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400180 this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps);
181 if (!this->numCoverageFragmentProcessors() &&
Brian Salomona811b122017-03-30 08:21:32 -0400182 GrProcessorAnalysisCoverage::kNone == coverageInput) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400183 analysis.fCanCombineOverlappedStencilAndCover = SkToBool(
Brian Salomon31853842017-03-28 16:32:05 -0400184 props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
185 } else {
186 // If we have non-clipping coverage processors we don't try to merge stencil steps as its
187 // unclear whether it will be correct. We don't expect this to happen in practice.
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400188 analysis.fCanCombineOverlappedStencilAndCover = false;
Brian Salomon31853842017-03-28 16:32:05 -0400189 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400190 analysis.fRequiresDstTexture =
191 SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
192 analysis.fCompatibleWithCoverageAsAlpha &=
Brian Salomon31853842017-03-28 16:32:05 -0400193 SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400194 analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
Brian Salomon4fc77402017-03-30 16:48:26 -0400195 props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
Brian Salomon31853842017-03-28 16:32:05 -0400196 if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400197 colorFPsToEliminate = this->numColorFragmentProcessors();
198 analysis.fInputColorType =
199 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
200 analysis.fUsesLocalCoords = coverageUsesLocalCoords;
Brian Salomon31853842017-03-28 16:32:05 -0400201 } else {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400202 analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500203 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400204 for (int i = 0; i < colorFPsToEliminate; ++i) {
205 fFragmentProcessors[i]->unref();
206 fFragmentProcessors[i] = nullptr;
Brian Salomon5dac9b32017-04-08 02:53:30 +0000207 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400208 for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
209 fFragmentProcessors[i]->addPendingExecution();
210 fFragmentProcessors[i]->unref();
211 }
212 fFragmentProcessorOffset = colorFPsToEliminate;
213 fColorFragmentProcessorCnt -= colorFPsToEliminate;
214
215 auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
216 outputCoverage, isMixedSamples, caps);
Brian Salomond61c9d92017-04-10 10:54:25 -0400217 fXP.fProcessor = xp.release();
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400218
Brian Salomond61c9d92017-04-10 10:54:25 -0400219 fFlags |= kFinalized_Flag;
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400220 analysis.fIsInitialized = true;
221 return analysis;
Brian Salomon70288c02017-03-24 12:27:17 -0400222}