stencil.c revision 7ec681f3
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 52#include "context.h" 53#include "macros.h" 54#include "stencil.h" 55#include "mtypes.h" 56 57 58static GLboolean 59validate_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 77static GLboolean 78validate_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 */ 107void 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->PopAttribState |= GL_STENCIL_BUFFER_BIT; 116 ctx->Stencil.Clear = (GLuint) s; 117} 118 119 120/** 121 * Set the function and reference value for stencil testing. 122 * 123 * \param frontfunc front test function. 124 * \param backfunc back test function. 125 * \param ref front and back reference value. 126 * \param mask front and back bitmask. 127 * 128 * \sa glStencilFunc(). 129 * 130 * Verifies the parameters and updates the respective values in 131 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies 132 * the driver via the dd_function_table::StencilFunc callback. 133 */ 134void GLAPIENTRY 135_mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask ) 136{ 137 GET_CURRENT_CONTEXT(ctx); 138 139 if (MESA_VERBOSE & VERBOSE_API) 140 _mesa_debug(ctx, "glStencilFuncSeparateATI()\n"); 141 142 if (!validate_stencil_func(ctx, frontfunc)) { 143 _mesa_error(ctx, GL_INVALID_ENUM, 144 "glStencilFuncSeparateATI(frontfunc)"); 145 return; 146 } 147 if (!validate_stencil_func(ctx, backfunc)) { 148 _mesa_error(ctx, GL_INVALID_ENUM, 149 "glStencilFuncSeparateATI(backfunc)"); 150 return; 151 } 152 153 /* set both front and back state */ 154 if (ctx->Stencil.Function[0] == frontfunc && 155 ctx->Stencil.Function[1] == backfunc && 156 ctx->Stencil.ValueMask[0] == mask && 157 ctx->Stencil.ValueMask[1] == mask && 158 ctx->Stencil.Ref[0] == ref && 159 ctx->Stencil.Ref[1] == ref) 160 return; 161 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 162 GL_STENCIL_BUFFER_BIT); 163 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 164 ctx->Stencil.Function[0] = frontfunc; 165 ctx->Stencil.Function[1] = backfunc; 166 ctx->Stencil.Ref[0] = ctx->Stencil.Ref[1] = ref; 167 ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask; 168 if (ctx->Driver.StencilFuncSeparate) { 169 ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT, 170 frontfunc, ref, mask); 171 ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, 172 backfunc, ref, mask); 173 } 174} 175 176 177/** 178 * Set the function and reference value for stencil testing. 179 * 180 * \param func test function. 181 * \param ref reference value. 182 * \param mask bitmask. 183 * 184 * \sa glStencilFunc(). 185 * 186 * Verifies the parameters and updates the respective values in 187 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies 188 * the driver via the dd_function_table::StencilFunc callback. 189 */ 190static void 191stencil_func(struct gl_context *ctx, GLenum func, GLint ref, GLuint mask) 192{ 193 const GLint face = ctx->Stencil.ActiveFace; 194 195 if (face != 0) { 196 if (ctx->Stencil.Function[face] == func && 197 ctx->Stencil.ValueMask[face] == mask && 198 ctx->Stencil.Ref[face] == ref) 199 return; 200 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 201 GL_STENCIL_BUFFER_BIT); 202 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 203 ctx->Stencil.Function[face] = func; 204 ctx->Stencil.Ref[face] = ref; 205 ctx->Stencil.ValueMask[face] = mask; 206 207 /* Only propagate the change to the driver if EXT_stencil_two_side 208 * is enabled. 209 */ 210 if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) { 211 ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask); 212 } 213 } 214 else { 215 /* set both front and back state */ 216 if (ctx->Stencil.Function[0] == func && 217 ctx->Stencil.Function[1] == func && 218 ctx->Stencil.ValueMask[0] == mask && 219 ctx->Stencil.ValueMask[1] == mask && 220 ctx->Stencil.Ref[0] == ref && 221 ctx->Stencil.Ref[1] == ref) 222 return; 223 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 224 GL_STENCIL_BUFFER_BIT); 225 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 226 ctx->Stencil.Function[0] = ctx->Stencil.Function[1] = func; 227 ctx->Stencil.Ref[0] = ctx->Stencil.Ref[1] = ref; 228 ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask; 229 if (ctx->Driver.StencilFuncSeparate) { 230 ctx->Driver.StencilFuncSeparate(ctx, 231 ((ctx->Stencil.TestTwoSide) 232 ? GL_FRONT : GL_FRONT_AND_BACK), 233 func, ref, mask); 234 } 235 } 236} 237 238 239void GLAPIENTRY 240_mesa_StencilFunc_no_error(GLenum func, GLint ref, GLuint mask) 241{ 242 GET_CURRENT_CONTEXT(ctx); 243 stencil_func(ctx, func, ref, mask); 244} 245 246 247void GLAPIENTRY 248_mesa_StencilFunc(GLenum func, GLint ref, GLuint mask) 249{ 250 GET_CURRENT_CONTEXT(ctx); 251 252 if (MESA_VERBOSE & VERBOSE_API) 253 _mesa_debug(ctx, "glStencilFunc()\n"); 254 255 if (!validate_stencil_func(ctx, func)) { 256 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)"); 257 return; 258 } 259 260 stencil_func(ctx, func, ref, mask); 261} 262 263 264/** 265 * Set the stencil writing mask. 266 * 267 * \param mask bit-mask to enable/disable writing of individual bits in the 268 * stencil planes. 269 * 270 * \sa glStencilMask(). 271 * 272 * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and 273 * notifies the driver via the dd_function_table::StencilMask callback. 274 */ 275void GLAPIENTRY 276_mesa_StencilMask( GLuint mask ) 277{ 278 GET_CURRENT_CONTEXT(ctx); 279 const GLint face = ctx->Stencil.ActiveFace; 280 281 if (MESA_VERBOSE & VERBOSE_API) 282 _mesa_debug(ctx, "glStencilMask()\n"); 283 284 if (face != 0) { 285 /* Only modify the EXT_stencil_two_side back-face state. 286 */ 287 if (ctx->Stencil.WriteMask[face] == mask) 288 return; 289 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 290 GL_STENCIL_BUFFER_BIT); 291 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 292 ctx->Stencil.WriteMask[face] = mask; 293 294 /* Only propagate the change to the driver if EXT_stencil_two_side 295 * is enabled. 296 */ 297 if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) { 298 ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask); 299 } 300 } 301 else { 302 /* set both front and back state */ 303 if (ctx->Stencil.WriteMask[0] == mask && 304 ctx->Stencil.WriteMask[1] == mask) 305 return; 306 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 307 GL_STENCIL_BUFFER_BIT); 308 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 309 ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask; 310 if (ctx->Driver.StencilMaskSeparate) { 311 ctx->Driver.StencilMaskSeparate(ctx, 312 ((ctx->Stencil.TestTwoSide) 313 ? GL_FRONT : GL_FRONT_AND_BACK), 314 mask); 315 } 316 } 317} 318 319 320/** 321 * Set the stencil test actions. 322 * 323 * \param fail action to take when stencil test fails. 324 * \param zfail action to take when stencil test passes, but depth test fails. 325 * \param zpass action to take when stencil test passes and the depth test 326 * passes (or depth testing is not enabled). 327 * 328 * \sa glStencilOp(). 329 * 330 * Verifies the parameters and updates the respective fields in 331 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies 332 * the driver via the dd_function_table::StencilOp callback. 333 */ 334static void 335stencil_op(struct gl_context *ctx, GLenum fail, GLenum zfail, GLenum zpass) 336{ 337 const GLint face = ctx->Stencil.ActiveFace; 338 339 if (face != 0) { 340 /* only set active face state */ 341 if (ctx->Stencil.ZFailFunc[face] == zfail && 342 ctx->Stencil.ZPassFunc[face] == zpass && 343 ctx->Stencil.FailFunc[face] == fail) 344 return; 345 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 346 GL_STENCIL_BUFFER_BIT); 347 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 348 ctx->Stencil.ZFailFunc[face] = zfail; 349 ctx->Stencil.ZPassFunc[face] = zpass; 350 ctx->Stencil.FailFunc[face] = fail; 351 352 /* Only propagate the change to the driver if EXT_stencil_two_side 353 * is enabled. 354 */ 355 if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) { 356 ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass); 357 } 358 } 359 else { 360 /* set both front and back state */ 361 if (ctx->Stencil.ZFailFunc[0] == zfail && 362 ctx->Stencil.ZFailFunc[1] == zfail && 363 ctx->Stencil.ZPassFunc[0] == zpass && 364 ctx->Stencil.ZPassFunc[1] == zpass && 365 ctx->Stencil.FailFunc[0] == fail && 366 ctx->Stencil.FailFunc[1] == fail) 367 return; 368 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 369 GL_STENCIL_BUFFER_BIT); 370 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 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 384void GLAPIENTRY 385_mesa_StencilOp_no_error(GLenum fail, GLenum zfail, GLenum zpass) 386{ 387 GET_CURRENT_CONTEXT(ctx); 388 stencil_op(ctx, fail, zfail, zpass); 389} 390 391 392void GLAPIENTRY 393_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass) 394{ 395 GET_CURRENT_CONTEXT(ctx); 396 397 if (MESA_VERBOSE & VERBOSE_API) 398 _mesa_debug(ctx, "glStencilOp()\n"); 399 400 if (!validate_stencil_op(ctx, fail)) { 401 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)"); 402 return; 403 } 404 405 if (!validate_stencil_op(ctx, zfail)) { 406 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)"); 407 return; 408 } 409 410 if (!validate_stencil_op(ctx, zpass)) { 411 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)"); 412 return; 413 } 414 415 stencil_op(ctx, fail, zfail, zpass); 416} 417 418 419/* GL_EXT_stencil_two_side */ 420void GLAPIENTRY 421_mesa_ActiveStencilFaceEXT(GLenum face) 422{ 423 GET_CURRENT_CONTEXT(ctx); 424 425 if (MESA_VERBOSE & VERBOSE_API) 426 _mesa_debug(ctx, "glActiveStencilFaceEXT()\n"); 427 428 if (!ctx->Extensions.EXT_stencil_two_side) { 429 _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT"); 430 return; 431 } 432 433 if (face == GL_FRONT || face == GL_BACK) { 434 ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2; 435 } 436 else { 437 _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)"); 438 } 439} 440 441 442static void 443stencil_op_separate(struct gl_context *ctx, GLenum face, GLenum sfail, 444 GLenum zfail, GLenum zpass) 445{ 446 GLboolean set = GL_FALSE; 447 448 if (face != GL_BACK) { 449 /* set front */ 450 if (ctx->Stencil.ZFailFunc[0] != zfail || 451 ctx->Stencil.ZPassFunc[0] != zpass || 452 ctx->Stencil.FailFunc[0] != sfail){ 453 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 454 GL_STENCIL_BUFFER_BIT); 455 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 456 ctx->Stencil.ZFailFunc[0] = zfail; 457 ctx->Stencil.ZPassFunc[0] = zpass; 458 ctx->Stencil.FailFunc[0] = sfail; 459 set = GL_TRUE; 460 } 461 } 462 463 if (face != GL_FRONT) { 464 /* set back */ 465 if (ctx->Stencil.ZFailFunc[1] != zfail || 466 ctx->Stencil.ZPassFunc[1] != zpass || 467 ctx->Stencil.FailFunc[1] != sfail) { 468 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 469 GL_STENCIL_BUFFER_BIT); 470 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 471 ctx->Stencil.ZFailFunc[1] = zfail; 472 ctx->Stencil.ZPassFunc[1] = zpass; 473 ctx->Stencil.FailFunc[1] = sfail; 474 set = GL_TRUE; 475 } 476 } 477 478 if (set && ctx->Driver.StencilOpSeparate) { 479 ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass); 480 } 481} 482 483 484void GLAPIENTRY 485_mesa_StencilOpSeparate_no_error(GLenum face, GLenum sfail, GLenum zfail, 486 GLenum zpass) 487{ 488 GET_CURRENT_CONTEXT(ctx); 489 stencil_op_separate(ctx, face, sfail, zfail, zpass); 490} 491 492 493void GLAPIENTRY 494_mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass) 495{ 496 GET_CURRENT_CONTEXT(ctx); 497 498 if (MESA_VERBOSE & VERBOSE_API) 499 _mesa_debug(ctx, "glStencilOpSeparate()\n"); 500 501 if (!validate_stencil_op(ctx, sfail)) { 502 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)"); 503 return; 504 } 505 506 if (!validate_stencil_op(ctx, zfail)) { 507 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)"); 508 return; 509 } 510 511 if (!validate_stencil_op(ctx, zpass)) { 512 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)"); 513 return; 514 } 515 516 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { 517 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)"); 518 return; 519 } 520 521 stencil_op_separate(ctx, face, sfail, zfail, zpass); 522} 523 524 525static void 526stencil_func_separate(struct gl_context *ctx, GLenum face, GLenum func, 527 GLint ref, GLuint mask) 528{ 529 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 530 GL_STENCIL_BUFFER_BIT); 531 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 532 533 if (face != GL_BACK) { 534 /* set front */ 535 ctx->Stencil.Function[0] = func; 536 ctx->Stencil.Ref[0] = ref; 537 ctx->Stencil.ValueMask[0] = mask; 538 } 539 540 if (face != GL_FRONT) { 541 /* set back */ 542 ctx->Stencil.Function[1] = func; 543 ctx->Stencil.Ref[1] = ref; 544 ctx->Stencil.ValueMask[1] = mask; 545 } 546 547 if (ctx->Driver.StencilFuncSeparate) { 548 ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask); 549 } 550} 551 552 553/* OpenGL 2.0 */ 554void GLAPIENTRY 555_mesa_StencilFuncSeparate_no_error(GLenum face, GLenum func, GLint ref, 556 GLuint mask) 557{ 558 GET_CURRENT_CONTEXT(ctx); 559 stencil_func_separate(ctx, face, func, ref, mask); 560} 561 562 563void GLAPIENTRY 564_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) 565{ 566 GET_CURRENT_CONTEXT(ctx); 567 568 if (MESA_VERBOSE & VERBOSE_API) 569 _mesa_debug(ctx, "glStencilFuncSeparate()\n"); 570 571 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { 572 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)"); 573 return; 574 } 575 576 if (!validate_stencil_func(ctx, func)) { 577 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)"); 578 return; 579 } 580 581 stencil_func_separate(ctx, face, func, ref, mask); 582} 583 584 585static void 586stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask) 587{ 588 FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL, 589 GL_STENCIL_BUFFER_BIT); 590 ctx->NewDriverState |= ctx->DriverFlags.NewStencil; 591 592 if (face != GL_BACK) { 593 ctx->Stencil.WriteMask[0] = mask; 594 } 595 596 if (face != GL_FRONT) { 597 ctx->Stencil.WriteMask[1] = mask; 598 } 599 600 if (ctx->Driver.StencilMaskSeparate) { 601 ctx->Driver.StencilMaskSeparate(ctx, face, mask); 602 } 603} 604 605 606/* OpenGL 2.0 */ 607void GLAPIENTRY 608_mesa_StencilMaskSeparate_no_error(GLenum face, GLuint mask) 609{ 610 GET_CURRENT_CONTEXT(ctx); 611 stencil_mask_separate(ctx, face, mask); 612} 613 614 615void GLAPIENTRY 616_mesa_StencilMaskSeparate(GLenum face, GLuint mask) 617{ 618 GET_CURRENT_CONTEXT(ctx); 619 620 if (MESA_VERBOSE & VERBOSE_API) 621 _mesa_debug(ctx, "glStencilMaskSeparate()\n"); 622 623 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { 624 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)"); 625 return; 626 } 627 628 stencil_mask_separate(ctx, face, mask); 629} 630 631 632/** 633 * Initialize the context stipple state. 634 * 635 * \param ctx GL context. 636 * 637 * Initializes __struct gl_contextRec::Stencil attribute group. 638 */ 639void 640_mesa_init_stencil(struct gl_context *ctx) 641{ 642 ctx->Stencil.Enabled = GL_FALSE; 643 ctx->Stencil.TestTwoSide = GL_FALSE; 644 ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 2 = GL_BACK */ 645 ctx->Stencil.Function[0] = GL_ALWAYS; 646 ctx->Stencil.Function[1] = GL_ALWAYS; 647 ctx->Stencil.Function[2] = GL_ALWAYS; 648 ctx->Stencil.FailFunc[0] = GL_KEEP; 649 ctx->Stencil.FailFunc[1] = GL_KEEP; 650 ctx->Stencil.FailFunc[2] = GL_KEEP; 651 ctx->Stencil.ZPassFunc[0] = GL_KEEP; 652 ctx->Stencil.ZPassFunc[1] = GL_KEEP; 653 ctx->Stencil.ZPassFunc[2] = GL_KEEP; 654 ctx->Stencil.ZFailFunc[0] = GL_KEEP; 655 ctx->Stencil.ZFailFunc[1] = GL_KEEP; 656 ctx->Stencil.ZFailFunc[2] = GL_KEEP; 657 ctx->Stencil.Ref[0] = 0; 658 ctx->Stencil.Ref[1] = 0; 659 ctx->Stencil.Ref[2] = 0; 660 661 /* 4.1.4 Stencil Test section of the GL-ES 3.0 specification says: 662 * 663 * "In the initial state, [...] the front and back stencil mask are both 664 * set to the value 2^s − 1, where s is greater than or equal to the 665 * number of bits in the deepest stencil buffer* supported by the GL 666 * implementation." 667 * 668 * Since the maximum supported precision for stencil buffers is 8 bits, 669 * mask values should be initialized to 2^8 - 1 = 0xFF. 670 */ 671 ctx->Stencil.ValueMask[0] = 0xFF; 672 ctx->Stencil.ValueMask[1] = 0xFF; 673 ctx->Stencil.ValueMask[2] = 0xFF; 674 ctx->Stencil.WriteMask[0] = 0xFF; 675 ctx->Stencil.WriteMask[1] = 0xFF; 676 ctx->Stencil.WriteMask[2] = 0xFF; 677 678 ctx->Stencil.Clear = 0; 679 ctx->Stencil._BackFace = 1; 680} 681