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 "include/private/SkColorData.h"
12
13class GrDrawOp;
14class GrFragmentProcessor;
15
16class GrProcessorAnalysisColor {
17public:
18 enum class Opaque {
19 kNo,
20 kYes,
21 };
22
23 constexpr GrProcessorAnalysisColor(Opaque opaque = Opaque::kNo)
24 : fFlags(opaque == Opaque::kYes ? kIsOpaque_Flag : 0)
25 , fColor(SK_PMColor4fTRANSPARENT) {}
26
27 GrProcessorAnalysisColor(const SkPMColor4f& color) { this->setToConstant(color); }
28
29 void setToConstant(const SkPMColor4f& color) {
30 fColor = color;
31 if (color.isOpaque()) {
32 fFlags = kColorIsKnown_Flag | kIsOpaque_Flag;
33 } else {
34 fFlags = kColorIsKnown_Flag;
35 }
36 }
37
38 void setToUnknown() { fFlags = 0; }
39
40 void setToUnknownOpaque() { fFlags = kIsOpaque_Flag; }
41
42 bool isUnknown() const { return SkToBool(fFlags == 0); }
43
44 bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); }
45
46 bool isConstant(SkPMColor4f* color = nullptr) const {
47 if (kColorIsKnown_Flag & fFlags) {
48 if (color) {
49 *color = fColor;
50 }
51 return true;
52 }
53 return false;
54 }
55
56 bool operator==(const GrProcessorAnalysisColor& that) const {
57 if (fFlags != that.fFlags) {
58 return false;
59 }
60 return (kColorIsKnown_Flag & fFlags) ? fColor == that.fColor : true;
61 }
62
63 /** The returned value reflects the common properties of the two inputs. */
64 static GrProcessorAnalysisColor Combine(const GrProcessorAnalysisColor& a,
65 const GrProcessorAnalysisColor& b) {
66 GrProcessorAnalysisColor result;
67 uint32_t commonFlags = a.fFlags & b.fFlags;
68 if ((kColorIsKnown_Flag & commonFlags) && a.fColor == b.fColor) {
69 result.fColor = a.fColor;
70 result.fFlags = a.fFlags;
71 } else if (kIsOpaque_Flag & commonFlags) {
72 result.fFlags = kIsOpaque_Flag;
73 }
74 return result;
75 }
76
77private:
78 enum Flags {
79 kColorIsKnown_Flag = 0x1,
80 kIsOpaque_Flag = 0x2,
81 };
82 uint32_t fFlags;
83 SkPMColor4f fColor;
84};
85
86enum class GrProcessorAnalysisCoverage { kNone, kSingleChannel, kLCD };
87
88/**
89 * GrColorFragmentProcessorAnalysis gathers invariant data from a set of color fragment processor.
90 * It is used to recognize optimizations that can simplify the generated shader or make blending
91 * more effecient.
92 */
93class GrColorFragmentProcessorAnalysis {
94public:
95 GrColorFragmentProcessorAnalysis() = delete;
96
97 GrColorFragmentProcessorAnalysis(const GrProcessorAnalysisColor& input,
98 std::unique_ptr<GrFragmentProcessor> const fps[],
99 int cnt);
100
101 bool isOpaque() const { return fIsOpaque; }
102
103 /**
104 * Are all the fragment processors compatible with conflating coverage with color prior to the
105 * the first fragment processor. This result assumes that processors that should be eliminated
106 * as indicated by initialProcessorsToEliminate() are in fact eliminated.
107 */
108 bool allProcessorsCompatibleWithCoverageAsAlpha() const {
109 return fCompatibleWithCoverageAsAlpha;
110 }
111
112 /**
113 * Do any of the fragment processors require local coords. This result assumes that
114 * processors that should be eliminated as indicated by initialProcessorsToEliminate() are in
115 * fact eliminated.
116 */
117 bool usesLocalCoords() const { return fUsesLocalCoords; }
118
119 /**
120 * If we detected that the result after the first N processors is a known color then we
121 * eliminate those N processors and replace the GrDrawOp's color input to the GrPipeline with
122 * the known output of the Nth processor, so that the Nth+1 fragment processor (or the XP if
123 * there are only N processors) sees its expected input. If this returns 0 then there are no
124 * processors to eliminate.
125 */
126 int initialProcessorsToEliminate(SkPMColor4f* newPipelineInputColor) const {
127 if (fProcessorsToEliminate > 0) {
128 *newPipelineInputColor = fLastKnownOutputColor;
129 }
130 return fProcessorsToEliminate;
131 }
132
133 /**
134 * Provides known information about the last processor's output color.
135 */
136 GrProcessorAnalysisColor outputColor() const {
137 if (fKnowOutputColor) {
138 return fLastKnownOutputColor;
139 }
140 return fIsOpaque ? GrProcessorAnalysisColor::Opaque::kYes
141 : GrProcessorAnalysisColor::Opaque::kNo;
142 }
143
144private:
145 bool fIsOpaque;
146 bool fCompatibleWithCoverageAsAlpha;
147 bool fUsesLocalCoords;
148 bool fKnowOutputColor;
149 int fProcessorsToEliminate;
150 SkPMColor4f fLastKnownOutputColor;
151};
152
153#endif
154