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 
numColorFragmentProcessors()36     int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
numCoverageFragmentProcessors()37     int numCoverageFragmentProcessors() const {
38         return this->numFragmentProcessors() - fColorFragmentProcessorCnt;
39     }
40 
colorFragmentProcessor(int idx)41     const GrFragmentProcessor* colorFragmentProcessor(int idx) const {
42         SkASSERT(idx < fColorFragmentProcessorCnt);
43         return fFragmentProcessors[idx + fFragmentProcessorOffset].get();
44     }
coverageFragmentProcessor(int idx)45     const GrFragmentProcessor* coverageFragmentProcessor(int idx) const {
46         return fFragmentProcessors[idx + fColorFragmentProcessorCnt +
47                                    fFragmentProcessorOffset].get();
48     }
49 
xferProcessor()50     const GrXferProcessor* xferProcessor() const {
51         SkASSERT(this->isFinalized());
52         return fXP.fProcessor;
53     }
refXferProcessor()54     sk_sp<const GrXferProcessor> refXferProcessor() const {
55         SkASSERT(this->isFinalized());
56         return sk_ref_sp(fXP.fProcessor);
57     }
58 
detachColorFragmentProcessor(int idx)59     std::unique_ptr<const GrFragmentProcessor> detachColorFragmentProcessor(int idx) {
60         SkASSERT(idx < fColorFragmentProcessorCnt);
61         return std::move(fFragmentProcessors[idx + fFragmentProcessorOffset]);
62     }
63 
detachCoverageFragmentProcessor(int idx)64     std::unique_ptr<const GrFragmentProcessor> detachCoverageFragmentProcessor(int idx) {
65         return std::move(
66                 fFragmentProcessors[idx + fFragmentProcessorOffset + fColorFragmentProcessorCnt]);
67     }
68 
69     /** Comparisons are only legal on finalized processor sets. */
70     bool operator==(const GrProcessorSet& that) const;
71     bool operator!=(const GrProcessorSet& that) const { return !(*this == that); }
72 
73     /**
74      * This is used to report results of processor analysis when a processor set is finalized (see
75      * below).
76      */
77     class Analysis {
78     public:
79         Analysis(const Analysis&) = default;
Analysis()80         Analysis() { *reinterpret_cast<uint32_t*>(this) = 0; }
81 
isInitialized()82         bool isInitialized() const { return fIsInitialized; }
usesLocalCoords()83         bool usesLocalCoords() const { return fUsesLocalCoords; }
requiresDstTexture()84         bool requiresDstTexture() const { return fRequiresDstTexture; }
requiresNonOverlappingDraws()85         bool requiresNonOverlappingDraws() const { return fRequiresNonOverlappingDraws; }
isCompatibleWithCoverageAsAlpha()86         bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
87         // Indicates whether all color fragment processors were eliminated in the analysis.
hasColorFragmentProcessor()88         bool hasColorFragmentProcessor() const { return fHasColorFragmentProcessor; }
89 
inputColorIsIgnored()90         bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; }
inputColorIsOverridden()91         bool inputColorIsOverridden() const {
92             return fInputColorType == kOverridden_InputColorType;
93         }
94 
95     private:
Analysis(Empty)96         constexpr Analysis(Empty)
97                 : fUsesLocalCoords(false)
98                 , fCompatibleWithCoverageAsAlpha(true)
99                 , fRequiresDstTexture(false)
100                 , fRequiresNonOverlappingDraws(false)
101                 , fHasColorFragmentProcessor(false)
102                 , fIsInitialized(true)
103                 , fInputColorType(kOriginal_InputColorType) {}
104         enum InputColorType : uint32_t {
105             kOriginal_InputColorType,
106             kOverridden_InputColorType,
107             kIgnored_InputColorType
108         };
109 
110         // MSVS 2015 won't pack different underlying types
111         using PackedBool = uint32_t;
112         using PackedInputColorType = uint32_t;
113 
114         PackedBool fUsesLocalCoords : 1;
115         PackedBool fCompatibleWithCoverageAsAlpha : 1;
116         PackedBool fRequiresDstTexture : 1;
117         PackedBool fRequiresNonOverlappingDraws : 1;
118         PackedBool fHasColorFragmentProcessor : 1;
119         PackedBool fIsInitialized : 1;
120         PackedInputColorType fInputColorType : 2;
121 
122         friend class GrProcessorSet;
123     };
124     GR_STATIC_ASSERT(sizeof(Analysis) <= sizeof(uint32_t));
125 
126     /**
127      * This analyzes the processors given an op's input color and coverage as well as a clip. The
128      * state of the processor set may change to an equivalent but more optimal set of processors.
129      * This new state requires that the caller respect the returned 'inputColorOverride'. This is
130      * indicated by the returned Analysis's inputColorIsOverridden(). 'inputColorOverride' will not
131      * be written if the analysis does not override the input color.
132      *
133      * This must be called before the processor set is used to construct a GrPipeline and may only
134      * be called once.
135      *
136      * This also puts the processors in "pending execution" state and must be called when an op
137      * that owns a processor set is recorded to ensure pending and writes are propagated to
138      * resources referred to by the processors. Otherwise, data hazards may occur.
139      */
140     Analysis finalize(
141             const GrProcessorAnalysisColor&, const GrProcessorAnalysisCoverage,
142             const GrAppliedClip*, const GrUserStencilSettings*, bool hasMixedSampledCoverage,
143             const GrCaps&, GrClampType, SkPMColor4f* inputColorOverride);
144 
isFinalized()145     bool isFinalized() const { return SkToBool(kFinalized_Flag & fFlags); }
146 
147     /** These are valid only for non-LCD coverage. */
148     static const GrProcessorSet& EmptySet();
149     static GrProcessorSet MakeEmptySet();
EmptySetAnalysis()150     static constexpr const Analysis EmptySetAnalysis() { return Analysis(Empty::kEmpty); }
151 
152 #ifdef SK_DEBUG
153     SkString dumpProcessors() const;
154 #endif
155 
visitProxies(const GrOp::VisitProxyFunc & func)156     void visitProxies(const GrOp::VisitProxyFunc& func) const {
157         for (int i = 0; i < this->numFragmentProcessors(); ++i) {
158             GrFragmentProcessor::TextureAccessIter iter(this->fragmentProcessor(i));
159             while (const GrFragmentProcessor::TextureSampler* sampler = iter.next()) {
160                 bool mipped = (GrSamplerState::Filter::kMipMap == sampler->samplerState().filter());
161                 func(sampler->proxy(), GrMipMapped(mipped));
162             }
163         }
164     }
165 
166 private:
GrProcessorSet(Empty)167     GrProcessorSet(Empty) : fXP((const GrXferProcessor*)nullptr), fFlags(kFinalized_Flag) {}
168 
numFragmentProcessors()169     int numFragmentProcessors() const {
170         return fFragmentProcessors.count() - fFragmentProcessorOffset;
171     }
172 
fragmentProcessor(int idx)173     const GrFragmentProcessor* fragmentProcessor(int idx) const {
174         return fFragmentProcessors[idx + fFragmentProcessorOffset].get();
175     }
176 
177     // This absurdly large limit allows Analysis and this to pack fields together.
178     static constexpr int kMaxColorProcessors = UINT8_MAX;
179 
180     enum Flags : uint16_t { kFinalized_Flag = 0x1 };
181 
182     union XP {
XP(const GrXPFactory * factory)183         XP(const GrXPFactory* factory) : fFactory(factory) {}
XP(const GrXferProcessor * processor)184         XP(const GrXferProcessor* processor) : fProcessor(processor) {}
XP(XP && that)185         explicit XP(XP&& that) : fProcessor(that.fProcessor) {
186             SkASSERT(fProcessor == that.fProcessor);
187             that.fProcessor = nullptr;
188         }
189         const GrXPFactory* fFactory;
190         const GrXferProcessor* fProcessor;
191     };
192 
xpFactory()193     const GrXPFactory* xpFactory() const {
194         SkASSERT(!this->isFinalized());
195         return fXP.fFactory;
196     }
197 
198     SkAutoSTArray<4, std::unique_ptr<const GrFragmentProcessor>> fFragmentProcessors;
199     XP fXP;
200     uint8_t fColorFragmentProcessorCnt = 0;
201     uint8_t fFragmentProcessorOffset = 0;
202     uint8_t fFlags;
203 };
204 
205 #endif
206