/* * 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" class GrAppliedClip; class GrXferProcessor; class GrXPFactory; class GrProcessorSet : private SkNoncopyable { public: GrProcessorSet(GrPaint&& paint); ~GrProcessorSet(); int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; } int numCoverageFragmentProcessors() const { return this->numFragmentProcessors() - fColorFragmentProcessorCnt; } int numFragmentProcessors() const { return fFragmentProcessors.count() - fFragmentProcessorOffset; } const GrFragmentProcessor* colorFragmentProcessor(int idx) const { SkASSERT(idx < fColorFragmentProcessorCnt); return fFragmentProcessors[idx + fFragmentProcessorOffset]; } const GrFragmentProcessor* coverageFragmentProcessor(int idx) const { return fFragmentProcessors[idx + fColorFragmentProcessorCnt + fFragmentProcessorOffset]; } const GrXferProcessor* xferProcessor() const { SkASSERT(this->isFinalized()); return fXP.fProcessor; } sk_sp refXferProcessor() const { SkASSERT(this->isFinalized()); return sk_ref_sp(fXP.fProcessor); } bool usesDistanceVectorField() const { return SkToBool(fFlags & kUseDistanceVectorField_Flag); } bool disableOutputConversionToSRGB() const { return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag); } bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); } /** 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(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: 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); } private: // This absurdly large limit allows Analysis and this to pack fields together. static constexpr int kMaxColorProcessors = UINT8_MAX; enum Flags : uint16_t { kUseDistanceVectorField_Flag = 0x1, kDisableOutputConversionToSRGB_Flag = 0x2, kAllowSRGBInputs_Flag = 0x4, kFinalized_Flag = 0x8 }; union XP { XP(const GrXPFactory* factory) : fFactory(factory) {} const GrXPFactory* fFactory; const GrXferProcessor* fProcessor; }; const GrXPFactory* xpFactory() const { SkASSERT(!this->isFinalized()); return fXP.fFactory; } SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors; XP fXP; uint8_t fColorFragmentProcessorCnt; uint8_t fFragmentProcessorOffset = 0; uint8_t fFlags; }; #endif