1 /*
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"
9 #include "GrAppliedClip.h"
10 #include "GrCaps.h"
11 #include "GrPipelineAnalysis.h"
12
GrProcessorSet(GrPaint && paint)13 GrProcessorSet::GrProcessorSet(GrPaint&& paint) {
14 fXPFactory = paint.fXPFactory;
15 fFlags = 0;
16 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;
32 }
33 if (paint.getDisableOutputConversionToSRGB()) {
34 fFlags |= kDisableOutputConversionToSRGB_Flag;
35 }
36 if (paint.getAllowSRGBInputs()) {
37 fFlags |= kAllowSRGBInputs_Flag;
38 }
39 }
40
~GrProcessorSet()41 GrProcessorSet::~GrProcessorSet() {
42 for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
43 if (this->isPendingExecution()) {
44 fFragmentProcessors[i]->completedExecution();
45 } else {
46 fFragmentProcessors[i]->unref();
47 }
48 }
49 }
50
makePendingExecution()51 void GrProcessorSet::makePendingExecution() {
52 SkASSERT(!(kPendingExecution_Flag & fFlags));
53 fFlags |= kPendingExecution_Flag;
54 for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
55 fFragmentProcessors[i]->addPendingExecution();
56 fFragmentProcessors[i]->unref();
57 }
58 }
59
operator ==(const GrProcessorSet & that) const60 bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
61 int fpCount = this->numFragmentProcessors();
62 if (((fFlags ^ that.fFlags) & ~kPendingExecution_Flag) ||
63 fpCount != that.numFragmentProcessors() ||
64 fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
65 return false;
66 }
67
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])) {
72 return false;
73 }
74 }
75 if (fXPFactory != that.fXPFactory) {
76 return false;
77 }
78 return true;
79 }
80
81 //////////////////////////////////////////////////////////////////////////////
82
internalInit(const GrPipelineAnalysisColor & colorInput,const GrPipelineAnalysisCoverage coverageInput,const GrProcessorSet & processors,const GrFragmentProcessor * clipFP,const GrCaps & caps)83 void GrProcessorSet::FragmentProcessorAnalysis::internalInit(
84 const GrPipelineAnalysisColor& colorInput,
85 const GrPipelineAnalysisCoverage coverageInput,
86 const GrProcessorSet& processors,
87 const GrFragmentProcessor* clipFP,
88 const GrCaps& caps) {
89 GrColorFragmentProcessorAnalysis colorInfo(colorInput);
90 fCompatibleWithCoverageAsAlpha = GrPipelineAnalysisCoverage::kLCD != coverageInput;
91 fValidInputColor = colorInput.isConstant(&fInputColor);
92
93 const GrFragmentProcessor* const* fps =
94 processors.fFragmentProcessors.get() + processors.fFragmentProcessorOffset;
95 colorInfo.analyzeProcessors(fps, processors.fColorFragmentProcessorCnt);
96 fCompatibleWithCoverageAsAlpha &= colorInfo.allProcessorsCompatibleWithCoverageAsAlpha();
97 fps += processors.fColorFragmentProcessorCnt;
98 int n = processors.numCoverageFragmentProcessors();
99 bool hasCoverageFP = n > 0;
100 fUsesLocalCoords = colorInfo.usesLocalCoords();
101 for (int i = 0; i < n; ++i) {
102 if (!fps[i]->compatibleWithCoverageAsAlpha()) {
103 fCompatibleWithCoverageAsAlpha = false;
104 // Other than tests that exercise atypical behavior we expect all coverage FPs to be
105 // compatible with the coverage-as-alpha optimization.
106 GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
107 }
108 fUsesLocalCoords |= fps[i]->usesLocalCoords();
109 }
110
111 if (clipFP) {
112 fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
113 fUsesLocalCoords |= clipFP->usesLocalCoords();
114 hasCoverageFP = true;
115 }
116 fInitialColorProcessorsToEliminate = colorInfo.initialProcessorsToEliminate(&fInputColor);
117 fValidInputColor |= SkToBool(fInitialColorProcessorsToEliminate);
118
119 GrPipelineAnalysisColor outputColor = colorInfo.outputColor();
120 if (outputColor.isConstant(&fKnownOutputColor)) {
121 fOutputColorType = static_cast<unsigned>(outputColor.isOpaque() ? ColorType::kOpaqueConstant
122 : ColorType::kConstant);
123 } else if (outputColor.isOpaque()) {
124 fOutputColorType = static_cast<unsigned>(ColorType::kOpaque);
125 } else {
126 fOutputColorType = static_cast<unsigned>(ColorType::kUnknown);
127 }
128
129 if (GrPipelineAnalysisCoverage::kLCD == coverageInput) {
130 fOutputCoverageType = static_cast<unsigned>(GrPipelineAnalysisCoverage::kLCD);
131 } else if (hasCoverageFP || GrPipelineAnalysisCoverage::kSingleChannel == coverageInput) {
132 fOutputCoverageType = static_cast<unsigned>(GrPipelineAnalysisCoverage::kSingleChannel);
133 } else {
134 fOutputCoverageType = static_cast<unsigned>(GrPipelineAnalysisCoverage::kNone);
135 }
136 }
137
init(const GrPipelineAnalysisColor & colorInput,const GrPipelineAnalysisCoverage coverageInput,const GrProcessorSet & processors,const GrAppliedClip * appliedClip,const GrCaps & caps)138 void GrProcessorSet::FragmentProcessorAnalysis::init(const GrPipelineAnalysisColor& colorInput,
139 const GrPipelineAnalysisCoverage coverageInput,
140 const GrProcessorSet& processors,
141 const GrAppliedClip* appliedClip,
142 const GrCaps& caps) {
143 const GrFragmentProcessor* clipFP =
144 appliedClip ? appliedClip->clipCoverageFragmentProcessor() : nullptr;
145 this->internalInit(colorInput, coverageInput, processors, clipFP, caps);
146 fIsInitializedWithProcessorSet = true;
147 }
148
FragmentProcessorAnalysis(const GrPipelineAnalysisColor & colorInput,const GrPipelineAnalysisCoverage coverageInput,const GrCaps & caps)149 GrProcessorSet::FragmentProcessorAnalysis::FragmentProcessorAnalysis(
150 const GrPipelineAnalysisColor& colorInput,
151 const GrPipelineAnalysisCoverage coverageInput,
152 const GrCaps& caps)
153 : FragmentProcessorAnalysis() {
154 this->internalInit(colorInput, coverageInput, GrProcessorSet(GrPaint()), nullptr, caps);
155 }
156
analyzeAndEliminateFragmentProcessors(FragmentProcessorAnalysis * analysis,const GrPipelineAnalysisColor & colorInput,const GrPipelineAnalysisCoverage coverageInput,const GrAppliedClip * clip,const GrCaps & caps)157 void GrProcessorSet::analyzeAndEliminateFragmentProcessors(
158 FragmentProcessorAnalysis* analysis,
159 const GrPipelineAnalysisColor& colorInput,
160 const GrPipelineAnalysisCoverage coverageInput,
161 const GrAppliedClip* clip,
162 const GrCaps& caps) {
163 analysis->init(colorInput, coverageInput, *this, clip, caps);
164 if (analysis->fInitialColorProcessorsToEliminate > 0) {
165 for (unsigned i = 0; i < analysis->fInitialColorProcessorsToEliminate; ++i) {
166 if (this->isPendingExecution()) {
167 fFragmentProcessors[i + fFragmentProcessorOffset]->completedExecution();
168 } else {
169 fFragmentProcessors[i + fFragmentProcessorOffset]->unref();
170 }
171 fFragmentProcessors[i + fFragmentProcessorOffset] = nullptr;
172 }
173 fFragmentProcessorOffset += analysis->fInitialColorProcessorsToEliminate;
174 fColorFragmentProcessorCnt -= analysis->fInitialColorProcessorsToEliminate;
175 SkASSERT(fFragmentProcessorOffset + fColorFragmentProcessorCnt <=
176 fFragmentProcessors.count());
177 analysis->fInitialColorProcessorsToEliminate = 0;
178 }
179 }
180