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