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