Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef GrStencil_DEFINED
     11 #define GrStencil_DEFINED
     12 
     13 #include "GrTypes.h"
     14 /**
     15  * Gr uses the stencil buffer to implement complex clipping inside the
     16  * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer
     17  * bits available for other uses by external code (clients). Client code can
     18  * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits
     19  * provided by clients that overlap the bits used to implement clipping.
     20  *
     21  * When code outside the GrDrawTarget class uses the stencil buffer the contract
     22  * is as follows:
     23  *
     24  * > Normal stencil funcs allow the client to pass / fail regardless of the
     25  *   reserved clip bits.
     26  * > Additional functions allow a test against the clip along with a limited
     27  *   set of tests against the client bits.
     28  * > Client can assume all client bits are zero initially.
     29  * > Client must ensure that after all its passes are finished it has only
     30  *   written to the color buffer in the region inside the clip. Furthermore, it
     31  *   must zero all client bits that were modifed (both inside and outside the
     32  *   clip).
     33  */
     34 
     35 /**
     36  * Determines which pixels pass / fail the stencil test.
     37  * Stencil test passes if (ref & mask) FUNC (stencil & mask) is true
     38  */
     39 enum GrStencilFunc {
     40     kAlways_StencilFunc = 0,
     41     kNever_StencilFunc,
     42     kGreater_StencilFunc,
     43     kGEqual_StencilFunc,
     44     kLess_StencilFunc,
     45     kLEqual_StencilFunc,
     46     kEqual_StencilFunc,
     47     kNotEqual_StencilFunc,
     48 
     49     // Gr stores the current clip in the
     50     // stencil buffer in the high bits that
     51     // are not directly accessible modifiable
     52     // via the GrDrawTarget interface. The below
     53     // stencil funcs test against the current
     54     // clip in addition to the GrDrawTarget
     55     // client's stencil bits.
     56 
     57     // pass if inside the clip
     58     kAlwaysIfInClip_StencilFunc,
     59     kEqualIfInClip_StencilFunc,
     60     kLessIfInClip_StencilFunc,
     61     kLEqualIfInClip_StencilFunc,
     62     kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0
     63 
     64     // counts
     65     kStencilFuncCount,
     66     kClipStencilFuncCount = kNonZeroIfInClip_StencilFunc -
     67                             kAlwaysIfInClip_StencilFunc + 1,
     68     kBasicStencilFuncCount = kStencilFuncCount - kClipStencilFuncCount
     69 };
     70 
     71 /**
     72  * Operations to perform based on whether stencil test passed failed.
     73  */
     74 enum GrStencilOp {
     75     kKeep_StencilOp = 0,    // preserve existing stencil value
     76     kReplace_StencilOp,     // replace with reference value from stencl test
     77     kIncWrap_StencilOp,     // increment and wrap at max
     78     kIncClamp_StencilOp,    // increment and clamp at max
     79     kDecWrap_StencilOp,     // decrement and wrap at 0
     80     kDecClamp_StencilOp,    // decrement and clamp at 0
     81     kZero_StencilOp,        // zero stencil bits
     82     kInvert_StencilOp,      // invert stencil bits
     83 
     84     kStencilOpCount
     85 };
     86 
     87 enum GrStencilFlags {
     88     kIsDisabled_StencilFlag      = 0x1,
     89     kNotDisabled_StencilFlag     = 0x2,
     90     kDoesWrite_StencilFlag       = 0x4,
     91     kDoesNotWrite_StencilFlag    = 0x8,
     92 };
     93 
     94 /**
     95  * GrStencilState needs to be a class with accessors and setters so that it
     96  * can maintain flags related to its current state. However, we also want to
     97  * be able to declare pre-made stencil settings at compile time (without
     98  * inserting static initializer code). So all the data members are in this
     99  * struct. A macro defined after the class can be used to jam an instance of
    100  * this struct that is created from an initializer list into a
    101  * GrStencilSettings. (We hang our heads in shame.)
    102  */
    103 struct GrStencilSettingsStruct {
    104     GrStencilOp fFrontPassOp : 8;    // op to perform when front faces pass
    105     GrStencilOp fBackPassOp : 8;     // op to perform when back faces pass
    106     GrStencilOp fFrontFailOp : 8;    // op to perform when front faces fail
    107     GrStencilOp fBackFailOp : 8;     // op to perform when back faces fail
    108     GrStencilFunc fFrontFunc : 8;    // test function for front faces
    109     GrStencilFunc fBackFunc : 8;     // test function for back faces
    110     int fPad0 : 8;
    111     int fPad1 : 8;
    112     unsigned short fFrontFuncMask;   // mask for front face test
    113     unsigned short fBackFuncMask;    // mask for back face test
    114     unsigned short fFrontFuncRef;    // reference value for front face test
    115     unsigned short fBackFuncRef;     // reference value for back face test
    116     unsigned short fFrontWriteMask;  // stencil write mask for front faces
    117     unsigned short fBackWriteMask;   // stencil write mask for back faces
    118     mutable uint32_t fFlags;
    119 };
    120 // We rely on this being packed and aligned (memcmp'ed and memcpy'ed)
    121 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) % 4 == 0);
    122 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) ==
    123                  4*sizeof(uint8_t) + // ops
    124                  2*sizeof(uint8_t) + // funcs
    125                  2*sizeof(uint8_t) + // pads
    126                  2*sizeof(unsigned short) + // func masks
    127                  2*sizeof(unsigned short) + // ref values
    128                  2*sizeof(unsigned short) + // write masks
    129                  sizeof(uint32_t)); // flags
    130 
    131 // This macro is used to compute the GrStencilSettingsStructs flags
    132 // associated to disabling. It is used both to define constant structure
    133 // initializers and inside GrStencilSettings::isDisabled()
    134 //
    135 #define GR_STENCIL_SETTINGS_IS_DISABLED(                                     \
    136     FRONT_PASS_OP,    BACK_PASS_OP,                                          \
    137     FRONT_FAIL_OP,    BACK_FAIL_OP,                                          \
    138     FRONT_FUNC,       BACK_FUNC)                                             \
    139     ((FRONT_PASS_OP) == kKeep_StencilOp &&                                   \
    140      (BACK_PASS_OP)  == kKeep_StencilOp &&                                   \
    141      (FRONT_FAIL_OP) == kKeep_StencilOp &&                                   \
    142      (BACK_FAIL_OP)  == kKeep_StencilOp &&                                   \
    143      (FRONT_FUNC)    == kAlways_StencilFunc &&                               \
    144      (BACK_FUNC)     == kAlways_StencilFunc)
    145 
    146 #define GR_STENCIL_SETTINGS_DOES_WRITE(                                      \
    147     FRONT_PASS_OP,    BACK_PASS_OP,                                          \
    148     FRONT_FAIL_OP,    BACK_FAIL_OP,                                          \
    149     FRONT_FUNC,       BACK_FUNC)                                             \
    150     (!(((FRONT_FUNC) == kNever_StencilFunc  ||                               \
    151         (FRONT_PASS_OP) == kKeep_StencilOp)  &&                              \
    152        ((BACK_FUNC) == kNever_StencilFunc  ||                                \
    153         (BACK_PASS_OP)  == kKeep_StencilOp) &&                               \
    154        ((FRONT_FUNC) == kAlways_StencilFunc ||                               \
    155         (FRONT_FAIL_OP) == kKeep_StencilOp) &&                               \
    156        ((BACK_FUNC)  == kAlways_StencilFunc ||                               \
    157         (BACK_FAIL_OP)  == kKeep_StencilOp)))
    158 
    159 #define GR_STENCIL_SETTINGS_DEFAULT_FLAGS(                                   \
    160     FRONT_PASS_OP,    BACK_PASS_OP,                                          \
    161     FRONT_FAIL_OP,    BACK_FAIL_OP,                                          \
    162     FRONT_FUNC,       BACK_FUNC)                                             \
    163   ((GR_STENCIL_SETTINGS_IS_DISABLED(FRONT_PASS_OP,BACK_PASS_OP,              \
    164       FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ?                     \
    165       kIsDisabled_StencilFlag : kNotDisabled_StencilFlag) |                  \
    166    (GR_STENCIL_SETTINGS_DOES_WRITE(FRONT_PASS_OP,BACK_PASS_OP,               \
    167       FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ?                     \
    168       kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag))
    169 
    170 /**
    171  * Class representing stencil state.
    172  */
    173 class GrStencilSettings : private GrStencilSettingsStruct {
    174 
    175 public:
    176     GrStencilSettings() {
    177         fPad0 = fPad1 = 0;
    178         this->setDisabled();
    179     }
    180 
    181     GrStencilOp frontPassOp() const { return fFrontPassOp; }
    182     GrStencilOp backPassOp() const { return fBackPassOp; }
    183     GrStencilOp frontFailOp() const { return fFrontFailOp; }
    184     GrStencilOp backFailOp() const { return fBackFailOp; }
    185     GrStencilFunc frontFunc() const { return fFrontFunc; }
    186     GrStencilFunc backFunc() const { return fBackFunc; }
    187     unsigned short frontFuncMask() const { return fFrontFuncMask; }
    188     unsigned short backFuncMask() const { return fBackFuncMask; }
    189     unsigned short frontFuncRef() const { return fFrontFuncRef; }
    190     unsigned short backFuncRef() const { return fBackFuncRef; }
    191     unsigned short frontWriteMask() const {return fFrontWriteMask; }
    192     unsigned short backWriteMask() const { return fBackWriteMask; }
    193 
    194     void setFrontPassOp(GrStencilOp op) { fFrontPassOp = op; fFlags = 0;}
    195     void setBackPassOp(GrStencilOp op) { fBackPassOp = op; fFlags = 0;}
    196     void setFrontFailOp(GrStencilOp op) {fFrontFailOp = op; fFlags = 0;}
    197     void setBackFailOp(GrStencilOp op) { fBackFailOp = op; fFlags = 0;}
    198     void setFrontFunc(GrStencilFunc func) { fFrontFunc = func; fFlags = 0;}
    199     void setBackFunc(GrStencilFunc func) { fBackFunc = func; fFlags = 0;}
    200     void setFrontFuncMask(unsigned short mask) { fFrontFuncMask = mask; }
    201     void setBackFuncMask(unsigned short mask) { fBackFuncMask = mask; }
    202     void setFrontFuncRef(unsigned short ref) { fFrontFuncRef = ref; }
    203     void setBackFuncRef(unsigned short ref) { fBackFuncRef = ref; }
    204     void setFrontWriteMask(unsigned short writeMask) { fFrontWriteMask = writeMask; }
    205     void setBackWriteMask(unsigned short writeMask) { fBackWriteMask = writeMask; }
    206 
    207     void setSame(GrStencilOp passOp,
    208                  GrStencilOp failOp,
    209                  GrStencilFunc func,
    210                  unsigned short funcMask,
    211                  unsigned short funcRef,
    212                  unsigned short writeMask) {
    213         fFrontPassOp        = passOp;
    214         fBackPassOp         = passOp;
    215         fFrontFailOp        = failOp;
    216         fBackFailOp         = failOp;
    217         fFrontFunc          = func;
    218         fBackFunc           = func;
    219         fFrontFuncMask      = funcMask;
    220         fBackFuncMask       = funcMask;
    221         fFrontFuncRef       = funcRef;
    222         fBackFuncRef        = funcRef;
    223         fFrontWriteMask     = writeMask;
    224         fBackWriteMask      = writeMask;
    225         fFlags = 0;
    226     }
    227 
    228     void setDisabled() {
    229         memset(this, 0, sizeof(*this));
    230         GR_STATIC_ASSERT(0 == kKeep_StencilOp);
    231         GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
    232         fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag;
    233     }
    234 
    235     bool isDisabled() const {
    236         if (fFlags & kIsDisabled_StencilFlag) {
    237             return true;
    238         }
    239         if (fFlags & kNotDisabled_StencilFlag) {
    240             return false;
    241         }
    242         bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED(
    243                             fFrontPassOp, fBackPassOp,
    244                             fFrontFailOp, fBackFailOp,
    245                             fFrontFunc ,fBackFunc);
    246         fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag;
    247         return disabled;
    248     }
    249 
    250     bool doesWrite() const {
    251         if (fFlags & kDoesWrite_StencilFlag) {
    252             return true;
    253         }
    254         if (fFlags & kDoesNotWrite_StencilFlag) {
    255             return false;
    256         }
    257         bool writes = GR_STENCIL_SETTINGS_DOES_WRITE(
    258                         fFrontPassOp, fBackPassOp,
    259                         fFrontFailOp, fBackFailOp,
    260                         fFrontFunc, fBackFunc);
    261         fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag;
    262         return writes;
    263     }
    264 
    265     void invalidate()  {
    266         // write an illegal value to the first member
    267         fFrontPassOp = (GrStencilOp)(uint8_t)-1;
    268         fFlags = 0;
    269     }
    270 
    271     bool operator == (const GrStencilSettings& s) const {
    272         static const size_t gCompareSize = sizeof(GrStencilSettings) -
    273                                            sizeof(fFlags);
    274         GrAssert((const char*)&fFlags + sizeof(fFlags) ==
    275                  (const char*)this + sizeof(GrStencilSettings));
    276         if (this->isDisabled() & s.isDisabled()) { // using & not &&
    277             return true;
    278         }
    279         return 0 == memcmp(this, &s, gCompareSize);
    280     }
    281 
    282     bool operator != (const GrStencilSettings& s) const {
    283         return !(*this == s);
    284     }
    285 
    286     GrStencilSettings& operator =(const GrStencilSettings& s) {
    287         memcpy(this, &s, sizeof(GrStencilSettings));
    288         return *this;
    289     }
    290 
    291 private:
    292     friend class GrGpu;
    293     enum {
    294         kMaxStencilClipPasses = 2  // maximum number of passes to add a clip
    295                                    // element to the stencil buffer.
    296     };
    297 
    298     /**
    299      * Given a thing to draw into the stencil clip, a fill type, and a set op
    300      * this function determines:
    301      *      1. Whether the thing can be draw directly to the stencil clip or
    302      *      needs to be drawn to the client portion of the stencil first.
    303      *      2. How many passes are needed.
    304      *      3. What those passes are.
    305      *      4. The fill rule that should actually be used to render (will
    306      *         always be non-inverted).
    307      *
    308      * @param op                the set op to combine this element with the
    309      *                          existing clip
    310      * @param stencilClipMask   mask with just the stencil bit used for clipping
    311      *                          enabled.
    312      * @param invertedFill      is this path inverted
    313      * @param numPasses         out: the number of passes needed to add the
    314      *                               element to the clip.
    315      * @param settings          out: the stencil settings to use for each pass
    316      *
    317      * @return true if the clip element's geometry can be drawn directly to the
    318      *         stencil clip bit. Will only be true if canBeDirect is true.
    319      *         numPasses will be 1 if return value is true.
    320      */
    321     static bool GetClipPasses(GrSetOp op,
    322                               bool canBeDirect,
    323                               unsigned int stencilClipMask,
    324                               bool invertedFill,
    325                               int* numPasses,
    326                               GrStencilSettings settings[kMaxStencilClipPasses]);
    327 };
    328 
    329 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
    330 
    331 #define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME,                          \
    332     FRONT_PASS_OP,    BACK_PASS_OP,                                          \
    333     FRONT_FAIL_OP,    BACK_FAIL_OP,                                          \
    334     FRONT_FUNC,       BACK_FUNC,                                             \
    335     FRONT_MASK,       BACK_MASK,                                             \
    336     FRONT_REF,        BACK_REF,                                              \
    337     FRONT_WRITE_MASK, BACK_WRITE_MASK)                                       \
    338     static const GrStencilSettingsStruct STRUCT_NAME = {                     \
    339         (FRONT_PASS_OP),    (BACK_PASS_OP),                                  \
    340         (FRONT_FAIL_OP),    (BACK_FAIL_OP),                                  \
    341         (FRONT_FUNC),       (BACK_FUNC),                                     \
    342         (0),                (0),                                             \
    343         (FRONT_MASK),       (BACK_MASK),                                     \
    344         (FRONT_REF),        (BACK_REF),                                      \
    345         (FRONT_WRITE_MASK), (BACK_WRITE_MASK),                               \
    346         GR_STENCIL_SETTINGS_DEFAULT_FLAGS(                                   \
    347             FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP,        \
    348             FRONT_FUNC, BACK_FUNC)                                           \
    349     };
    350 
    351 #define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR)            \
    352     reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR)
    353 
    354 #define GR_STATIC_CONST_SAME_STENCIL_STRUCT(STRUCT_NAME,                     \
    355     PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK)                           \
    356     GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, (PASS_OP), (PASS_OP),        \
    357     (FAIL_OP),(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF),       \
    358     (WRITE_MASK),(WRITE_MASK))
    359 
    360 #define GR_STATIC_CONST_STENCIL(NAME,                                        \
    361     FRONT_PASS_OP,    BACK_PASS_OP,                                          \
    362     FRONT_FAIL_OP,    BACK_FAIL_OP,                                          \
    363     FRONT_FUNC,       BACK_FUNC,                                             \
    364     FRONT_MASK,       BACK_MASK,                                             \
    365     FRONT_REF,        BACK_REF,                                              \
    366     FRONT_WRITE_MASK, BACK_WRITE_MASK)                                       \
    367     GR_STATIC_CONST_STENCIL_STRUCT(NAME ## _STRUCT,                          \
    368     (FRONT_PASS_OP),(BACK_PASS_OP),(FRONT_FAIL_OP),(BACK_FAIL_OP),           \
    369     (FRONT_FUNC),(BACK_FUNC),(FRONT_MASK),(BACK_MASK),                       \
    370     (FRONT_REF),(BACK_REF),(FRONT_WRITE_MASK),(BACK_WRITE_MASK))             \
    371     static const GrStencilSettings& NAME =                                   \
    372         *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT));
    373 
    374 
    375 #define GR_STATIC_CONST_SAME_STENCIL(NAME,                                   \
    376     PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK)                           \
    377     GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP),           \
    378     (FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK),   \
    379     (WRITE_MASK))
    380 
    381 #endif
    382