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