blob: 22fa63589f659d55b7965ddaf159c67c2539c2f2 [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 }
31 if (paint.usesDistanceVectorField()) {
32 fFlags |= kUseDistanceVectorField_Flag;
33 }
34 } else {
35 SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
36 fColorFragmentProcessorCnt = 0;
Brian Salomonf87e2b92017-01-19 11:31:50 -050037 }
Brian Salomon92ce5942017-01-18 11:01:10 -050038}
Brian Salomon5298dc82017-02-22 11:52:03 -050039
Brian Salomon54d212e2017-03-21 14:22:38 -040040GrProcessorSet::~GrProcessorSet() {
Brian Salomon70288c02017-03-24 12:27:17 -040041 for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -040042 if (this->isFinalized()) {
Brian Salomon70288c02017-03-24 12:27:17 -040043 fFragmentProcessors[i]->completedExecution();
44 } else {
45 fFragmentProcessors[i]->unref();
Brian Salomon54d212e2017-03-21 14:22:38 -040046 }
47 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -040048 if (this->isFinalized() && this->xferProcessor()) {
Brian Salomond61c9d92017-04-10 10:54:25 -040049 this->xferProcessor()->unref();
Brian Salomon54d212e2017-03-21 14:22:38 -040050 }
51}
52
53bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
Brian Salomon48d1b4c2017-04-08 07:38:53 -040054 SkASSERT(this->isFinalized());
55 SkASSERT(that.isFinalized());
Brian Salomon70288c02017-03-24 12:27:17 -040056 int fpCount = this->numFragmentProcessors();
Brian Salomon48d1b4c2017-04-08 07:38:53 -040057 if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
Brian Salomon54d212e2017-03-21 14:22:38 -040058 fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
59 return false;
60 }
Brian Salomon70288c02017-03-24 12:27:17 -040061
62 for (int i = 0; i < fpCount; ++i) {
63 int a = i + fFragmentProcessorOffset;
64 int b = i + that.fFragmentProcessorOffset;
65 if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
Brian Salomon54d212e2017-03-21 14:22:38 -040066 return false;
67 }
68 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -040069 // Most of the time both of these are null
70 if (!this->xferProcessor() && !that.xferProcessor()) {
71 return true;
Brian Salomon54d212e2017-03-21 14:22:38 -040072 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -040073 const GrXferProcessor& thisXP = this->xferProcessor()
74 ? *this->xferProcessor()
75 : GrPorterDuffXPFactory::SimpleSrcOverXP();
76 const GrXferProcessor& thatXP = that.xferProcessor()
77 ? *that.xferProcessor()
78 : GrPorterDuffXPFactory::SimpleSrcOverXP();
79 return thisXP.isEqual(thatXP);
Brian Salomon54d212e2017-03-21 14:22:38 -040080}
81
Brian Salomon48d1b4c2017-04-08 07:38:53 -040082GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
83 const GrProcessorAnalysisCoverage coverageInput,
84 const GrAppliedClip* clip, bool isMixedSamples,
85 const GrCaps& caps, GrColor* overrideInputColor) {
86 SkASSERT(!this->isFinalized());
87 SkASSERT(!fFragmentProcessorOffset);
Brian Salomon5298dc82017-02-22 11:52:03 -050088
Brian Salomon48d1b4c2017-04-08 07:38:53 -040089 GrProcessorSet::Analysis analysis;
Brian Salomon5298dc82017-02-22 11:52:03 -050090
Brian Salomon48d1b4c2017-04-08 07:38:53 -040091 const GrFragmentProcessor* clipFP = clip ? clip->clipCoverageFragmentProcessor() : nullptr;
92 GrColorFragmentProcessorAnalysis colorAnalysis(colorInput);
93 analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
94
95 const GrFragmentProcessor* const* fps = fFragmentProcessors.get() + fFragmentProcessorOffset;
96 colorAnalysis.analyzeProcessors(fps, fColorFragmentProcessorCnt);
97 analysis.fCompatibleWithCoverageAsAlpha &=
98 colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
99 fps += fColorFragmentProcessorCnt;
100 int n = this->numCoverageFragmentProcessors();
Brian Salomon5298dc82017-02-22 11:52:03 -0500101 bool hasCoverageFP = n > 0;
Brian Salomon31853842017-03-28 16:32:05 -0400102 bool coverageUsesLocalCoords = false;
Brian Salomonbfafcba2017-03-02 08:49:19 -0500103 for (int i = 0; i < n; ++i) {
Brian Salomon5298dc82017-02-22 11:52:03 -0500104 if (!fps[i]->compatibleWithCoverageAsAlpha()) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400105 analysis.fCompatibleWithCoverageAsAlpha = false;
Brian Salomon5298dc82017-02-22 11:52:03 -0500106 // Other than tests that exercise atypical behavior we expect all coverage FPs to be
107 // compatible with the coverage-as-alpha optimization.
108 GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
Brian Salomon5298dc82017-02-22 11:52:03 -0500109 }
Brian Salomon31853842017-03-28 16:32:05 -0400110 coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500111 }
112
113 if (clipFP) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400114 analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
Brian Salomon31853842017-03-28 16:32:05 -0400115 coverageUsesLocalCoords |= clipFP->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500116 hasCoverageFP = true;
117 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400118 int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
119 analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
120 colorFPsToEliminate ? Analysis::kOverridden_InputColorType
121 : Analysis::kOriginal_InputColorType);
Brian Salomon5298dc82017-02-22 11:52:03 -0500122
Brian Salomona811b122017-03-30 08:21:32 -0400123 GrProcessorAnalysisCoverage outputCoverage;
124 if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
125 outputCoverage = GrProcessorAnalysisCoverage::kLCD;
126 } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
127 outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
Brian Salomon5298dc82017-02-22 11:52:03 -0500128 } else {
Brian Salomona811b122017-03-30 08:21:32 -0400129 outputCoverage = GrProcessorAnalysisCoverage::kNone;
Brian Salomon31853842017-03-28 16:32:05 -0400130 }
Brian Salomon31853842017-03-28 16:32:05 -0400131
132 GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400133 this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps);
134 if (!this->numCoverageFragmentProcessors() &&
Brian Salomona811b122017-03-30 08:21:32 -0400135 GrProcessorAnalysisCoverage::kNone == coverageInput) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400136 analysis.fCanCombineOverlappedStencilAndCover = SkToBool(
Brian Salomon31853842017-03-28 16:32:05 -0400137 props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
138 } else {
139 // If we have non-clipping coverage processors we don't try to merge stencil steps as its
140 // unclear whether it will be correct. We don't expect this to happen in practice.
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400141 analysis.fCanCombineOverlappedStencilAndCover = false;
Brian Salomon31853842017-03-28 16:32:05 -0400142 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400143 analysis.fRequiresDstTexture =
144 SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
145 analysis.fCompatibleWithCoverageAsAlpha &=
Brian Salomon31853842017-03-28 16:32:05 -0400146 SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400147 analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
Brian Salomon4fc77402017-03-30 16:48:26 -0400148 props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
Brian Salomon31853842017-03-28 16:32:05 -0400149 if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400150 colorFPsToEliminate = this->numColorFragmentProcessors();
151 analysis.fInputColorType =
152 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
153 analysis.fUsesLocalCoords = coverageUsesLocalCoords;
Brian Salomon31853842017-03-28 16:32:05 -0400154 } else {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400155 analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500156 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400157 for (int i = 0; i < colorFPsToEliminate; ++i) {
158 fFragmentProcessors[i]->unref();
159 fFragmentProcessors[i] = nullptr;
Brian Salomon5dac9b32017-04-08 02:53:30 +0000160 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400161 for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
162 fFragmentProcessors[i]->addPendingExecution();
163 fFragmentProcessors[i]->unref();
164 }
165 fFragmentProcessorOffset = colorFPsToEliminate;
166 fColorFragmentProcessorCnt -= colorFPsToEliminate;
167
168 auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
169 outputCoverage, isMixedSamples, caps);
Brian Salomond61c9d92017-04-10 10:54:25 -0400170 fXP.fProcessor = xp.release();
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400171
Brian Salomond61c9d92017-04-10 10:54:25 -0400172 fFlags |= kFinalized_Flag;
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400173 analysis.fIsInitialized = true;
174 return analysis;
Brian Salomon70288c02017-03-24 12:27:17 -0400175}