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 #include "GrStencil.h"
     11 
     12 ////////////////////////////////////////////////////////////////////////////////
     13 // Stencil Rules for Merging user stencil space into clip
     14 
     15 // We can't include the clip bit in the ref or mask values because the division
     16 // between user and clip bits in the stencil depends on the number of stencil
     17 // bits in the runtime. Comments below indicate what the code should do to
     18 // incorporate the clip bit into these settings.
     19 
     20 ///////
     21 // Replace
     22 
     23 // set the ref to be the clip bit, but mask it out for the test
     24 GR_STATIC_CONST_SAME_STENCIL(gUserToClipReplace,
     25     kReplace_StencilOp,
     26     kZero_StencilOp,
     27     kLess_StencilFunc,
     28     0xffff,           // unset clip bit
     29     0x0000,           // set clip bit
     30     0xffff);
     31 
     32 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipReplace,
     33     kReplace_StencilOp,
     34     kZero_StencilOp,
     35     kEqual_StencilFunc,
     36     0xffff,           // unset clip bit
     37     0x0000,           // set clip bit
     38     0xffff);
     39 
     40 ///////
     41 // Intersect
     42 GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect,
     43     kReplace_StencilOp,
     44     kZero_StencilOp,
     45     kLess_StencilFunc,
     46     0xffff,
     47     0x0000,           // set clip bit
     48     0xffff);
     49 
     50 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipIsect,
     51     kReplace_StencilOp,
     52     kZero_StencilOp,
     53     kEqual_StencilFunc,
     54     0xffff,
     55     0x0000,           // set clip bit
     56     0xffff);
     57 
     58 ///////
     59 // Difference
     60 GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff,
     61     kReplace_StencilOp,
     62     kZero_StencilOp,
     63     kEqual_StencilFunc,
     64     0xffff,
     65     0x0000,           // set clip bit
     66     0xffff);
     67 
     68 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipDiff,
     69     kReplace_StencilOp,
     70     kZero_StencilOp,
     71     kLess_StencilFunc,
     72     0xffff,
     73     0x0000,           // set clip bit
     74     0xffff);
     75 
     76 ///////
     77 // Union
     78 
     79 // first pass makes all the passing cases >= just clip bit set.
     80 GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass0,
     81     kReplace_StencilOp,
     82     kKeep_StencilOp,
     83     kLEqual_StencilFunc,
     84     0xffff,
     85     0x0001,           // set clip bit
     86     0xffff);
     87 
     88 // second pass allows anything greater than just clip bit set to pass
     89 GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass1,
     90     kReplace_StencilOp,
     91     kZero_StencilOp,
     92     kLEqual_StencilFunc,
     93     0xffff,
     94     0x0000,           // set clip bit
     95     0xffff);
     96 
     97 // first pass finds zeros in the user bits and if found sets
     98 // the clip bit to 1
     99 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass0,
    100     kReplace_StencilOp,
    101     kKeep_StencilOp,
    102     kEqual_StencilFunc,
    103     0xffff,
    104     0x0000,           // set clip bit
    105     0x0000            // set clip bit
    106 );
    107 
    108 // second pass zeros the user bits
    109 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass1,
    110     kZero_StencilOp,
    111     kZero_StencilOp,
    112     kLess_StencilFunc,
    113     0xffff,
    114     0x0000,
    115     0xffff            // unset clip bit
    116 );
    117 
    118 ///////
    119 // Xor
    120 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0,
    121     kInvert_StencilOp,
    122     kKeep_StencilOp,
    123     kEqual_StencilFunc,
    124     0xffff,           // unset clip bit
    125     0x0000,
    126     0xffff);
    127 
    128 GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1,
    129     kReplace_StencilOp,
    130     kZero_StencilOp,
    131     kGreater_StencilFunc,
    132     0xffff,
    133     0x0000,          // set clip bit
    134     0xffff);
    135 
    136 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0,
    137     kInvert_StencilOp,
    138     kKeep_StencilOp,
    139     kEqual_StencilFunc,
    140     0xffff,           // unset clip bit
    141     0x0000,
    142     0xffff);
    143 
    144 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass1,
    145     kReplace_StencilOp,
    146     kZero_StencilOp,
    147     kLess_StencilFunc,
    148     0xffff,
    149     0x0000,          // set clip bit
    150     0xffff);
    151 
    152 ///////
    153 // Reverse Diff
    154 GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass0,
    155     kInvert_StencilOp,
    156     kZero_StencilOp,
    157     kLess_StencilFunc,
    158     0xffff,         // unset clip bit
    159     0x0000,         // set clip bit
    160     0xffff);
    161 
    162 GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass1,
    163     kReplace_StencilOp,
    164     kZero_StencilOp,
    165     kEqual_StencilFunc,
    166     0x0000,          // set clip bit
    167     0x0000,          // set clip bit
    168     0xffff);
    169 
    170 // We are looking for stencil values that are all zero. The first pass sets the
    171 // clip bit if the stencil is all zeros. The second pass clears the user bits.
    172 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass0,
    173     kInvert_StencilOp,
    174     kZero_StencilOp,
    175     kEqual_StencilFunc,
    176     0xffff,
    177     0x0000,
    178     0x0000           // set clip bit
    179 );
    180 
    181 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass1,
    182     kZero_StencilOp,
    183     kZero_StencilOp,
    184     kAlways_StencilFunc,
    185     0xffff,
    186     0x0000,
    187     0xffff           // unset clip bit
    188 );
    189 
    190 ///////
    191 // Direct to Stencil
    192 
    193 // We can render a clip element directly without first writing to the client
    194 // portion of the clip when the fill is not inverse and the set operation will
    195 // only modify the in/out status of samples covered by the clip element.
    196 
    197 // this one only works if used right after stencil clip was cleared.
    198 // Our clip mask creation code doesn't allow midstream replace ops.
    199 GR_STATIC_CONST_SAME_STENCIL(gReplaceClip,
    200     kReplace_StencilOp,
    201     kReplace_StencilOp,
    202     kAlways_StencilFunc,
    203     0xffff,
    204     0x0000,           // set clip bit
    205     0x0000            // set clipBit
    206 );
    207 
    208 GR_STATIC_CONST_SAME_STENCIL(gUnionClip,
    209     kReplace_StencilOp,
    210     kReplace_StencilOp,
    211     kAlways_StencilFunc,
    212     0xffff,
    213     0x0000,           // set clip bit
    214     0x0000            // set clip bit
    215 );
    216 
    217 GR_STATIC_CONST_SAME_STENCIL(gXorClip,
    218     kInvert_StencilOp,
    219     kInvert_StencilOp,
    220     kAlways_StencilFunc,
    221     0xffff,
    222     0x0000,
    223     0x0000            // set clip bit
    224 );
    225 
    226 GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
    227     kZero_StencilOp,
    228     kZero_StencilOp,
    229     kAlways_StencilFunc,
    230     0xffff,
    231     0x0000,
    232     0x0000            // set clip bit
    233 );
    234 
    235 bool GrStencilSettings::GetClipPasses(
    236                             SkRegion::Op op,
    237                             bool canBeDirect,
    238                             unsigned int stencilClipMask,
    239                             bool invertedFill,
    240                             int* numPasses,
    241                             GrStencilSettings settings[kMaxStencilClipPasses]) {
    242     if (canBeDirect && !invertedFill) {
    243         *numPasses = 0;
    244         switch (op) {
    245             case SkRegion::kReplace_Op:
    246                 *numPasses = 1;
    247                 settings[0] = gReplaceClip;
    248                 break;
    249             case SkRegion::kUnion_Op:
    250                 *numPasses = 1;
    251                 settings[0] = gUnionClip;
    252                 break;
    253             case SkRegion::kXOR_Op:
    254                 *numPasses = 1;
    255                 settings[0] = gXorClip;
    256                 break;
    257             case SkRegion::kDifference_Op:
    258                 *numPasses = 1;
    259                 settings[0] = gDiffClip;
    260                 break;
    261             default: // suppress warning
    262                 break;
    263         }
    264         if (1 == *numPasses) {
    265             settings[0].fFuncRefs[kFront_Face]   |= stencilClipMask;
    266             settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
    267             settings[0].fFuncRefs[kBack_Face] =
    268                 settings[0].fFuncRefs[kFront_Face];
    269             settings[0].fWriteMasks[kBack_Face] =
    270                 settings[0].fWriteMasks[kFront_Face];
    271             return true;
    272         }
    273     }
    274     switch (op) {
    275         // if we make the path renderer go to stencil we always give it a
    276         // non-inverted fill and we use the stencil rules on the client->clipbit
    277         // pass to select either the zeros or nonzeros.
    278         case SkRegion::kReplace_Op:
    279             *numPasses= 1;
    280             settings[0] = invertedFill ? gInvUserToClipReplace :
    281                                          gUserToClipReplace;
    282             settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
    283             settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
    284             settings[0].fFuncMasks[kBack_Face] =
    285                 settings[0].fFuncMasks[kFront_Face];
    286             settings[0].fFuncRefs[kBack_Face] =
    287                 settings[0].fFuncRefs[kFront_Face];
    288             break;
    289         case SkRegion::kIntersect_Op:
    290             *numPasses = 1;
    291             settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
    292             settings[0].fFuncRefs[kFront_Face] = stencilClipMask;
    293             settings[0].fFuncRefs[kBack_Face] =
    294                 settings[0].fFuncRefs[kFront_Face];
    295             break;
    296         case SkRegion::kUnion_Op:
    297             *numPasses = 2;
    298             if (invertedFill) {
    299                 settings[0] = gInvUserToClipUnionPass0;
    300                 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
    301                 settings[0].fFuncMasks[kBack_Face] =
    302                     settings[0].fFuncMasks[kFront_Face];
    303                 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
    304                 settings[0].fFuncRefs[kBack_Face] =
    305                     settings[0].fFuncRefs[kFront_Face];
    306                 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
    307                 settings[0].fWriteMasks[kBack_Face] =
    308                     settings[0].fWriteMasks[kFront_Face];
    309 
    310                 settings[1] = gInvUserToClipUnionPass1;
    311                 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
    312                 settings[1].fWriteMasks[kBack_Face] &=
    313                     settings[1].fWriteMasks[kFront_Face];
    314 
    315             } else {
    316                 settings[0] = gUserToClipUnionPass0;
    317                 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
    318                 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
    319                 settings[0].fFuncMasks[kBack_Face] =
    320                     settings[0].fFuncMasks[kFront_Face];
    321                 settings[0].fFuncRefs[kBack_Face] =
    322                     settings[0].fFuncRefs[kFront_Face];
    323 
    324                 settings[1] = gUserToClipUnionPass1;
    325                 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
    326                 settings[1].fFuncRefs[kBack_Face] =
    327                     settings[1].fFuncRefs[kFront_Face];
    328             }
    329             break;
    330         case SkRegion::kXOR_Op:
    331             *numPasses = 2;
    332             if (invertedFill) {
    333                 settings[0] = gInvUserToClipXorPass0;
    334                 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
    335                 settings[0].fFuncMasks[kBack_Face] =
    336                     settings[0].fFuncMasks[kFront_Face];
    337 
    338                 settings[1] = gInvUserToClipXorPass1;
    339                 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
    340                 settings[1].fFuncRefs[kBack_Face] =
    341                     settings[1].fFuncRefs[kFront_Face];
    342             } else {
    343                 settings[0] = gUserToClipXorPass0;
    344                 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
    345                 settings[0].fFuncMasks[kBack_Face] =
    346                     settings[0].fFuncMasks[kFront_Face];
    347 
    348                 settings[1] = gUserToClipXorPass1;
    349                 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
    350                 settings[1].fFuncRefs[kBack_Face] =
    351                     settings[1].fFuncRefs[kFront_Face];
    352             }
    353             break;
    354         case SkRegion::kDifference_Op:
    355             *numPasses = 1;
    356             settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
    357             settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
    358             settings[0].fFuncRefs[kBack_Face] =
    359                 settings[0].fFuncRefs[kFront_Face];
    360             break;
    361         case SkRegion::kReverseDifference_Op:
    362             if (invertedFill) {
    363                 *numPasses = 2;
    364                 settings[0] = gInvUserToClipRDiffPass0;
    365                 settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
    366                 settings[0].fWriteMasks[kBack_Face] =
    367                     settings[0].fWriteMasks[kFront_Face];
    368                 settings[1] = gInvUserToClipRDiffPass1;
    369                 settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
    370                 settings[1].fWriteMasks[kBack_Face] =
    371                     settings[1].fWriteMasks[kFront_Face];
    372             } else {
    373                 *numPasses = 2;
    374                 settings[0] = gUserToClipRDiffPass0;
    375                 settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
    376                 settings[0].fFuncMasks[kBack_Face] =
    377                     settings[0].fFuncMasks[kFront_Face];
    378                 settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
    379                 settings[0].fFuncRefs[kBack_Face] =
    380                     settings[0].fFuncRefs[kFront_Face];
    381 
    382                 settings[1] = gUserToClipRDiffPass1;
    383                 settings[1].fFuncMasks[kFront_Face] |= stencilClipMask;
    384                 settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
    385                 settings[1].fFuncMasks[kBack_Face] =
    386                     settings[1].fFuncMasks[kFront_Face];
    387                 settings[1].fFuncRefs[kBack_Face] =
    388                     settings[1].fFuncRefs[kFront_Face];
    389             }
    390             break;
    391         default:
    392             SkFAIL("Unknown set op");
    393     }
    394     return false;
    395 }
    396