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