fbo-mrt-alphatest: Actually require MRTs to be available.
[piglit.git] / tests / general / select.c
blobc71fe20411b3155a6bc71af39a5f42892d6ffa7e
1 /*
2 * Copyright © 2011
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
13 * Software.
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
21 * IN THE SOFTWARE.
23 * Authors:
24 * Pierre-Eric Pelloux-Prayer <pelloux@gmail.com>
26 * Description:
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
48 #define MIN_Z 1
49 #define MAX_Z 2
50 #define NAME_STACK_0 3
52 /**
53 * Draw 4 objects and handle name stack
55 static void
56 draw_objects()
58 float zscale = (float)(~0u);
59 glInitNames();
61 /* no draw call issued for name '0' */
62 glPushName(0);
64 /* OBJECT 1 */
65 glPushName(1);
66 /* draw object */
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;
76 /* OBJECT 2 */
77 /* 2 draw calls for name '2' */
78 glPushName(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;
90 /* OBJECT 3 */
91 glPopName();
92 glPushName(3);
93 /* drawn offscreen */
94 piglit_draw_rect_z(0.3, 250, 45, 280, 20);
96 /* OBJECT 4 */
97 /* glLoadName instead of glPushName */
98 glLoadName(4);
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
113 static bool
114 compare_hit_record(GLuint* hit1, GLuint* hit2)
116 int i;
117 float zscale = (float)(~0u);
118 float diffz;
120 if (hit1[NAME_STACK_DEPTH] != hit2[NAME_STACK_DEPTH]) {
121 printf("\t%s : Incorrect name stack depth : %u %u\n",
122 __FUNCTION__,
123 hit1[NAME_STACK_DEPTH],
124 hit2[NAME_STACK_DEPTH]);
125 return false;
128 diffz = abs(hit1[MIN_Z] - hit2[MIN_Z])/zscale;
129 if (diffz > 0.1) {
130 printf("\t%s : Incorrect Minz : %u %u (%f %f) %f\n",
131 __FUNCTION__,
132 hit1[MIN_Z],
133 hit2[MIN_Z],
134 hit1[MIN_Z] / zscale,
135 hit2[MIN_Z] / zscale,
136 diffz);
137 return false;
140 diffz = abs(hit1[MAX_Z] - hit2[MAX_Z])/zscale;
141 if (diffz > 0.1) {
142 printf("\t%s : Incorrect Maxz : %u %u (%f %f) %f\n",
143 __FUNCTION__,
144 hit1[MAX_Z],
145 hit2[MAX_Z],
146 hit1[MAX_Z] / zscale,
147 hit2[MAX_Z] / zscale,
148 diffz);
149 return false;
152 for (i=0; i<hit1[NAME_STACK_DEPTH]; i++) {
153 if (hit1[NAME_STACK_0 + i] != hit2[NAME_STACK_0 + i])
154 return false;
156 return true;
160 * Helper function to check select buffer
162 static bool
163 validate_select_buffer(GLuint* buffer)
165 int i,j;
166 GLint hits = glRenderMode(GL_RENDER);
167 bool object_hit_found[3] = {false, false, false};
168 GLuint* ptr;
170 if (hits != 3) {
171 printf("\t%s : unexpected hit count:%d\n", __FUNCTION__, hits);
172 return false;
175 ptr = buffer;
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;
184 break;
188 if (j == 3)
189 return false;
191 /* advance pointer */
192 ptr += 3 + ptr[NAME_STACK_DEPTH];
195 return true;
198 void
199 test_case_setup(bool depth, bool stencil, bool alpha, bool scissor) {
200 if (depth)
201 glEnable(GL_DEPTH_TEST);
202 else
203 glDisable(GL_DEPTH_TEST);
205 if (stencil)
206 glEnable(GL_STENCIL_TEST);
207 else
208 glDisable(GL_STENCIL_TEST);
210 if (alpha)
211 glEnable(GL_ALPHA_TEST);
212 else
213 glDisable(GL_ALPHA_TEST);
215 if (scissor)
216 glEnable(GL_SCISSOR_TEST);
217 else
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);
227 enum piglit_result
228 piglit_display(void)
230 return PIGLIT_FAIL;
233 enum piglit_result
234 do_blit_test(void)
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);
244 draw_objects();
246 return validate_select_buffer(buff) ? PIGLIT_PASS : PIGLIT_FAIL;
249 void piglit_init(int argc, char**argv)
251 enum piglit_result pass;
253 if (argc < 2) {
254 test_case_setup(false, false, false, false);
255 pass = do_blit_test();
256 } else {
257 test_case_setup(
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);