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#include "api_exec_decl.h" 57 58#include "state_tracker/st_context.h" 59 60static GLboolean 61validate_stencil_op(struct gl_context *ctx, GLenum op) 62{ 63 switch (op) { 64 case GL_KEEP: 65 case GL_ZERO: 66 case GL_REPLACE: 67 case GL_INCR: 68 case GL_DECR: 69 case GL_INVERT: 70 case GL_INCR_WRAP: 71 case GL_DECR_WRAP: 72 return GL_TRUE; 73 default: 74 return GL_FALSE; 75 } 76} 77 78 79static GLboolean 80validate_stencil_func(struct gl_context *ctx, GLenum func) 81{ 82 switch (func) { 83 case GL_NEVER: 84 case GL_LESS: 85 case GL_LEQUAL: 86 case GL_GREATER: 87 case GL_GEQUAL: 88 case GL_EQUAL: 89 case GL_NOTEQUAL: 90 case GL_ALWAYS: 91 return GL_TRUE; 92 default: 93 return GL_FALSE; 94 } 95} 96 97 98/** 99 * Set the clear value for the stencil buffer. 100 * 101 * \param s clear value. 102 * 103 * \sa glClearStencil(). 104 * 105 * Updates gl_stencil_attrib::Clear. On change 106 * flushes the vertices and notifies the driver via 107 * the dd_function_table::ClearStencil callback. 108 */ 109void GLAPIENTRY 110_mesa_ClearStencil( GLint s ) 111{ 112 GET_CURRENT_CONTEXT(ctx); 113 114 if (MESA_VERBOSE & VERBOSE_API) 115 _mesa_debug(ctx, "glClearStencil(%d)\n", s); 116 117 ctx->PopAttribState |= GL_STENCIL_BUFFER_BIT; 118 ctx->Stencil.Clear = (GLuint) s; 119} 120 121 122/** 123 * Set the function and reference value for stencil testing. 124 * 125 * \param frontfunc front test function. 126 * \param backfunc back test function. 127 * \param ref front and back reference value. 128 * \param mask front and back bitmask. 129 * 130 * \sa glStencilFunc(). 131 * 132 * Verifies the parameters and updates the respective values in 133 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies 134 * the driver via the dd_function_table::StencilFunc callback. 135 */ 136void GLAPIENTRY 137_mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask ) 138{ 139 GET_CURRENT_CONTEXT(ctx); 140 141 if (MESA_VERBOSE & VERBOSE_API) 142 _mesa_debug(ctx, "glStencilFuncSeparateATI()\n"); 143 144 if (!validate_stencil_func(ctx, frontfunc)) { 145 _mesa_error(ctx, GL_INVALID_ENUM, 146 "glStencilFuncSeparateATI(frontfunc)"); 147 return; 148 } 149 if (!validate_stencil_func(ctx, backfunc)) { 150 _mesa_error(ctx, GL_INVALID_ENUM, 151 "glStencilFuncSeparateATI(backfunc)"); 152 return; 153 } 154 155 /* set both front and back state */ 156 if (ctx->Stencil.Function[0] == frontfunc && 157 ctx->Stencil.Function[1] == backfunc && 158 ctx->Stencil.ValueMask[0] == mask && 159 ctx->Stencil.ValueMask[1] == mask && 160 ctx->Stencil.Ref[0] == ref && 161 ctx->Stencil.Ref[1] == ref) 162 return; 163 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 164 ctx->NewDriverState |= ST_NEW_DSA; 165 ctx->Stencil.Function[0] = frontfunc; 166 ctx->Stencil.Function[1] = backfunc; 167 ctx->Stencil.Ref[0] = ctx->Stencil.Ref[1] = ref; 168 ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask; 169} 170 171 172/** 173 * Set the function and reference value for stencil testing. 174 * 175 * \param func test function. 176 * \param ref reference value. 177 * \param mask bitmask. 178 * 179 * \sa glStencilFunc(). 180 * 181 * Verifies the parameters and updates the respective values in 182 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies 183 * the driver via the dd_function_table::StencilFunc callback. 184 */ 185static void 186stencil_func(struct gl_context *ctx, GLenum func, GLint ref, GLuint mask) 187{ 188 const GLint face = ctx->Stencil.ActiveFace; 189 190 if (face != 0) { 191 if (ctx->Stencil.Function[face] == func && 192 ctx->Stencil.ValueMask[face] == mask && 193 ctx->Stencil.Ref[face] == ref) 194 return; 195 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 196 ctx->NewDriverState |= ST_NEW_DSA; 197 ctx->Stencil.Function[face] = func; 198 ctx->Stencil.Ref[face] = ref; 199 ctx->Stencil.ValueMask[face] = mask; 200 } 201 else { 202 /* set both front and back state */ 203 if (ctx->Stencil.Function[0] == func && 204 ctx->Stencil.Function[1] == func && 205 ctx->Stencil.ValueMask[0] == mask && 206 ctx->Stencil.ValueMask[1] == mask && 207 ctx->Stencil.Ref[0] == ref && 208 ctx->Stencil.Ref[1] == ref) 209 return; 210 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 211 ctx->NewDriverState |= ST_NEW_DSA; 212 ctx->Stencil.Function[0] = ctx->Stencil.Function[1] = func; 213 ctx->Stencil.Ref[0] = ctx->Stencil.Ref[1] = ref; 214 ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask; 215 } 216} 217 218 219void GLAPIENTRY 220_mesa_StencilFunc_no_error(GLenum func, GLint ref, GLuint mask) 221{ 222 GET_CURRENT_CONTEXT(ctx); 223 stencil_func(ctx, func, ref, mask); 224} 225 226 227void GLAPIENTRY 228_mesa_StencilFunc(GLenum func, GLint ref, GLuint mask) 229{ 230 GET_CURRENT_CONTEXT(ctx); 231 232 if (MESA_VERBOSE & VERBOSE_API) 233 _mesa_debug(ctx, "glStencilFunc()\n"); 234 235 if (!validate_stencil_func(ctx, func)) { 236 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)"); 237 return; 238 } 239 240 stencil_func(ctx, func, ref, mask); 241} 242 243 244/** 245 * Set the stencil writing mask. 246 * 247 * \param mask bit-mask to enable/disable writing of individual bits in the 248 * stencil planes. 249 * 250 * \sa glStencilMask(). 251 * 252 * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and 253 * notifies the driver via the dd_function_table::StencilMask callback. 254 */ 255void GLAPIENTRY 256_mesa_StencilMask( GLuint mask ) 257{ 258 GET_CURRENT_CONTEXT(ctx); 259 const GLint face = ctx->Stencil.ActiveFace; 260 261 if (MESA_VERBOSE & VERBOSE_API) 262 _mesa_debug(ctx, "glStencilMask()\n"); 263 264 if (face != 0) { 265 /* Only modify the EXT_stencil_two_side back-face state. 266 */ 267 if (ctx->Stencil.WriteMask[face] == mask) 268 return; 269 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 270 ctx->NewDriverState |= ST_NEW_DSA; 271 ctx->Stencil.WriteMask[face] = mask; 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, 0, GL_STENCIL_BUFFER_BIT); 279 ctx->NewDriverState |= ST_NEW_DSA; 280 ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask; 281 } 282} 283 284 285/** 286 * Set the stencil test actions. 287 * 288 * \param fail action to take when stencil test fails. 289 * \param zfail action to take when stencil test passes, but depth test fails. 290 * \param zpass action to take when stencil test passes and the depth test 291 * passes (or depth testing is not enabled). 292 * 293 * \sa glStencilOp(). 294 * 295 * Verifies the parameters and updates the respective fields in 296 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies 297 * the driver via the dd_function_table::StencilOp callback. 298 */ 299static void 300stencil_op(struct gl_context *ctx, GLenum fail, GLenum zfail, GLenum zpass) 301{ 302 const GLint face = ctx->Stencil.ActiveFace; 303 304 if (face != 0) { 305 /* only set active face state */ 306 if (ctx->Stencil.ZFailFunc[face] == zfail && 307 ctx->Stencil.ZPassFunc[face] == zpass && 308 ctx->Stencil.FailFunc[face] == fail) 309 return; 310 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 311 ctx->NewDriverState |= ST_NEW_DSA; 312 ctx->Stencil.ZFailFunc[face] = zfail; 313 ctx->Stencil.ZPassFunc[face] = zpass; 314 ctx->Stencil.FailFunc[face] = fail; 315 } 316 else { 317 /* set both front and back state */ 318 if (ctx->Stencil.ZFailFunc[0] == zfail && 319 ctx->Stencil.ZFailFunc[1] == zfail && 320 ctx->Stencil.ZPassFunc[0] == zpass && 321 ctx->Stencil.ZPassFunc[1] == zpass && 322 ctx->Stencil.FailFunc[0] == fail && 323 ctx->Stencil.FailFunc[1] == fail) 324 return; 325 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 326 ctx->NewDriverState |= ST_NEW_DSA; 327 ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail; 328 ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass; 329 ctx->Stencil.FailFunc[0] = ctx->Stencil.FailFunc[1] = fail; 330 } 331} 332 333 334void GLAPIENTRY 335_mesa_StencilOp_no_error(GLenum fail, GLenum zfail, GLenum zpass) 336{ 337 GET_CURRENT_CONTEXT(ctx); 338 stencil_op(ctx, fail, zfail, zpass); 339} 340 341 342void GLAPIENTRY 343_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass) 344{ 345 GET_CURRENT_CONTEXT(ctx); 346 347 if (MESA_VERBOSE & VERBOSE_API) 348 _mesa_debug(ctx, "glStencilOp()\n"); 349 350 if (!validate_stencil_op(ctx, fail)) { 351 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)"); 352 return; 353 } 354 355 if (!validate_stencil_op(ctx, zfail)) { 356 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)"); 357 return; 358 } 359 360 if (!validate_stencil_op(ctx, zpass)) { 361 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)"); 362 return; 363 } 364 365 stencil_op(ctx, fail, zfail, zpass); 366} 367 368 369/* GL_EXT_stencil_two_side */ 370void GLAPIENTRY 371_mesa_ActiveStencilFaceEXT(GLenum face) 372{ 373 GET_CURRENT_CONTEXT(ctx); 374 375 if (MESA_VERBOSE & VERBOSE_API) 376 _mesa_debug(ctx, "glActiveStencilFaceEXT()\n"); 377 378 if (!ctx->Extensions.EXT_stencil_two_side) { 379 _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT"); 380 return; 381 } 382 383 if (face == GL_FRONT || face == GL_BACK) { 384 ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2; 385 } 386 else { 387 _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)"); 388 } 389} 390 391 392static void 393stencil_op_separate(struct gl_context *ctx, GLenum face, GLenum sfail, 394 GLenum zfail, GLenum zpass) 395{ 396 if (face != GL_BACK) { 397 /* set front */ 398 if (ctx->Stencil.ZFailFunc[0] != zfail || 399 ctx->Stencil.ZPassFunc[0] != zpass || 400 ctx->Stencil.FailFunc[0] != sfail){ 401 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 402 ctx->NewDriverState |= ST_NEW_DSA; 403 ctx->Stencil.ZFailFunc[0] = zfail; 404 ctx->Stencil.ZPassFunc[0] = zpass; 405 ctx->Stencil.FailFunc[0] = sfail; 406 } 407 } 408 409 if (face != GL_FRONT) { 410 /* set back */ 411 if (ctx->Stencil.ZFailFunc[1] != zfail || 412 ctx->Stencil.ZPassFunc[1] != zpass || 413 ctx->Stencil.FailFunc[1] != sfail) { 414 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 415 ctx->NewDriverState |= ST_NEW_DSA; 416 ctx->Stencil.ZFailFunc[1] = zfail; 417 ctx->Stencil.ZPassFunc[1] = zpass; 418 ctx->Stencil.FailFunc[1] = sfail; 419 } 420 } 421} 422 423 424void GLAPIENTRY 425_mesa_StencilOpSeparate_no_error(GLenum face, GLenum sfail, GLenum zfail, 426 GLenum zpass) 427{ 428 GET_CURRENT_CONTEXT(ctx); 429 stencil_op_separate(ctx, face, sfail, zfail, zpass); 430} 431 432 433void GLAPIENTRY 434_mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass) 435{ 436 GET_CURRENT_CONTEXT(ctx); 437 438 if (MESA_VERBOSE & VERBOSE_API) 439 _mesa_debug(ctx, "glStencilOpSeparate()\n"); 440 441 if (!validate_stencil_op(ctx, sfail)) { 442 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)"); 443 return; 444 } 445 446 if (!validate_stencil_op(ctx, zfail)) { 447 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)"); 448 return; 449 } 450 451 if (!validate_stencil_op(ctx, zpass)) { 452 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)"); 453 return; 454 } 455 456 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { 457 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)"); 458 return; 459 } 460 461 stencil_op_separate(ctx, face, sfail, zfail, zpass); 462} 463 464 465static void 466stencil_func_separate(struct gl_context *ctx, GLenum face, GLenum func, 467 GLint ref, GLuint mask) 468{ 469 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 470 ctx->NewDriverState |= ST_NEW_DSA; 471 472 if (face != GL_BACK) { 473 /* set front */ 474 ctx->Stencil.Function[0] = func; 475 ctx->Stencil.Ref[0] = ref; 476 ctx->Stencil.ValueMask[0] = mask; 477 } 478 479 if (face != GL_FRONT) { 480 /* set back */ 481 ctx->Stencil.Function[1] = func; 482 ctx->Stencil.Ref[1] = ref; 483 ctx->Stencil.ValueMask[1] = mask; 484 } 485} 486 487 488/* OpenGL 2.0 */ 489void GLAPIENTRY 490_mesa_StencilFuncSeparate_no_error(GLenum face, GLenum func, GLint ref, 491 GLuint mask) 492{ 493 GET_CURRENT_CONTEXT(ctx); 494 stencil_func_separate(ctx, face, func, ref, mask); 495} 496 497 498void GLAPIENTRY 499_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) 500{ 501 GET_CURRENT_CONTEXT(ctx); 502 503 if (MESA_VERBOSE & VERBOSE_API) 504 _mesa_debug(ctx, "glStencilFuncSeparate()\n"); 505 506 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { 507 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)"); 508 return; 509 } 510 511 if (!validate_stencil_func(ctx, func)) { 512 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)"); 513 return; 514 } 515 516 stencil_func_separate(ctx, face, func, ref, mask); 517} 518 519 520static void 521stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask) 522{ 523 FLUSH_VERTICES(ctx, 0, GL_STENCIL_BUFFER_BIT); 524 ctx->NewDriverState |= ST_NEW_DSA; 525 526 if (face != GL_BACK) { 527 ctx->Stencil.WriteMask[0] = mask; 528 } 529 530 if (face != GL_FRONT) { 531 ctx->Stencil.WriteMask[1] = mask; 532 } 533} 534 535 536/* OpenGL 2.0 */ 537void GLAPIENTRY 538_mesa_StencilMaskSeparate_no_error(GLenum face, GLuint mask) 539{ 540 GET_CURRENT_CONTEXT(ctx); 541 stencil_mask_separate(ctx, face, mask); 542} 543 544 545void GLAPIENTRY 546_mesa_StencilMaskSeparate(GLenum face, GLuint mask) 547{ 548 GET_CURRENT_CONTEXT(ctx); 549 550 if (MESA_VERBOSE & VERBOSE_API) 551 _mesa_debug(ctx, "glStencilMaskSeparate()\n"); 552 553 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { 554 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)"); 555 return; 556 } 557 558 stencil_mask_separate(ctx, face, mask); 559} 560 561 562/** 563 * Initialize the context stipple state. 564 * 565 * \param ctx GL context. 566 * 567 * Initializes __struct gl_contextRec::Stencil attribute group. 568 */ 569void 570_mesa_init_stencil(struct gl_context *ctx) 571{ 572 ctx->Stencil.Enabled = GL_FALSE; 573 ctx->Stencil.TestTwoSide = GL_FALSE; 574 ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 2 = GL_BACK */ 575 ctx->Stencil.Function[0] = GL_ALWAYS; 576 ctx->Stencil.Function[1] = GL_ALWAYS; 577 ctx->Stencil.Function[2] = GL_ALWAYS; 578 ctx->Stencil.FailFunc[0] = GL_KEEP; 579 ctx->Stencil.FailFunc[1] = GL_KEEP; 580 ctx->Stencil.FailFunc[2] = GL_KEEP; 581 ctx->Stencil.ZPassFunc[0] = GL_KEEP; 582 ctx->Stencil.ZPassFunc[1] = GL_KEEP; 583 ctx->Stencil.ZPassFunc[2] = GL_KEEP; 584 ctx->Stencil.ZFailFunc[0] = GL_KEEP; 585 ctx->Stencil.ZFailFunc[1] = GL_KEEP; 586 ctx->Stencil.ZFailFunc[2] = GL_KEEP; 587 ctx->Stencil.Ref[0] = 0; 588 ctx->Stencil.Ref[1] = 0; 589 ctx->Stencil.Ref[2] = 0; 590 591 /* 4.1.4 Stencil Test section of the GL-ES 3.0 specification says: 592 * 593 * "In the initial state, [...] the front and back stencil mask are both 594 * set to the value 2^s − 1, where s is greater than or equal to the 595 * number of bits in the deepest stencil buffer* supported by the GL 596 * implementation." 597 * 598 * Since the maximum supported precision for stencil buffers is 8 bits, 599 * mask values should be initialized to 2^8 - 1 = 0xFF. 600 */ 601 ctx->Stencil.ValueMask[0] = 0xFF; 602 ctx->Stencil.ValueMask[1] = 0xFF; 603 ctx->Stencil.ValueMask[2] = 0xFF; 604 ctx->Stencil.WriteMask[0] = 0xFF; 605 ctx->Stencil.WriteMask[1] = 0xFF; 606 ctx->Stencil.WriteMask[2] = 0xFF; 607 608 ctx->Stencil.Clear = 0; 609 ctx->Stencil._BackFace = 1; 610} 611