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; } requiresNonOverlappingDraws()84 bool requiresNonOverlappingDraws() const { return fRequiresNonOverlappingDraws; } isCompatibleWithCoverageAsAlpha()85 bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; } 86 inputColorIsIgnored()87 bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; } inputColorIsOverridden()88 bool inputColorIsOverridden() const { 89 return fInputColorType == kOverridden_InputColorType; 90 } 91 92 private: Analysis(Empty)93 constexpr Analysis(Empty) 94 : fUsesLocalCoords(false) 95 , fCompatibleWithCoverageAsAlpha(true) 96 , fRequiresDstTexture(false) 97 , fRequiresNonOverlappingDraws(false) 98 , fIsInitialized(true) 99 , fInputColorType(kOriginal_InputColorType) {} 100 enum InputColorType : uint32_t { 101 kOriginal_InputColorType, 102 kOverridden_InputColorType, 103 kIgnored_InputColorType 104 }; 105 106 // MSVS 2015 won't pack different underlying types 107 using PackedBool = uint32_t; 108 using PackedInputColorType = uint32_t; 109 110 PackedBool fUsesLocalCoords : 1; 111 PackedBool fCompatibleWithCoverageAsAlpha : 1; 112 PackedBool fRequiresDstTexture : 1; 113 PackedBool fRequiresNonOverlappingDraws : 1; 114 PackedBool fIsInitialized : 1; 115 PackedInputColorType fInputColorType : 2; 116 117 friend class GrProcessorSet; 118 }; 119 GR_STATIC_ASSERT(sizeof(Analysis) <= sizeof(uint32_t)); 120 121 /** 122 * This analyzes the processors given an op's input color and coverage as well as a clip. The 123 * state of the processor set may change to an equivalent but more optimal set of processors. 124 * This new state requires that the caller respect the returned 'inputColorOverride'. This is 125 * indicated by the returned Analysis's inputColorIsOverridden(). 'inputColorOverride' will not 126 * be written if the analysis does not override the input color. 127 * 128 * This must be called before the processor set is used to construct a GrPipeline and may only 129 * be called once. 130 * 131 * This also puts the processors in "pending execution" state and must be called when an op 132 * that owns a processor set is recorded to ensure pending and writes are propagated to 133 * resources referred to by the processors. Otherwise, data hazards may occur. 134 */ 135 Analysis finalize(const GrProcessorAnalysisColor& colorInput, 136 const GrProcessorAnalysisCoverage coverageInput, const GrAppliedClip*, 137 bool isMixedSamples, const GrCaps&, SkPMColor4f* inputColorOverride); 138 isFinalized()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(); EmptySetAnalysis()144 static constexpr const Analysis EmptySetAnalysis() { return Analysis(Empty::kEmpty); } 145 146 #ifdef SK_DEBUG 147 SkString dumpProcessors() const; 148 #endif 149 visitProxies(const std::function<void (GrSurfaceProxy *)> & func)150 void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) const { 151 for (int i = 0; i < this->numFragmentProcessors(); ++i) { 152 GrFragmentProcessor::TextureAccessIter iter(this->fragmentProcessor(i)); 153 while (const GrFragmentProcessor::TextureSampler* sampler = iter.next()) { 154 func(sampler->proxy()); 155 } 156 } 157 } 158 159 private: GrProcessorSet(Empty)160 GrProcessorSet(Empty) : fXP((const GrXferProcessor*)nullptr), fFlags(kFinalized_Flag) {} 161 numFragmentProcessors()162 int numFragmentProcessors() const { 163 return fFragmentProcessors.count() - fFragmentProcessorOffset; 164 } 165 fragmentProcessor(int idx)166 const GrFragmentProcessor* fragmentProcessor(int idx) const { 167 return fFragmentProcessors[idx + fFragmentProcessorOffset].get(); 168 } 169 170 // This absurdly large limit allows Analysis and this to pack fields together. 171 static constexpr int kMaxColorProcessors = UINT8_MAX; 172 173 enum Flags : uint16_t { kFinalized_Flag = 0x1 }; 174 175 union XP { XP(const GrXPFactory * factory)176 XP(const GrXPFactory* factory) : fFactory(factory) {} XP(const GrXferProcessor * processor)177 XP(const GrXferProcessor* processor) : fProcessor(processor) {} XP(XP && that)178 explicit XP(XP&& that) : fProcessor(that.fProcessor) { 179 SkASSERT(fProcessor == that.fProcessor); 180 that.fProcessor = nullptr; 181 } 182 const GrXPFactory* fFactory; 183 const GrXferProcessor* fProcessor; 184 }; 185 xpFactory()186 const GrXPFactory* xpFactory() const { 187 SkASSERT(!this->isFinalized()); 188 return fXP.fFactory; 189 } 190 191 SkAutoSTArray<4, std::unique_ptr<const GrFragmentProcessor>> fFragmentProcessors; 192 XP fXP; 193 uint8_t fColorFragmentProcessorCnt = 0; 194 uint8_t fFragmentProcessorOffset = 0; 195 uint8_t fFlags; 196 }; 197 198 #endif 199