blob: 93617649a3b6121cbe18dc4b9dbac5a8ba41e514 [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 Salomon48d1b4c2017-04-08 07:38:53 -040014GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
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) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -040043 if (this->isFinalized()) {
Brian Salomon70288c02017-03-24 12:27:17 -040044 fFragmentProcessors[i]->completedExecution();
45 } else {
46 fFragmentProcessors[i]->unref();
Brian Salomon54d212e2017-03-21 14:22:38 -040047 }
48 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -040049 if (this->isFinalized() && this->xferProcessor()) {
50 this->xferProcessor()->completedExecution();
Brian Salomon54d212e2017-03-21 14:22:38 -040051 }
52}
53
54bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
Brian Salomon48d1b4c2017-04-08 07:38:53 -040055 SkASSERT(this->isFinalized());
56 SkASSERT(that.isFinalized());
Brian Salomon70288c02017-03-24 12:27:17 -040057 int fpCount = this->numFragmentProcessors();
Brian Salomon48d1b4c2017-04-08 07:38:53 -040058 if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
Brian Salomon54d212e2017-03-21 14:22:38 -040059 fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
60 return false;
61 }
Brian Salomon70288c02017-03-24 12:27:17 -040062
63 for (int i = 0; i < fpCount; ++i) {
64 int a = i + fFragmentProcessorOffset;
65 int b = i + that.fFragmentProcessorOffset;
66 if (!fFragmentProcessors[a]->isEqual(*that.fFragmentProcessors[b])) {
Brian Salomon54d212e2017-03-21 14:22:38 -040067 return false;
68 }
69 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -040070 // Most of the time both of these are null
71 if (!this->xferProcessor() && !that.xferProcessor()) {
72 return true;
Brian Salomon54d212e2017-03-21 14:22:38 -040073 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -040074 const GrXferProcessor& thisXP = this->xferProcessor()
75 ? *this->xferProcessor()
76 : GrPorterDuffXPFactory::SimpleSrcOverXP();
77 const GrXferProcessor& thatXP = that.xferProcessor()
78 ? *that.xferProcessor()
79 : GrPorterDuffXPFactory::SimpleSrcOverXP();
80 return thisXP.isEqual(thatXP);
Brian Salomon54d212e2017-03-21 14:22:38 -040081}
82
Brian Salomon48d1b4c2017-04-08 07:38:53 -040083GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
84 const GrProcessorAnalysisCoverage coverageInput,
85 const GrAppliedClip* clip, bool isMixedSamples,
86 const GrCaps& caps, GrColor* overrideInputColor) {
87 SkASSERT(!this->isFinalized());
88 SkASSERT(!fFragmentProcessorOffset);
Brian Salomon5298dc82017-02-22 11:52:03 -050089
Brian Salomon48d1b4c2017-04-08 07:38:53 -040090 GrProcessorSet::Analysis analysis;
Brian Salomon5298dc82017-02-22 11:52:03 -050091
Brian Salomon48d1b4c2017-04-08 07:38:53 -040092 const GrFragmentProcessor* clipFP = clip ? clip->clipCoverageFragmentProcessor() : nullptr;
93 GrColorFragmentProcessorAnalysis colorAnalysis(colorInput);
94 analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
95
96 const GrFragmentProcessor* const* fps = fFragmentProcessors.get() + fFragmentProcessorOffset;
97 colorAnalysis.analyzeProcessors(fps, fColorFragmentProcessorCnt);
98 analysis.fCompatibleWithCoverageAsAlpha &=
99 colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
100 fps += fColorFragmentProcessorCnt;
101 int n = this->numCoverageFragmentProcessors();
Brian Salomon5298dc82017-02-22 11:52:03 -0500102 bool hasCoverageFP = n > 0;
Brian Salomon31853842017-03-28 16:32:05 -0400103 bool coverageUsesLocalCoords = false;
Brian Salomonbfafcba2017-03-02 08:49:19 -0500104 for (int i = 0; i < n; ++i) {
Brian Salomon5298dc82017-02-22 11:52:03 -0500105 if (!fps[i]->compatibleWithCoverageAsAlpha()) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400106 analysis.fCompatibleWithCoverageAsAlpha = false;
Brian Salomon5298dc82017-02-22 11:52:03 -0500107 // Other than tests that exercise atypical behavior we expect all coverage FPs to be
108 // compatible with the coverage-as-alpha optimization.
109 GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
Brian Salomon5298dc82017-02-22 11:52:03 -0500110 }
Brian Salomon31853842017-03-28 16:32:05 -0400111 coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500112 }
113
114 if (clipFP) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400115 analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
Brian Salomon31853842017-03-28 16:32:05 -0400116 coverageUsesLocalCoords |= clipFP->usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500117 hasCoverageFP = true;
118 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400119 int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
120 analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
121 colorFPsToEliminate ? Analysis::kOverridden_InputColorType
122 : Analysis::kOriginal_InputColorType);
Brian Salomon5298dc82017-02-22 11:52:03 -0500123
Brian Salomona811b122017-03-30 08:21:32 -0400124 GrProcessorAnalysisCoverage outputCoverage;
125 if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
126 outputCoverage = GrProcessorAnalysisCoverage::kLCD;
127 } else if (hasCoverageFP || GrProcessorAnalysisCoverage::kSingleChannel == coverageInput) {
128 outputCoverage = GrProcessorAnalysisCoverage::kSingleChannel;
Brian Salomon5298dc82017-02-22 11:52:03 -0500129 } else {
Brian Salomona811b122017-03-30 08:21:32 -0400130 outputCoverage = GrProcessorAnalysisCoverage::kNone;
Brian Salomon31853842017-03-28 16:32:05 -0400131 }
Brian Salomon31853842017-03-28 16:32:05 -0400132
133 GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400134 this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps);
135 if (!this->numCoverageFragmentProcessors() &&
Brian Salomona811b122017-03-30 08:21:32 -0400136 GrProcessorAnalysisCoverage::kNone == coverageInput) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400137 analysis.fCanCombineOverlappedStencilAndCover = SkToBool(
Brian Salomon31853842017-03-28 16:32:05 -0400138 props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
139 } else {
140 // If we have non-clipping coverage processors we don't try to merge stencil steps as its
141 // unclear whether it will be correct. We don't expect this to happen in practice.
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400142 analysis.fCanCombineOverlappedStencilAndCover = false;
Brian Salomon31853842017-03-28 16:32:05 -0400143 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400144 analysis.fRequiresDstTexture =
145 SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
146 analysis.fCompatibleWithCoverageAsAlpha &=
Brian Salomon31853842017-03-28 16:32:05 -0400147 SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400148 analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
Brian Salomon4fc77402017-03-30 16:48:26 -0400149 props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
Brian Salomon31853842017-03-28 16:32:05 -0400150 if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400151 colorFPsToEliminate = this->numColorFragmentProcessors();
152 analysis.fInputColorType =
153 static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
154 analysis.fUsesLocalCoords = coverageUsesLocalCoords;
Brian Salomon31853842017-03-28 16:32:05 -0400155 } else {
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400156 analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
Brian Salomon5298dc82017-02-22 11:52:03 -0500157 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400158 for (int i = 0; i < colorFPsToEliminate; ++i) {
159 fFragmentProcessors[i]->unref();
160 fFragmentProcessors[i] = nullptr;
Brian Salomon5dac9b32017-04-08 02:53:30 +0000161 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -0400162 for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
163 fFragmentProcessors[i]->addPendingExecution();
164 fFragmentProcessors[i]->unref();
165 }
166 fFragmentProcessorOffset = colorFPsToEliminate;
167 fColorFragmentProcessorCnt -= colorFPsToEliminate;
168
169 auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
170 outputCoverage, isMixedSamples, caps);
171 fXP.fProcessor = xp.get();
172 if (fXP.fProcessor) {
173 fXP.fProcessor->addPendingExecution();
174 }
175 fFlags |= kFinalized_Flag;
176
177 analysis.fIsInitialized = true;
178 return analysis;
Brian Salomon70288c02017-03-24 12:27:17 -0400179}