Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstencil.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.1 00004 * 00005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00050 #include "glheader.h" 00051 #include "imports.h" 00052 #include "context.h" 00053 #include "macros.h" 00054 #include "stencil.h" 00055 #include "mtypes.h" 00056 00057 00058 static GLboolean 00059 validate_stencil_op(GLcontext *ctx, GLenum op) 00060 { 00061 switch (op) { 00062 case GL_KEEP: 00063 case GL_ZERO: 00064 case GL_REPLACE: 00065 case GL_INCR: 00066 case GL_DECR: 00067 case GL_INVERT: 00068 return GL_TRUE; 00069 case GL_INCR_WRAP_EXT: 00070 case GL_DECR_WRAP_EXT: 00071 if (ctx->Extensions.EXT_stencil_wrap) { 00072 return GL_TRUE; 00073 } 00074 /* FALL-THROUGH */ 00075 default: 00076 return GL_FALSE; 00077 } 00078 } 00079 00080 00081 static GLboolean 00082 validate_stencil_func(GLcontext *ctx, GLenum func) 00083 { 00084 switch (func) { 00085 case GL_NEVER: 00086 case GL_LESS: 00087 case GL_LEQUAL: 00088 case GL_GREATER: 00089 case GL_GEQUAL: 00090 case GL_EQUAL: 00091 case GL_NOTEQUAL: 00092 case GL_ALWAYS: 00093 return GL_TRUE; 00094 default: 00095 return GL_FALSE; 00096 } 00097 } 00098 00099 00111 void GLAPIENTRY 00112 _mesa_ClearStencil( GLint s ) 00113 { 00114 GET_CURRENT_CONTEXT(ctx); 00115 ASSERT_OUTSIDE_BEGIN_END(ctx); 00116 00117 if (ctx->Stencil.Clear == (GLuint) s) 00118 return; 00119 00120 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00121 ctx->Stencil.Clear = (GLuint) s; 00122 00123 if (ctx->Driver.ClearStencil) { 00124 ctx->Driver.ClearStencil( ctx, s ); 00125 } 00126 } 00127 00128 00143 void GLAPIENTRY 00144 _mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask ) 00145 { 00146 GET_CURRENT_CONTEXT(ctx); 00147 const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 00148 ASSERT_OUTSIDE_BEGIN_END(ctx); 00149 00150 if (!validate_stencil_func(ctx, frontfunc)) { 00151 _mesa_error(ctx, GL_INVALID_ENUM, 00152 "glStencilFuncSeparateATI(frontfunc)"); 00153 return; 00154 } 00155 if (!validate_stencil_func(ctx, backfunc)) { 00156 _mesa_error(ctx, GL_INVALID_ENUM, 00157 "glStencilFuncSeparateATI(backfunc)"); 00158 return; 00159 } 00160 00161 ref = CLAMP( ref, 0, stencilMax ); 00162 00163 /* set both front and back state */ 00164 if (ctx->Stencil.Function[0] == frontfunc && 00165 ctx->Stencil.Function[1] == backfunc && 00166 ctx->Stencil.ValueMask[0] == mask && 00167 ctx->Stencil.ValueMask[1] == mask && 00168 ctx->Stencil.Ref[0] == ref && 00169 ctx->Stencil.Ref[1] == ref) 00170 return; 00171 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00172 ctx->Stencil.Function[0] = frontfunc; 00173 ctx->Stencil.Function[1] = backfunc; 00174 ctx->Stencil.Ref[0] = ctx->Stencil.Ref[1] = ref; 00175 ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask; 00176 if (ctx->Driver.StencilFuncSeparate) { 00177 ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT, 00178 frontfunc, ref, mask); 00179 ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, 00180 backfunc, ref, mask); 00181 } 00182 } 00183 00184 00198 void GLAPIENTRY 00199 _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask ) 00200 { 00201 GET_CURRENT_CONTEXT(ctx); 00202 const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 00203 const GLint face = ctx->Stencil.ActiveFace; 00204 ASSERT_OUTSIDE_BEGIN_END(ctx); 00205 00206 if (!validate_stencil_func(ctx, func)) { 00207 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)"); 00208 return; 00209 } 00210 00211 ref = CLAMP( ref, 0, stencilMax ); 00212 00213 if (face != 0) { 00214 if (ctx->Stencil.Function[face] == func && 00215 ctx->Stencil.ValueMask[face] == mask && 00216 ctx->Stencil.Ref[face] == ref) 00217 return; 00218 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00219 ctx->Stencil.Function[face] = func; 00220 ctx->Stencil.Ref[face] = ref; 00221 ctx->Stencil.ValueMask[face] = mask; 00222 00223 /* Only propagate the change to the driver if EXT_stencil_two_side 00224 * is enabled. 00225 */ 00226 if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) { 00227 ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask); 00228 } 00229 } 00230 else { 00231 /* set both front and back state */ 00232 if (ctx->Stencil.Function[0] == func && 00233 ctx->Stencil.Function[1] == func && 00234 ctx->Stencil.ValueMask[0] == mask && 00235 ctx->Stencil.ValueMask[1] == mask && 00236 ctx->Stencil.Ref[0] == ref && 00237 ctx->Stencil.Ref[1] == ref) 00238 return; 00239 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00240 ctx->Stencil.Function[0] = ctx->Stencil.Function[1] = func; 00241 ctx->Stencil.Ref[0] = ctx->Stencil.Ref[1] = ref; 00242 ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask; 00243 if (ctx->Driver.StencilFuncSeparate) { 00244 ctx->Driver.StencilFuncSeparate(ctx, 00245 ((ctx->Stencil.TestTwoSide) 00246 ? GL_FRONT : GL_FRONT_AND_BACK), 00247 func, ref, mask); 00248 } 00249 } 00250 } 00251 00252 00264 void GLAPIENTRY 00265 _mesa_StencilMask( GLuint mask ) 00266 { 00267 GET_CURRENT_CONTEXT(ctx); 00268 const GLint face = ctx->Stencil.ActiveFace; 00269 00270 ASSERT_OUTSIDE_BEGIN_END(ctx); 00271 00272 if (face != 0) { 00273 /* Only modify the EXT_stencil_two_side back-face state. 00274 */ 00275 if (ctx->Stencil.WriteMask[face] == mask) 00276 return; 00277 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00278 ctx->Stencil.WriteMask[face] = mask; 00279 00280 /* Only propagate the change to the driver if EXT_stencil_two_side 00281 * is enabled. 00282 */ 00283 if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) { 00284 ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask); 00285 } 00286 } 00287 else { 00288 /* set both front and back state */ 00289 if (ctx->Stencil.WriteMask[0] == mask && 00290 ctx->Stencil.WriteMask[1] == mask) 00291 return; 00292 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00293 ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask; 00294 if (ctx->Driver.StencilMaskSeparate) { 00295 ctx->Driver.StencilMaskSeparate(ctx, 00296 ((ctx->Stencil.TestTwoSide) 00297 ? GL_FRONT : GL_FRONT_AND_BACK), 00298 mask); 00299 } 00300 } 00301 } 00302 00303 00318 void GLAPIENTRY 00319 _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass) 00320 { 00321 GET_CURRENT_CONTEXT(ctx); 00322 const GLint face = ctx->Stencil.ActiveFace; 00323 00324 ASSERT_OUTSIDE_BEGIN_END(ctx); 00325 00326 if (!validate_stencil_op(ctx, fail)) { 00327 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)"); 00328 return; 00329 } 00330 if (!validate_stencil_op(ctx, zfail)) { 00331 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)"); 00332 return; 00333 } 00334 if (!validate_stencil_op(ctx, zpass)) { 00335 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)"); 00336 return; 00337 } 00338 00339 if (face != 0) { 00340 /* only set active face state */ 00341 if (ctx->Stencil.ZFailFunc[face] == zfail && 00342 ctx->Stencil.ZPassFunc[face] == zpass && 00343 ctx->Stencil.FailFunc[face] == fail) 00344 return; 00345 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00346 ctx->Stencil.ZFailFunc[face] = zfail; 00347 ctx->Stencil.ZPassFunc[face] = zpass; 00348 ctx->Stencil.FailFunc[face] = fail; 00349 00350 /* Only propagate the change to the driver if EXT_stencil_two_side 00351 * is enabled. 00352 */ 00353 if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) { 00354 ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass); 00355 } 00356 } 00357 else { 00358 /* set both front and back state */ 00359 if (ctx->Stencil.ZFailFunc[0] == zfail && 00360 ctx->Stencil.ZFailFunc[1] == zfail && 00361 ctx->Stencil.ZPassFunc[0] == zpass && 00362 ctx->Stencil.ZPassFunc[1] == zpass && 00363 ctx->Stencil.FailFunc[0] == fail && 00364 ctx->Stencil.FailFunc[1] == fail) 00365 return; 00366 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00367 ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail; 00368 ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass; 00369 ctx->Stencil.FailFunc[0] = ctx->Stencil.FailFunc[1] = fail; 00370 if (ctx->Driver.StencilOpSeparate) { 00371 ctx->Driver.StencilOpSeparate(ctx, 00372 ((ctx->Stencil.TestTwoSide) 00373 ? GL_FRONT : GL_FRONT_AND_BACK), 00374 fail, zfail, zpass); 00375 } 00376 } 00377 } 00378 00379 00380 00381 #if _HAVE_FULL_GL 00382 /* GL_EXT_stencil_two_side */ 00383 void GLAPIENTRY 00384 _mesa_ActiveStencilFaceEXT(GLenum face) 00385 { 00386 GET_CURRENT_CONTEXT(ctx); 00387 ASSERT_OUTSIDE_BEGIN_END(ctx); 00388 00389 if (!ctx->Extensions.EXT_stencil_two_side) { 00390 _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT"); 00391 return; 00392 } 00393 00394 if (face == GL_FRONT || face == GL_BACK) { 00395 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00396 ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2; 00397 } 00398 else { 00399 _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)"); 00400 } 00401 } 00402 #endif 00403 00404 00405 00412 void GLAPIENTRY 00413 _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass) 00414 { 00415 GLboolean set = GL_FALSE; 00416 GET_CURRENT_CONTEXT(ctx); 00417 ASSERT_OUTSIDE_BEGIN_END(ctx); 00418 00419 if (!validate_stencil_op(ctx, sfail)) { 00420 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)"); 00421 return; 00422 } 00423 if (!validate_stencil_op(ctx, zfail)) { 00424 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)"); 00425 return; 00426 } 00427 if (!validate_stencil_op(ctx, zpass)) { 00428 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)"); 00429 return; 00430 } 00431 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { 00432 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)"); 00433 return; 00434 } 00435 00436 if (face != GL_BACK) { 00437 /* set front */ 00438 if (ctx->Stencil.ZFailFunc[0] != zfail || 00439 ctx->Stencil.ZPassFunc[0] != zpass || 00440 ctx->Stencil.FailFunc[0] != sfail){ 00441 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00442 ctx->Stencil.ZFailFunc[0] = zfail; 00443 ctx->Stencil.ZPassFunc[0] = zpass; 00444 ctx->Stencil.FailFunc[0] = sfail; 00445 set = GL_TRUE; 00446 } 00447 } 00448 if (face != GL_FRONT) { 00449 /* set back */ 00450 if (ctx->Stencil.ZFailFunc[1] != zfail || 00451 ctx->Stencil.ZPassFunc[1] != zpass || 00452 ctx->Stencil.FailFunc[1] != sfail) { 00453 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00454 ctx->Stencil.ZFailFunc[1] = zfail; 00455 ctx->Stencil.ZPassFunc[1] = zpass; 00456 ctx->Stencil.FailFunc[1] = sfail; 00457 set = GL_TRUE; 00458 } 00459 } 00460 if (set && ctx->Driver.StencilOpSeparate) { 00461 ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass); 00462 } 00463 } 00464 00465 00466 /* OpenGL 2.0 */ 00467 void GLAPIENTRY 00468 _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) 00469 { 00470 GET_CURRENT_CONTEXT(ctx); 00471 const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 00472 ASSERT_OUTSIDE_BEGIN_END(ctx); 00473 00474 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { 00475 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)"); 00476 return; 00477 } 00478 if (!validate_stencil_func(ctx, func)) { 00479 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)"); 00480 return; 00481 } 00482 00483 ref = CLAMP(ref, 0, stencilMax); 00484 00485 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00486 00487 if (face != GL_BACK) { 00488 /* set front */ 00489 ctx->Stencil.Function[0] = func; 00490 ctx->Stencil.Ref[0] = ref; 00491 ctx->Stencil.ValueMask[0] = mask; 00492 } 00493 if (face != GL_FRONT) { 00494 /* set back */ 00495 ctx->Stencil.Function[1] = func; 00496 ctx->Stencil.Ref[1] = ref; 00497 ctx->Stencil.ValueMask[1] = mask; 00498 } 00499 if (ctx->Driver.StencilFuncSeparate) { 00500 ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask); 00501 } 00502 } 00503 00504 00505 /* OpenGL 2.0 */ 00506 void GLAPIENTRY 00507 _mesa_StencilMaskSeparate(GLenum face, GLuint mask) 00508 { 00509 GET_CURRENT_CONTEXT(ctx); 00510 ASSERT_OUTSIDE_BEGIN_END(ctx); 00511 00512 if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { 00513 _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)"); 00514 return; 00515 } 00516 00517 FLUSH_VERTICES(ctx, _NEW_STENCIL); 00518 00519 if (face != GL_BACK) { 00520 ctx->Stencil.WriteMask[0] = mask; 00521 } 00522 if (face != GL_FRONT) { 00523 ctx->Stencil.WriteMask[1] = mask; 00524 } 00525 if (ctx->Driver.StencilMaskSeparate) { 00526 ctx->Driver.StencilMaskSeparate(ctx, face, mask); 00527 } 00528 } 00529 00530 00534 void 00535 _mesa_update_stencil(GLcontext *ctx) 00536 { 00537 const GLint face = ctx->Stencil._BackFace; 00538 00539 ctx->Stencil._TestTwoSide = 00540 (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] || 00541 ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] || 00542 ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] || 00543 ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] || 00544 ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] || 00545 ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] || 00546 ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]); 00547 } 00548 00549 00557 void 00558 _mesa_init_stencil(GLcontext *ctx) 00559 { 00560 ctx->Stencil.Enabled = GL_FALSE; 00561 ctx->Stencil.TestTwoSide = GL_FALSE; 00562 ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 2 = GL_BACK */ 00563 ctx->Stencil.Function[0] = GL_ALWAYS; 00564 ctx->Stencil.Function[1] = GL_ALWAYS; 00565 ctx->Stencil.Function[2] = GL_ALWAYS; 00566 ctx->Stencil.FailFunc[0] = GL_KEEP; 00567 ctx->Stencil.FailFunc[1] = GL_KEEP; 00568 ctx->Stencil.FailFunc[2] = GL_KEEP; 00569 ctx->Stencil.ZPassFunc[0] = GL_KEEP; 00570 ctx->Stencil.ZPassFunc[1] = GL_KEEP; 00571 ctx->Stencil.ZPassFunc[2] = GL_KEEP; 00572 ctx->Stencil.ZFailFunc[0] = GL_KEEP; 00573 ctx->Stencil.ZFailFunc[1] = GL_KEEP; 00574 ctx->Stencil.ZFailFunc[2] = GL_KEEP; 00575 ctx->Stencil.Ref[0] = 0; 00576 ctx->Stencil.Ref[1] = 0; 00577 ctx->Stencil.Ref[2] = 0; 00578 ctx->Stencil.ValueMask[0] = ~0U; 00579 ctx->Stencil.ValueMask[1] = ~0U; 00580 ctx->Stencil.ValueMask[2] = ~0U; 00581 ctx->Stencil.WriteMask[0] = ~0U; 00582 ctx->Stencil.WriteMask[1] = ~0U; 00583 ctx->Stencil.WriteMask[2] = ~0U; 00584 ctx->Stencil.Clear = 0; 00585 ctx->Stencil._BackFace = 1; 00586 } Generated on Sun May 27 2012 04:20:29 for ReactOS by
1.7.6.1
|