Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2016 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 
      9 #ifndef GrStencilSettings_DEFINED
     10 #define GrStencilSettings_DEFINED
     11 
     12 #include "GrUserStencilSettings.h"
     13 #include "SkRegion.h"
     14 
     15 class GrProcessorKeyBuilder;
     16 
     17 enum class GrStencilTest : uint16_t {
     18     kAlways,
     19     kNever,
     20     kGreater,
     21     kGEqual,
     22     kLess,
     23     kLEqual,
     24     kEqual,
     25     kNotEqual
     26 };
     27 static constexpr int kGrStencilTestCount = 1 + (int)GrStencilTest::kNotEqual;
     28 
     29 enum class GrStencilOp : uint8_t {
     30     kKeep,
     31     kZero,
     32     kReplace, // Replace stencil value with fRef (only the bits enabled in fWriteMask).
     33     kInvert,
     34     kIncWrap,
     35     kDecWrap,
     36     // NOTE: clamping occurs before the write mask. So if the MSB is zero and masked out, stencil
     37     // values will still wrap when using clamping ops.
     38     kIncClamp,
     39     kDecClamp
     40 };
     41 static constexpr int kGrStencilOpCount = 1 + (int)GrStencilOp::kDecClamp;
     42 
     43 /**
     44  * This class defines concrete stencil settings that map directly to the underlying hardware. It
     45  * is deduced from user stencil settings, stencil clip status, and the number of bits in the
     46  * target stencil buffer.
     47  */
     48 class GrStencilSettings {
     49 public:
     50     GrStencilSettings() { this->setDisabled(); }
     51     GrStencilSettings(const GrUserStencilSettings& user, bool hasStencilClip, int numStencilBits) {
     52         this->reset(user, hasStencilClip, numStencilBits);
     53     }
     54     GrStencilSettings(const GrStencilSettings& that) { this->reset(that); }
     55     GrStencilSettings& operator=(const GrStencilSettings& that) { this->reset(that); return *this; }
     56 
     57     void invalidate() { fFlags |= kInvalid_PrivateFlag; }
     58     void setDisabled() { fFlags = kAll_StencilFlags; }
     59     void reset(const GrUserStencilSettings&, bool hasStencilClip, int numStencilBits);
     60     void reset(const GrStencilSettings&);
     61 
     62     bool isValid() const { return !(fFlags & kInvalid_PrivateFlag); }
     63     bool isDisabled() const { SkASSERT(this->isValid()); return fFlags & kDisabled_StencilFlag; }
     64     bool doesWrite() const { SkASSERT(this->isValid());
     65                              return !(fFlags & kNoModifyStencil_StencilFlag); }
     66     bool isTwoSided() const { SkASSERT(this->isValid());
     67                               return !(fFlags & kSingleSided_StencilFlag); }
     68     bool usesWrapOp() const { SkASSERT(this->isValid());
     69                               return !(fFlags & kNoWrapOps_StencilFlag); }
     70 
     71     void genKey(GrProcessorKeyBuilder* b) const;
     72 
     73     bool operator!=(const GrStencilSettings& that) const { return !(*this == that); }
     74     bool operator==(const GrStencilSettings&) const;
     75 
     76     struct Face : public GrTStencilFaceSettings<GrStencilTest, GrStencilOp> {
     77         void reset(const GrUserStencilSettings::Face&, bool useStencilClip, int numStencilBits);
     78         void setDisabled();
     79     };
     80 
     81     const Face& front() const { SkASSERT(!this->isDisabled()); return fFront; }
     82     const Face& back() const { SkASSERT(this->isTwoSided()); return fBack; }
     83 
     84     /**
     85      * Given a thing to draw into the stencil clip, a fill type, and a set op
     86      * this function determines:
     87      *      1. Whether the thing can be draw directly to the stencil clip or
     88      *      needs to be drawn to the client portion of the stencil first.
     89      *      2. How many passes are needed.
     90      *      3. What those passes are.
     91      *
     92      * @param op                the set op to combine this element with the existing clip
     93      * @param canBeDirect       can the caller draw this element directly (without using stencil)?
     94      * @param invertedFill      is this path inverted
     95      * @param drawDirectToClip  out: true if caller should draw the element directly, false if it
     96      *                          should draw it into the user stencil bits first.
     97      *
     98      * @return a null-terminated array of settings for stencil passes.
     99      *
    100      *         If drawDirectToClip is false, the caller must first draw the element into the user
    101      *         stencil bits, and then cover the clip area with multiple passes using the returned
    102      *         stencil settings.
    103      *
    104      *         If drawDirectToClip is true, the returned array will only have one pass and the
    105      *         caller should use those stencil settings while drawing the element directly.
    106      */
    107     static GrUserStencilSettings const* const* GetClipPasses(SkRegion::Op op,
    108                                                              bool canBeDirect,
    109                                                              bool invertedFill,
    110                                                              bool* drawDirectToClip);
    111 
    112     /** Gets the user stencil settings to directly set the clip bit. */
    113     static const GrUserStencilSettings* SetClipBitSettings(bool setToInside);
    114 
    115 private:
    116     // Internal flag for backends to optionally mark their tracked stencil state as invalid.
    117     enum { kInvalid_PrivateFlag = (kLast_StencilFlag << 1) };
    118 
    119     uint32_t   fFlags;
    120     Face       fFront;
    121     Face       fBack;
    122 };
    123 
    124 #endif
    125