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 explicit 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