1 /*
2  * BEGIN_COPYRIGHT -*- glean -*-
3  *
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.
7  *
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:
14  *
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
17  * Software.
18  *
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.
26  *
27  * END_COPYRIGHT
28  */
29 
30 /** @file two-sided-stencil.c
31  *
32  *  Test two-sided stencil extensions
33  *
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.
38  *
39  * 	Note: Must check writeMask of set_stencil_state to make sure it's correct
40  *
41  *   	Authors:
42  *     	Brian Paul <brianp@valinux.com>
43  *     	Adapted to Piglit by Juliet Fru <julietfru@gmail.com>, September 2015.
44  */
45 
46 #include "piglit-util-gl.h"
47 
48 #include <assert.h>
49 #include <string.h>
50 
51 
52 PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_compat_version = 20;
53 
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;
58 
59 PIGLIT_GL_TEST_CONFIG_END
60 
61 /*  two-sided methods. */
62 #define ATI 1
63 #define EXT 2
64 #define GL2 3
65 
66 GLint stencil_bits, stencil_max;
67 
68 
69 static bool
have_stencil_wrap(void)70 have_stencil_wrap(void)
71 {
72 	if (piglit_get_gl_version() >= 2.0) {
73 		return true;
74 	} else if (piglit_is_extension_supported("GL_EXT_stencil_wrap")) {
75 		return true;
76 	}
77 	return false;
78 }
79 
80 
81 /* Draw four quads:
82  * Bottom row uses GL_CCW
83  * Top row uses GL_CW
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.
88  */
89 static bool
render_test(GLuint expectedFront,GLuint expectedBack)90 render_test(GLuint expectedFront, GLuint expectedBack)
91 {
92 	GLint x0 = 0;
93 	GLint x1 = piglit_width / 2;
94 	GLint x2 = piglit_width;
95 	GLint y0 = 0;
96 	GLint y1 = piglit_width / 2;
97 	GLint y2 = piglit_width;
98 
99 	glFrontFace(GL_CCW);	/* this the GL default */
100 
101 	/* lower left quad = front-facing */
102 	glBegin(GL_TRIANGLE_FAN);
103 	glVertex2f(x0, y0);
104 	glVertex2f(x1, y0);
105 	glVertex2f(x1, y1);
106 	glVertex2f(x0, y1);
107 	glEnd();
108 
109 	/* lower right quad = back-facing */
110 	glBegin(GL_TRIANGLE_FAN);
111 	glVertex2f(x1, y0);
112 	glVertex2f(x1, y1);
113 	glVertex2f(x2, y1);
114 	glVertex2f(x2, y0);
115 	glEnd();
116 
117 	glFrontFace(GL_CW);
118 
119 	/* upper left quad = front-facing */
120 	glBegin(GL_TRIANGLE_FAN);
121 	glVertex2f(x0, y1);
122 	glVertex2f(x0, y2);
123 	glVertex2f(x1, y2);
124 	glVertex2f(x1, y1);
125 	glEnd();
126 
127 	/* upper right quad = back-facing */
128 	glBegin(GL_TRIANGLE_FAN);
129 	glVertex2f(x1, y1);
130 	glVertex2f(x2, y1);
131 	glVertex2f(x2, y2);
132 	glVertex2f(x1, y2);
133 	glEnd();
134 
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;
141 
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);
146 
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);
151 
152 	if (lowerLeftVal != upperLeftVal) {
153 		printf(" FAIL:\n"
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);
157 		return false;
158 	}
159 
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,
164 		       upperRightVal);
165 		return false;
166 	}
167 
168 
169 	if (lowerLeftVal != expectedFront) {
170 		printf("FAIL:\n\tExpected front-face stencil value is "
171 		       "%d but found %d \n", expectedFront, lowerLeftVal);
172 		return false;
173 	} else if (lowerRightVal != expectedBack) {
174 		printf("FAIL:\n\tExpected back-face stencil value is "
175 		       "%d but found %d \n", expectedBack, lowerRightVal);
176 		return false;
177 	} else {
178 		return true;
179 	}
180 }
181 
182 
183 static bool
compare_state(int method,GLenum found,GLenum expected,const char * msg)184 compare_state(int method, GLenum found, GLenum expected, const char *msg)
185 {
186 	if (found != expected) {
187 		printf(" FAIL:\n\tQuery of %s state failed for ", msg);
188 		switch (method) {
189 		case ATI:
190 			printf("GL_ATI_separate_stencil\n");
191 			break;
192 		case EXT:
193 			printf("GL_EXT_stencil_two_side\n");
194 			break;
195 		case GL2:
196 			printf("GL 2.x two-sided stencil\n");
197 			break;
198 		default:
199 			printf("\n");
200 			assert(0);
201 		}
202 
203 		printf("\tFound 0x%x, expected 0x%x\n", found, expected);
204 		return false;
205 	}
206 	return true;
207 }
208 
209 
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
213  */
214 static bool
set_stencil_state(int method,GLenum frontStencilFail,GLenum backStencilFail,GLenum frontZFail,GLenum backZFail,GLenum frontZPass,GLenum backZPass,GLenum frontFunc,GLenum backFunc,GLint frontRef,GLint backRef,GLuint frontMask,GLuint backMask,GLuint frontWriteMask,GLuint backWriteMask)215 set_stencil_state(int method,
216 		  GLenum frontStencilFail,
217 		  GLenum backStencilFail,
218 		  GLenum frontZFail,
219 		  GLenum backZFail,
220 		  GLenum frontZPass,
221 		  GLenum backZPass,
222 		  GLenum frontFunc,
223 		  GLenum backFunc,
224 		  GLint frontRef,
225 		  GLint backRef,
226 		  GLuint frontMask,
227 		  GLuint backMask,
228 		  GLuint frontWriteMask, GLuint backWriteMask)
229 {
230 	GLint get_frontStencilFail;
231 	GLint get_backStencilFail;
232 	GLint get_frontZFail;
233 	GLint get_backZFail;
234 	GLint get_frontZPass;
235 	GLint get_backZPass;
236 	GLint get_frontFunc;
237 	GLint get_backFunc;
238 	GLint get_frontRef;
239 	GLint get_backRef;
240 	GLint get_frontMask;
241 	GLint get_backMask;
242 	GLint get_frontWriteMask;
243 	GLint get_backWriteMask;
244 	GLint twoEnabled;
245 
246 	switch (method) {
247 	case ATI:
248 		assert(frontRef == backRef);
249 		assert(frontMask == backMask);
250 		assert(frontWriteMask == backWriteMask);
251 
252 		/* set state */
253 		glStencilOpSeparateATI(GL_FRONT,
254 				       frontStencilFail,
255 				       frontZFail, frontZPass);
256 
257 		glStencilOpSeparateATI(GL_BACK,
258 				       backStencilFail, backZFail, backZPass);
259 
260 		glStencilFuncSeparateATI(frontFunc, backFunc, frontRef,
261 					 frontMask);
262 
263 		glStencilMask(frontWriteMask);
264 
265 		/* get state */
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);
273 
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,
277 			      &get_backZFail);
278 		glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI,
279 			      &get_backZPass);
280 		get_backRef = get_frontRef;
281 		get_backMask = get_frontMask;
282 		get_backWriteMask = get_frontWriteMask;
283 		twoEnabled = GL_TRUE;
284 		break;
285 
286 	case EXT:
287 		/* set state */
288 		glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
289 
290 		glActiveStencilFaceEXT(GL_FRONT);
291 		glStencilOp(frontStencilFail, frontZFail, frontZPass);
292 		glStencilFunc(frontFunc, frontRef, frontMask);
293 		glStencilMask(frontWriteMask);
294 
295 		glActiveStencilFaceEXT(GL_BACK);
296 		glStencilOp(backStencilFail, backZFail, backZPass);
297 		glStencilFunc(backFunc, backRef, backMask);
298 		glStencilMask(backWriteMask);
299 
300 		/* get state */
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);
318 		break;
319 
320 	case GL2:
321 		/* set state */
322 		glStencilOpSeparate(GL_FRONT,
323 				    frontStencilFail, frontZFail, frontZPass);
324 		glStencilOpSeparate(GL_BACK,
325 				    backStencilFail, backZFail, backZPass);
326 		glStencilFuncSeparate(GL_FRONT, frontFunc, frontRef,
327 				      frontMask);
328 		glStencilFuncSeparate(GL_BACK, backFunc, backRef, backMask);
329 		glStencilMaskSeparate(GL_FRONT, frontWriteMask);
330 		glStencilMaskSeparate(GL_BACK, backWriteMask);
331 
332 		/* get state */
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);
340 
341 		glGetIntegerv(GL_STENCIL_BACK_FUNC, &get_backFunc);
342 		glGetIntegerv(GL_STENCIL_BACK_FAIL, &get_backStencilFail);
343 		glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL,
344 			      &get_backZFail);
345 		glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS,
346 			      &get_backZPass);
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;
351 		break;
352 
353 	default:
354 		assert(0);
355 	}
356 
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;
366 
367 
368 	if (!piglit_check_gl_error(GL_NO_ERROR)) {
369 		return false;
370 	}
371 
372 	/* see if state-get matches state-set */
373 
374 	if (!compare_state(method, get_frontStencilFail, frontStencilFail,
375 			   "front stencil fail"))
376 		return false;
377 
378 	if (!compare_state(method, get_backStencilFail, backStencilFail,
379 			   "back stencil fail"))
380 		return false;
381 
382 	if (!compare_state(method, get_frontZFail, frontZFail,
383 			   "front Z fail"))
384 		return false;
385 
386 	if (!compare_state(method, get_backZFail, backZFail, "back Z fail"))
387 		return false;
388 
389 	if (!compare_state(method, get_frontZPass, frontZPass,
390 			   "front Z pass"))
391 		return false;
392 
393 	if (!compare_state(method, get_backZPass, backZPass, "back Z pass"))
394 		return false;
395 
396 	if (!compare_state(method, get_frontFunc, frontFunc,
397 			   "front stencil func"))
398 		return false;
399 
400 	if (!compare_state(method, get_backFunc, backFunc,
401 			   "back stencil func"))
402 		return false;
403 
404 	if (!compare_state(method, get_frontRef, frontRef,
405 			   "front stencil ref"))
406 		return false;
407 
408 	if (!compare_state(method, get_backRef, backRef, "back stencil ref"))
409 		return false;
410 
411 	if (!compare_state(method, get_frontMask, frontMask,
412 			   "front stencil mask"))
413 		return false;
414 
415 	if (!compare_state(method, get_backMask, backMask,
416 			   "back stencil mask"))
417 		return false;
418 
419 	if (!compare_state(method, get_frontWriteMask, frontWriteMask,
420 			   "front stencil writemask"))
421 		return false;
422 
423 	if (!compare_state(method, get_backWriteMask, backWriteMask,
424 			   "back stencil writemask"))
425 		return false;
426 
427 	if (!compare_state(method, twoEnabled, GL_TRUE, "two-side enable"))
428 		return false;
429 
430 	return true;
431 }
432 
433 
434 static bool
set_stencil_state2(int method,GLenum frontStencilFail,GLenum backStencilFail,GLenum frontZFail,GLenum backZFail,GLenum frontZPass,GLenum backZPass,GLenum frontFunc,GLenum backFunc,GLint ref,GLuint mask,GLuint writeMask)435 set_stencil_state2(int method,
436 		   GLenum frontStencilFail,
437 		   GLenum backStencilFail,
438 		   GLenum frontZFail,
439 		   GLenum backZFail,
440 		   GLenum frontZPass,
441 		   GLenum backZPass,
442 		   GLenum frontFunc,
443 		   GLenum backFunc,
444 		   GLint ref,
445 		   GLuint mask,
446 		   GLuint writeMask)
447 {
448 	return set_stencil_state(method, frontStencilFail,
449 				 backStencilFail, frontZFail, backZFail,
450 				 frontZPass, backZPass, frontFunc, backFunc,
451 				 ref,	/* frontRef */
452 				 ref,	/* backRef */
453 				 mask,	/* frontMask */
454 				 mask,	/* backMask */
455 				 writeMask,	/* frontWriteMask */
456 				 writeMask);	/* backWriteMask */
457 }
458 
459 
460 void
reset_stencil_state(int method)461 reset_stencil_state(int method)
462 {
463 	switch (method) {
464 	case ATI:
465 		break;
466 	case EXT:
467 		glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
468 		glActiveStencilFaceEXT(GL_FRONT);
469 		break;
470 	case GL2:
471 		break;
472 	default:
473 		assert(0);
474 	}
475 }
476 
477 
478 static bool
test_stencil(int method)479 test_stencil(int method)
480 {
481 	bool pass;
482 
483 	glEnable(GL_STENCIL_TEST);
484 
485 	/**
486 	 * No depth testing
487 	 */
488 	glDisable(GL_DEPTH_TEST);
489 
490 	glClear(GL_COLOR_BUFFER_BIT |
491 		GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
492 
493 
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 */
500 	if (pass)
501 		pass = render_test(5, 5);
502 	reset_stencil_state(method);
503 	if (!pass)
504 		return false;
505 
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 */
512 	if (pass)
513 		pass = render_test(6, 4);
514 	reset_stencil_state(method);
515 	if (!pass)
516 		return false;
517 
518 	/* if front==6, keep
519 	 * if back<6, replace with zero
520 	 * final: front=6, back=0
521 	 */
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 */
527 	if (pass)
528 		pass = render_test(6, 0);
529 	reset_stencil_state(method);
530 	if (!pass)
531 		return false;
532 
533 	/* if front!=10, keep, else decr
534 	 * if back<10, keep, else incr
535 	 * final: front=6, back=1
536 	 */
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 */
542 	if (pass)
543 		pass = render_test(6, 1);
544 	reset_stencil_state(method);
545 	if (!pass)
546 		return false;
547 
548 	if (method != ATI) {
549 		/* if front!=10, keep, else decr
550 		 * if back<10, keep, else incr
551 		 * final: front=6, back=1
552 		 */
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 */
560 		if (pass)
561 			pass = render_test(0x66, 0x11);
562 		reset_stencil_state(method);
563 		if (!pass)
564 			return false;
565 	}
566 
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);
573 
574 	/* ============================================================
575 	 * Now begin tests with depth test
576 	 */
577 	glEnable(GL_DEPTH_TEST);
578 	glDepthFunc(GL_LESS);
579 
580 	glClear(GL_COLOR_BUFFER_BIT |
581 		GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
582 
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 */
589 	if (pass)
590 		pass = render_test(7, 7);
591 	reset_stencil_state(method);
592 	if (!pass)
593 		return false;
594 
595 
596 	/* GL_LESS test should fail everywhere
597 	 * decr front to 5, incr back to 2
598 	 */
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 */
604 	if (pass)
605 		pass = render_test(6, 8);
606 	reset_stencil_state(method);
607 	if (!pass)
608 		return false;
609 
610 
611 	/* set depth test = GL_EQUAL
612 	 * Z test should pass everywhere
613 	 * set front to 3
614 	 * decr back to 7
615 	 */
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 */
622 	if (pass)
623 		pass = render_test(3, 7);
624 	reset_stencil_state(method);
625 	if (!pass)
626 		return false;
627 
628 
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 */
635 	if (pass)
636 		pass = render_test(4, 6);
637 	reset_stencil_state(method);
638 	if (!pass)
639 		return false;
640 
641 
642 	/* ============================================================
643 	 * Disable depth test
644 	 */
645 	glDisable(GL_DEPTH_TEST);
646 
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)
651 	 */
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 */
657 	if (pass)
658 		pass = render_test(3, 6);
659 	reset_stencil_state(method);
660 	if (!pass)
661 		return false;
662 
663 	/* ============================================================
664 	 * Test common two-sided stencil modes for shadow volume rendering
665 	 * Requires stencil /- wrap feature.
666 	 */
667 
668 	if (!have_stencil_wrap())
669 		return true;
670 
671 	glClear(GL_COLOR_BUFFER_BIT |
672 		GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
673 
674 	glEnable(GL_DEPTH_TEST);
675 	glDepthFunc(GL_LESS);
676 
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
681 	 */
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 */
687 	if (pass)
688 		pass = render_test(1, stencil_max);
689 	reset_stencil_state(method);
690 	if (!pass)
691 		return false;
692 
693 
694 	/* "Z-fail" method:
695 	 * front face: decr on zfail
696 	 * back face: incr on zfail
697 	 * both front and back Z-test should fail here
698 	 */
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 */
704 	if (pass)
705 		pass = render_test(0, 0);
706 	reset_stencil_state(method);
707 	if (!pass)
708 		return false;
709 
710 
711 	return true;
712 }
713 
714 
715 void
piglit_init(int argc,char ** argv)716 piglit_init(int argc, char **argv)
717 {
718 	/* no initialization */
719 }
720 
721 
722 enum piglit_result
piglit_display(void)723 piglit_display(void)
724 {
725 	bool pass = true;
726 
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);
731 
732 	glViewport(0, 0, piglit_width, piglit_width);
733 	glMatrixMode(GL_PROJECTION);
734 	glLoadIdentity();
735 	glOrtho(0, piglit_width, 0, piglit_width, -1, 1);
736 	glMatrixMode(GL_MODELVIEW);
737 	glLoadIdentity();
738 
739 	if (piglit_is_extension_supported("GL_ATI_separate_stencil")) {
740 		pass = test_stencil(ATI) && pass;
741 	}
742 
743 	if (piglit_is_extension_supported("GL_EXT_stencil_two_side")) {
744 		pass = test_stencil(EXT) && pass;
745 	}
746 
747 	if (piglit_get_gl_version() >= 2.0) {
748 		pass = test_stencil(GL2) && pass;
749 	}
750 
751 	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
752 }
753