|  | /* | 
|  | * Copyright 2017 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #ifndef GrProcessorSet_DEFINED | 
|  | #define GrProcessorSet_DEFINED | 
|  |  | 
|  | #include "GrFragmentProcessor.h" | 
|  | #include "GrPaint.h" | 
|  | #include "GrProcessorAnalysis.h" | 
|  | #include "SkTemplates.h" | 
|  | #include "GrXferProcessor.h" | 
|  |  | 
|  | class GrAppliedClip; | 
|  | class GrXPFactory; | 
|  |  | 
|  | class GrProcessorSet { | 
|  | private: | 
|  | // Arbitrary constructor arg for empty set and analysis | 
|  | enum class Empty { kEmpty }; | 
|  |  | 
|  | public: | 
|  | GrProcessorSet(GrPaint&&); | 
|  | GrProcessorSet(SkBlendMode); | 
|  | GrProcessorSet(std::unique_ptr<GrFragmentProcessor> colorFP); | 
|  | GrProcessorSet(GrProcessorSet&&); | 
|  | GrProcessorSet(const GrProcessorSet&) = delete; | 
|  | GrProcessorSet& operator=(const GrProcessorSet&) = delete; | 
|  |  | 
|  | ~GrProcessorSet(); | 
|  |  | 
|  | int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; } | 
|  | int numCoverageFragmentProcessors() const { | 
|  | return this->numFragmentProcessors() - fColorFragmentProcessorCnt; | 
|  | } | 
|  |  | 
|  | const GrFragmentProcessor* colorFragmentProcessor(int idx) const { | 
|  | SkASSERT(idx < fColorFragmentProcessorCnt); | 
|  | return fFragmentProcessors[idx + fFragmentProcessorOffset].get(); | 
|  | } | 
|  | const GrFragmentProcessor* coverageFragmentProcessor(int idx) const { | 
|  | return fFragmentProcessors[idx + fColorFragmentProcessorCnt + | 
|  | fFragmentProcessorOffset].get(); | 
|  | } | 
|  |  | 
|  | const GrXferProcessor* xferProcessor() const { | 
|  | SkASSERT(this->isFinalized()); | 
|  | return fXP.fProcessor; | 
|  | } | 
|  | sk_sp<const GrXferProcessor> refXferProcessor() const { | 
|  | SkASSERT(this->isFinalized()); | 
|  | return sk_ref_sp(fXP.fProcessor); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<const GrFragmentProcessor> detachColorFragmentProcessor(int idx) { | 
|  | SkASSERT(idx < fColorFragmentProcessorCnt); | 
|  | return std::move(fFragmentProcessors[idx + fFragmentProcessorOffset]); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<const GrFragmentProcessor> detachCoverageFragmentProcessor(int idx) { | 
|  | return std::move( | 
|  | fFragmentProcessors[idx + fFragmentProcessorOffset + fColorFragmentProcessorCnt]); | 
|  | } | 
|  |  | 
|  | /** Comparisons are only legal on finalized processor sets. */ | 
|  | bool operator==(const GrProcessorSet& that) const; | 
|  | bool operator!=(const GrProcessorSet& that) const { return !(*this == that); } | 
|  |  | 
|  | /** | 
|  | * This is used to report results of processor analysis when a processor set is finalized (see | 
|  | * below). | 
|  | */ | 
|  | class Analysis { | 
|  | public: | 
|  | Analysis(const Analysis&) = default; | 
|  | Analysis() { *reinterpret_cast<uint32_t*>(this) = 0; } | 
|  |  | 
|  | bool isInitialized() const { return fIsInitialized; } | 
|  | bool usesLocalCoords() const { return fUsesLocalCoords; } | 
|  | bool requiresDstTexture() const { return fRequiresDstTexture; } | 
|  | bool canCombineOverlappedStencilAndCover() const { | 
|  | return fCanCombineOverlappedStencilAndCover; | 
|  | } | 
|  | bool requiresBarrierBetweenOverlappingDraws() const { | 
|  | return fRequiresBarrierBetweenOverlappingDraws; | 
|  | } | 
|  | bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; } | 
|  |  | 
|  | bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; } | 
|  | bool inputColorIsOverridden() const { | 
|  | return fInputColorType == kOverridden_InputColorType; | 
|  | } | 
|  |  | 
|  | private: | 
|  | constexpr Analysis(Empty) | 
|  | : fUsesLocalCoords(false) | 
|  | , fCompatibleWithCoverageAsAlpha(true) | 
|  | , fRequiresDstTexture(false) | 
|  | , fCanCombineOverlappedStencilAndCover(true) | 
|  | , fRequiresBarrierBetweenOverlappingDraws(false) | 
|  | , fIsInitialized(true) | 
|  | , fInputColorType(kOriginal_InputColorType) {} | 
|  | enum InputColorType : uint32_t { | 
|  | kOriginal_InputColorType, | 
|  | kOverridden_InputColorType, | 
|  | kIgnored_InputColorType | 
|  | }; | 
|  |  | 
|  | // MSVS 2015 won't pack different underlying types | 
|  | using PackedBool = uint32_t; | 
|  | using PackedInputColorType = uint32_t; | 
|  |  | 
|  | PackedBool fUsesLocalCoords : 1; | 
|  | PackedBool fCompatibleWithCoverageAsAlpha : 1; | 
|  | PackedBool fRequiresDstTexture : 1; | 
|  | PackedBool fCanCombineOverlappedStencilAndCover : 1; | 
|  | PackedBool fRequiresBarrierBetweenOverlappingDraws : 1; | 
|  | PackedBool fIsInitialized : 1; | 
|  | PackedInputColorType fInputColorType : 2; | 
|  |  | 
|  | friend class GrProcessorSet; | 
|  | }; | 
|  | GR_STATIC_ASSERT(sizeof(Analysis) <= sizeof(uint32_t)); | 
|  |  | 
|  | /** | 
|  | * This analyzes the processors given an op's input color and coverage as well as a clip. The | 
|  | * state of the processor set may change to an equivalent but more optimal set of processors. | 
|  | * This new state requires that the caller respect the returned 'inputColorOverride'. This is | 
|  | * indicated by the returned Analysis's inputColorIsOverriden(). 'inputColorOverride' will not | 
|  | * be written if the analysis does not override the input color. | 
|  | * | 
|  | * This must be called before the processor set is used to construct a GrPipeline and may only | 
|  | * be called once. | 
|  | * | 
|  | * This also puts the processors in "pending execution" state and must be called when an op | 
|  | * that owns a processor set is recorded to ensure pending and writes are propagated to | 
|  | * resources referred to by the processors. Otherwise, data hazards may occur. | 
|  | */ | 
|  | Analysis finalize(const GrProcessorAnalysisColor& colorInput, | 
|  | const GrProcessorAnalysisCoverage coverageInput, const GrAppliedClip*, | 
|  | bool isMixedSamples, const GrCaps&, GrColor* inputColorOverride); | 
|  |  | 
|  | bool isFinalized() const { return SkToBool(kFinalized_Flag & fFlags); } | 
|  |  | 
|  | /** These are valid only for non-LCD coverage. */ | 
|  | static const GrProcessorSet& EmptySet(); | 
|  | static GrProcessorSet MakeEmptySet(); | 
|  | static constexpr const Analysis EmptySetAnalysis() { return Analysis(Empty::kEmpty); } | 
|  |  | 
|  | SkString dumpProcessors() const; | 
|  |  | 
|  | void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) const { | 
|  | for (int i = 0; i < this->numFragmentProcessors(); ++i) { | 
|  | GrFragmentProcessor::TextureAccessIter iter(this->fragmentProcessor(i)); | 
|  | while (const GrFragmentProcessor::TextureSampler* sampler = iter.next()) { | 
|  | func(sampler->proxy()); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | GrProcessorSet(Empty) : fXP((const GrXferProcessor*)nullptr), fFlags(kFinalized_Flag) {} | 
|  |  | 
|  | int numFragmentProcessors() const { | 
|  | return fFragmentProcessors.count() - fFragmentProcessorOffset; | 
|  | } | 
|  |  | 
|  | const GrFragmentProcessor* fragmentProcessor(int idx) const { | 
|  | return fFragmentProcessors[idx + fFragmentProcessorOffset].get(); | 
|  | } | 
|  |  | 
|  | // This absurdly large limit allows Analysis and this to pack fields together. | 
|  | static constexpr int kMaxColorProcessors = UINT8_MAX; | 
|  |  | 
|  | enum Flags : uint16_t { kFinalized_Flag = 0x1 }; | 
|  |  | 
|  | union XP { | 
|  | XP(const GrXPFactory* factory) : fFactory(factory) {} | 
|  | XP(const GrXferProcessor* processor) : fProcessor(processor) {} | 
|  | explicit XP(XP&& that) : fProcessor(that.fProcessor) { | 
|  | SkASSERT(fProcessor == that.fProcessor); | 
|  | that.fProcessor = nullptr; | 
|  | } | 
|  | const GrXPFactory* fFactory; | 
|  | const GrXferProcessor* fProcessor; | 
|  | }; | 
|  |  | 
|  | const GrXPFactory* xpFactory() const { | 
|  | SkASSERT(!this->isFinalized()); | 
|  | return fXP.fFactory; | 
|  | } | 
|  |  | 
|  | SkAutoSTArray<4, std::unique_ptr<const GrFragmentProcessor>> fFragmentProcessors; | 
|  | XP fXP; | 
|  | uint8_t fColorFragmentProcessorCnt = 0; | 
|  | uint8_t fFragmentProcessorOffset = 0; | 
|  | uint8_t fFlags; | 
|  | }; | 
|  |  | 
|  | #endif |