Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.1
      4  *
      5  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR 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    ASSERT_OUTSIDE_BEGIN_END(ctx);
    112 
    113    if (ctx->Stencil.Clear == (GLuint) s)
    114       return;
    115 
    116    FLUSH_VERTICES(ctx, _NEW_STENCIL);
    117    ctx->Stencil.Clear = (GLuint) s;
    118 }
    119 
    120 
    121 /**
    122  * Set the function and reference value for stencil testing.
    123  *
    124  * \param frontfunc front test function.
    125  * \param backfunc back test function.
    126  * \param ref front and back reference value.
    127  * \param mask front and back bitmask.
    128  *
    129  * \sa glStencilFunc().
    130  *
    131  * Verifies the parameters and updates the respective values in
    132  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
    133  * driver via the dd_function_table::StencilFunc callback.
    134  */
    135 void GLAPIENTRY
    136 _mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask )
    137 {
    138    GET_CURRENT_CONTEXT(ctx);
    139    const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
    140    ASSERT_OUTSIDE_BEGIN_END(ctx);
    141 
    142    if (MESA_VERBOSE & VERBOSE_API)
    143       _mesa_debug(ctx, "glStencilFuncSeparateATI()\n");
    144 
    145    if (!validate_stencil_func(ctx, frontfunc)) {
    146       _mesa_error(ctx, GL_INVALID_ENUM,
    147                   "glStencilFuncSeparateATI(frontfunc)");
    148       return;
    149    }
    150    if (!validate_stencil_func(ctx, backfunc)) {
    151       _mesa_error(ctx, GL_INVALID_ENUM,
    152                   "glStencilFuncSeparateATI(backfunc)");
    153       return;
    154    }
    155 
    156    ref = CLAMP( ref, 0, stencilMax );
    157 
    158    /* set both front and back state */
    159    if (ctx->Stencil.Function[0] == frontfunc &&
    160        ctx->Stencil.Function[1] == backfunc &&
    161        ctx->Stencil.ValueMask[0] == mask &&
    162        ctx->Stencil.ValueMask[1] == mask &&
    163        ctx->Stencil.Ref[0] == ref &&
    164        ctx->Stencil.Ref[1] == ref)
    165       return;
    166    FLUSH_VERTICES(ctx, _NEW_STENCIL);
    167    ctx->Stencil.Function[0]  = frontfunc;
    168    ctx->Stencil.Function[1]  = backfunc;
    169    ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
    170    ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
    171    if (ctx->Driver.StencilFuncSeparate) {
    172       ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
    173                                       frontfunc, ref, mask);
    174       ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
    175                                       backfunc, ref, mask);
    176    }
    177 }
    178 
    179 
    180 /**
    181  * Set the function and reference value for stencil testing.
    182  *
    183  * \param func test function.
    184  * \param ref reference value.
    185  * \param mask bitmask.
    186  *
    187  * \sa glStencilFunc().
    188  *
    189  * Verifies the parameters and updates the respective values in
    190  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
    191  * driver via the dd_function_table::StencilFunc callback.
    192  */
    193 void GLAPIENTRY
    194 _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
    195 {
    196    GET_CURRENT_CONTEXT(ctx);
    197    const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
    198    const GLint face = ctx->Stencil.ActiveFace;
    199    ASSERT_OUTSIDE_BEGIN_END(ctx);
    200 
    201    if (MESA_VERBOSE & VERBOSE_API)
    202       _mesa_debug(ctx, "glStencilFunc()\n");
    203 
    204    if (!validate_stencil_func(ctx, func)) {
    205       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
    206       return;
    207    }
    208 
    209    ref = CLAMP( ref, 0, stencilMax );
    210 
    211    if (face != 0) {
    212       if (ctx->Stencil.Function[face] == func &&
    213           ctx->Stencil.ValueMask[face] == mask &&
    214           ctx->Stencil.Ref[face] == ref)
    215          return;
    216       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    217       ctx->Stencil.Function[face] = func;
    218       ctx->Stencil.Ref[face] = ref;
    219       ctx->Stencil.ValueMask[face] = mask;
    220 
    221       /* Only propagate the change to the driver if EXT_stencil_two_side
    222        * is enabled.
    223        */
    224       if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
    225          ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
    226       }
    227    }
    228    else {
    229       /* set both front and back state */
    230       if (ctx->Stencil.Function[0] == func &&
    231           ctx->Stencil.Function[1] == func &&
    232           ctx->Stencil.ValueMask[0] == mask &&
    233           ctx->Stencil.ValueMask[1] == mask &&
    234           ctx->Stencil.Ref[0] == ref &&
    235           ctx->Stencil.Ref[1] == ref)
    236          return;
    237       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    238       ctx->Stencil.Function[0]  = ctx->Stencil.Function[1]  = func;
    239       ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
    240       ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
    241       if (ctx->Driver.StencilFuncSeparate) {
    242          ctx->Driver.StencilFuncSeparate(ctx,
    243 					 ((ctx->Stencil.TestTwoSide)
    244 					  ? GL_FRONT : GL_FRONT_AND_BACK),
    245                                          func, ref, mask);
    246       }
    247    }
    248 }
    249 
    250 
    251 /**
    252  * Set the stencil writing mask.
    253  *
    254  * \param mask bit-mask to enable/disable writing of individual bits in the
    255  * stencil planes.
    256  *
    257  * \sa glStencilMask().
    258  *
    259  * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and
    260  * notifies the driver via the dd_function_table::StencilMask callback.
    261  */
    262 void GLAPIENTRY
    263 _mesa_StencilMask( GLuint mask )
    264 {
    265    GET_CURRENT_CONTEXT(ctx);
    266    const GLint face = ctx->Stencil.ActiveFace;
    267 
    268    if (MESA_VERBOSE & VERBOSE_API)
    269       _mesa_debug(ctx, "glStencilMask()\n");
    270 
    271    ASSERT_OUTSIDE_BEGIN_END(ctx);
    272 
    273    if (face != 0) {
    274       /* Only modify the EXT_stencil_two_side back-face state.
    275        */
    276       if (ctx->Stencil.WriteMask[face] == mask)
    277          return;
    278       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    279       ctx->Stencil.WriteMask[face] = mask;
    280 
    281       /* Only propagate the change to the driver if EXT_stencil_two_side
    282        * is enabled.
    283        */
    284       if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
    285          ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
    286       }
    287    }
    288    else {
    289       /* set both front and back state */
    290       if (ctx->Stencil.WriteMask[0] == mask &&
    291           ctx->Stencil.WriteMask[1] == mask)
    292          return;
    293       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    294       ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
    295       if (ctx->Driver.StencilMaskSeparate) {
    296          ctx->Driver.StencilMaskSeparate(ctx,
    297 					 ((ctx->Stencil.TestTwoSide)
    298 					  ? GL_FRONT : GL_FRONT_AND_BACK),
    299 					  mask);
    300       }
    301    }
    302 }
    303 
    304 
    305 /**
    306  * Set the stencil test actions.
    307  *
    308  * \param fail action to take when stencil test fails.
    309  * \param zfail action to take when stencil test passes, but depth test fails.
    310  * \param zpass action to take when stencil test passes and the depth test
    311  * passes (or depth testing is not enabled).
    312  *
    313  * \sa glStencilOp().
    314  *
    315  * Verifies the parameters and updates the respective fields in
    316  * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
    317  * driver via the dd_function_table::StencilOp callback.
    318  */
    319 void GLAPIENTRY
    320 _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
    321 {
    322    GET_CURRENT_CONTEXT(ctx);
    323    const GLint face = ctx->Stencil.ActiveFace;
    324 
    325    if (MESA_VERBOSE & VERBOSE_API)
    326       _mesa_debug(ctx, "glStencilOp()\n");
    327 
    328    ASSERT_OUTSIDE_BEGIN_END(ctx);
    329 
    330    if (!validate_stencil_op(ctx, fail)) {
    331       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)");
    332       return;
    333    }
    334    if (!validate_stencil_op(ctx, zfail)) {
    335       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)");
    336       return;
    337    }
    338    if (!validate_stencil_op(ctx, zpass)) {
    339       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
    340       return;
    341    }
    342 
    343    if (face != 0) {
    344       /* only set active face state */
    345       if (ctx->Stencil.ZFailFunc[face] == zfail &&
    346           ctx->Stencil.ZPassFunc[face] == zpass &&
    347           ctx->Stencil.FailFunc[face] == fail)
    348          return;
    349       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    350       ctx->Stencil.ZFailFunc[face] = zfail;
    351       ctx->Stencil.ZPassFunc[face] = zpass;
    352       ctx->Stencil.FailFunc[face] = fail;
    353 
    354       /* Only propagate the change to the driver if EXT_stencil_two_side
    355        * is enabled.
    356        */
    357       if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
    358          ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
    359       }
    360    }
    361    else {
    362       /* set both front and back state */
    363       if (ctx->Stencil.ZFailFunc[0] == zfail &&
    364           ctx->Stencil.ZFailFunc[1] == zfail &&
    365           ctx->Stencil.ZPassFunc[0] == zpass &&
    366           ctx->Stencil.ZPassFunc[1] == zpass &&
    367           ctx->Stencil.FailFunc[0] == fail &&
    368           ctx->Stencil.FailFunc[1] == fail)
    369          return;
    370       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    371       ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
    372       ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
    373       ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
    374       if (ctx->Driver.StencilOpSeparate) {
    375          ctx->Driver.StencilOpSeparate(ctx,
    376 				       ((ctx->Stencil.TestTwoSide)
    377 					? GL_FRONT : GL_FRONT_AND_BACK),
    378                                        fail, zfail, zpass);
    379       }
    380    }
    381 }
    382 
    383 
    384 
    385 #if _HAVE_FULL_GL
    386 /* GL_EXT_stencil_two_side */
    387 void GLAPIENTRY
    388 _mesa_ActiveStencilFaceEXT(GLenum face)
    389 {
    390    GET_CURRENT_CONTEXT(ctx);
    391    ASSERT_OUTSIDE_BEGIN_END(ctx);
    392 
    393    if (MESA_VERBOSE & VERBOSE_API)
    394       _mesa_debug(ctx, "glActiveStencilFaceEXT()\n");
    395 
    396    if (!ctx->Extensions.EXT_stencil_two_side) {
    397       _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
    398       return;
    399    }
    400 
    401    if (face == GL_FRONT || face == GL_BACK) {
    402       FLUSH_VERTICES(ctx, _NEW_STENCIL);
    403       ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
    404    }
    405    else {
    406       _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
    407    }
    408 }
    409 #endif
    410 
    411 
    412 
    413 /**
    414  * OpenGL 2.0 function.
    415  * \todo Make StencilOp() call this function.  And eventually remove the
    416  * ctx->Driver.StencilOp function and use ctx->Driver.StencilOpSeparate
    417  * instead.
    418  */
    419 void GLAPIENTRY
    420 _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
    421 {
    422    GLboolean set = GL_FALSE;
    423    GET_CURRENT_CONTEXT(ctx);
    424    ASSERT_OUTSIDE_BEGIN_END(ctx);
    425 
    426    if (MESA_VERBOSE & VERBOSE_API)
    427       _mesa_debug(ctx, "glStencilOpSeparate()\n");
    428 
    429    if (!validate_stencil_op(ctx, sfail)) {
    430       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
    431       return;
    432    }
    433    if (!validate_stencil_op(ctx, zfail)) {
    434       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)");
    435       return;
    436    }
    437    if (!validate_stencil_op(ctx, zpass)) {
    438       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)");
    439       return;
    440    }
    441    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
    442       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
    443       return;
    444    }
    445 
    446    if (face != GL_BACK) {
    447       /* set front */
    448       if (ctx->Stencil.ZFailFunc[0] != zfail ||
    449           ctx->Stencil.ZPassFunc[0] != zpass ||
    450           ctx->Stencil.FailFunc[0] != sfail){
    451          FLUSH_VERTICES(ctx, _NEW_STENCIL);
    452          ctx->Stencil.ZFailFunc[0] = zfail;
    453          ctx->Stencil.ZPassFunc[0] = zpass;
    454          ctx->Stencil.FailFunc[0] = sfail;
    455          set = GL_TRUE;
    456       }
    457    }
    458    if (face != GL_FRONT) {
    459       /* set back */
    460       if (ctx->Stencil.ZFailFunc[1] != zfail ||
    461           ctx->Stencil.ZPassFunc[1] != zpass ||
    462           ctx->Stencil.FailFunc[1] != sfail) {
    463          FLUSH_VERTICES(ctx, _NEW_STENCIL);
    464          ctx->Stencil.ZFailFunc[1] = zfail;
    465          ctx->Stencil.ZPassFunc[1] = zpass;
    466          ctx->Stencil.FailFunc[1] = sfail;
    467          set = GL_TRUE;
    468       }
    469    }
    470    if (set && ctx->Driver.StencilOpSeparate) {
    471       ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
    472    }
    473 }
    474 
    475 
    476 /* OpenGL 2.0 */
    477 void GLAPIENTRY
    478 _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
    479 {
    480    GET_CURRENT_CONTEXT(ctx);
    481    const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
    482    ASSERT_OUTSIDE_BEGIN_END(ctx);
    483 
    484    if (MESA_VERBOSE & VERBOSE_API)
    485       _mesa_debug(ctx, "glStencilFuncSeparate()\n");
    486 
    487    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
    488       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
    489       return;
    490    }
    491    if (!validate_stencil_func(ctx, func)) {
    492       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
    493       return;
    494    }
    495 
    496    ref = CLAMP(ref, 0, stencilMax);
    497 
    498    FLUSH_VERTICES(ctx, _NEW_STENCIL);
    499 
    500    if (face != GL_BACK) {
    501       /* set front */
    502       ctx->Stencil.Function[0] = func;
    503       ctx->Stencil.Ref[0] = ref;
    504       ctx->Stencil.ValueMask[0] = mask;
    505    }
    506    if (face != GL_FRONT) {
    507       /* set back */
    508       ctx->Stencil.Function[1] = func;
    509       ctx->Stencil.Ref[1] = ref;
    510       ctx->Stencil.ValueMask[1] = mask;
    511    }
    512    if (ctx->Driver.StencilFuncSeparate) {
    513       ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
    514    }
    515 }
    516 
    517 
    518 /* OpenGL 2.0 */
    519 void GLAPIENTRY
    520 _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
    521 {
    522    GET_CURRENT_CONTEXT(ctx);
    523    ASSERT_OUTSIDE_BEGIN_END(ctx);
    524 
    525    if (MESA_VERBOSE & VERBOSE_API)
    526       _mesa_debug(ctx, "glStencilMaskSeparate()\n");
    527 
    528    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
    529       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
    530       return;
    531    }
    532 
    533    FLUSH_VERTICES(ctx, _NEW_STENCIL);
    534 
    535    if (face != GL_BACK) {
    536       ctx->Stencil.WriteMask[0] = mask;
    537    }
    538    if (face != GL_FRONT) {
    539       ctx->Stencil.WriteMask[1] = mask;
    540    }
    541    if (ctx->Driver.StencilMaskSeparate) {
    542       ctx->Driver.StencilMaskSeparate(ctx, face, mask);
    543    }
    544 }
    545 
    546 
    547 /**
    548  * Update derived stencil state.
    549  */
    550 void
    551 _mesa_update_stencil(struct gl_context *ctx)
    552 {
    553    const GLint face = ctx->Stencil._BackFace;
    554 
    555    ctx->Stencil._Enabled = (ctx->Stencil.Enabled &&
    556                             ctx->DrawBuffer->Visual.stencilBits > 0);
    557 
    558     ctx->Stencil._TestTwoSide =
    559        ctx->Stencil._Enabled &&
    560        (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] ||
    561 	ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] ||
    562 	ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] ||
    563 	ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] ||
    564 	ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] ||
    565 	ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] ||
    566 	ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]);
    567 }
    568 
    569 
    570 /**
    571  * Initialize the context stipple state.
    572  *
    573  * \param ctx GL context.
    574  *
    575  * Initializes __struct gl_contextRec::Stencil attribute group.
    576  */
    577 void
    578 _mesa_init_stencil(struct gl_context *ctx)
    579 {
    580    ctx->Stencil.Enabled = GL_FALSE;
    581    ctx->Stencil.TestTwoSide = GL_FALSE;
    582    ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 2 = GL_BACK */
    583    ctx->Stencil.Function[0] = GL_ALWAYS;
    584    ctx->Stencil.Function[1] = GL_ALWAYS;
    585    ctx->Stencil.Function[2] = GL_ALWAYS;
    586    ctx->Stencil.FailFunc[0] = GL_KEEP;
    587    ctx->Stencil.FailFunc[1] = GL_KEEP;
    588    ctx->Stencil.FailFunc[2] = GL_KEEP;
    589    ctx->Stencil.ZPassFunc[0] = GL_KEEP;
    590    ctx->Stencil.ZPassFunc[1] = GL_KEEP;
    591    ctx->Stencil.ZPassFunc[2] = GL_KEEP;
    592    ctx->Stencil.ZFailFunc[0] = GL_KEEP;
    593    ctx->Stencil.ZFailFunc[1] = GL_KEEP;
    594    ctx->Stencil.ZFailFunc[2] = GL_KEEP;
    595    ctx->Stencil.Ref[0] = 0;
    596    ctx->Stencil.Ref[1] = 0;
    597    ctx->Stencil.Ref[2] = 0;
    598    ctx->Stencil.ValueMask[0] = ~0U;
    599    ctx->Stencil.ValueMask[1] = ~0U;
    600    ctx->Stencil.ValueMask[2] = ~0U;
    601    ctx->Stencil.WriteMask[0] = ~0U;
    602    ctx->Stencil.WriteMask[1] = ~0U;
    603    ctx->Stencil.WriteMask[2] = ~0U;
    604    ctx->Stencil.Clear = 0;
    605    ctx->Stencil._BackFace = 1;
    606 }
    607