Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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