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 GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiff,
    171     kInvert_StencilOp,
    172     kZero_StencilOp,
    173     kEqual_StencilFunc,
    174     0xffff,
    175     0x0000,
    176     0x0000           // set clip bit
    177 );
    178 ///////
    179 // Direct to Stencil
    180 
    181 // We can render a clip element directly without first writing to the client
    182 // portion of the clip when the fill is not inverse and the set operation will
    183 // only modify the in/out status of samples covered by the clip element.
    184 
    185 // this one only works if used right after stencil clip was cleared.
    186 // Our GrClip doesn't allow midstream replace ops.
    187 GR_STATIC_CONST_SAME_STENCIL(gReplaceClip,
    188     kReplace_StencilOp,
    189     kReplace_StencilOp,
    190     kAlways_StencilFunc,
    191     0xffff,
    192     0x0000,           // set clip bit
    193     0x0000            // set clipBit
    194 );
    195 
    196 GR_STATIC_CONST_SAME_STENCIL(gUnionClip,
    197     kReplace_StencilOp,
    198     kReplace_StencilOp,
    199     kAlways_StencilFunc,
    200     0xffff,
    201     0x0000,           // set clip bit
    202     0x0000            // set clip bit
    203 );
    204 
    205 GR_STATIC_CONST_SAME_STENCIL(gXorClip,
    206     kInvert_StencilOp,
    207     kInvert_StencilOp,
    208     kAlways_StencilFunc,
    209     0xffff,
    210     0x0000,
    211     0x0000            // set clip bit
    212 );
    213 
    214 GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
    215     kZero_StencilOp,
    216     kZero_StencilOp,
    217     kAlways_StencilFunc,
    218     0xffff,
    219     0x0000,
    220     0x0000            // set clip bit
    221 );
    222 
    223 bool GrStencilSettings::GetClipPasses(GrSetOp op,
    224                                       bool canBeDirect,
    225                                       unsigned int stencilClipMask,
    226                                       bool invertedFill,
    227                                       int* numPasses,
    228                                       GrStencilSettings settings[kMaxStencilClipPasses]) {
    229     if (canBeDirect && !invertedFill) {
    230         *numPasses = 0;
    231         switch (op) {
    232             case kReplace_SetOp:
    233                 *numPasses = 1;
    234                 settings[0] = gReplaceClip;
    235                 break;
    236             case kUnion_SetOp:
    237                 *numPasses = 1;
    238                 settings[0] = gUnionClip;
    239                 break;
    240             case kXor_SetOp:
    241                 *numPasses = 1;
    242                 settings[0] = gXorClip;
    243                 break;
    244             case kDifference_SetOp:
    245                 *numPasses = 1;
    246                 settings[0] = gDiffClip;
    247                 break;
    248             default: // suppress warning
    249                 break;
    250         }
    251         if (1 == *numPasses) {
    252             settings[0].fFrontFuncRef |= stencilClipMask;
    253             settings[0].fFrontWriteMask |= stencilClipMask;
    254             settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
    255             settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
    256             return true;
    257         }
    258     }
    259     switch (op) {
    260         // if we make the path renderer go to stencil we always give it a
    261         // non-inverted fill and we use the stencil rules on the client->clipbit
    262         // pass to select either the zeros or nonzeros.
    263         case kReplace_SetOp:
    264             *numPasses= 1;
    265             settings[0] = invertedFill ? gInvUserToClipReplace : gUserToClipReplace;
    266             settings[0].fFrontFuncMask &= ~stencilClipMask;
    267             settings[0].fFrontFuncRef |= stencilClipMask;
    268             settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
    269             settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
    270             break;
    271         case kIntersect_SetOp:
    272             *numPasses = 1;
    273             settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
    274             settings[0].fFrontFuncRef = stencilClipMask;
    275             settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
    276             break;
    277         case kUnion_SetOp:
    278             *numPasses = 2;
    279             if (invertedFill) {
    280                 settings[0] = gInvUserToClipUnionPass0;
    281                 settings[0].fFrontFuncMask &= ~stencilClipMask;
    282                 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
    283                 settings[0].fFrontFuncRef |= stencilClipMask;
    284                 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
    285                 settings[0].fFrontWriteMask |= stencilClipMask;
    286                 settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
    287 
    288                 settings[1] = gInvUserToClipUnionPass1;
    289                 settings[1].fFrontWriteMask &= ~stencilClipMask;
    290                 settings[1].fBackWriteMask &= settings[1].fFrontWriteMask;
    291 
    292             } else {
    293                 settings[0] = gUserToClipUnionPass0;
    294                 settings[0].fFrontFuncMask &= ~stencilClipMask;
    295                 settings[0].fFrontFuncRef |= stencilClipMask;
    296                 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
    297                 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
    298 
    299                 settings[1] = gUserToClipUnionPass1;
    300                 settings[1].fFrontFuncRef |= stencilClipMask;
    301                 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
    302             }
    303             break;
    304         case kXor_SetOp:
    305             *numPasses = 2;
    306             if (invertedFill) {
    307                 settings[0] = gInvUserToClipXorPass0;
    308                 settings[0].fFrontFuncMask &= ~stencilClipMask;
    309                 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
    310 
    311                 settings[1] = gInvUserToClipXorPass1;
    312                 settings[1].fFrontFuncRef |= stencilClipMask;
    313                 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
    314             } else {
    315                 settings[0] = gUserToClipXorPass0;
    316                 settings[0].fFrontFuncMask &= ~stencilClipMask;
    317                 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
    318 
    319                 settings[1] = gUserToClipXorPass1;
    320                 settings[1].fFrontFuncRef |= stencilClipMask;
    321                 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
    322             }
    323             break;
    324         case kDifference_SetOp:
    325             *numPasses = 1;
    326             settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
    327             settings[0].fFrontFuncRef |= stencilClipMask;
    328             settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
    329             break;
    330         case kReverseDifference_SetOp:
    331             if (invertedFill) {
    332                 *numPasses = 1;
    333                 settings[0] = gInvUserToClipRDiff;
    334                 settings[0].fFrontWriteMask |= stencilClipMask;
    335                 settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
    336             } else {
    337                 *numPasses = 2;
    338                 settings[0] = gUserToClipRDiffPass0;
    339                 settings[0].fFrontFuncMask &= ~stencilClipMask;
    340                 settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
    341                 settings[0].fFrontFuncRef |= stencilClipMask;
    342                 settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
    343 
    344                 settings[1] = gUserToClipRDiffPass1;
    345                 settings[1].fFrontFuncMask |= stencilClipMask;
    346                 settings[1].fFrontFuncRef |= stencilClipMask;
    347                 settings[1].fBackFuncMask = settings[1].fFrontFuncMask;
    348                 settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
    349             }
    350             break;
    351         default:
    352             GrCrash("Unknown set op");
    353     }
    354     return false;
    355 }
    356