2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
31 * Note: There's some conflict between GL_EXT_stencil_two_side and
32 * OpenGL 2.0's two-sided stencil feature.
34 * With GL_EXT_stencil_two_side, calling glStencilOp/Func/Mask() only the
35 * front OR back face state (as set by glActiveStencilFaceEXT) is set.
37 * But with OpenGL 2.0, calling glStencilOp/Func/Mask() sets BOTH the
38 * front AND back state.
40 * Also, note that GL_ATI_separate_stencil is different as well:
41 * glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, ...) vs.
42 * glStencilFuncSeparate(GLenum face, GLenum func, ...).
44 * This problem is solved by keeping three sets of stencil state:
45 * state[0] = GL_FRONT state.
46 * state[1] = OpenGL 2.0 / GL_ATI_separate_stencil GL_BACK state.
47 * state[2] = GL_EXT_stencil_two_side GL_BACK state.
60 validate_stencil_op(struct gl_context
*ctx
, GLenum op
)
79 validate_stencil_func(struct gl_context
*ctx
, GLenum func
)
98 * Set the clear value for the stencil buffer.
100 * \param s clear value.
102 * \sa glClearStencil().
104 * Updates gl_stencil_attrib::Clear. On change
105 * flushes the vertices and notifies the driver via
106 * the dd_function_table::ClearStencil callback.
109 _mesa_ClearStencil( GLint s
)
111 GET_CURRENT_CONTEXT(ctx
);
113 ctx
->Stencil
.Clear
= (GLuint
) s
;
118 * Set the function and reference value for stencil testing.
120 * \param frontfunc front test function.
121 * \param backfunc back test function.
122 * \param ref front and back reference value.
123 * \param mask front and back bitmask.
125 * \sa glStencilFunc().
127 * Verifies the parameters and updates the respective values in
128 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
129 * driver via the dd_function_table::StencilFunc callback.
132 _mesa_StencilFuncSeparateATI( GLenum frontfunc
, GLenum backfunc
, GLint ref
, GLuint mask
)
134 GET_CURRENT_CONTEXT(ctx
);
136 if (MESA_VERBOSE
& VERBOSE_API
)
137 _mesa_debug(ctx
, "glStencilFuncSeparateATI()\n");
139 if (!validate_stencil_func(ctx
, frontfunc
)) {
140 _mesa_error(ctx
, GL_INVALID_ENUM
,
141 "glStencilFuncSeparateATI(frontfunc)");
144 if (!validate_stencil_func(ctx
, backfunc
)) {
145 _mesa_error(ctx
, GL_INVALID_ENUM
,
146 "glStencilFuncSeparateATI(backfunc)");
150 /* set both front and back state */
151 if (ctx
->Stencil
.Function
[0] == frontfunc
&&
152 ctx
->Stencil
.Function
[1] == backfunc
&&
153 ctx
->Stencil
.ValueMask
[0] == mask
&&
154 ctx
->Stencil
.ValueMask
[1] == mask
&&
155 ctx
->Stencil
.Ref
[0] == ref
&&
156 ctx
->Stencil
.Ref
[1] == ref
)
158 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
159 ctx
->Stencil
.Function
[0] = frontfunc
;
160 ctx
->Stencil
.Function
[1] = backfunc
;
161 ctx
->Stencil
.Ref
[0] = ctx
->Stencil
.Ref
[1] = ref
;
162 ctx
->Stencil
.ValueMask
[0] = ctx
->Stencil
.ValueMask
[1] = mask
;
163 if (ctx
->Driver
.StencilFuncSeparate
) {
164 ctx
->Driver
.StencilFuncSeparate(ctx
, GL_FRONT
,
165 frontfunc
, ref
, mask
);
166 ctx
->Driver
.StencilFuncSeparate(ctx
, GL_BACK
,
167 backfunc
, ref
, mask
);
173 * Set the function and reference value for stencil testing.
175 * \param func test function.
176 * \param ref reference value.
177 * \param mask bitmask.
179 * \sa glStencilFunc().
181 * Verifies the parameters and updates the respective values in
182 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
183 * driver via the dd_function_table::StencilFunc callback.
186 _mesa_StencilFunc( GLenum func
, GLint ref
, GLuint mask
)
188 GET_CURRENT_CONTEXT(ctx
);
189 const GLint face
= ctx
->Stencil
.ActiveFace
;
191 if (MESA_VERBOSE
& VERBOSE_API
)
192 _mesa_debug(ctx
, "glStencilFunc()\n");
194 if (!validate_stencil_func(ctx
, func
)) {
195 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilFunc(func)");
200 if (ctx
->Stencil
.Function
[face
] == func
&&
201 ctx
->Stencil
.ValueMask
[face
] == mask
&&
202 ctx
->Stencil
.Ref
[face
] == ref
)
204 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
205 ctx
->Stencil
.Function
[face
] = func
;
206 ctx
->Stencil
.Ref
[face
] = ref
;
207 ctx
->Stencil
.ValueMask
[face
] = mask
;
209 /* Only propagate the change to the driver if EXT_stencil_two_side
212 if (ctx
->Driver
.StencilFuncSeparate
&& ctx
->Stencil
.TestTwoSide
) {
213 ctx
->Driver
.StencilFuncSeparate(ctx
, GL_BACK
, func
, ref
, mask
);
217 /* set both front and back state */
218 if (ctx
->Stencil
.Function
[0] == func
&&
219 ctx
->Stencil
.Function
[1] == func
&&
220 ctx
->Stencil
.ValueMask
[0] == mask
&&
221 ctx
->Stencil
.ValueMask
[1] == mask
&&
222 ctx
->Stencil
.Ref
[0] == ref
&&
223 ctx
->Stencil
.Ref
[1] == ref
)
225 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
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
),
240 * Set the stencil writing mask.
242 * \param mask bit-mask to enable/disable writing of individual bits in the
245 * \sa glStencilMask().
247 * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and
248 * notifies the driver via the dd_function_table::StencilMask callback.
251 _mesa_StencilMask( GLuint mask
)
253 GET_CURRENT_CONTEXT(ctx
);
254 const GLint face
= ctx
->Stencil
.ActiveFace
;
256 if (MESA_VERBOSE
& VERBOSE_API
)
257 _mesa_debug(ctx
, "glStencilMask()\n");
260 /* Only modify the EXT_stencil_two_side back-face state.
262 if (ctx
->Stencil
.WriteMask
[face
] == mask
)
264 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
265 ctx
->Stencil
.WriteMask
[face
] = mask
;
267 /* Only propagate the change to the driver if EXT_stencil_two_side
270 if (ctx
->Driver
.StencilMaskSeparate
&& ctx
->Stencil
.TestTwoSide
) {
271 ctx
->Driver
.StencilMaskSeparate(ctx
, GL_BACK
, mask
);
275 /* set both front and back state */
276 if (ctx
->Stencil
.WriteMask
[0] == mask
&&
277 ctx
->Stencil
.WriteMask
[1] == mask
)
279 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
280 ctx
->Stencil
.WriteMask
[0] = ctx
->Stencil
.WriteMask
[1] = mask
;
281 if (ctx
->Driver
.StencilMaskSeparate
) {
282 ctx
->Driver
.StencilMaskSeparate(ctx
,
283 ((ctx
->Stencil
.TestTwoSide
)
284 ? GL_FRONT
: GL_FRONT_AND_BACK
),
292 * Set the stencil test actions.
294 * \param fail action to take when stencil test fails.
295 * \param zfail action to take when stencil test passes, but depth test fails.
296 * \param zpass action to take when stencil test passes and the depth test
297 * passes (or depth testing is not enabled).
301 * Verifies the parameters and updates the respective fields in
302 * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
303 * driver via the dd_function_table::StencilOp callback.
306 _mesa_StencilOp(GLenum fail
, GLenum zfail
, GLenum zpass
)
308 GET_CURRENT_CONTEXT(ctx
);
309 const GLint face
= ctx
->Stencil
.ActiveFace
;
311 if (MESA_VERBOSE
& VERBOSE_API
)
312 _mesa_debug(ctx
, "glStencilOp()\n");
314 if (!validate_stencil_op(ctx
, fail
)) {
315 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilOp(sfail)");
318 if (!validate_stencil_op(ctx
, zfail
)) {
319 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilOp(zfail)");
322 if (!validate_stencil_op(ctx
, zpass
)) {
323 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilOp(zpass)");
328 /* only set active face state */
329 if (ctx
->Stencil
.ZFailFunc
[face
] == zfail
&&
330 ctx
->Stencil
.ZPassFunc
[face
] == zpass
&&
331 ctx
->Stencil
.FailFunc
[face
] == fail
)
333 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
334 ctx
->Stencil
.ZFailFunc
[face
] = zfail
;
335 ctx
->Stencil
.ZPassFunc
[face
] = zpass
;
336 ctx
->Stencil
.FailFunc
[face
] = fail
;
338 /* Only propagate the change to the driver if EXT_stencil_two_side
341 if (ctx
->Driver
.StencilOpSeparate
&& ctx
->Stencil
.TestTwoSide
) {
342 ctx
->Driver
.StencilOpSeparate(ctx
, GL_BACK
, fail
, zfail
, zpass
);
346 /* set both front and back state */
347 if (ctx
->Stencil
.ZFailFunc
[0] == zfail
&&
348 ctx
->Stencil
.ZFailFunc
[1] == zfail
&&
349 ctx
->Stencil
.ZPassFunc
[0] == zpass
&&
350 ctx
->Stencil
.ZPassFunc
[1] == zpass
&&
351 ctx
->Stencil
.FailFunc
[0] == fail
&&
352 ctx
->Stencil
.FailFunc
[1] == fail
)
354 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
355 ctx
->Stencil
.ZFailFunc
[0] = ctx
->Stencil
.ZFailFunc
[1] = zfail
;
356 ctx
->Stencil
.ZPassFunc
[0] = ctx
->Stencil
.ZPassFunc
[1] = zpass
;
357 ctx
->Stencil
.FailFunc
[0] = ctx
->Stencil
.FailFunc
[1] = fail
;
358 if (ctx
->Driver
.StencilOpSeparate
) {
359 ctx
->Driver
.StencilOpSeparate(ctx
,
360 ((ctx
->Stencil
.TestTwoSide
)
361 ? GL_FRONT
: GL_FRONT_AND_BACK
),
369 /* GL_EXT_stencil_two_side */
371 _mesa_ActiveStencilFaceEXT(GLenum face
)
373 GET_CURRENT_CONTEXT(ctx
);
375 if (MESA_VERBOSE
& VERBOSE_API
)
376 _mesa_debug(ctx
, "glActiveStencilFaceEXT()\n");
378 if (!ctx
->Extensions
.EXT_stencil_two_side
) {
379 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glActiveStencilFaceEXT");
383 if (face
== GL_FRONT
|| face
== GL_BACK
) {
384 ctx
->Stencil
.ActiveFace
= (face
== GL_FRONT
) ? 0 : 2;
387 _mesa_error(ctx
, GL_INVALID_ENUM
, "glActiveStencilFaceEXT(face)");
394 * OpenGL 2.0 function.
395 * \todo Make StencilOp() call this function. And eventually remove the
396 * ctx->Driver.StencilOp function and use ctx->Driver.StencilOpSeparate
400 _mesa_StencilOpSeparate(GLenum face
, GLenum sfail
, GLenum zfail
, GLenum zpass
)
402 GLboolean set
= GL_FALSE
;
403 GET_CURRENT_CONTEXT(ctx
);
405 if (MESA_VERBOSE
& VERBOSE_API
)
406 _mesa_debug(ctx
, "glStencilOpSeparate()\n");
408 if (!validate_stencil_op(ctx
, sfail
)) {
409 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilOpSeparate(sfail)");
412 if (!validate_stencil_op(ctx
, zfail
)) {
413 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilOpSeparate(zfail)");
416 if (!validate_stencil_op(ctx
, zpass
)) {
417 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilOpSeparate(zpass)");
420 if (face
!= GL_FRONT
&& face
!= GL_BACK
&& face
!= GL_FRONT_AND_BACK
) {
421 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilOpSeparate(face)");
425 if (face
!= GL_BACK
) {
427 if (ctx
->Stencil
.ZFailFunc
[0] != zfail
||
428 ctx
->Stencil
.ZPassFunc
[0] != zpass
||
429 ctx
->Stencil
.FailFunc
[0] != sfail
){
430 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
431 ctx
->Stencil
.ZFailFunc
[0] = zfail
;
432 ctx
->Stencil
.ZPassFunc
[0] = zpass
;
433 ctx
->Stencil
.FailFunc
[0] = sfail
;
437 if (face
!= GL_FRONT
) {
439 if (ctx
->Stencil
.ZFailFunc
[1] != zfail
||
440 ctx
->Stencil
.ZPassFunc
[1] != zpass
||
441 ctx
->Stencil
.FailFunc
[1] != sfail
) {
442 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
443 ctx
->Stencil
.ZFailFunc
[1] = zfail
;
444 ctx
->Stencil
.ZPassFunc
[1] = zpass
;
445 ctx
->Stencil
.FailFunc
[1] = sfail
;
449 if (set
&& ctx
->Driver
.StencilOpSeparate
) {
450 ctx
->Driver
.StencilOpSeparate(ctx
, face
, sfail
, zfail
, zpass
);
457 _mesa_StencilFuncSeparate(GLenum face
, GLenum func
, GLint ref
, GLuint mask
)
459 GET_CURRENT_CONTEXT(ctx
);
461 if (MESA_VERBOSE
& VERBOSE_API
)
462 _mesa_debug(ctx
, "glStencilFuncSeparate()\n");
464 if (face
!= GL_FRONT
&& face
!= GL_BACK
&& face
!= GL_FRONT_AND_BACK
) {
465 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilFuncSeparate(face)");
468 if (!validate_stencil_func(ctx
, func
)) {
469 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilFuncSeparate(func)");
473 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
475 if (face
!= GL_BACK
) {
477 ctx
->Stencil
.Function
[0] = func
;
478 ctx
->Stencil
.Ref
[0] = ref
;
479 ctx
->Stencil
.ValueMask
[0] = mask
;
481 if (face
!= GL_FRONT
) {
483 ctx
->Stencil
.Function
[1] = func
;
484 ctx
->Stencil
.Ref
[1] = ref
;
485 ctx
->Stencil
.ValueMask
[1] = mask
;
487 if (ctx
->Driver
.StencilFuncSeparate
) {
488 ctx
->Driver
.StencilFuncSeparate(ctx
, face
, func
, ref
, mask
);
495 _mesa_StencilMaskSeparate(GLenum face
, GLuint mask
)
497 GET_CURRENT_CONTEXT(ctx
);
499 if (MESA_VERBOSE
& VERBOSE_API
)
500 _mesa_debug(ctx
, "glStencilMaskSeparate()\n");
502 if (face
!= GL_FRONT
&& face
!= GL_BACK
&& face
!= GL_FRONT_AND_BACK
) {
503 _mesa_error(ctx
, GL_INVALID_ENUM
, "glStencilaMaskSeparate(face)");
507 FLUSH_VERTICES(ctx
, _NEW_STENCIL
);
509 if (face
!= GL_BACK
) {
510 ctx
->Stencil
.WriteMask
[0] = mask
;
512 if (face
!= GL_FRONT
) {
513 ctx
->Stencil
.WriteMask
[1] = mask
;
515 if (ctx
->Driver
.StencilMaskSeparate
) {
516 ctx
->Driver
.StencilMaskSeparate(ctx
, face
, mask
);
522 * Update derived stencil state.
525 _mesa_update_stencil(struct gl_context
*ctx
)
527 const GLint face
= ctx
->Stencil
._BackFace
;
529 ctx
->Stencil
._Enabled
= (ctx
->Stencil
.Enabled
&&
530 ctx
->DrawBuffer
->Visual
.stencilBits
> 0);
532 ctx
->Stencil
._TestTwoSide
=
533 ctx
->Stencil
._Enabled
&&
534 (ctx
->Stencil
.Function
[0] != ctx
->Stencil
.Function
[face
] ||
535 ctx
->Stencil
.FailFunc
[0] != ctx
->Stencil
.FailFunc
[face
] ||
536 ctx
->Stencil
.ZPassFunc
[0] != ctx
->Stencil
.ZPassFunc
[face
] ||
537 ctx
->Stencil
.ZFailFunc
[0] != ctx
->Stencil
.ZFailFunc
[face
] ||
538 ctx
->Stencil
.Ref
[0] != ctx
->Stencil
.Ref
[face
] ||
539 ctx
->Stencil
.ValueMask
[0] != ctx
->Stencil
.ValueMask
[face
] ||
540 ctx
->Stencil
.WriteMask
[0] != ctx
->Stencil
.WriteMask
[face
]);
542 ctx
->Stencil
._WriteEnabled
=
543 ctx
->Stencil
._Enabled
&&
544 (ctx
->Stencil
.WriteMask
[0] != 0 ||
545 (ctx
->Stencil
._TestTwoSide
&& ctx
->Stencil
.WriteMask
[face
] != 0));
550 * Initialize the context stipple state.
552 * \param ctx GL context.
554 * Initializes __struct gl_contextRec::Stencil attribute group.
557 _mesa_init_stencil(struct gl_context
*ctx
)
559 ctx
->Stencil
.Enabled
= GL_FALSE
;
560 ctx
->Stencil
.TestTwoSide
= GL_FALSE
;
561 ctx
->Stencil
.ActiveFace
= 0; /* 0 = GL_FRONT, 2 = GL_BACK */
562 ctx
->Stencil
.Function
[0] = GL_ALWAYS
;
563 ctx
->Stencil
.Function
[1] = GL_ALWAYS
;
564 ctx
->Stencil
.Function
[2] = GL_ALWAYS
;
565 ctx
->Stencil
.FailFunc
[0] = GL_KEEP
;
566 ctx
->Stencil
.FailFunc
[1] = GL_KEEP
;
567 ctx
->Stencil
.FailFunc
[2] = GL_KEEP
;
568 ctx
->Stencil
.ZPassFunc
[0] = GL_KEEP
;
569 ctx
->Stencil
.ZPassFunc
[1] = GL_KEEP
;
570 ctx
->Stencil
.ZPassFunc
[2] = GL_KEEP
;
571 ctx
->Stencil
.ZFailFunc
[0] = GL_KEEP
;
572 ctx
->Stencil
.ZFailFunc
[1] = GL_KEEP
;
573 ctx
->Stencil
.ZFailFunc
[2] = GL_KEEP
;
574 ctx
->Stencil
.Ref
[0] = 0;
575 ctx
->Stencil
.Ref
[1] = 0;
576 ctx
->Stencil
.Ref
[2] = 0;
577 ctx
->Stencil
.ValueMask
[0] = ~0U;
578 ctx
->Stencil
.ValueMask
[1] = ~0U;
579 ctx
->Stencil
.ValueMask
[2] = ~0U;
580 ctx
->Stencil
.WriteMask
[0] = ~0U;
581 ctx
->Stencil
.WriteMask
[1] = ~0U;
582 ctx
->Stencil
.WriteMask
[2] = ~0U;
583 ctx
->Stencil
.Clear
= 0;
584 ctx
->Stencil
._BackFace
= 1;