Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 
     26 /**
     27  * \file stencil.c
     28  * Stencil operations.
     29  *
     30  * Note: There's some conflict between GL_EXT_stencil_two_side and
     31  * OpenGL 2.0's two-sided stencil feature.
     32  *
     33  * With GL_EXT_stencil_two_side, calling glStencilOp/Func/Mask() only the
     34  * front OR back face state (as set by glActiveStencilFaceEXT) is set.
     35  *
     36  * But with OpenGL 2.0, calling glStencilOp/Func/Mask() sets BOTH the
     37  * front AND back state.
     38  *
     39  * Also, note that GL_ATI_separate_stencil is different as well:
     40  * glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, ...)  vs.
     41  * glStencilFuncSeparate(GLenum face, GLenum func, ...).
     42  *
     43  * This problem is solved by keeping three sets of stencil state:
     44  *  state[0] = GL_FRONT state.
     45  *  state[1] = OpenGL 2.0 / GL_ATI_separate_stencil GL_BACK state.
     46  *  state[2] = GL_EXT_stencil_two_side GL_BACK state.
     47  */
     48 
     49 
     50 #include "glheader.h"
     51 #include "imports.h"
     52 #include "context.h"
     53 #include "macros.h"
     54 #include "stencil.h"
     55 #include "mtypes.h"
     56 
     57 
     58 static GLboolean
     59 validate_stencil_op(struct gl_context *ctx, GLenum op)
     60 {
     61    switch (op) {
     62    case GL_KEEP:
     63    case GL_ZERO:
     64    case GL_REPLACE:
     65    case GL_INCR:
     66    case GL_DECR:
     67    case GL_INVERT:
     68    case GL_INCR_WRAP:
     69    case GL_DECR_WRAP:
     70       return GL_TRUE;
     71    default:
     72       return GL_FALSE;
     73    }
     74 }
     75 
     76 
     77 static GLboolean
     78 validate_stencil_func(struct gl_context *ctx, GLenum func)
     79 {
     80    switch (func) {
     81    case GL_NEVER:
     82    case GL_LESS:
     83    case GL_LEQUAL:
     84    case GL_GREATER:
     85    case GL_GEQUAL:
     86    case GL_EQUAL:
     87    case GL_NOTEQUAL:
     88    case GL_ALWAYS:
     89       return GL_TRUE;
     90    default:
     91       return GL_FALSE;
     92    }
     93 }
     94 
     95 
     96 /**
     97  * Set the clear value for the stencil buffer.
     98  *
     99  * \param s clear value.
    100  *
    101  * \sa glClearStencil().
    102  *
    103  * Updates gl_stencil_attrib::Clear. On change
    104  * flushes the vertices and notifies the driver via
    105  * the dd_function_table::ClearStencil callback.
    106  */
    107 void GLAPIENTRY
    108 _mesa_ClearStencil( GLint s )
    109 {
    110    GET_CURRENT_CONTEXT(ctx);
    111 
    112    if (MESA_VERBOSE & VERBOSE_API)
    113       _mesa_debug(ctx, "glClearStencil(%d)\n", s);
    114 
    115    ctx->Stencil.Clear = (GLuint) s;
    116 }
    117 
    118 
    119 /**
    120  * Set the function and reference value for stencil testing.
    121  *
    122  * \param frontfunc front test function.
    123  * \param backfunc back test function.
    124  * \param ref front and back reference value.
    125  * \param mask front and back bitmask.
    126  *
    127  * \sa glStencilFunc().
    128  *
    129  * Verifies the parameters and updates the respective values in
    130  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
    131  * the driver via the dd_function_table::StencilFunc callback.
    132  */
    133 void GLAPIENTRY
    134 _mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask )
    135 {
    136    GET_CURRENT_CONTEXT(ctx);
    137 
    138    if (MESA_VERBOSE & VERBOSE_API)
    139       _mesa_debug(ctx, "glStencilFuncSeparateATI()\n");
    140 
    141    if (!validate_stencil_func(ctx, frontfunc)) {
    142       _mesa_error(ctx, GL_INVALID_ENUM,
    143                   "glStencilFuncSeparateATI(frontfunc)");
    144       return;
    145    }
    146    if (!validate_stencil_func(ctx, backfunc)) {
    147       _mesa_error(ctx, GL_INVALID_ENUM,
    148                   "glStencilFuncSeparateATI(backfunc)");
    149       return;
    150    }
    151 
    152    /* set both front and back state */
    153    if (ctx->Stencil.Function[0] == frontfunc &&
    154        ctx->Stencil.Function[1] == backfunc &&
    155        ctx->Stencil.ValueMask[0] == mask &&
    156        ctx->Stencil.ValueMask[1] == mask &&
    157        ctx->Stencil.Ref[0] == ref &&
    158        ctx->Stencil.Ref[1] == ref)
    159       return;
    160    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    161    ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    162    ctx->Stencil.Function[0]  = frontfunc;
    163    ctx->Stencil.Function[1]  = backfunc;
    164    ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
    165    ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
    166    if (ctx->Driver.StencilFuncSeparate) {
    167       ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
    168                                       frontfunc, ref, mask);
    169       ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
    170                                       backfunc, ref, mask);
    171    }
    172 }
    173 
    174 
    175 /**
    176  * Set the function and reference value for stencil testing.
    177  *
    178  * \param func test function.
    179  * \param ref reference value.
    180  * \param mask bitmask.
    181  *
    182  * \sa glStencilFunc().
    183  *
    184  * Verifies the parameters and updates the respective values in
    185  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
    186  * the driver via the dd_function_table::StencilFunc callback.
    187  */
    188 static void
    189 stencil_func(struct gl_context *ctx, GLenum func, GLint ref, GLuint mask)
    190 {
    191    const GLint face = ctx->Stencil.ActiveFace;
    192 
    193    if (face != 0) {
    194       if (ctx->Stencil.Function[face] == func &&
    195           ctx->Stencil.ValueMask[face] == mask &&
    196           ctx->Stencil.Ref[face] == ref)
    197          return;
    198       FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    199       ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    200       ctx->Stencil.Function[face] = func;
    201       ctx->Stencil.Ref[face] = ref;
    202       ctx->Stencil.ValueMask[face] = mask;
    203 
    204       /* Only propagate the change to the driver if EXT_stencil_two_side
    205        * is enabled.
    206        */
    207       if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
    208          ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
    209       }
    210    }
    211    else {
    212       /* set both front and back state */
    213       if (ctx->Stencil.Function[0] == func &&
    214           ctx->Stencil.Function[1] == func &&
    215           ctx->Stencil.ValueMask[0] == mask &&
    216           ctx->Stencil.ValueMask[1] == mask &&
    217           ctx->Stencil.Ref[0] == ref &&
    218           ctx->Stencil.Ref[1] == ref)
    219          return;
    220       FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    221       ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    222       ctx->Stencil.Function[0]  = ctx->Stencil.Function[1]  = func;
    223       ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
    224       ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
    225       if (ctx->Driver.StencilFuncSeparate) {
    226          ctx->Driver.StencilFuncSeparate(ctx,
    227 					 ((ctx->Stencil.TestTwoSide)
    228 					  ? GL_FRONT : GL_FRONT_AND_BACK),
    229                                          func, ref, mask);
    230       }
    231    }
    232 }
    233 
    234 
    235 void GLAPIENTRY
    236 _mesa_StencilFunc_no_error(GLenum func, GLint ref, GLuint mask)
    237 {
    238    GET_CURRENT_CONTEXT(ctx);
    239    stencil_func(ctx, func, ref, mask);
    240 }
    241 
    242 
    243 void GLAPIENTRY
    244 _mesa_StencilFunc(GLenum func, GLint ref, GLuint mask)
    245 {
    246    GET_CURRENT_CONTEXT(ctx);
    247 
    248    if (MESA_VERBOSE & VERBOSE_API)
    249       _mesa_debug(ctx, "glStencilFunc()\n");
    250 
    251    if (!validate_stencil_func(ctx, func)) {
    252       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
    253       return;
    254    }
    255 
    256    stencil_func(ctx, func, ref, mask);
    257 }
    258 
    259 
    260 /**
    261  * Set the stencil writing mask.
    262  *
    263  * \param mask bit-mask to enable/disable writing of individual bits in the
    264  * stencil planes.
    265  *
    266  * \sa glStencilMask().
    267  *
    268  * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and
    269  * notifies the driver via the dd_function_table::StencilMask callback.
    270  */
    271 void GLAPIENTRY
    272 _mesa_StencilMask( GLuint mask )
    273 {
    274    GET_CURRENT_CONTEXT(ctx);
    275    const GLint face = ctx->Stencil.ActiveFace;
    276 
    277    if (MESA_VERBOSE & VERBOSE_API)
    278       _mesa_debug(ctx, "glStencilMask()\n");
    279 
    280    if (face != 0) {
    281       /* Only modify the EXT_stencil_two_side back-face state.
    282        */
    283       if (ctx->Stencil.WriteMask[face] == mask)
    284          return;
    285       FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    286       ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    287       ctx->Stencil.WriteMask[face] = mask;
    288 
    289       /* Only propagate the change to the driver if EXT_stencil_two_side
    290        * is enabled.
    291        */
    292       if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
    293          ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
    294       }
    295    }
    296    else {
    297       /* set both front and back state */
    298       if (ctx->Stencil.WriteMask[0] == mask &&
    299           ctx->Stencil.WriteMask[1] == mask)
    300          return;
    301       FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    302       ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    303       ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
    304       if (ctx->Driver.StencilMaskSeparate) {
    305          ctx->Driver.StencilMaskSeparate(ctx,
    306 					 ((ctx->Stencil.TestTwoSide)
    307 					  ? GL_FRONT : GL_FRONT_AND_BACK),
    308 					  mask);
    309       }
    310    }
    311 }
    312 
    313 
    314 /**
    315  * Set the stencil test actions.
    316  *
    317  * \param fail action to take when stencil test fails.
    318  * \param zfail action to take when stencil test passes, but depth test fails.
    319  * \param zpass action to take when stencil test passes and the depth test
    320  * passes (or depth testing is not enabled).
    321  *
    322  * \sa glStencilOp().
    323  *
    324  * Verifies the parameters and updates the respective fields in
    325  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
    326  * the driver via the dd_function_table::StencilOp callback.
    327  */
    328 static void
    329 stencil_op(struct gl_context *ctx, GLenum fail, GLenum zfail, GLenum zpass)
    330 {
    331    const GLint face = ctx->Stencil.ActiveFace;
    332 
    333    if (face != 0) {
    334       /* only set active face state */
    335       if (ctx->Stencil.ZFailFunc[face] == zfail &&
    336           ctx->Stencil.ZPassFunc[face] == zpass &&
    337           ctx->Stencil.FailFunc[face] == fail)
    338          return;
    339       FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    340       ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    341       ctx->Stencil.ZFailFunc[face] = zfail;
    342       ctx->Stencil.ZPassFunc[face] = zpass;
    343       ctx->Stencil.FailFunc[face] = fail;
    344 
    345       /* Only propagate the change to the driver if EXT_stencil_two_side
    346        * is enabled.
    347        */
    348       if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
    349          ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
    350       }
    351    }
    352    else {
    353       /* set both front and back state */
    354       if (ctx->Stencil.ZFailFunc[0] == zfail &&
    355           ctx->Stencil.ZFailFunc[1] == zfail &&
    356           ctx->Stencil.ZPassFunc[0] == zpass &&
    357           ctx->Stencil.ZPassFunc[1] == zpass &&
    358           ctx->Stencil.FailFunc[0] == fail &&
    359           ctx->Stencil.FailFunc[1] == fail)
    360          return;
    361       FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    362       ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    363       ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
    364       ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
    365       ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
    366       if (ctx->Driver.StencilOpSeparate) {
    367          ctx->Driver.StencilOpSeparate(ctx,
    368 				       ((ctx->Stencil.TestTwoSide)
    369 					? GL_FRONT : GL_FRONT_AND_BACK),
    370                                        fail, zfail, zpass);
    371       }
    372    }
    373 }
    374 
    375 
    376 void GLAPIENTRY
    377 _mesa_StencilOp_no_error(GLenum fail, GLenum zfail, GLenum zpass)
    378 {
    379    GET_CURRENT_CONTEXT(ctx);
    380    stencil_op(ctx, fail, zfail, zpass);
    381 }
    382 
    383 
    384 void GLAPIENTRY
    385 _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
    386 {
    387    GET_CURRENT_CONTEXT(ctx);
    388 
    389    if (MESA_VERBOSE & VERBOSE_API)
    390       _mesa_debug(ctx, "glStencilOp()\n");
    391 
    392    if (!validate_stencil_op(ctx, fail)) {
    393       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)");
    394       return;
    395    }
    396 
    397    if (!validate_stencil_op(ctx, zfail)) {
    398       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)");
    399       return;
    400    }
    401 
    402    if (!validate_stencil_op(ctx, zpass)) {
    403       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
    404       return;
    405    }
    406 
    407    stencil_op(ctx, fail, zfail, zpass);
    408 }
    409 
    410 
    411 /* GL_EXT_stencil_two_side */
    412 void GLAPIENTRY
    413 _mesa_ActiveStencilFaceEXT(GLenum face)
    414 {
    415    GET_CURRENT_CONTEXT(ctx);
    416 
    417    if (MESA_VERBOSE & VERBOSE_API)
    418       _mesa_debug(ctx, "glActiveStencilFaceEXT()\n");
    419 
    420    if (!ctx->Extensions.EXT_stencil_two_side) {
    421       _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
    422       return;
    423    }
    424 
    425    if (face == GL_FRONT || face == GL_BACK) {
    426       ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
    427    }
    428    else {
    429       _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
    430    }
    431 }
    432 
    433 
    434 static void
    435 stencil_op_separate(struct gl_context *ctx, GLenum face, GLenum sfail,
    436                     GLenum zfail, GLenum zpass)
    437 {
    438    GLboolean set = GL_FALSE;
    439 
    440    if (face != GL_BACK) {
    441       /* set front */
    442       if (ctx->Stencil.ZFailFunc[0] != zfail ||
    443           ctx->Stencil.ZPassFunc[0] != zpass ||
    444           ctx->Stencil.FailFunc[0] != sfail){
    445          FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    446          ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    447          ctx->Stencil.ZFailFunc[0] = zfail;
    448          ctx->Stencil.ZPassFunc[0] = zpass;
    449          ctx->Stencil.FailFunc[0] = sfail;
    450          set = GL_TRUE;
    451       }
    452    }
    453 
    454    if (face != GL_FRONT) {
    455       /* set back */
    456       if (ctx->Stencil.ZFailFunc[1] != zfail ||
    457           ctx->Stencil.ZPassFunc[1] != zpass ||
    458           ctx->Stencil.FailFunc[1] != sfail) {
    459          FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    460          ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    461          ctx->Stencil.ZFailFunc[1] = zfail;
    462          ctx->Stencil.ZPassFunc[1] = zpass;
    463          ctx->Stencil.FailFunc[1] = sfail;
    464          set = GL_TRUE;
    465       }
    466    }
    467 
    468    if (set && ctx->Driver.StencilOpSeparate) {
    469       ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
    470    }
    471 }
    472 
    473 
    474 void GLAPIENTRY
    475 _mesa_StencilOpSeparate_no_error(GLenum face, GLenum sfail, GLenum zfail,
    476                                  GLenum zpass)
    477 {
    478    GET_CURRENT_CONTEXT(ctx);
    479    stencil_op_separate(ctx, face, sfail, zfail, zpass);
    480 }
    481 
    482 
    483 void GLAPIENTRY
    484 _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
    485 {
    486    GET_CURRENT_CONTEXT(ctx);
    487 
    488    if (MESA_VERBOSE & VERBOSE_API)
    489       _mesa_debug(ctx, "glStencilOpSeparate()\n");
    490 
    491    if (!validate_stencil_op(ctx, sfail)) {
    492       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
    493       return;
    494    }
    495 
    496    if (!validate_stencil_op(ctx, zfail)) {
    497       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)");
    498       return;
    499    }
    500 
    501    if (!validate_stencil_op(ctx, zpass)) {
    502       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)");
    503       return;
    504    }
    505 
    506    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
    507       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
    508       return;
    509    }
    510 
    511    stencil_op_separate(ctx, face, sfail, zfail, zpass);
    512 }
    513 
    514 
    515 static void
    516 stencil_func_separate(struct gl_context *ctx, GLenum face, GLenum func,
    517                       GLint ref, GLuint mask)
    518 {
    519    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    520    ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    521 
    522    if (face != GL_BACK) {
    523       /* set front */
    524       ctx->Stencil.Function[0] = func;
    525       ctx->Stencil.Ref[0] = ref;
    526       ctx->Stencil.ValueMask[0] = mask;
    527    }
    528 
    529    if (face != GL_FRONT) {
    530       /* set back */
    531       ctx->Stencil.Function[1] = func;
    532       ctx->Stencil.Ref[1] = ref;
    533       ctx->Stencil.ValueMask[1] = mask;
    534    }
    535 
    536    if (ctx->Driver.StencilFuncSeparate) {
    537       ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
    538    }
    539 }
    540 
    541 
    542 /* OpenGL 2.0 */
    543 void GLAPIENTRY
    544 _mesa_StencilFuncSeparate_no_error(GLenum face, GLenum func, GLint ref,
    545                                    GLuint mask)
    546 {
    547    GET_CURRENT_CONTEXT(ctx);
    548    stencil_func_separate(ctx, face, func, ref, mask);
    549 }
    550 
    551 
    552 void GLAPIENTRY
    553 _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
    554 {
    555    GET_CURRENT_CONTEXT(ctx);
    556 
    557    if (MESA_VERBOSE & VERBOSE_API)
    558       _mesa_debug(ctx, "glStencilFuncSeparate()\n");
    559 
    560    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
    561       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
    562       return;
    563    }
    564 
    565    if (!validate_stencil_func(ctx, func)) {
    566       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
    567       return;
    568    }
    569 
    570    stencil_func_separate(ctx, face, func, ref, mask);
    571 }
    572 
    573 
    574 static void
    575 stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask)
    576 {
    577    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
    578    ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    579 
    580    if (face != GL_BACK) {
    581       ctx->Stencil.WriteMask[0] = mask;
    582    }
    583 
    584    if (face != GL_FRONT) {
    585       ctx->Stencil.WriteMask[1] = mask;
    586    }
    587 
    588    if (ctx->Driver.StencilMaskSeparate) {
    589       ctx->Driver.StencilMaskSeparate(ctx, face, mask);
    590    }
    591 }
    592 
    593 
    594 /* OpenGL 2.0 */
    595 void GLAPIENTRY
    596 _mesa_StencilMaskSeparate_no_error(GLenum face, GLuint mask)
    597 {
    598    GET_CURRENT_CONTEXT(ctx);
    599    stencil_mask_separate(ctx, face, mask);
    600 }
    601 
    602 
    603 void GLAPIENTRY
    604 _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
    605 {
    606    GET_CURRENT_CONTEXT(ctx);
    607 
    608    if (MESA_VERBOSE & VERBOSE_API)
    609       _mesa_debug(ctx, "glStencilMaskSeparate()\n");
    610 
    611    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
    612       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
    613       return;
    614    }
    615 
    616    stencil_mask_separate(ctx, face, mask);
    617 }
    618 
    619 
    620 /**
    621  * Initialize the context stipple state.
    622  *
    623  * \param ctx GL context.
    624  *
    625  * Initializes __struct gl_contextRec::Stencil attribute group.
    626  */
    627 void
    628 _mesa_init_stencil(struct gl_context *ctx)
    629 {
    630    ctx->Stencil.Enabled = GL_FALSE;
    631    ctx->Stencil.TestTwoSide = GL_FALSE;
    632    ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 2 = GL_BACK */
    633    ctx->Stencil.Function[0] = GL_ALWAYS;
    634    ctx->Stencil.Function[1] = GL_ALWAYS;
    635    ctx->Stencil.Function[2] = GL_ALWAYS;
    636    ctx->Stencil.FailFunc[0] = GL_KEEP;
    637    ctx->Stencil.FailFunc[1] = GL_KEEP;
    638    ctx->Stencil.FailFunc[2] = GL_KEEP;
    639    ctx->Stencil.ZPassFunc[0] = GL_KEEP;
    640    ctx->Stencil.ZPassFunc[1] = GL_KEEP;
    641    ctx->Stencil.ZPassFunc[2] = GL_KEEP;
    642    ctx->Stencil.ZFailFunc[0] = GL_KEEP;
    643    ctx->Stencil.ZFailFunc[1] = GL_KEEP;
    644    ctx->Stencil.ZFailFunc[2] = GL_KEEP;
    645    ctx->Stencil.Ref[0] = 0;
    646    ctx->Stencil.Ref[1] = 0;
    647    ctx->Stencil.Ref[2] = 0;
    648 
    649    /* 4.1.4 Stencil Test section of the GL-ES 3.0 specification says:
    650     *
    651     *     "In the initial state, [...] the front and back stencil mask are both
    652     *     set to the value 2^s  1, where s is greater than or equal to the
    653     *     number of bits in the deepest stencil buffer* supported by the GL
    654     *     implementation."
    655     *
    656     * Since the maximum supported precision for stencil buffers is 8 bits,
    657     * mask values should be initialized to 2^8 - 1 = 0xFF.
    658     */
    659    ctx->Stencil.ValueMask[0] = 0xFF;
    660    ctx->Stencil.ValueMask[1] = 0xFF;
    661    ctx->Stencil.ValueMask[2] = 0xFF;
    662    ctx->Stencil.WriteMask[0] = 0xFF;
    663    ctx->Stencil.WriteMask[1] = 0xFF;
    664    ctx->Stencil.WriteMask[2] = 0xFF;
    665 
    666    ctx->Stencil.Clear = 0;
    667    ctx->Stencil._BackFace = 1;
    668 }
    669