Line data Source code
1 : /*
2 : * Copyright 2014 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 : #ifndef GrProcessorAnalysis_DEFINED
9 : #define GrProcessorAnalysis_DEFINED
10 :
11 : #include "GrColor.h"
12 :
13 : class GrDrawOp;
14 : class GrFragmentProcessor;
15 : class GrPrimitiveProcessor;
16 :
17 : class GrProcessorAnalysisColor {
18 : public:
19 : enum class Opaque {
20 : kNo,
21 : kYes,
22 : };
23 :
24 0 : GrProcessorAnalysisColor(Opaque opaque = Opaque::kNo)
25 0 : : fFlags(opaque == Opaque::kYes ? kIsOpaque_Flag : 0) {}
26 :
27 0 : GrProcessorAnalysisColor(GrColor color) { this->setToConstant(color); }
28 :
29 0 : void setToConstant(GrColor color) {
30 0 : fColor = color;
31 0 : if (GrColorIsOpaque(color)) {
32 0 : fFlags = kColorIsKnown_Flag | kIsOpaque_Flag;
33 : } else {
34 0 : fFlags = kColorIsKnown_Flag;
35 : }
36 0 : }
37 :
38 0 : void setToUnknown() { fFlags = 0; }
39 :
40 : void setToUnknownOpaque() { fFlags = kIsOpaque_Flag; }
41 :
42 0 : bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); }
43 :
44 0 : bool isConstant(GrColor* color = nullptr) const {
45 0 : if (kColorIsKnown_Flag & fFlags) {
46 0 : if (color) {
47 0 : *color = fColor;
48 : }
49 0 : return true;
50 : }
51 0 : return false;
52 : }
53 :
54 : bool operator==(const GrProcessorAnalysisColor& that) const {
55 : if (fFlags != that.fFlags) {
56 : return false;
57 : }
58 : return (kColorIsKnown_Flag & fFlags) ? fColor == that.fColor : true;
59 : }
60 :
61 : /** The returned value reflects the common properties of the two inputs. */
62 : static GrProcessorAnalysisColor Combine(const GrProcessorAnalysisColor& a,
63 : const GrProcessorAnalysisColor& b) {
64 : GrProcessorAnalysisColor result;
65 : uint32_t commonFlags = a.fFlags & b.fFlags;
66 : if ((kColorIsKnown_Flag & commonFlags) && a.fColor == b.fColor) {
67 : result.fColor = a.fColor;
68 : result.fFlags = a.fFlags;
69 : } else if (kIsOpaque_Flag & commonFlags) {
70 : result.fFlags = kIsOpaque_Flag;
71 : }
72 : return result;
73 : }
74 :
75 : private:
76 : enum Flags {
77 : kColorIsKnown_Flag = 0x1,
78 : kIsOpaque_Flag = 0x2,
79 : };
80 : uint32_t fFlags;
81 : GrColor fColor;
82 : };
83 :
84 : enum class GrProcessorAnalysisCoverage { kNone, kSingleChannel, kLCD };
85 :
86 : /**
87 : * GrColorFragmentProcessorAnalysis gathers invariant data from a set of color fragment processor.
88 : * It is used to recognize optimizations that can simplify the generated shader or make blending
89 : * more effecient.
90 : */
91 : class GrColorFragmentProcessorAnalysis {
92 : public:
93 0 : GrColorFragmentProcessorAnalysis() = default;
94 :
95 0 : GrColorFragmentProcessorAnalysis(const GrProcessorAnalysisColor& input)
96 0 : : GrColorFragmentProcessorAnalysis() {
97 0 : fAllProcessorsCompatibleWithCoverageAsAlpha = true;
98 0 : fIsOpaque = input.isOpaque();
99 : GrColor color;
100 0 : if (input.isConstant(&color)) {
101 0 : fLastKnownOutputColor = GrColor4f::FromGrColor(color);
102 0 : fProcessorsVisitedWithKnownOutput = 0;
103 : }
104 0 : }
105 :
106 : void reset(const GrProcessorAnalysisColor& input) {
107 : *this = GrColorFragmentProcessorAnalysis(input);
108 : }
109 :
110 : /**
111 : * Runs through a series of processors and updates calculated values. This can be called
112 : * repeatedly for cases when the sequence of processors is not in a contiguous array.
113 : */
114 : void analyzeProcessors(const GrFragmentProcessor* const* processors, int cnt);
115 :
116 : bool isOpaque() const { return fIsOpaque; }
117 :
118 : /**
119 : * Are all the fragment processors compatible with conflating coverage with color prior to the
120 : * the first fragment processor. This result does not consider processors that should be
121 : * eliminated as indicated by initialProcessorsToEliminate().
122 : */
123 0 : bool allProcessorsCompatibleWithCoverageAsAlpha() const {
124 0 : return fAllProcessorsCompatibleWithCoverageAsAlpha;
125 : }
126 :
127 : /**
128 : * Do any of the fragment processors require local coords. This result does not consider
129 : * processors that should be eliminated as indicated by initialProcessorsToEliminate().
130 : */
131 0 : bool usesLocalCoords() const { return fUsesLocalCoords; }
132 :
133 : /**
134 : * If we detected that the result after the first N processors is a known color then we
135 : * eliminate those N processors and replace the GrDrawOp's color input to the GrPipeline with
136 : * the known output of the Nth processor, so that the Nth+1 fragment processor (or the XP if
137 : * there are only N processors) sees its expected input. If this returns 0 then there are no
138 : * processors to eliminate.
139 : */
140 0 : int initialProcessorsToEliminate(GrColor* newPipelineInputColor) const {
141 0 : if (fProcessorsVisitedWithKnownOutput > 0) {
142 0 : *newPipelineInputColor = fLastKnownOutputColor.toGrColor();
143 : }
144 0 : return SkTMax(0, fProcessorsVisitedWithKnownOutput);
145 : }
146 :
147 0 : int initialProcessorsToEliminate(GrColor4f* newPipelineInputColor) const {
148 0 : if (fProcessorsVisitedWithKnownOutput > 0) {
149 0 : *newPipelineInputColor = fLastKnownOutputColor;
150 : }
151 0 : return SkTMax(0, fProcessorsVisitedWithKnownOutput);
152 : }
153 :
154 0 : GrProcessorAnalysisColor outputColor() const {
155 0 : if (fProcessorsVisitedWithKnownOutput != fTotalProcessorsVisited) {
156 0 : return GrProcessorAnalysisColor(fIsOpaque ? GrProcessorAnalysisColor::Opaque::kYes
157 0 : : GrProcessorAnalysisColor::Opaque::kNo);
158 : }
159 0 : return GrProcessorAnalysisColor(fLastKnownOutputColor.toGrColor());
160 : }
161 :
162 : private:
163 : int fTotalProcessorsVisited = 0;
164 : // negative one means even the color is unknown before adding the first processor.
165 : int fProcessorsVisitedWithKnownOutput = -1;
166 : bool fIsOpaque = false;
167 : bool fAllProcessorsCompatibleWithCoverageAsAlpha = true;
168 : bool fUsesLocalCoords = false;
169 : GrColor4f fLastKnownOutputColor;
170 : };
171 :
172 : #endif
|