1 /*
2 * Copyright © 2011 Intel Corporation
3 *
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:
10 *
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.
14 *
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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * @file glx-query-drawable.c
26 *
27 * Test the behavior of glXQueryDrawable(). See GLX 1.4 spec, Section 3.3.6
28 * Querying Attributes.
29 *
30 * For usage information, see usage_error();
31 */
32
33 #include "piglit-util-gl.h"
34 #include "piglit-glx-util.h"
35
36 int piglit_width = 137;
37 int piglit_height = 119;
38 GLXFBConfig config = None;
39
40 enum _drawable_type {
41 WINDOW,
42 GLXWINDOW,
43 GLXPIXMAP,
44 GLXPBUFFER,
45 };
46
47 int drawable_type /* = WINDOW */;
48
49 void
usage_error()50 usage_error()
51 {
52 const char *message =
53 "usage:\n"
54 " glx-query-drawable --bad-drawable\n"
55 " Call glXQueryDrawable(drawable=0) and expect that error\n"
56 " GLXBadDrawable is generated.\n"
57 "\n"
58 " glx-query-drawable --attr=GLX_WIDTH\n"
59 " glx-query-drawable --attr=GLX_HEIGHT\n"
60 " glx-query-drawable --attr=GLX_FBCONFIG_ID\n"
61 " glx-query-drawable --attr=GLX_PRESERVED_CONTENTS (pbuffer only)\n"
62 " Call glXQueryDrawable() with the given attribute.\n"
63 "\n"
64 " Options:\n"
65 " -auto"
66 " --type={GLX{WINDOW,PIXMAP,PBUFFER},WINDOW}\n"
67 " Default is: not -auto, WINDOW\n";
68 printf("%s", message);
69 piglit_report_result(PIGLIT_FAIL);
70 }
71
72 /***************************************************************************/
73
74 /**
75 * @name X Error Handlers
76 * @{
77 */
78
79 bool found_error_glxbaddrawable = false;
80
81 static int
expect_no_error(Display * display,XErrorEvent * error)82 expect_no_error(Display *display, XErrorEvent *error)
83 {
84 static char buf[256];
85 XGetErrorText(display, error->error_code, buf, 256);
86 fprintf(stderr, "error: unexpected X error: %s\n", buf);
87 piglit_report_result(PIGLIT_FAIL);
88 return 0;
89 }
90
91 static int
expect_glxbaddrawable(Display * display,XErrorEvent * error)92 expect_glxbaddrawable(Display *display, XErrorEvent *error)
93 {
94 if (piglit_glx_get_error(display, error) == GLXBadDrawable) {
95 found_error_glxbaddrawable = true;
96 } else {
97 static char buf[256];
98 XGetErrorText(display, error->error_code, buf, 256);
99 fprintf(stderr, "error: unexpected X error: %s\n", buf);
100 piglit_report_result(PIGLIT_FAIL);
101 }
102 return 0;
103 }
104
105 /***************************************************************************/
106
107 /**
108 * @}
109 * @name Test Functions
110 * @{
111 */
112
query_width(Display * display,GLXDrawable draw)113 static void query_width(Display *display, GLXDrawable draw) {
114 unsigned int width = 0;
115
116 XSetErrorHandler(expect_no_error);
117 glXQueryDrawable(display, draw, GLX_WIDTH, &width);
118
119 /* Sync before checking width in order to catch X errors. */
120 XSync(display, 0);
121
122 if (width != piglit_width) {
123 fprintf(stderr,
124 "error: width=%d but glXQueryDrawable returned %d\n",
125 piglit_width, width);
126 piglit_report_result(PIGLIT_FAIL);
127 }
128
129 piglit_report_result(PIGLIT_PASS);
130 }
131
query_height(Display * display,GLXDrawable draw)132 static void query_height(Display *display, GLXDrawable draw) {
133 unsigned int height = 0;
134
135 XSetErrorHandler(expect_no_error);
136 glXQueryDrawable(display, draw, GLX_HEIGHT, &height);
137
138 /* Sync before checking height in order to catch X errors. */
139 XSync(display, 0);
140
141 if (height != piglit_height) {
142 fprintf(stderr,
143 "error: height=%d but glXQueryDrawable returned %d\n",
144 piglit_height, height);
145 piglit_report_result(PIGLIT_FAIL);
146 }
147
148 piglit_report_result(PIGLIT_PASS);
149 }
150
query_fbconfig_id(Display * display,GLXDrawable draw)151 static void query_fbconfig_id(Display *display, GLXDrawable draw) {
152 unsigned int id = 0;
153 int piglit_id = 0;
154 enum piglit_result result = PIGLIT_PASS;
155
156 XSetErrorHandler(expect_no_error);
157 glXQueryDrawable(display, draw, GLX_FBCONFIG_ID, &id);
158 glXGetFBConfigAttrib(display, config, GLX_FBCONFIG_ID, &piglit_id);
159
160 /* Sync before checking in order to catch X errors. */
161 XSync(display, 0);
162
163 if (id == 0) {
164 fprintf(stderr, "error: no fbconfig id returned\n");
165 result = PIGLIT_FAIL;
166 }
167
168 if (id != piglit_id) {
169 if (!(drawable_type == WINDOW && id == None)) {
170 fprintf(stderr, "error: id=%d but should be %d\n",
171 id, piglit_id);
172 result = PIGLIT_FAIL;
173 }
174 }
175
176 piglit_report_result(result);
177 }
178
query_preserved_contents(Display * display,GLXDrawable draw)179 static void query_preserved_contents(Display *display, GLXDrawable draw) {
180 unsigned int contents = 42;
181 enum piglit_result result = PIGLIT_PASS;
182
183 if ((contents == True) || (contents == False)) {
184 fprintf(stderr, "This is a very strange dojo\n");
185 piglit_report_result(PIGLIT_SKIP);
186 return;
187 }
188
189 XSetErrorHandler(expect_no_error);
190 glXQueryDrawable(display, draw, GLX_PRESERVED_CONTENTS, &contents);
191
192 /* Sync before checking in order to catch X errors. */
193 XSync(display, 0);
194
195 if ((contents != True) && (contents != False)) {
196 fprintf(stderr, "error: Unexpected value %d\n", contents);
197 result = PIGLIT_FAIL;
198 }
199
200 piglit_report_result(result);
201 }
202
query_bad_drawable(Display * display,GLXDrawable draw)203 static void query_bad_drawable(Display *display, GLXDrawable draw) {
204 unsigned int width;
205 (void) draw;
206
207 XSetErrorHandler(expect_glxbaddrawable);
208 glXQueryDrawable(display, 0, GLX_WIDTH, &width);
209 XSync(display, 0);
210
211 if (!found_error_glxbaddrawable) {
212 fprintf(stderr,
213 "error: glXQueryDrawable(draw=0) did not generate "
214 "GLXBadDrawable\n");
215 piglit_report_result(PIGLIT_FAIL);
216 }
217
218 piglit_report_result(PIGLIT_PASS);
219 }
220
221 /** @} */
222
223 /***************************************************************************/
224
225 static void
parse_args(int argc,char ** argv,void (** test_func)(Display *,GLXDrawable))226 parse_args(int argc, char **argv,
227 void (**test_func)(Display*, GLXDrawable))
228 {
229 int i;
230
231 /* Count of parsed args, excluding -auto. */
232 int num_parsed_args = 0;
233
234 for (i = 1; i < argc; ++i) {
235 const char *arg = argv[i];
236 if (!strncmp(arg, "-auto", 5)) {
237 piglit_automatic = 1;
238 } else if (!strncmp(arg, "--bad-drawable", 14)) {
239 ++num_parsed_args;
240 *test_func = query_bad_drawable;
241 } else if (!strncmp(arg, "--attr=GLX_WIDTH", 16)) {
242 ++num_parsed_args;
243 *test_func = query_width;
244 } else if (!strncmp(arg, "--attr=GLX_HEIGHT", 17)) {
245 ++num_parsed_args;
246 *test_func = query_height;
247 } else if (!strncmp(arg, "--attr=GLX_FBCONFIG_ID", 22)) {
248 ++num_parsed_args;
249 *test_func = query_fbconfig_id;
250 } else if (!strncmp(arg, "--attr=GLX_PRESERVED_CONTENTS", 29)) {
251 ++num_parsed_args;
252 *test_func = query_preserved_contents;
253 } else if (!strncmp(arg, "--type=GLXWINDOW", 16)) {
254 ++num_parsed_args;
255 drawable_type = GLXWINDOW;
256 } else if (!strncmp(arg, "--type=GLXPIXMAP", 16)) {
257 ++num_parsed_args;
258 drawable_type = GLXPIXMAP;
259 } else if (!strncmp(arg, "--type=GLXPBUFFER", 17)) {
260 ++num_parsed_args;
261 drawable_type = GLXPBUFFER;
262 } else if (!strncmp(arg, "--type=WINDOW", 13)) {
263 ++num_parsed_args;
264 drawable_type = WINDOW;
265 } else {
266 /* Unrecognized argument. */
267 usage_error();
268 }
269 }
270
271 if (*test_func == query_preserved_contents)
272 if (drawable_type != GLXPBUFFER)
273 usage_error();
274
275 if (num_parsed_args < 1) {
276 usage_error();
277 }
278 }
279
main(int argc,char ** argv)280 int main(int argc, char **argv) {
281 Display *display;
282 XVisualInfo *visual;
283 GLXDrawable draw;
284 GLXContext ctx;
285 void (*test_func)(Display*, GLXDrawable);
286
287 parse_args(argc, argv, &test_func);
288
289 display = piglit_get_glx_display();
290 piglit_require_glx_version(display, 1, 3);
291
292 visual = piglit_get_glx_visual(display);
293 config = piglit_glx_get_fbconfig_for_visinfo(display, visual);
294 ctx = piglit_get_glx_context(display, visual);
295
296 switch (drawable_type) {
297 case GLXWINDOW:
298 draw = glXCreateWindow(display, config,
299 piglit_get_glx_window(display, visual),
300 NULL);
301 break;
302 case GLXPIXMAP:
303 draw = glXCreatePixmap(display, config,
304 XCreatePixmap(display,
305 DefaultRootWindow(display),
306 piglit_width, piglit_height,
307 visual->depth),
308 NULL);
309 break;
310 case GLXPBUFFER: {
311 int attribs[] = { GLX_PBUFFER_WIDTH, piglit_width,
312 GLX_PBUFFER_HEIGHT, piglit_height,
313 None };
314 draw = glXCreatePbuffer(display, config, attribs);
315 break;
316 }
317 case WINDOW:
318 draw = piglit_get_glx_window(display, visual);
319 break;
320 default:
321 assert(0);
322 draw = 0;
323 }
324
325 glXMakeCurrent(display, draw, ctx);
326
327 /* Must initialize static variables of this function. */
328 piglit_glx_get_error(display, NULL);
329
330 test_func(display, draw);
331
332 return 0;
333 }
334