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