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
17struct GrUserStencilSettings;
18class GrAppliedClip;
19class GrXPFactory;
20
21class GrProcessorSet {
22private:
23 // Arbitrary constructor arg for empty set and analysis
24 enum class Empty { kEmpty };
25
26public:
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
152private:
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