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