2 * BEGIN_COPYRIGHT -*- glean -*-
4 * Copyright (C) 1999 Allen Akin All Rights Reserved.
5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
6 * Copyright (C) 2015 Intel Corporation All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
30 /** @file two-sided-stencil.c
32 * Test two-sided stencil extensions
34 * This test could be better:
35 * 1. Generate random state vectors, render and compare to expected values
36 * 2. Exercise separate front/back reference values and masks for the
37 * EXT and GL2 variations.
39 * Note: Must check writeMask of set_stencil_state to make sure it's correct
42 * Brian Paul <brianp@valinux.com>
43 * Adapted to Piglit by Juliet Fru <julietfru@gmail.com>, September 2015.
46 #include "piglit-util-gl.h"
52 PIGLIT_GL_TEST_CONFIG_BEGIN config
.supports_gl_compat_version
= 20;
54 config
.window_visual
=
55 PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DEPTH
|
56 PIGLIT_GL_VISUAL_STENCIL
;
57 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
59 PIGLIT_GL_TEST_CONFIG_END
61 /* two-sided methods. */
66 GLint stencil_bits
, stencil_max
;
70 have_stencil_wrap(void)
72 if (piglit_get_gl_version() >= 2.0) {
74 } else if (piglit_is_extension_supported("GL_EXT_stencil_wrap")) {
82 * Bottom row uses GL_CCW
84 * Left column is front-facing
85 * Right column is back-facing
86 * Check the values in the stencil buffer to see if they match
87 * the expected values.
90 render_test(GLuint expectedFront
, GLuint expectedBack
)
93 GLint x1
= piglit_width
/ 2;
94 GLint x2
= piglit_width
;
96 GLint y1
= piglit_width
/ 2;
97 GLint y2
= piglit_width
;
99 glFrontFace(GL_CCW
); /* this the GL default */
101 /* lower left quad = front-facing */
102 glBegin(GL_TRIANGLE_FAN
);
109 /* lower right quad = back-facing */
110 glBegin(GL_TRIANGLE_FAN
);
119 /* upper left quad = front-facing */
120 glBegin(GL_TRIANGLE_FAN
);
127 /* upper right quad = back-facing */
128 glBegin(GL_TRIANGLE_FAN
);
135 GLint midXleft
= (x0
+ x1
) / 2;
136 GLint midXright
= (x1
+ x2
) / 2;
137 GLint midYlower
= (y0
+ y1
) / 2;
138 GLint midYupper
= (y1
+ y2
) / 2;
139 GLuint lowerLeftVal
, lowerRightVal
;
140 GLuint upperLeftVal
, upperRightVal
;
142 glReadPixels(midXleft
, midYlower
, 1, 1,
143 GL_STENCIL_INDEX
, GL_UNSIGNED_INT
, &lowerLeftVal
);
144 glReadPixels(midXright
, midYlower
, 1, 1,
145 GL_STENCIL_INDEX
, GL_UNSIGNED_INT
, &lowerRightVal
);
147 glReadPixels(midXleft
, midYupper
, 1, 1,
148 GL_STENCIL_INDEX
, GL_UNSIGNED_INT
, &upperLeftVal
);
149 glReadPixels(midXright
, midYupper
, 1, 1,
150 GL_STENCIL_INDEX
, GL_UNSIGNED_INT
, &upperRightVal
);
152 if (lowerLeftVal
!= upperLeftVal
) {
154 "\tLower-left value (%d) doesn't match upper-left "
155 "value (%d).\n \t Looks like a front/back "
156 "orientation bug.\n", lowerLeftVal
, upperLeftVal
);
160 if (lowerRightVal
!= upperRightVal
) {
161 printf(" FAIL:\n\tLower-right value (%d) doesn't match"
162 " upper-right value (%d).\n\tLooks like "
163 "a front/back-face orientation bug.\n", lowerRightVal
,
169 if (lowerLeftVal
!= expectedFront
) {
170 printf("FAIL:\n\tExpected front-face stencil value is "
171 "%d but found %d \n", expectedFront
, lowerLeftVal
);
173 } else if (lowerRightVal
!= expectedBack
) {
174 printf("FAIL:\n\tExpected back-face stencil value is "
175 "%d but found %d \n", expectedBack
, lowerRightVal
);
184 compare_state(int method
, GLenum found
, GLenum expected
, const char *msg
)
186 if (found
!= expected
) {
187 printf(" FAIL:\n\tQuery of %s state failed for ", msg
);
190 printf("GL_ATI_separate_stencil\n");
193 printf("GL_EXT_stencil_two_side\n");
196 printf("GL 2.x two-sided stencil\n");
203 printf("\tFound 0x%x, expected 0x%x\n", found
, expected
);
210 /* Set stencil state, plus read it back and check that it's correct.
211 * Note: we only test with one reference value and one mask value
212 * even though EXT and GL2 support separate front/back refs/masks
215 set_stencil_state(int method
,
216 GLenum frontStencilFail
,
217 GLenum backStencilFail
,
228 GLuint frontWriteMask
, GLuint backWriteMask
)
230 GLint get_frontStencilFail
;
231 GLint get_backStencilFail
;
232 GLint get_frontZFail
;
234 GLint get_frontZPass
;
242 GLint get_frontWriteMask
;
243 GLint get_backWriteMask
;
248 assert(frontRef
== backRef
);
249 assert(frontMask
== backMask
);
250 assert(frontWriteMask
== backWriteMask
);
253 glStencilOpSeparateATI(GL_FRONT
,
255 frontZFail
, frontZPass
);
257 glStencilOpSeparateATI(GL_BACK
,
258 backStencilFail
, backZFail
, backZPass
);
260 glStencilFuncSeparateATI(frontFunc
, backFunc
, frontRef
,
263 glStencilMask(frontWriteMask
);
266 glGetIntegerv(GL_STENCIL_FAIL
, &get_frontStencilFail
);
267 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL
, &get_frontZFail
);
268 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS
, &get_frontZPass
);
269 glGetIntegerv(GL_STENCIL_FUNC
, &get_frontFunc
);
270 glGetIntegerv(GL_STENCIL_REF
, &get_frontRef
);
271 glGetIntegerv(GL_STENCIL_VALUE_MASK
, &get_frontMask
);
272 glGetIntegerv(GL_STENCIL_WRITEMASK
, &get_frontWriteMask
);
274 glGetIntegerv(GL_STENCIL_BACK_FUNC_ATI
, &get_backFunc
);
275 glGetIntegerv(GL_STENCIL_BACK_FAIL_ATI
, &get_backStencilFail
);
276 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI
,
278 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI
,
280 get_backRef
= get_frontRef
;
281 get_backMask
= get_frontMask
;
282 get_backWriteMask
= get_frontWriteMask
;
283 twoEnabled
= GL_TRUE
;
288 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
290 glActiveStencilFaceEXT(GL_FRONT
);
291 glStencilOp(frontStencilFail
, frontZFail
, frontZPass
);
292 glStencilFunc(frontFunc
, frontRef
, frontMask
);
293 glStencilMask(frontWriteMask
);
295 glActiveStencilFaceEXT(GL_BACK
);
296 glStencilOp(backStencilFail
, backZFail
, backZPass
);
297 glStencilFunc(backFunc
, backRef
, backMask
);
298 glStencilMask(backWriteMask
);
301 glActiveStencilFaceEXT(GL_FRONT
);
302 glGetIntegerv(GL_STENCIL_FAIL
, &get_frontStencilFail
);
303 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL
, &get_frontZFail
);
304 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS
, &get_frontZPass
);
305 glGetIntegerv(GL_STENCIL_FUNC
, &get_frontFunc
);
306 glGetIntegerv(GL_STENCIL_REF
, &get_frontRef
);
307 glGetIntegerv(GL_STENCIL_VALUE_MASK
, &get_frontMask
);
308 glGetIntegerv(GL_STENCIL_WRITEMASK
, &get_frontWriteMask
);
309 glActiveStencilFaceEXT(GL_BACK
);
310 glGetIntegerv(GL_STENCIL_FAIL
, &get_backStencilFail
);
311 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL
, &get_backZFail
);
312 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS
, &get_backZPass
);
313 glGetIntegerv(GL_STENCIL_FUNC
, &get_backFunc
);
314 glGetIntegerv(GL_STENCIL_REF
, &get_backRef
);
315 glGetIntegerv(GL_STENCIL_VALUE_MASK
, &get_backMask
);
316 glGetIntegerv(GL_STENCIL_WRITEMASK
, &get_backWriteMask
);
317 glGetIntegerv(GL_STENCIL_TEST_TWO_SIDE_EXT
, &twoEnabled
);
322 glStencilOpSeparate(GL_FRONT
,
323 frontStencilFail
, frontZFail
, frontZPass
);
324 glStencilOpSeparate(GL_BACK
,
325 backStencilFail
, backZFail
, backZPass
);
326 glStencilFuncSeparate(GL_FRONT
, frontFunc
, frontRef
,
328 glStencilFuncSeparate(GL_BACK
, backFunc
, backRef
, backMask
);
329 glStencilMaskSeparate(GL_FRONT
, frontWriteMask
);
330 glStencilMaskSeparate(GL_BACK
, backWriteMask
);
333 glGetIntegerv(GL_STENCIL_FAIL
, &get_frontStencilFail
);
334 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL
, &get_frontZFail
);
335 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS
, &get_frontZPass
);
336 glGetIntegerv(GL_STENCIL_FUNC
, &get_frontFunc
);
337 glGetIntegerv(GL_STENCIL_REF
, &get_frontRef
);
338 glGetIntegerv(GL_STENCIL_VALUE_MASK
, &get_frontMask
);
339 glGetIntegerv(GL_STENCIL_WRITEMASK
, &get_frontWriteMask
);
341 glGetIntegerv(GL_STENCIL_BACK_FUNC
, &get_backFunc
);
342 glGetIntegerv(GL_STENCIL_BACK_FAIL
, &get_backStencilFail
);
343 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL
,
345 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS
,
347 glGetIntegerv(GL_STENCIL_BACK_REF
, &get_backRef
);
348 glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK
, &get_backMask
);
349 glGetIntegerv(GL_STENCIL_BACK_WRITEMASK
, &get_backWriteMask
);
350 twoEnabled
= GL_TRUE
;
357 /* mask off bits we don't care about */
358 get_frontMask
&= stencil_max
;
359 frontMask
&= stencil_max
;
360 get_backMask
&= stencil_max
;
361 backMask
&= stencil_max
;
362 get_frontWriteMask
&= stencil_max
;
363 frontWriteMask
&= stencil_max
;
364 get_backWriteMask
&= stencil_max
;
365 backWriteMask
&= stencil_max
;
368 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
372 /* see if state-get matches state-set */
374 if (!compare_state(method
, get_frontStencilFail
, frontStencilFail
,
375 "front stencil fail"))
378 if (!compare_state(method
, get_backStencilFail
, backStencilFail
,
379 "back stencil fail"))
382 if (!compare_state(method
, get_frontZFail
, frontZFail
,
386 if (!compare_state(method
, get_backZFail
, backZFail
, "back Z fail"))
389 if (!compare_state(method
, get_frontZPass
, frontZPass
,
393 if (!compare_state(method
, get_backZPass
, backZPass
, "back Z pass"))
396 if (!compare_state(method
, get_frontFunc
, frontFunc
,
397 "front stencil func"))
400 if (!compare_state(method
, get_backFunc
, backFunc
,
401 "back stencil func"))
404 if (!compare_state(method
, get_frontRef
, frontRef
,
405 "front stencil ref"))
408 if (!compare_state(method
, get_backRef
, backRef
, "back stencil ref"))
411 if (!compare_state(method
, get_frontMask
, frontMask
,
412 "front stencil mask"))
415 if (!compare_state(method
, get_backMask
, backMask
,
416 "back stencil mask"))
419 if (!compare_state(method
, get_frontWriteMask
, frontWriteMask
,
420 "front stencil writemask"))
423 if (!compare_state(method
, get_backWriteMask
, backWriteMask
,
424 "back stencil writemask"))
427 if (!compare_state(method
, twoEnabled
, GL_TRUE
, "two-side enable"))
435 set_stencil_state2(int method
,
436 GLenum frontStencilFail
,
437 GLenum backStencilFail
,
448 return set_stencil_state(method
, frontStencilFail
,
449 backStencilFail
, frontZFail
, backZFail
,
450 frontZPass
, backZPass
, frontFunc
, backFunc
,
453 mask
, /* frontMask */
455 writeMask
, /* frontWriteMask */
456 writeMask
); /* backWriteMask */
461 reset_stencil_state(int method
)
467 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
468 glActiveStencilFaceEXT(GL_FRONT
);
479 test_stencil(int method
)
483 glEnable(GL_STENCIL_TEST
);
488 glDisable(GL_DEPTH_TEST
);
490 glClear(GL_COLOR_BUFFER_BIT
|
491 GL_STENCIL_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
494 /* set stencil buffer vals to 5 */
495 pass
= set_stencil_state2(method
, GL_KEEP
, GL_KEEP
, /* stencil fail */
496 GL_KEEP
, GL_KEEP
, /* z fail */
497 GL_REPLACE
, GL_REPLACE
, /* z pass */
498 GL_ALWAYS
, GL_ALWAYS
, /* stencil func */
499 5, ~0, ~0); /* ref, mask, set write_mask to ~0 */
501 pass
= render_test(5, 5);
502 reset_stencil_state(method
);
506 /* incr front val to 6, decr back val to 4 */
507 pass
= set_stencil_state2(method
, GL_KEEP
, GL_KEEP
, /* stencil fail */
508 GL_KEEP
, GL_KEEP
, /* z fail */
509 GL_INCR
, GL_DECR
, /* z pass */
510 GL_ALWAYS
, GL_ALWAYS
, /* stencil func */
511 5, ~0, ~0); /* ref, mask, set write_mask to ~0 */
513 pass
= render_test(6, 4);
514 reset_stencil_state(method
);
519 * if back<6, replace with zero
520 * final: front=6, back=0
522 pass
= set_stencil_state2(method
, GL_KEEP
, GL_ZERO
, /* stencil fail */
523 GL_KEEP
, GL_KEEP
, /* z fail */
524 GL_KEEP
, GL_KEEP
, /* z pass */
525 GL_EQUAL
, GL_LESS
, /* stencil func */
526 6, ~0, ~0); /* ref, mask, set write_mask to ~0 */
528 pass
= render_test(6, 0);
529 reset_stencil_state(method
);
533 /* if front!=10, keep, else decr
534 * if back<10, keep, else incr
535 * final: front=6, back=1
537 pass
= set_stencil_state2(method
, GL_DECR
, GL_INCR
, /* stencil fail */
538 GL_KEEP
, GL_KEEP
, /* z fail */
539 GL_KEEP
, GL_KEEP
, /* z pass */
540 GL_NOTEQUAL
, GL_LESS
, /* stencil func */
541 10, ~0, ~0); /* ref, mask, set write_mask to ~0 */
543 pass
= render_test(6, 1);
544 reset_stencil_state(method
);
549 /* if front!=10, keep, else decr
550 * if back<10, keep, else incr
551 * final: front=6, back=1
553 pass
= set_stencil_state(method
, GL_DECR
, GL_INCR
, /* stencil fail */
554 GL_KEEP
, GL_KEEP
, /* z fail */
555 GL_REPLACE
, GL_REPLACE
, /* z pass */
556 GL_ALWAYS
, GL_ALWAYS
, /* stencil func */
557 0xf6, 0xf1, /* ref */
558 0xff, 0xff, /* mask */
559 0x60, 0x10); /* writeMask */
561 pass
= render_test(0x66, 0x11);
562 reset_stencil_state(method
);
567 /* reset write mask for clear */
568 set_stencil_state(method
, GL_KEEP
, GL_KEEP
, /* stencil fail */
569 GL_KEEP
, GL_KEEP
, /* z fail */
570 GL_REPLACE
, GL_REPLACE
, /* z pass */
571 GL_ALWAYS
, GL_ALWAYS
, /* stencil func */
572 0, 0, ~0, ~0, ~0, ~0);
574 /* ============================================================
575 * Now begin tests with depth test
577 glEnable(GL_DEPTH_TEST
);
578 glDepthFunc(GL_LESS
);
580 glClear(GL_COLOR_BUFFER_BIT
|
581 GL_STENCIL_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
583 /* set stencil buffer vals to 7, set Z values */
584 pass
= set_stencil_state2(method
, GL_KEEP
, GL_KEEP
, /* stencil fail */
585 GL_KEEP
, GL_KEEP
, /* z fail */
586 GL_REPLACE
, GL_REPLACE
, /* z pass */
587 GL_ALWAYS
, GL_ALWAYS
, /* stencil func */
588 7, ~0, ~0); /* ref, mask, set write_mask to ~0 */
590 pass
= render_test(7, 7);
591 reset_stencil_state(method
);
596 /* GL_LESS test should fail everywhere
597 * decr front to 5, incr back to 2
599 pass
= set_stencil_state2(method
, GL_KEEP
, GL_KEEP
, /* stencil fail */
600 GL_DECR
, GL_INCR
, /* z fail */
601 GL_KEEP
, GL_KEEP
, /* z pass */
602 GL_ALWAYS
, GL_ALWAYS
, /* stencil func */
603 99, ~0, ~0); /* ref, mask, set write_mask to ~0 */
605 pass
= render_test(6, 8);
606 reset_stencil_state(method
);
611 /* set depth test = GL_EQUAL
612 * Z test should pass everywhere
616 glDepthFunc(GL_EQUAL
);
617 pass
= set_stencil_state2(method
, GL_KEEP
, GL_KEEP
, /* stencil fail */
618 GL_KEEP
, GL_KEEP
, /* z fail */
619 GL_REPLACE
, GL_DECR
, /* z pass */
620 GL_ALWAYS
, GL_ALWAYS
, /* stencil func */
621 3, ~0, ~0); /* ref, mask, set write_mask to ~0 */
623 pass
= render_test(3, 7);
624 reset_stencil_state(method
);
629 /* incr front to 4 (by z pass), decr back to 6 (by stencil fail) */
630 pass
= set_stencil_state2(method
, GL_DECR
, GL_DECR
, /* stencil fail */
631 GL_KEEP
, GL_KEEP
, /* z fail */
632 GL_INCR
, GL_REPLACE
, /* z pass */
633 GL_EQUAL
, GL_EQUAL
, /* stencil func */
634 3, ~0, ~0); /* ref, mask, set write_mask to ~0 */
636 pass
= render_test(4, 6);
637 reset_stencil_state(method
);
642 /* ============================================================
645 glDisable(GL_DEPTH_TEST
);
647 /* test stencil value mask
648 * only test bit 1 in stencil values
649 * if !(front&0x2 == 15&0x2), decr to 3 (should happen)
650 * if !(back&0x2 == 15&0x2), incr to 7 (should not happen)
652 pass
= set_stencil_state2(method
, GL_DECR
, GL_INCR
, /* stencil fail */
653 GL_KEEP
, GL_KEEP
, /* z fail */
654 GL_KEEP
, GL_KEEP
, /* z pass */
655 GL_EQUAL
, GL_EQUAL
, /* stencil func */
656 15, 0x2, ~0); /* ref, mask, set write_mask to ~0 */
658 pass
= render_test(3, 6);
659 reset_stencil_state(method
);
663 /* ============================================================
664 * Test common two-sided stencil modes for shadow volume rendering
665 * Requires stencil /- wrap feature.
668 if (!have_stencil_wrap())
671 glClear(GL_COLOR_BUFFER_BIT
|
672 GL_STENCIL_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
674 glEnable(GL_DEPTH_TEST
);
675 glDepthFunc(GL_LESS
);
677 /* "traditional / Z-pass" method:
678 * front face: incr on zpass
679 * back face: decr on zpass
680 * both front and back Z-test should pass here
682 pass
= set_stencil_state2(method
, GL_KEEP
, GL_KEEP
, /* stencil fail */
683 GL_KEEP
, GL_KEEP
, /* z fail */
684 GL_INCR_WRAP_EXT
, GL_DECR_WRAP_EXT
, /* z pass */
685 GL_ALWAYS
, GL_ALWAYS
, /* stencil func */
686 0, ~0, ~0); /* ref, mask, set write_mask to ~0 */
688 pass
= render_test(1, stencil_max
);
689 reset_stencil_state(method
);
695 * front face: decr on zfail
696 * back face: incr on zfail
697 * both front and back Z-test should fail here
699 pass
= set_stencil_state2(method
, GL_KEEP
, GL_KEEP
, /* stencil fail */
700 GL_DECR_WRAP_EXT
, GL_INCR_WRAP_EXT
, /* z fail */
701 GL_KEEP
, GL_KEEP
, /* z pass */
702 GL_ALWAYS
, GL_ALWAYS
, /* stencil func */
703 0, ~0, ~0); /* ref, mask, set write_mask to ~0 */
705 pass
= render_test(0, 0);
706 reset_stencil_state(method
);
716 piglit_init(int argc
, char **argv
)
718 /* no initialization */
727 /* how many stencil bits (we assume at least 8 above) */
728 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
729 stencil_max
= (1 << stencil_bits
) - 1;
730 assert(stencil_bits
>= 8);
732 glViewport(0, 0, piglit_width
, piglit_width
);
733 glMatrixMode(GL_PROJECTION
);
735 glOrtho(0, piglit_width
, 0, piglit_width
, -1, 1);
736 glMatrixMode(GL_MODELVIEW
);
739 if (piglit_is_extension_supported("GL_ATI_separate_stencil")) {
740 pass
= test_stencil(ATI
) && pass
;
743 if (piglit_is_extension_supported("GL_EXT_stencil_two_side")) {
744 pass
= test_stencil(EXT
) && pass
;
747 if (piglit_get_gl_version() >= 2.0) {
748 pass
= test_stencil(GL2
) && pass
;
751 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;