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 | #ifndef GrProcessorSet_DEFINED |
9 | #define GrProcessorSet_DEFINED |
10 | |
11 | #include "include/private/SkTemplates.h" |
12 | #include "src/gpu/GrFragmentProcessor.h" |
13 | #include "src/gpu/GrPaint.h" |
14 | #include "src/gpu/GrProcessorAnalysis.h" |
15 | #include "src/gpu/GrXferProcessor.h" |
16 | |
17 | struct GrUserStencilSettings; |
18 | class GrAppliedClip; |
19 | class GrXPFactory; |
20 | |
21 | class GrProcessorSet { |
22 | private: |
23 | // Arbitrary constructor arg for empty set and analysis |
24 | enum class Empty { kEmpty }; |
25 | |
26 | public: |
27 | GrProcessorSet(GrPaint&&); |
28 | GrProcessorSet(SkBlendMode); |
29 | GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP); |
30 | GrProcessorSet(GrProcessorSet&&); |
31 | GrProcessorSet(const GrProcessorSet&) = delete; |
32 | GrProcessorSet& operator=(const GrProcessorSet&) = delete; |
33 | |
34 | ~GrProcessorSet(); |
35 | |
36 | bool hasColorFragmentProcessor() const { return fColorFragmentProcessor != nullptr; } |
37 | bool hasCoverageFragmentProcessor() const { return fCoverageFragmentProcessor != nullptr; } |
38 | |
39 | const GrFragmentProcessor* colorFragmentProcessor() const { |
40 | return fColorFragmentProcessor.get(); |
41 | } |
42 | const GrFragmentProcessor* coverageFragmentProcessor() const { |
43 | return fCoverageFragmentProcessor.get(); |
44 | } |
45 | |
46 | const GrXferProcessor* xferProcessor() const { |
47 | SkASSERT(this->isFinalized()); |
48 | return fXP.fProcessor; |
49 | } |
50 | sk_sp<const GrXferProcessor> refXferProcessor() const { |
51 | SkASSERT(this->isFinalized()); |
52 | return sk_ref_sp(fXP.fProcessor); |
53 | } |
54 | |
55 | std::unique_ptr<GrFragmentProcessor> detachColorFragmentProcessor() { |
56 | return std::move(fColorFragmentProcessor); |
57 | } |
58 | |
59 | std::unique_ptr<GrFragmentProcessor> detachCoverageFragmentProcessor() { |
60 | return std::move(fCoverageFragmentProcessor); |
61 | } |
62 | |
63 | /** Comparisons are only legal on finalized processor sets. */ |
64 | bool operator==(const GrProcessorSet& that) const; |
65 | bool operator!=(const GrProcessorSet& that) const { return !(*this == that); } |
66 | |
67 | /** |
68 | * This is used to report results of processor analysis when a processor set is finalized (see |
69 | * below). |
70 | */ |
71 | class Analysis { |
72 | public: |
73 | Analysis(const Analysis&) = default; |
74 | Analysis() { *reinterpret_cast<uint32_t*>(this) = 0; } |
75 | |
76 | bool isInitialized() const { return fIsInitialized; } |
77 | bool usesLocalCoords() const { return fUsesLocalCoords; } |
78 | bool requiresDstTexture() const { return fRequiresDstTexture; } |
79 | bool requiresNonOverlappingDraws() const { return fRequiresNonOverlappingDraws; } |
80 | bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; } |
81 | // Indicates whether all color fragment processors were eliminated in the analysis. |
82 | bool hasColorFragmentProcessor() const { return fHasColorFragmentProcessor; } |
83 | |
84 | bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; } |
85 | bool inputColorIsOverridden() const { |
86 | return fInputColorType == kOverridden_InputColorType; |
87 | } |
88 | |
89 | private: |
90 | constexpr Analysis(Empty) |
91 | : fUsesLocalCoords(false) |
92 | , fCompatibleWithCoverageAsAlpha(true) |
93 | , fRequiresDstTexture(false) |
94 | , fRequiresNonOverlappingDraws(false) |
95 | , fHasColorFragmentProcessor(false) |
96 | , fIsInitialized(true) |
97 | , fInputColorType(kOriginal_InputColorType) {} |
98 | enum InputColorType : uint32_t { |
99 | kOriginal_InputColorType, |
100 | kOverridden_InputColorType, |
101 | kIgnored_InputColorType |
102 | }; |
103 | |
104 | // MSVS 2015 won't pack different underlying types |
105 | using PackedBool = uint32_t; |
106 | using PackedInputColorType = uint32_t; |
107 | |
108 | PackedBool fUsesLocalCoords : 1; |
109 | PackedBool fCompatibleWithCoverageAsAlpha : 1; |
110 | PackedBool fRequiresDstTexture : 1; |
111 | PackedBool fRequiresNonOverlappingDraws : 1; |
112 | PackedBool fHasColorFragmentProcessor : 1; |
113 | PackedBool fIsInitialized : 1; |
114 | PackedInputColorType fInputColorType : 2; |
115 | |
116 | friend class GrProcessorSet; |
117 | }; |
118 | static_assert(sizeof(Analysis) <= sizeof(uint32_t)); |
119 | |
120 | /** |
121 | * This analyzes the processors given an op's input color and coverage as well as a clip. The |
122 | * state of the processor set may change to an equivalent but more optimal set of processors. |
123 | * This new state requires that the caller respect the returned 'inputColorOverride'. This is |
124 | * indicated by the returned Analysis's inputColorIsOverridden(). 'inputColorOverride' will not |
125 | * be written if the analysis does not override the input color. |
126 | * |
127 | * This must be called before the processor set is used to construct a GrPipeline and may only |
128 | * be called once. |
129 | * |
130 | * This also puts the processors in "pending execution" state and must be called when an op |
131 | * that owns a processor set is recorded to ensure pending and writes are propagated to |
132 | * resources referred to by the processors. Otherwise, data hazards may occur. |
133 | */ |
134 | Analysis finalize( |
135 | const GrProcessorAnalysisColor&, const GrProcessorAnalysisCoverage, |
136 | const GrAppliedClip*, const GrUserStencilSettings*, bool hasMixedSampledCoverage, |
137 | const GrCaps&, GrClampType, SkPMColor4f* inputColorOverride); |
138 | |
139 | bool isFinalized() const { return SkToBool(kFinalized_Flag & fFlags); } |
140 | |
141 | /** These are valid only for non-LCD coverage. */ |
142 | static const GrProcessorSet& EmptySet(); |
143 | static GrProcessorSet MakeEmptySet(); |
144 | static constexpr Analysis EmptySetAnalysis() { return Analysis(Empty::kEmpty); } |
145 | |
146 | #if GR_TEST_UTILS |
147 | SkString dumpProcessors() const; |
148 | #endif |
149 | |
150 | void visitProxies(const GrOp::VisitProxyFunc& func) const; |
151 | |
152 | private: |
153 | GrProcessorSet(Empty) : fXP((const GrXferProcessor*)nullptr), fFlags(kFinalized_Flag) {} |
154 | |
155 | int numFragmentProcessors() const { |
156 | return (fColorFragmentProcessor ? 1 : 0) + (fCoverageFragmentProcessor ? 1 : 0); |
157 | } |
158 | |
159 | enum Flags : uint16_t { kFinalized_Flag = 0x1 }; |
160 | |
161 | union XP { |
162 | XP(const GrXPFactory* factory) : fFactory(factory) {} |
163 | XP(const GrXferProcessor* processor) : fProcessor(processor) {} |
164 | explicit XP(XP&& that) : fProcessor(that.fProcessor) { |
165 | SkASSERT(fProcessor == that.fProcessor); |
166 | that.fProcessor = nullptr; |
167 | } |
168 | const GrXPFactory* fFactory; |
169 | const GrXferProcessor* fProcessor; |
170 | }; |
171 | |
172 | const GrXPFactory* xpFactory() const { |
173 | SkASSERT(!this->isFinalized()); |
174 | return fXP.fFactory; |
175 | } |
176 | |
177 | std::unique_ptr<GrFragmentProcessor> fColorFragmentProcessor; |
178 | std::unique_ptr<GrFragmentProcessor> fCoverageFragmentProcessor; |
179 | XP fXP; |
180 | uint8_t fFlags = 0; |
181 | }; |
182 | |
183 | #endif |
184 | |