| 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 |  | 
|---|
| 36 | int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; } | 
|---|
| 37 | int numCoverageFragmentProcessors() const { | 
|---|
| 38 | return this->numFragmentProcessors() - fColorFragmentProcessorCnt; | 
|---|
| 39 | } | 
|---|
| 40 |  | 
|---|
| 41 | const GrFragmentProcessor* colorFragmentProcessor(int idx) const { | 
|---|
| 42 | SkASSERT(idx < fColorFragmentProcessorCnt); | 
|---|
| 43 | return fFragmentProcessors[idx + fFragmentProcessorOffset].get(); | 
|---|
| 44 | } | 
|---|
| 45 | const GrFragmentProcessor* coverageFragmentProcessor(int idx) const { | 
|---|
| 46 | return fFragmentProcessors[idx + fColorFragmentProcessorCnt + | 
|---|
| 47 | fFragmentProcessorOffset].get(); | 
|---|
| 48 | } | 
|---|
| 49 |  | 
|---|
| 50 | const GrXferProcessor* xferProcessor() const { | 
|---|
| 51 | SkASSERT(this->isFinalized()); | 
|---|
| 52 | return fXP.fProcessor; | 
|---|
| 53 | } | 
|---|
| 54 | sk_sp<const GrXferProcessor> refXferProcessor() const { | 
|---|
| 55 | SkASSERT(this->isFinalized()); | 
|---|
| 56 | return sk_ref_sp(fXP.fProcessor); | 
|---|
| 57 | } | 
|---|
| 58 |  | 
|---|
| 59 | std::unique_ptr<const GrFragmentProcessor> detachColorFragmentProcessor(int idx) { | 
|---|
| 60 | SkASSERT(idx < fColorFragmentProcessorCnt); | 
|---|
| 61 | return std::move(fFragmentProcessors[idx + fFragmentProcessorOffset]); | 
|---|
| 62 | } | 
|---|
| 63 |  | 
|---|
| 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; | 
|---|
| 80 | Analysis() { *reinterpret_cast<uint32_t*>(this) = 0; } | 
|---|
| 81 |  | 
|---|
| 82 | bool isInitialized() const { return fIsInitialized; } | 
|---|
| 83 | bool usesLocalCoords() const { return fUsesLocalCoords; } | 
|---|
| 84 | bool requiresDstTexture() const { return fRequiresDstTexture; } | 
|---|
| 85 | bool requiresNonOverlappingDraws() const { return fRequiresNonOverlappingDraws; } | 
|---|
| 86 | bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; } | 
|---|
| 87 | // Indicates whether all color fragment processors were eliminated in the analysis. | 
|---|
| 88 | bool hasColorFragmentProcessor() const { return fHasColorFragmentProcessor; } | 
|---|
| 89 |  | 
|---|
| 90 | bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; } | 
|---|
| 91 | bool inputColorIsOverridden() const { | 
|---|
| 92 | return fInputColorType == kOverridden_InputColorType; | 
|---|
| 93 | } | 
|---|
| 94 |  | 
|---|
| 95 | private: | 
|---|
| 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 | 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 |  | 
|---|
| 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(); | 
|---|
| 150 | static constexpr const Analysis EmptySetAnalysis() { return Analysis(Empty::kEmpty); } | 
|---|
| 151 |  | 
|---|
| 152 | #ifdef SK_DEBUG | 
|---|
| 153 | SkString dumpProcessors() const; | 
|---|
| 154 | #endif | 
|---|
| 155 |  | 
|---|
| 156 | void visitProxies(const GrOp::VisitProxyFunc& func) const; | 
|---|
| 157 |  | 
|---|
| 158 | private: | 
|---|
| 159 | GrProcessorSet(Empty) : fXP((const GrXferProcessor*)nullptr), fFlags(kFinalized_Flag) {} | 
|---|
| 160 |  | 
|---|
| 161 | int numFragmentProcessors() const { | 
|---|
| 162 | return fFragmentProcessors.count() - fFragmentProcessorOffset; | 
|---|
| 163 | } | 
|---|
| 164 |  | 
|---|
| 165 | const GrFragmentProcessor* fragmentProcessor(int idx) const { | 
|---|
| 166 | return fFragmentProcessors[idx + fFragmentProcessorOffset].get(); | 
|---|
| 167 | } | 
|---|
| 168 |  | 
|---|
| 169 | // This absurdly large limit allows Analysis and this to pack fields together. | 
|---|
| 170 | static constexpr int kMaxColorProcessors = UINT8_MAX; | 
|---|
| 171 |  | 
|---|
| 172 | enum Flags : uint16_t { kFinalized_Flag = 0x1 }; | 
|---|
| 173 |  | 
|---|
| 174 | union XP { | 
|---|
| 175 | XP(const GrXPFactory* factory) : fFactory(factory) {} | 
|---|
| 176 | XP(const GrXferProcessor* processor) : fProcessor(processor) {} | 
|---|
| 177 | explicit XP(XP&& that) : fProcessor(that.fProcessor) { | 
|---|
| 178 | SkASSERT(fProcessor == that.fProcessor); | 
|---|
| 179 | that.fProcessor = nullptr; | 
|---|
| 180 | } | 
|---|
| 181 | const GrXPFactory* fFactory; | 
|---|
| 182 | const GrXferProcessor* fProcessor; | 
|---|
| 183 | }; | 
|---|
| 184 |  | 
|---|
| 185 | const GrXPFactory* xpFactory() const { | 
|---|
| 186 | SkASSERT(!this->isFinalized()); | 
|---|
| 187 | return fXP.fFactory; | 
|---|
| 188 | } | 
|---|
| 189 |  | 
|---|
| 190 | SkAutoSTArray<4, std::unique_ptr<GrFragmentProcessor>> fFragmentProcessors; | 
|---|
| 191 | XP fXP; | 
|---|
| 192 | uint8_t fColorFragmentProcessorCnt = 0; | 
|---|
| 193 | uint8_t fFragmentProcessorOffset = 0; | 
|---|
| 194 | uint8_t fFlags; | 
|---|
| 195 | }; | 
|---|
| 196 |  | 
|---|
| 197 | #endif | 
|---|
| 198 |  | 
|---|