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, _NEW_STENCIL);
    161    ctx->Stencil.Function[0]  = frontfunc;
    162    ctx->Stencil.Function[1]  = backfunc;
    163    ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
    164    ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
    165    if (ctx->Driver.StencilFuncSeparate) {
    166       ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
    167                                       frontfunc, ref, mask);
    168       ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
    169                                       backfunc, ref, mask);
    170    }
    171 }
    172 
    173 
    174 /**
    175  * Set the function and reference value for stencil testing.
    176  *
    177  * \param func test function.
    178  * \param ref reference value.
    179  * \param mask bitmask.
    180  *
    181  * \sa glStencilFunc().
    182  *
    183  * Verifies the parameters and updates the respective values in
    184  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
    185  * the driver via the dd_function_table::StencilFunc callback.
    186  */
    187 void GLAPIENTRY
    188 _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
    189 {
    190    GET_CURRENT_CONTEXT(ctx);
    191    const GLint face = ctx->Stencil.ActiveFace;
    192 
    193    if (MESA_VERBOSE & VERBOSE_API)
    194       _mesa_debug(ctx, "glStencilFunc()\n");
    195 
    196    if (!validate_stencil_func(ctx, func)) {
    197       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
    198       return;
    199    }
    200 
    201    if (face != 0) {
    202       if (ctx->Stencil.Function[face] == func &&
    203           ctx->Stencil.ValueMask[face] == mask &&
    204           ctx->Stencil.Ref[face] == ref)
    205          return;
    206       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    207       ctx->Stencil.Function[face] = func;
    208       ctx->Stencil.Ref[face] = ref;
    209       ctx->Stencil.ValueMask[face] = mask;
    210 
    211       /* Only propagate the change to the driver if EXT_stencil_two_side
    212        * is enabled.
    213        */
    214       if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
    215          ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
    216       }
    217    }
    218    else {
    219       /* set both front and back state */
    220       if (ctx->Stencil.Function[0] == func &&
    221           ctx->Stencil.Function[1] == func &&
    222           ctx->Stencil.ValueMask[0] == mask &&
    223           ctx->Stencil.ValueMask[1] == mask &&
    224           ctx->Stencil.Ref[0] == ref &&
    225           ctx->Stencil.Ref[1] == ref)
    226          return;
    227       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    228       ctx->Stencil.Function[0]  = ctx->Stencil.Function[1]  = func;
    229       ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
    230       ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
    231       if (ctx->Driver.StencilFuncSeparate) {
    232          ctx->Driver.StencilFuncSeparate(ctx,
    233 					 ((ctx->Stencil.TestTwoSide)
    234 					  ? GL_FRONT : GL_FRONT_AND_BACK),
    235                                          func, ref, mask);
    236       }
    237    }
    238 }
    239 
    240 
    241 /**
    242  * Set the stencil writing mask.
    243  *
    244  * \param mask bit-mask to enable/disable writing of individual bits in the
    245  * stencil planes.
    246  *
    247  * \sa glStencilMask().
    248  *
    249  * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and
    250  * notifies the driver via the dd_function_table::StencilMask callback.
    251  */
    252 void GLAPIENTRY
    253 _mesa_StencilMask( GLuint mask )
    254 {
    255    GET_CURRENT_CONTEXT(ctx);
    256    const GLint face = ctx->Stencil.ActiveFace;
    257 
    258    if (MESA_VERBOSE & VERBOSE_API)
    259       _mesa_debug(ctx, "glStencilMask()\n");
    260 
    261    if (face != 0) {
    262       /* Only modify the EXT_stencil_two_side back-face state.
    263        */
    264       if (ctx->Stencil.WriteMask[face] == mask)
    265          return;
    266       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    267       ctx->Stencil.WriteMask[face] = mask;
    268 
    269       /* Only propagate the change to the driver if EXT_stencil_two_side
    270        * is enabled.
    271        */
    272       if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
    273          ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
    274       }
    275    }
    276    else {
    277       /* set both front and back state */
    278       if (ctx->Stencil.WriteMask[0] == mask &&
    279           ctx->Stencil.WriteMask[1] == mask)
    280          return;
    281       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    282       ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
    283       if (ctx->Driver.StencilMaskSeparate) {
    284          ctx->Driver.StencilMaskSeparate(ctx,
    285 					 ((ctx->Stencil.TestTwoSide)
    286 					  ? GL_FRONT : GL_FRONT_AND_BACK),
    287 					  mask);
    288       }
    289    }
    290 }
    291 
    292 
    293 /**
    294  * Set the stencil test actions.
    295  *
    296  * \param fail action to take when stencil test fails.
    297  * \param zfail action to take when stencil test passes, but depth test fails.
    298  * \param zpass action to take when stencil test passes and the depth test
    299  * passes (or depth testing is not enabled).
    300  *
    301  * \sa glStencilOp().
    302  *
    303  * Verifies the parameters and updates the respective fields in
    304  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies
    305  * the driver via the dd_function_table::StencilOp callback.
    306  */
    307 void GLAPIENTRY
    308 _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
    309 {
    310    GET_CURRENT_CONTEXT(ctx);
    311    const GLint face = ctx->Stencil.ActiveFace;
    312 
    313    if (MESA_VERBOSE & VERBOSE_API)
    314       _mesa_debug(ctx, "glStencilOp()\n");
    315 
    316    if (!validate_stencil_op(ctx, fail)) {
    317       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)");
    318       return;
    319    }
    320    if (!validate_stencil_op(ctx, zfail)) {
    321       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)");
    322       return;
    323    }
    324    if (!validate_stencil_op(ctx, zpass)) {
    325       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
    326       return;
    327    }
    328 
    329    if (face != 0) {
    330       /* only set active face state */
    331       if (ctx->Stencil.ZFailFunc[face] == zfail &&
    332           ctx->Stencil.ZPassFunc[face] == zpass &&
    333           ctx->Stencil.FailFunc[face] == fail)
    334          return;
    335       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    336       ctx->Stencil.ZFailFunc[face] = zfail;
    337       ctx->Stencil.ZPassFunc[face] = zpass;
    338       ctx->Stencil.FailFunc[face] = fail;
    339 
    340       /* Only propagate the change to the driver if EXT_stencil_two_side
    341        * is enabled.
    342        */
    343       if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
    344          ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
    345       }
    346    }
    347    else {
    348       /* set both front and back state */
    349       if (ctx->Stencil.ZFailFunc[0] == zfail &&
    350           ctx->Stencil.ZFailFunc[1] == zfail &&
    351           ctx->Stencil.ZPassFunc[0] == zpass &&
    352           ctx->Stencil.ZPassFunc[1] == zpass &&
    353           ctx->Stencil.FailFunc[0] == fail &&
    354           ctx->Stencil.FailFunc[1] == fail)
    355          return;
    356       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    357       ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
    358       ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
    359       ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
    360       if (ctx->Driver.StencilOpSeparate) {
    361          ctx->Driver.StencilOpSeparate(ctx,
    362 				       ((ctx->Stencil.TestTwoSide)
    363 					? GL_FRONT : GL_FRONT_AND_BACK),
    364                                        fail, zfail, zpass);
    365       }
    366    }
    367 }
    368 
    369 
    370 
    371 /* GL_EXT_stencil_two_side */
    372 void GLAPIENTRY
    373 _mesa_ActiveStencilFaceEXT(GLenum face)
    374 {
    375    GET_CURRENT_CONTEXT(ctx);
    376 
    377    if (MESA_VERBOSE & VERBOSE_API)
    378       _mesa_debug(ctx, "glActiveStencilFaceEXT()\n");
    379 
    380    if (!ctx->Extensions.EXT_stencil_two_side) {
    381       _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
    382       return;
    383    }
    384 
    385    if (face == GL_FRONT || face == GL_BACK) {
    386       ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
    387    }
    388    else {
    389       _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
    390    }
    391 }
    392 
    393 
    394 
    395 void GLAPIENTRY
    396 _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
    397 {
    398    GLboolean set = GL_FALSE;
    399    GET_CURRENT_CONTEXT(ctx);
    400 
    401    if (MESA_VERBOSE & VERBOSE_API)
    402       _mesa_debug(ctx, "glStencilOpSeparate()\n");
    403 
    404    if (!validate_stencil_op(ctx, sfail)) {
    405       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
    406       return;
    407    }
    408    if (!validate_stencil_op(ctx, zfail)) {
    409       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)");
    410       return;
    411    }
    412    if (!validate_stencil_op(ctx, zpass)) {
    413       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)");
    414       return;
    415    }
    416    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
    417       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
    418       return;
    419    }
    420 
    421    if (face != GL_BACK) {
    422       /* set front */
    423       if (ctx->Stencil.ZFailFunc[0] != zfail ||
    424           ctx->Stencil.ZPassFunc[0] != zpass ||
    425           ctx->Stencil.FailFunc[0] != sfail){
    426          FLUSH_VERTICES(ctx, _NEW_STENCIL);
    427          ctx->Stencil.ZFailFunc[0] = zfail;
    428          ctx->Stencil.ZPassFunc[0] = zpass;
    429          ctx->Stencil.FailFunc[0] = sfail;
    430          set = GL_TRUE;
    431       }
    432    }
    433    if (face != GL_FRONT) {
    434       /* set back */
    435       if (ctx->Stencil.ZFailFunc[1] != zfail ||
    436           ctx->Stencil.ZPassFunc[1] != zpass ||
    437           ctx->Stencil.FailFunc[1] != sfail) {
    438          FLUSH_VERTICES(ctx, _NEW_STENCIL);
    439          ctx->Stencil.ZFailFunc[1] = zfail;
    440          ctx->Stencil.ZPassFunc[1] = zpass;
    441          ctx->Stencil.FailFunc[1] = sfail;
    442          set = GL_TRUE;
    443       }
    444    }
    445    if (set && ctx->Driver.StencilOpSeparate) {
    446       ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
    447    }
    448 }
    449 
    450 
    451 /* OpenGL 2.0 */
    452 void GLAPIENTRY
    453 _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
    454 {
    455    GET_CURRENT_CONTEXT(ctx);
    456 
    457    if (MESA_VERBOSE & VERBOSE_API)
    458       _mesa_debug(ctx, "glStencilFuncSeparate()\n");
    459 
    460    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
    461       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
    462       return;
    463    }
    464    if (!validate_stencil_func(ctx, func)) {
    465       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
    466       return;
    467    }
    468 
    469    FLUSH_VERTICES(ctx, _NEW_STENCIL);
    470 
    471    if (face != GL_BACK) {
    472       /* set front */
    473       ctx->Stencil.Function[0] = func;
    474       ctx->Stencil.Ref[0] = ref;
    475       ctx->Stencil.ValueMask[0] = mask;
    476    }
    477    if (face != GL_FRONT) {
    478       /* set back */
    479       ctx->Stencil.Function[1] = func;
    480       ctx->Stencil.Ref[1] = ref;
    481       ctx->Stencil.ValueMask[1] = mask;
    482    }
    483    if (ctx->Driver.StencilFuncSeparate) {
    484       ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
    485    }
    486 }
    487 
    488 
    489 /* OpenGL 2.0 */
    490 void GLAPIENTRY
    491 _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
    492 {
    493    GET_CURRENT_CONTEXT(ctx);
    494 
    495    if (MESA_VERBOSE & VERBOSE_API)
    496       _mesa_debug(ctx, "glStencilMaskSeparate()\n");
    497 
    498    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
    499       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
    500       return;
    501    }
    502 
    503    FLUSH_VERTICES(ctx, _NEW_STENCIL);
    504 
    505    if (face != GL_BACK) {
    506       ctx->Stencil.WriteMask[0] = mask;
    507    }
    508    if (face != GL_FRONT) {
    509       ctx->Stencil.WriteMask[1] = mask;
    510    }
    511    if (ctx->Driver.StencilMaskSeparate) {
    512       ctx->Driver.StencilMaskSeparate(ctx, face, mask);
    513    }
    514 }
    515 
    516 
    517 /**
    518  * Update derived stencil state.
    519  */
    520 void
    521 _mesa_update_stencil(struct gl_context *ctx)
    522 {
    523    const GLint face = ctx->Stencil._BackFace;
    524 
    525    ctx->Stencil._Enabled = (ctx->Stencil.Enabled &&
    526                             ctx->DrawBuffer->Visual.stencilBits > 0);
    527 
    528     ctx->Stencil._TestTwoSide =
    529        ctx->Stencil._Enabled &&
    530        (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] ||
    531 	ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] ||
    532 	ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] ||
    533 	ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] ||
    534 	ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] ||
    535 	ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] ||
    536 	ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]);
    537 
    538    ctx->Stencil._WriteEnabled =
    539       ctx->Stencil._Enabled &&
    540       (ctx->Stencil.WriteMask[0] != 0 ||
    541        (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[face] != 0));
    542 }
    543 
    544 
    545 /**
    546  * Initialize the context stipple state.
    547  *
    548  * \param ctx GL context.
    549  *
    550  * Initializes __struct gl_contextRec::Stencil attribute group.
    551  */
    552 void
    553 _mesa_init_stencil(struct gl_context *ctx)
    554 {
    555    ctx->Stencil.Enabled = GL_FALSE;
    556    ctx->Stencil.TestTwoSide = GL_FALSE;
    557    ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 2 = GL_BACK */
    558    ctx->Stencil.Function[0] = GL_ALWAYS;
    559    ctx->Stencil.Function[1] = GL_ALWAYS;
    560    ctx->Stencil.Function[2] = GL_ALWAYS;
    561    ctx->Stencil.FailFunc[0] = GL_KEEP;
    562    ctx->Stencil.FailFunc[1] = GL_KEEP;
    563    ctx->Stencil.FailFunc[2] = GL_KEEP;
    564    ctx->Stencil.ZPassFunc[0] = GL_KEEP;
    565    ctx->Stencil.ZPassFunc[1] = GL_KEEP;
    566    ctx->Stencil.ZPassFunc[2] = GL_KEEP;
    567    ctx->Stencil.ZFailFunc[0] = GL_KEEP;
    568    ctx->Stencil.ZFailFunc[1] = GL_KEEP;
    569    ctx->Stencil.ZFailFunc[2] = GL_KEEP;
    570    ctx->Stencil.Ref[0] = 0;
    571    ctx->Stencil.Ref[1] = 0;
    572    ctx->Stencil.Ref[2] = 0;
    573 
    574    /* 4.1.4 Stencil Test section of the GL-ES 3.0 specification says:
    575     *
    576     *     "In the initial state, [...] the front and back stencil mask are both
    577     *     set to the value 2^s  1, where s is greater than or equal to the
    578     *     number of bits in the deepest stencil buffer* supported by the GL
    579     *     implementation."
    580     *
    581     * Since the maximum supported precision for stencil buffers is 8 bits,
    582     * mask values should be initialized to 2^8 - 1 = 0xFF.
    583     */
    584    ctx->Stencil.ValueMask[0] = 0xFF;
    585    ctx->Stencil.ValueMask[1] = 0xFF;
    586    ctx->Stencil.ValueMask[2] = 0xFF;
    587    ctx->Stencil.WriteMask[0] = 0xFF;
    588    ctx->Stencil.WriteMask[1] = 0xFF;
    589    ctx->Stencil.WriteMask[2] = 0xFF;
    590 
    591    ctx->Stencil.Clear = 0;
    592    ctx->Stencil._BackFace = 1;
    593 }
    594