blob: 8bdf6b63d171e498e92b407e63f4771a93c2cced [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 Salomon92ce5942017-01-18 11:01:10 -050012
13GrProcessorSet::GrProcessorSet(GrPaint&& paint) {
14 fXPFactory = paint.fXPFactory;
Brian Salomonf87e2b92017-01-19 11:31:50 -050015 fFlags = 0;
Brian Salomon8d2f90b2017-03-13 09:11:58 -040016 if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
17 fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
18 fFragmentProcessors.reset(paint.numTotalFragmentProcessors());
19 int i = 0;
20 for (auto& fp : paint.fColorFragmentProcessors) {
21 fFragmentProcessors[i++] = fp.release();
22 }
23 for (auto& fp : paint.fCoverageFragmentProcessors) {
24 fFragmentProcessors[i++] = fp.release();
25 }
26 if (paint.usesDistanceVectorField()) {
27 fFlags |= kUseDistanceVectorField_Flag;
28 }
29 } else {
30 SkDebugf("Insane number of color fragment processors in paint. Dropping all processors.");
31 fColorFragmentProcessorCnt = 0;
Brian Salomonf87e2b92017-01-19 11:31:50 -050032 }
33 if (paint.getDisableOutputConversionToSRGB()) {
34 fFlags |= kDisableOutputConversionToSRGB_Flag;
35 }
36 if (paint.getAllowSRGBInputs()) {
37 fFlags |= kAllowSRGBInputs_Flag;
38 }
Brian Salomon92ce5942017-01-18 11:01:10 -050039}
Brian Salomon5298dc82017-02-22 11:52:03 -050040
Brian Salomon54d212e2017-03-21 14:22:38 -040041GrProcessorSet::~GrProcessorSet() {
Brian Salomon70288c02017-03-24 12:27:17 -040042 for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
43 if (this->isPendingExecution()) {
44 fFragmentProcessors[i]->completedExecution();
45 } else {
46 fFragmentProcessors[i]->unref();
Brian Salomon54d212e2017-03-21 14:22:38 -040047 }
48 }
49}
50
51void GrProcessorSet::makePendingExecution() {
52 SkASSERT(!(kPendingExecution_Flag & fFlags));
53 fFlags |= kPendingExecution_Flag;
Brian Salomon70288c02017-03-24 12:27:17 -040054 for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
Brian Salomon54d212e2017-03-21 14:22:38 -040055 fFragmentProcessors[i]->addPendingExecution();
56 fFragmentProcessors[i]->unref();
57 }
58}
59
60bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
Brian Salomon70288c02017-03-24 12:27:17 -040061 int fpCount = this->numFragmentProcessors();
Brian Salomon54d212e2017-03-21 14:22:38 -040062 if (((fFlags ^ that.fFlags) & ~kPendingExecution_Flag) ||
Brian Salomon70288c02017-03-24 12:27:17 -040063 fpCount != that.numFragmentProcessors() ||
Brian Salomon54d212e2017-03-21 14:22:38 -040064 fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
65 return false;
66 }
Brian Salomon70288c02017-03-24 12:27:17 -040067
68 for (int i = 0; i < fpCount; ++i) {
69 int a = i + fFragmentProcessorOffset;
70 int b = i + that.fFragmentProcessorOffset;
71 if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
Brian Salomon54d212e2017-03-21 14:22:38 -040072 return false;
73 }
74 }
75 if (fXPFactory != that.fXPFactory) {
76 return false;
77 }
78 return true;
79}
80
Brian Salomon5298dc82017-02-22 11:52:03 -050081//////////////////////////////////////////////////////////////////////////////
82
Brian Salomona811b122017-03-30 08:21:32 -040083void GrProcessorSet::Analysis::internalInit(const GrProcessorAnalysisColor& colorInput,
84 const GrProcessorAnalysisCoverage coverageInput,
85 const GrProcessorSet& processors,
86 const GrFragmentProcessor* clipFP,
87 const GrCaps& caps) {
Brian Salomonc0b642c2017-03-27 13:09:36 -040088 GrColorFragmentProcessorAnalysis colorInfo(colorInput);
Brian Salomona811b122017-03-30 08:21:32 -040089 fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
Brian Salomon8d2f90b2017-03-13 09:11:58 -040090 fValidInputColor = colorInput.isConstant(&fInputColor);
Brian Salomon5298dc82017-02-22 11:52:03 -050091
Brian Salomon70288c02017-03-24 12:27:17 -040092 const GrFragmentProcessor* const* fps =
93 processors.fFragmentProcessors.get() + processors.fFragmentProcessorOffset;
Brian Salomon5298dc82017-02-22 11:52:03 -050094 colorInfo.analyzeProcessors(fps, processors.fColorFragmentProcessorCnt);
95 fCompatibleWithCoverageAsAlpha &= colorInfo.allProcessorsCompatibleWithCoverageAsAlpha();
96 fps += processors.fColorFragmentProcessorCnt;
97 int n = processors.numCoverageFragmentProcessors();
98 bool hasCoverageFP = n > 0;
Brian Salomon31853842017-03-28 16:32:05 -040099 bool coverageUsesLocalCoords = false;
Brian Salomonbfafcba2017-03-02 08:49:19 -0500100 for (int i = 0; i < n; ++i) {
Brian Salomon5298dc82017-02-22 11:52:03 -0500101 if (!fps[i]->compatibleWithCoverageAsAlpha()) {
102 fCompatibleWithCoverageAsAlpha = false;
103 // Other than tests that exercise atypical behavior we expect all coverage FPs to be
104 // compatible with the coverage-as-alpha optimization.
105 GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
Brian Salomon5298dc82017-02-22 11:52:03 -0500106 }
Brian Salomon31853842017-03-28 16:32:05 -0400107 coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500108 }
109
110 if (clipFP) {
111 fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
Brian Salomon31853842017-03-28 16:32:05 -0400112 coverageUsesLocalCoords |= clipFP->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500113 hasCoverageFP = true;
114 }
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400115 fInitialColorProcessorsToEliminate = colorInfo.initialProcessorsToEliminate(&fInputColor);
116 fValidInputColor |= SkToBool(fInitialColorProcessorsToEliminate);
Brian Salomon5298dc82017-02-22 11:52:03 -0500117
Brian Salomona811b122017-03-30 08:21:32 -0400118 GrProcessorAnalysisColor outputColor = colorInfo.outputColor();
Brian Salomonc0b642c2017-03-27 13:09:36 -0400119 if (outputColor.isConstant(&fKnownOutputColor)) {
Brian Salomon1c6025c2017-03-29 14:25:04 -0400120 fOutputColorType = static_cast<unsigned>(ColorType::kConstant);
Brian Salomonc0b642c2017-03-27 13:09:36 -0400121 } else if (outputColor.isOpaque()) {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400122 fOutputColorType = static_cast<unsigned>(ColorType::kOpaque);
Brian Salomon5298dc82017-02-22 11:52:03 -0500123 } else {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400124 fOutputColorType = static_cast<unsigned>(ColorType::kUnknown);
Brian Salomon5298dc82017-02-22 11:52:03 -0500125 }
126
Brian Salomona811b122017-03-30 08:21:32 -0400127 GrProcessorAnalysisCoverage outputCoverage;
128 if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
129 outputCoverage = GrProcessorAnalysisCoverage::kLCD;
130 } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
131 outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
Brian Salomon5298dc82017-02-22 11:52:03 -0500132 } else {
Brian Salomona811b122017-03-30 08:21:32 -0400133 outputCoverage = GrProcessorAnalysisCoverage::kNone;
Brian Salomon31853842017-03-28 16:32:05 -0400134 }
135 fOutputCoverageType = static_cast<unsigned>(outputCoverage);
136
137 GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
138 processors.fXPFactory, colorInfo.outputColor(), outputCoverage, caps);
139 if (!processors.numCoverageFragmentProcessors() &&
Brian Salomona811b122017-03-30 08:21:32 -0400140 GrProcessorAnalysisCoverage::kNone == coverageInput) {
Brian Salomon31853842017-03-28 16:32:05 -0400141 fCanCombineOverlappedStencilAndCover = SkToBool(
142 props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
143 } else {
144 // If we have non-clipping coverage processors we don't try to merge stencil steps as its
145 // unclear whether it will be correct. We don't expect this to happen in practice.
146 fCanCombineOverlappedStencilAndCover = false;
147 }
148 fRequiresDstTexture = SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
149 fIgnoresInputColor = SkToBool(props & GrXPFactory::AnalysisProperties::kIgnoresInputColor);
150 fCompatibleWithCoverageAsAlpha &=
151 SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
Brian Salomon4fc77402017-03-30 16:48:26 -0400152 fRequiresBarrierBetweenOverlappingDraws = SkToBool(
153 props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
Brian Salomon31853842017-03-28 16:32:05 -0400154 if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
155 fInitialColorProcessorsToEliminate = processors.numColorFragmentProcessors();
156 // If the output of the last color stage is known then the kIgnoresInputColor optimization
157 // may depend upon it being the input to the xp.
158 if (!outputColor.isConstant(&fInputColor)) {
159 // Otherwise, the only property the XP factory could have relied upon to compute
160 // kIgnoresInputColor is opaqueness.
161 fInputColor = GrColor_WHITE;
162 }
163 fValidInputColor = true;
164 fUsesLocalCoords = coverageUsesLocalCoords;
165 } else {
166 fUsesLocalCoords = coverageUsesLocalCoords | colorInfo.usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500167 }
168}
169
Brian Salomona811b122017-03-30 08:21:32 -0400170void GrProcessorSet::Analysis::init(const GrProcessorAnalysisColor& colorInput,
171 const GrProcessorAnalysisCoverage coverageInput,
172 const GrProcessorSet& processors,
173 const GrAppliedClip* appliedClip,
174 const GrCaps& caps) {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400175 const GrFragmentProcessor* clipFP =
176 appliedClip ? appliedClip->clipCoverageFragmentProcessor() : nullptr;
177 this->internalInit(colorInput, coverageInput, processors, clipFP, caps);
178 fIsInitializedWithProcessorSet = true;
Brian Salomon5298dc82017-02-22 11:52:03 -0500179}
180
Brian Salomona811b122017-03-30 08:21:32 -0400181GrProcessorSet::Analysis::Analysis(const GrProcessorAnalysisColor& colorInput,
182 const GrProcessorAnalysisCoverage coverageInput,
183 const GrXPFactory* factory,
184 const GrCaps& caps)
185 : Analysis() {
Brian Salomon31853842017-03-28 16:32:05 -0400186 GrPaint paint;
187 paint.setXPFactory(factory);
188 this->internalInit(colorInput, coverageInput, GrProcessorSet(std::move(paint)), nullptr, caps);
Brian Salomon5298dc82017-02-22 11:52:03 -0500189}
Brian Salomon70288c02017-03-24 12:27:17 -0400190
Brian Salomonc0b642c2017-03-27 13:09:36 -0400191void GrProcessorSet::analyzeAndEliminateFragmentProcessors(
Brian Salomona811b122017-03-30 08:21:32 -0400192 Analysis* analysis,
193 const GrProcessorAnalysisColor& colorInput,
194 const GrProcessorAnalysisCoverage coverageInput,
Brian Salomonc0b642c2017-03-27 13:09:36 -0400195 const GrAppliedClip* clip,
196 const GrCaps& caps) {
Brian Salomon70288c02017-03-24 12:27:17 -0400197 analysis->init(colorInput, coverageInput, *this, clip, caps);
198 if (analysis->fInitialColorProcessorsToEliminate > 0) {
199 for (unsigned i = 0; i < analysis->fInitialColorProcessorsToEliminate; ++i) {
200 if (this->isPendingExecution()) {
201 fFragmentProcessors[i + fFragmentProcessorOffset]->completedExecution();
202 } else {
203 fFragmentProcessors[i + fFragmentProcessorOffset]->unref();
204 }
205 fFragmentProcessors[i + fFragmentProcessorOffset] = nullptr;
206 }
207 fFragmentProcessorOffset += analysis->fInitialColorProcessorsToEliminate;
208 fColorFragmentProcessorCnt -= analysis->fInitialColorProcessorsToEliminate;
209 SkASSERT(fFragmentProcessorOffset + fColorFragmentProcessorCnt <=
210 fFragmentProcessors.count());
211 analysis->fInitialColorProcessorsToEliminate = 0;
212 }
213}