Home | History | Annotate | Download | only in gpu
      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 "GrFragmentProcessor.h"
     12 #include "GrPaint.h"
     13 #include "GrProcessorAnalysis.h"
     14 #include "SkTemplates.h"
     15 #include "GrXferProcessor.h"
     16 
     17 class GrAppliedClip;
     18 class GrXPFactory;
     19 
     20 class GrProcessorSet : private SkNoncopyable {
     21 private:
     22     // Arbitrary constructor arg for empty set and analysis
     23     enum class Empty { kEmpty };
     24 
     25 public:
     26     GrProcessorSet(GrPaint&& paint);
     27     GrProcessorSet(SkBlendMode mode);
     28     GrProcessorSet(sk_sp<GrFragmentProcessor> colorFP);
     29 
     30     ~GrProcessorSet();
     31 
     32     int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
     33     int numCoverageFragmentProcessors() const {
     34         return this->numFragmentProcessors() - fColorFragmentProcessorCnt;
     35     }
     36     int numFragmentProcessors() const {
     37         return fFragmentProcessors.count() - fFragmentProcessorOffset;
     38     }
     39 
     40     const GrFragmentProcessor* colorFragmentProcessor(int idx) const {
     41         SkASSERT(idx < fColorFragmentProcessorCnt);
     42         return fFragmentProcessors[idx + fFragmentProcessorOffset];
     43     }
     44     const GrFragmentProcessor* coverageFragmentProcessor(int idx) const {
     45         return fFragmentProcessors[idx + fColorFragmentProcessorCnt + fFragmentProcessorOffset];
     46     }
     47 
     48     const GrXferProcessor* xferProcessor() const {
     49         SkASSERT(this->isFinalized());
     50         return fXP.fProcessor;
     51     }
     52     sk_sp<const GrXferProcessor> refXferProcessor() const {
     53         SkASSERT(this->isFinalized());
     54         return sk_ref_sp(fXP.fProcessor);
     55     }
     56 
     57     /** Comparisons are only legal on finalized processor sets. */
     58     bool operator==(const GrProcessorSet& that) const;
     59     bool operator!=(const GrProcessorSet& that) const { return !(*this == that); }
     60 
     61     /**
     62      * This is used to report results of processor analysis when a processor set is finalized (see
     63      * below).
     64      */
     65     class Analysis {
     66     public:
     67         Analysis(const Analysis&) = default;
     68         Analysis() { *reinterpret_cast<uint32_t*>(this) = 0; }
     69 
     70         bool isInitialized() const { return fIsInitialized; }
     71         bool usesLocalCoords() const { return fUsesLocalCoords; }
     72         bool requiresDstTexture() const { return fRequiresDstTexture; }
     73         bool canCombineOverlappedStencilAndCover() const {
     74             return fCanCombineOverlappedStencilAndCover;
     75         }
     76         bool requiresBarrierBetweenOverlappingDraws() const {
     77             return fRequiresBarrierBetweenOverlappingDraws;
     78         }
     79         bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
     80 
     81         bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; }
     82         bool inputColorIsOverridden() const {
     83             return fInputColorType == kOverridden_InputColorType;
     84         }
     85 
     86     private:
     87         constexpr Analysis(Empty)
     88                 : fUsesLocalCoords(false)
     89                 , fCompatibleWithCoverageAsAlpha(true)
     90                 , fRequiresDstTexture(false)
     91                 , fCanCombineOverlappedStencilAndCover(true)
     92                 , fRequiresBarrierBetweenOverlappingDraws(false)
     93                 , fIsInitialized(true)
     94                 , fInputColorType(kOriginal_InputColorType) {}
     95         enum InputColorType : uint32_t {
     96             kOriginal_InputColorType,
     97             kOverridden_InputColorType,
     98             kIgnored_InputColorType
     99         };
    100 
    101         // MSVS 2015 won't pack different underlying types
    102         using PackedBool = uint32_t;
    103         using PackedInputColorType = uint32_t;
    104 
    105         PackedBool fUsesLocalCoords : 1;
    106         PackedBool fCompatibleWithCoverageAsAlpha : 1;
    107         PackedBool fRequiresDstTexture : 1;
    108         PackedBool fCanCombineOverlappedStencilAndCover : 1;
    109         PackedBool fRequiresBarrierBetweenOverlappingDraws : 1;
    110         PackedBool fIsInitialized : 1;
    111         PackedInputColorType fInputColorType : 2;
    112 
    113         friend class GrProcessorSet;
    114     };
    115     GR_STATIC_ASSERT(sizeof(Analysis) <= sizeof(uint32_t));
    116 
    117     /**
    118      * This analyzes the processors given an op's input color and coverage as well as a clip. The
    119      * state of the processor set may change to an equivalent but more optimal set of processors.
    120      * This new state requires that the caller respect the returned 'inputColorOverride'. This is
    121      * indicated by the returned Analysis's inputColorIsOverriden(). 'inputColorOverride' will not
    122      * be written if the analysis does not override the input color.
    123      *
    124      * This must be called before the processor set is used to construct a GrPipeline and may only
    125      * be called once.
    126      *
    127      * This also puts the processors in "pending execution" state and must be called when an op
    128      * that owns a processor set is recorded to ensure pending and writes are propagated to
    129      * resources referred to by the processors. Otherwise, data hazards may occur.
    130      */
    131     Analysis finalize(const GrProcessorAnalysisColor& colorInput,
    132                       const GrProcessorAnalysisCoverage coverageInput, const GrAppliedClip*,
    133                       bool isMixedSamples, const GrCaps&, GrColor* inputColorOverride);
    134 
    135     bool isFinalized() const { return SkToBool(kFinalized_Flag & fFlags); }
    136 
    137     /** These are valid only for non-LCD coverage. */
    138     static const GrProcessorSet& EmptySet();
    139     static constexpr const Analysis EmptySetAnalysis() { return Analysis(Empty::kEmpty); }
    140 
    141     SkString dumpProcessors() const;
    142 
    143 private:
    144     GrProcessorSet(Empty) : fXP((const GrXferProcessor*)nullptr), fFlags(kFinalized_Flag) {}
    145 
    146     // This absurdly large limit allows Analysis and this to pack fields together.
    147     static constexpr int kMaxColorProcessors = UINT8_MAX;
    148 
    149     enum Flags : uint16_t { kFinalized_Flag = 0x1 };
    150 
    151     union XP {
    152         XP(const GrXPFactory* factory) : fFactory(factory) {}
    153         XP(const GrXferProcessor* processor) : fProcessor(processor) {}
    154         const GrXPFactory* fFactory;
    155         const GrXferProcessor* fProcessor;
    156     };
    157 
    158     const GrXPFactory* xpFactory() const {
    159         SkASSERT(!this->isFinalized());
    160         return fXP.fFactory;
    161     }
    162 
    163     SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
    164     XP fXP;
    165     uint8_t fColorFragmentProcessorCnt = 0;
    166     uint8_t fFragmentProcessorOffset = 0;
    167     uint8_t fFlags;
    168 };
    169 
    170 #endif
    171