fix the spelling in whole piglit
[piglit.git] / tests / util / piglit-glx-util.c
blob2d813b874300cd531d45bb3680d0dd6c73db3752
1 /*
2 * Copyright © 2009 Intel Corporation
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 * Eric Anholt <eric@anholt.net>
28 #include "piglit-util-gl.h"
29 #include "piglit-glx-util.h"
31 #ifndef _WIN32
32 __attribute__((weak)) int piglit_width = 100;
33 __attribute__((weak)) int piglit_height = 100;
34 #endif
36 Display *
37 piglit_get_glx_display()
39 Display *dpy;
41 dpy = XOpenDisplay(NULL);
42 if (!dpy) {
43 fprintf(stderr, "couldn't open display\n");
44 piglit_report_result(PIGLIT_FAIL);
47 return dpy;
50 XVisualInfo *
51 piglit_get_glx_visual(Display *dpy)
53 XVisualInfo *visinfo;
54 int attrib[] = {
55 GLX_RGBA,
56 GLX_RED_SIZE, 1,
57 GLX_GREEN_SIZE, 1,
58 GLX_BLUE_SIZE, 1,
59 GLX_DEPTH_SIZE, 1,
60 GLX_STENCIL_SIZE, 1,
61 GLX_DOUBLEBUFFER,
62 None
64 int screen = DefaultScreen(dpy);
66 visinfo = glXChooseVisual(dpy, screen, attrib);
67 if (visinfo == NULL) {
68 fprintf(stderr,
69 "Couldn't get an RGBA, double-buffered visual\n");
70 piglit_report_result(PIGLIT_FAIL);
73 return visinfo;
76 GLXContext
77 piglit_get_glx_context(Display *dpy, XVisualInfo *visinfo)
79 return piglit_get_glx_context_share(dpy, visinfo, NULL);
82 GLXContext
83 piglit_get_glx_context_share(Display *dpy, XVisualInfo *visinfo, GLXContext share)
85 GLXContext ctx;
87 ctx = glXCreateContext(dpy, visinfo, share, True);
88 if (ctx == None) {
89 fprintf(stderr, "glXCreateContext failed\n");
90 piglit_report_result(PIGLIT_FAIL);
93 return ctx;
96 static Window
97 _piglit_get_glx_window(Display *dpy, XVisualInfo *visinfo, bool map, bool fullscreen)
99 XSetWindowAttributes window_attr;
100 unsigned long mask;
101 int screen = DefaultScreen(dpy);
102 Window root_win = RootWindow(dpy, screen);
103 Window win;
105 window_attr.background_pixel = 0;
106 window_attr.border_pixel = 0;
107 window_attr.colormap = XCreateColormap(dpy, root_win,
108 visinfo->visual, AllocNone);
109 window_attr.event_mask = StructureNotifyMask | ExposureMask |
110 KeyPressMask;
111 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
113 if (fullscreen) {
114 window_attr.override_redirect = True;
115 mask |= CWOverrideRedirect;
116 piglit_width = DisplayWidth(dpy, screen);
117 piglit_height = DisplayHeight(dpy, screen);
120 win = XCreateWindow(dpy, root_win, 0, 0,
121 piglit_width, piglit_height,
122 0, visinfo->depth, InputOutput,
123 visinfo->visual, mask, &window_attr);
125 if (piglit_automatic)
126 piglit_glx_window_set_no_input(dpy, win);
128 if (map)
129 XMapWindow(dpy, win);
131 return win;
134 Window
135 piglit_get_glx_window_unmapped(Display *dpy, XVisualInfo *visinfo)
137 return _piglit_get_glx_window(dpy, visinfo, false, false);
140 Window
141 piglit_get_glx_window_fullscreen(Display *dpy, XVisualInfo *visinfo)
143 return _piglit_get_glx_window(dpy, visinfo, true, true);
146 Window
147 piglit_get_glx_window(Display *dpy, XVisualInfo *visinfo)
149 return _piglit_get_glx_window(dpy, visinfo, true, false);
152 bool
153 piglit_is_glx_extension_supported(Display *dpy, const char *name)
155 int screen = DefaultScreen(dpy);
156 const char *const glx_extension_list =
157 glXQueryExtensionsString(dpy, screen);
159 return piglit_is_extension_in_string(glx_extension_list, name);
162 void
163 piglit_require_glx_extension(Display *dpy, const char *name)
165 if (!piglit_is_glx_extension_supported(dpy, name)) {
166 fprintf(stderr, "Test requires %s\n", name);
167 piglit_report_result(PIGLIT_SKIP);
172 void
173 piglit_require_glx_version(Display *dpy, int major, int minor)
175 int glxMajor;
176 int glxMinor;
178 if (! glXQueryVersion(dpy, & glxMajor, & glxMinor)) {
179 fprintf(stderr, "Could not query GLX version!\n");
180 piglit_report_result(PIGLIT_FAIL);
183 if (glxMajor != major || glxMinor < minor) {
184 fprintf(stderr, "Test requires GLX %d.%d. Got %d.%d.\n",
185 major, minor, glxMajor, glxMinor);
186 piglit_report_result(PIGLIT_SKIP);
191 void
192 piglit_glx_event_loop(Display *dpy, enum piglit_result (*draw)(Display *dpy))
194 for (;;) {
195 XEvent event;
196 XNextEvent (dpy, &event);
198 if (event.type == KeyPress) {
199 int keysyms_per_keycode_return;
200 KeySym *sym = XGetKeyboardMapping (dpy,
201 event.xkey.keycode,
203 &keysyms_per_keycode_return);
205 if (sym[0] == XK_Escape || sym[0] == XK_q || sym[0] == XK_Q)
206 break;
207 else
208 draw(dpy);
209 } else if (event.type == Expose) {
210 enum piglit_result result = draw(dpy);
212 if (piglit_automatic) {
214 * Rerun if we have failed and have a
215 * pending expose event, which might be an
216 * indication of invalid front buffer
217 * contents.
219 if (result == PIGLIT_FAIL &&
220 XCheckTypedEvent(dpy, Expose, &event)) {
221 fprintf(stderr,
222 "Pending expose event- "
223 "rerunning.\n");
224 XPutBackEvent(dpy, &event);
225 continue;
227 XCloseDisplay(dpy);
228 piglit_report_result(result);
229 break;
236 static enum piglit_result
237 piglit_iterate_visuals_event_loop(Display *dpy,
238 enum piglit_result (*draw)(Display *dpy,
239 GLXFBConfig config),
240 GLXFBConfig config)
242 for (;;) {
243 XEvent event;
244 XNextEvent (dpy, &event);
246 if (event.type == Expose) {
247 return draw(dpy, config);
252 void
253 piglit_glx_window_set_no_input(Display *dpy, GLXDrawable win)
255 XWMHints *hints;
256 hints = XAllocWMHints();
257 hints->flags |= InputHint;
258 hints->input = False;
260 XSetWMHints(dpy, win, hints);
262 XFree(hints);
265 void
266 piglit_glx_set_no_input(void)
268 Display *d;
269 GLXDrawable win;
271 d = glXGetCurrentDisplay();
272 win = glXGetCurrentDrawable();
274 piglit_glx_window_set_no_input(d, win);
277 enum piglit_result
278 piglit_glx_iterate_pixmap_fbconfigs(enum piglit_result (*draw)(Display *dpy,
279 GLXFBConfig config))
281 int screen;
282 GLXFBConfig *configs;
283 int n_configs;
284 int i, j;
285 bool any_fail = false;
286 bool any_pass = false;
287 Window root_win;
288 int *depths, n_depths;
290 Display *dpy = XOpenDisplay(NULL);
291 if (!dpy) {
292 fprintf(stderr, "couldn't open display\n");
293 piglit_report_result(PIGLIT_FAIL);
295 screen = DefaultScreen(dpy);
296 root_win = RootWindow(dpy, screen);
297 depths = XListDepths(dpy, screen, &n_depths);
299 configs = glXGetFBConfigs(dpy, screen, &n_configs);
300 if (!configs) {
301 fprintf(stderr, "No GLX FB configs\n");
302 piglit_report_result(PIGLIT_SKIP);
305 for (i = 0; i < n_configs; i++) {
306 GLXFBConfig config = configs[i];
307 enum piglit_result result;
308 GLXContext ctx;
309 Pixmap pix;
310 GLXPixmap glx_pix;
311 int draw_types;
312 int depth;
314 glXGetFBConfigAttrib(dpy, config, GLX_DRAWABLE_TYPE,
315 &draw_types);
317 if (!(draw_types & GLX_PIXMAP_BIT))
318 continue;
320 glXGetFBConfigAttrib(dpy, config, GLX_BUFFER_SIZE,
321 &depth);
323 /* Ensure XCreatePixmap will succeed */
324 for (j = 0; j < n_depths; j++)
325 if (depths[j] == depth)
326 break;
327 if (j == n_depths) {
328 int id;
329 glXGetFBConfigAttrib(dpy, config, GLX_FBCONFIG_ID, &id);
330 fprintf(stderr, "fbconfig %d has GLX_PIXMAP_BIT but there "
331 "is no pixmap format for depth %d, this "
332 "is a server bug\n", id, depth);
333 any_fail = true;
334 continue;
337 ctx = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE,
338 NULL, true);
339 pix = XCreatePixmap(dpy, root_win,
340 piglit_width, piglit_height, depth);
341 glx_pix = glXCreatePixmap(dpy, config, pix, NULL);
342 glXMakeCurrent(dpy, glx_pix, ctx);
344 result = draw(dpy, config);
346 if (result == PIGLIT_FAIL)
347 any_fail = true;
348 else if (result == PIGLIT_PASS)
349 any_pass = true;
351 XFreePixmap(dpy, pix);
352 glXDestroyContext(dpy, ctx);
355 XFree(depths);
356 XFree(configs);
358 if (any_fail)
359 return PIGLIT_FAIL;
360 else if (any_pass)
361 return PIGLIT_PASS;
362 else
363 return PIGLIT_SKIP;
366 enum piglit_result
367 piglit_glx_iterate_visuals(enum piglit_result (*draw)(Display *dpy,
368 GLXFBConfig config))
370 int screen;
371 GLXFBConfig *configs;
372 int n_configs;
373 int i;
374 bool any_fail = false;
375 bool any_pass = false;
377 Display *dpy = XOpenDisplay(NULL);
378 if (!dpy) {
379 fprintf(stderr, "couldn't open display\n");
380 piglit_report_result(PIGLIT_FAIL);
382 screen = DefaultScreen(dpy);
384 configs = glXGetFBConfigs(dpy, screen, &n_configs);
385 if (!configs) {
386 fprintf(stderr, "No GLX FB configs\n");
387 piglit_report_result(PIGLIT_SKIP);
390 for (i = 0; i < n_configs; i++) {
391 enum piglit_result result;
392 XVisualInfo *visinfo;
393 GLXContext ctx;
394 GLXDrawable d;
396 visinfo = glXGetVisualFromFBConfig(dpy, configs[i]);
397 if (!visinfo)
398 continue;
400 ctx = piglit_get_glx_context(dpy, visinfo);
401 d = piglit_get_glx_window(dpy, visinfo);
402 glXMakeCurrent(dpy, d, ctx);
403 XFree(visinfo);
405 result = piglit_iterate_visuals_event_loop(dpy, draw,
406 configs[i]);
407 if (result == PIGLIT_FAIL)
408 any_fail = true;
409 else if (result == PIGLIT_PASS)
410 any_pass = true;
412 XDestroyWindow(dpy, d);
413 glXDestroyContext(dpy, ctx);
416 XFree(configs);
418 if (any_fail)
419 return PIGLIT_FAIL;
420 else if (any_pass)
421 return PIGLIT_PASS;
422 else
423 return PIGLIT_SKIP;
426 GLXFBConfig
427 piglit_glx_get_fbconfig_for_visinfo(Display *dpy, XVisualInfo *visinfo)
429 int i, nconfigs;
430 GLXFBConfig ret = None, *configs;
432 configs = glXGetFBConfigs(dpy, visinfo->screen, &nconfigs);
433 if (!configs)
434 return None;
436 for (i = 0; i < nconfigs; i++) {
437 int v;
439 if (glXGetFBConfigAttrib(dpy, configs[i], GLX_VISUAL_ID, &v))
440 continue;
442 if (v == visinfo->visualid) {
443 ret = configs[i];
444 break;
448 XFree(configs);
449 return ret;
453 * If you use this in an X error handler - and you will - pre-call it as:
454 * piglit_glx_get_error(dpy, NULL);
455 * outside the error handler to cache errbase. Otherwise this will
456 * generate protocol, and you'll deadlock.
458 * Returns -1 if the error is not a GLX error, otherwise returns the
459 * GLX error code.
462 piglit_glx_get_error(Display *dpy, XErrorEvent *err)
464 static int errbase, evbase;
466 if (!errbase)
467 glXQueryExtension(dpy, &errbase, &evbase);
469 if (!err)
470 return -1;
472 if (err->error_code < errbase ||
473 err->error_code > errbase + GLXBadProfileARB)
474 return -1;
476 return err->error_code - errbase;
480 * Convert a GLX error code to a printable string
482 * \sa piglit_glx_get_error
484 const char *
485 piglit_glx_error_string(int err)
487 static const char *const error_table[] = {
488 "GLXBadContext",
489 "GLXBadContextState",
490 "GLXBadDrawable",
491 "GLXBadPixmap",
492 "GLXBadContextTag",
493 "GLXBadCurrentWindow",
494 "GLXBadRenderRequest",
495 "GLXBadLargeRequest",
496 "GLXUnsupportedPrivateRequest",
497 "GLXBadFBConfig",
498 "GLXBadPbuffer",
499 "GLXBadCurrentDrawable",
500 "GLXBadWindow",
501 "GLXBadProfileARB"
504 if (err < 0) {
505 return "non-GLX error";
506 } else if (err >= ARRAY_SIZE(error_table)) {
507 return "unknown GLX error";
508 } else {
509 return error_table[err];
514 * Get the procedure addresses for a group of function names
516 * \note
517 * If any call to \c glXGetProcAddress fails, this function will call
518 * \c piglit_report_result with \c PIGLIT_FAIL.
520 void
521 piglit_glx_get_all_proc_addresses(const struct piglit_glx_proc_reference *procedures,
522 unsigned num)
524 unsigned i;
526 for (i = 0; i < num; i++) {
527 *procedures[i].procedure =
528 glXGetProcAddress((const GLubyte *) procedures[i].name);
529 if (*procedures[i].procedure == NULL) {
530 fprintf(stderr,
531 "Failed to get function pointer for %s.\n",
532 procedures[i].name);
533 piglit_report_result(PIGLIT_FAIL);