4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * Pierre-Eric Pelloux-Prayer <pelloux@gmail.com>
27 * This test represents a simple usage of GL_SELECT rendering mode.
28 * It draws several squares to screen, with various GL_..._TEST active,
29 * and then verifies the number of hits and the content of the select buffer.
30 * Based on this documentation: http://glprogramming.com/red/chapter13.html
34 #include "piglit-util-gl.h"
36 PIGLIT_GL_TEST_CONFIG_BEGIN
38 config
.supports_gl_compat_version
= 10;
40 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DEPTH
| PIGLIT_GL_VISUAL_STENCIL
;
42 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
44 PIGLIT_GL_TEST_CONFIG_END
46 GLuint ReferenceHitEntries
[3][64];
47 #define NAME_STACK_DEPTH 0
50 #define NAME_STACK_0 3
53 * Draw 4 objects and handle name stack
58 float zscale
= (float)(~0u);
61 /* no draw call issued for name '0' */
67 glColor3f(1.0, 0.0, 0.0);
68 piglit_draw_rect_z(0.8, 10, 30, 50, 50);
69 /* fill reference buffer */
70 ReferenceHitEntries
[0][NAME_STACK_DEPTH
] = 2;
71 ReferenceHitEntries
[0][MIN_Z
] = (GLuint
)roundf(zscale
* ((1 - 0.8) * 0.5));
72 ReferenceHitEntries
[0][MAX_Z
] = ReferenceHitEntries
[0][MIN_Z
];
73 ReferenceHitEntries
[0][NAME_STACK_0
] = 0;
74 ReferenceHitEntries
[0][NAME_STACK_0
+ 1] = 1;
77 /* 2 draw calls for name '2' */
79 glColor3f(0.0, 1.0, 0.0);
80 piglit_draw_rect_z(0.5, 40, 5, 25, 30);
81 piglit_draw_rect_z(0.4, 10, 75, 25, 10);
82 /* fill reference buffer */
83 ReferenceHitEntries
[1][NAME_STACK_DEPTH
] = 3;
84 ReferenceHitEntries
[1][MIN_Z
] = (GLuint
)roundf(zscale
* ((1 - 0.5)*0.5));
85 ReferenceHitEntries
[1][MAX_Z
] = (GLuint
)roundf(zscale
* ((1 - 0.4)*0.5));
86 ReferenceHitEntries
[1][NAME_STACK_0
] = 0;
87 ReferenceHitEntries
[1][NAME_STACK_0
+ 1] = 1;
88 ReferenceHitEntries
[1][NAME_STACK_0
+ 2] = 2;
94 piglit_draw_rect_z(0.3, 250, 45, 280, 20);
97 /* glLoadName instead of glPushName */
99 glColor3f(0.0, 0.0, 1.0);
100 piglit_draw_rect_z(0.2, 50, 45, 80, 20);
101 /* fill reference buffer */
102 ReferenceHitEntries
[2][NAME_STACK_DEPTH
] = 3;
103 ReferenceHitEntries
[2][MIN_Z
] = (GLuint
)roundf(zscale
* ((1 - 0.2)*0.5));
104 ReferenceHitEntries
[2][MAX_Z
] = ReferenceHitEntries
[2][MIN_Z
];
105 ReferenceHitEntries
[2][NAME_STACK_0
] = 0;
106 ReferenceHitEntries
[2][NAME_STACK_0
+ 1] = 1;
107 ReferenceHitEntries
[2][NAME_STACK_0
+ 2] = 4;
111 * Helper function to compare 2 hit records
114 compare_hit_record(GLuint
* hit1
, GLuint
* hit2
)
117 float zscale
= (float)(~0u);
120 if (hit1
[NAME_STACK_DEPTH
] != hit2
[NAME_STACK_DEPTH
]) {
121 printf("\t%s : Incorrect name stack depth : %u %u\n",
123 hit1
[NAME_STACK_DEPTH
],
124 hit2
[NAME_STACK_DEPTH
]);
128 diffz
= abs(hit1
[MIN_Z
] - hit2
[MIN_Z
])/zscale
;
130 printf("\t%s : Incorrect Minz : %u %u (%f %f) %f\n",
134 hit1
[MIN_Z
] / zscale
,
135 hit2
[MIN_Z
] / zscale
,
140 diffz
= abs(hit1
[MAX_Z
] - hit2
[MAX_Z
])/zscale
;
142 printf("\t%s : Incorrect Maxz : %u %u (%f %f) %f\n",
146 hit1
[MAX_Z
] / zscale
,
147 hit2
[MAX_Z
] / zscale
,
152 for (i
=0; i
<hit1
[NAME_STACK_DEPTH
]; i
++) {
153 if (hit1
[NAME_STACK_0
+ i
] != hit2
[NAME_STACK_0
+ i
])
160 * Helper function to check select buffer
163 validate_select_buffer(GLuint
* buffer
)
166 GLint hits
= glRenderMode(GL_RENDER
);
167 bool object_hit_found
[3] = {false, false, false};
171 printf("\t%s : unexpected hit count:%d\n", __FUNCTION__
, hits
);
176 /* ordering in select buffer isn't necessarly the same as drawing order,
177 * so we need to look for each hit entry
179 for (i
=0; i
<hits
; i
++) {
180 for (j
=0; j
<3; j
++) {
181 if (!object_hit_found
[j
]) {
182 if (compare_hit_record(ptr
, ReferenceHitEntries
[j
])) {
183 object_hit_found
[j
] = true;
191 /* advance pointer */
192 ptr
+= 3 + ptr
[NAME_STACK_DEPTH
];
199 test_case_setup(bool depth
, bool stencil
, bool alpha
, bool scissor
) {
201 glEnable(GL_DEPTH_TEST
);
203 glDisable(GL_DEPTH_TEST
);
206 glEnable(GL_STENCIL_TEST
);
208 glDisable(GL_STENCIL_TEST
);
211 glEnable(GL_ALPHA_TEST
);
213 glDisable(GL_ALPHA_TEST
);
216 glEnable(GL_SCISSOR_TEST
);
218 glDisable(GL_SCISSOR_TEST
);
220 /* setup all test functions to never pass */
221 glDepthFunc(GL_NEVER
);
222 glStencilFunc(GL_NEVER
, 0, 0);
223 glAlphaFunc(GL_NEVER
, 0);
224 glScissor(0, 0, 0, 0);
236 GLuint buff
[64] = {0};
237 glSelectBuffer(64, buff
);
239 piglit_ortho_projection(piglit_width
, piglit_height
, GL_FALSE
);
240 glClearColor(0.5, 0.5, 0.5, 0.0);
242 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
243 glRenderMode(GL_SELECT
);
246 return validate_select_buffer(buff
) ? PIGLIT_PASS
: PIGLIT_FAIL
;
249 void piglit_init(int argc
, char**argv
)
251 enum piglit_result pass
;
254 test_case_setup(false, false, false, false);
255 pass
= do_blit_test();
258 strcmp(argv
[1], "depth") == 0,
259 strcmp(argv
[1], "stencil") == 0,
260 strcmp(argv
[1], "alpha") == 0,
261 strcmp(argv
[1], "scissor") == 0);
262 pass
= do_blit_test();
264 piglit_report_result(pass
);