|  | /* | 
|  | * 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 "include/private/base/SkTemplates.h" | 
|  | #include "src/gpu/ganesh/GrFragmentProcessor.h" | 
|  | #include "src/gpu/ganesh/GrPaint.h" | 
|  | #include "src/gpu/ganesh/GrProcessorAnalysis.h" | 
|  | #include "src/gpu/ganesh/GrXferProcessor.h" | 
|  |  | 
|  | struct GrUserStencilSettings; | 
|  | 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(); | 
|  |  | 
|  | bool hasColorFragmentProcessor() const { return fColorFragmentProcessor != nullptr; } | 
|  | bool hasCoverageFragmentProcessor() const { return fCoverageFragmentProcessor != nullptr; } | 
|  |  | 
|  | const GrFragmentProcessor* colorFragmentProcessor() const { | 
|  | return fColorFragmentProcessor.get(); | 
|  | } | 
|  | const GrFragmentProcessor* coverageFragmentProcessor() const { | 
|  | return fCoverageFragmentProcessor.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<GrFragmentProcessor> detachColorFragmentProcessor() { | 
|  | return std::move(fColorFragmentProcessor); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<GrFragmentProcessor> detachCoverageFragmentProcessor() { | 
|  | return std::move(fCoverageFragmentProcessor); | 
|  | } | 
|  |  | 
|  | /** 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; } | 
|  |  | 
|  | Analysis& operator=(const Analysis &other) = default; | 
|  |  | 
|  | bool isInitialized() const { return fIsInitialized; } | 
|  | bool usesLocalCoords() const { return fUsesLocalCoords; } | 
|  | bool requiresDstTexture() const { return fRequiresDstTexture; } | 
|  | bool requiresNonOverlappingDraws() const { return fRequiresNonOverlappingDraws; } | 
|  | bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; } | 
|  | // Indicates whether all color fragment processors were eliminated in the analysis. | 
|  | bool hasColorFragmentProcessor() const { return fHasColorFragmentProcessor; } | 
|  |  | 
|  | bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; } | 
|  | bool inputColorIsOverridden() const { | 
|  | return fInputColorType == kOverridden_InputColorType; | 
|  | } | 
|  | bool usesNonCoherentHWBlending() const { return fUsesNonCoherentHWBlending; } | 
|  | bool unaffectedByDstValue() const { return fUnaffectedByDstValue; } | 
|  |  | 
|  | private: | 
|  | constexpr Analysis(Empty) | 
|  | : fUsesLocalCoords(false) | 
|  | , fCompatibleWithCoverageAsAlpha(true) | 
|  | , fRequiresDstTexture(false) | 
|  | , fRequiresNonOverlappingDraws(false) | 
|  | , fHasColorFragmentProcessor(false) | 
|  | , fIsInitialized(true) | 
|  | , fUsesNonCoherentHWBlending(false) | 
|  | , fUnaffectedByDstValue(false) | 
|  | , 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 fRequiresNonOverlappingDraws : 1; | 
|  | PackedBool fHasColorFragmentProcessor : 1; | 
|  | PackedBool fIsInitialized : 1; | 
|  | PackedBool fUsesNonCoherentHWBlending : 1; | 
|  | PackedBool fUnaffectedByDstValue : 1; | 
|  | PackedInputColorType fInputColorType : 2; | 
|  |  | 
|  | friend class GrProcessorSet; | 
|  | }; | 
|  | 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 inputColorIsOverridden(). '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&, const GrProcessorAnalysisCoverage, | 
|  | const GrAppliedClip*, const GrUserStencilSettings*, const GrCaps&, | 
|  | GrClampType, SkPMColor4f* 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 Analysis EmptySetAnalysis() { return Analysis(Empty::kEmpty); } | 
|  |  | 
|  | #if GR_TEST_UTILS | 
|  | SkString dumpProcessors() const; | 
|  | #endif | 
|  |  | 
|  | void visitProxies(const GrVisitProxyFunc&) const; | 
|  |  | 
|  | private: | 
|  | GrProcessorSet(Empty) : fXP((const GrXferProcessor*)nullptr), fFlags(kFinalized_Flag) {} | 
|  |  | 
|  | int numFragmentProcessors() const { | 
|  | return (fColorFragmentProcessor ? 1 : 0) + (fCoverageFragmentProcessor ? 1 : 0); | 
|  | } | 
|  |  | 
|  | 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; | 
|  | } | 
|  |  | 
|  | std::unique_ptr<GrFragmentProcessor> fColorFragmentProcessor; | 
|  | std::unique_ptr<GrFragmentProcessor> fCoverageFragmentProcessor; | 
|  | XP fXP; | 
|  | uint8_t fFlags = 0; | 
|  | }; | 
|  |  | 
|  | #endif |