glx-multithread-texture: Avoid front-buffer rendering.
[piglit.git] / tests / util / piglit-framework-gl / piglit_glut_framework.c
blob8ac2f657b6c35389a2e869beba1a49c15c03d4b0
1 /*
2 * Copyright 2012 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.
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
29 #include "piglit_glut_framework.h"
30 #include "piglit-util-gl.h"
32 struct piglit_glut_framework {
33 struct piglit_gl_framework gl_fw;
35 enum piglit_result result;
36 int window;
39 /**
40 * This global variable exists because GLUT's API requires that data be passed
41 * to the display function via a global. Ugh, GLUT is such an awful API.
43 static struct piglit_glut_framework glut_fw;
45 static void
46 destroy(struct piglit_gl_framework *gl_fw)
48 piglit_gl_framework_teardown(gl_fw);
50 glut_fw.result = 0;
51 glut_fw.window = 0;
55 #ifdef _WIN32
57 /* Catch any exceptions and abort immediately.
59 * At least with certain implementations of GLUT (namely
60 * freeglut-2.8.1), the glutDisplayFunc()'s callback called inside a
61 * WindowProc callback function.
63 * And on certain cases (depending on the Windows version and 32 vs 64
64 * bits processes) uncaught exceptions inside WindowProc callbacks are
65 * silently ignored! (See Remarks section of
66 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms633573.aspx
67 * page.) The end result is that automatic tests end up blocking
68 * waiting for user input when an uncaught exceptionhappens, as control
69 * flow is interrupted before it reaches piglit_report_result(), and
70 * the process never aborts.
72 * By installing our own exception handler we can ensure that uncaught
73 * exceptions will never be silently ignored.
75 * NOTE: SetUnhandledExceptionFilter does not work here, as some Windows
76 * versions never call the unhandled exception filter. We must use MSVC
77 * __try/__except statements, or in MinGW, the __try1/__except1 macros.
79 static LONG WINAPI
80 exception_filter(PEXCEPTION_POINTERS pExceptionInfo)
82 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
84 fflush(stdout);
85 fprintf(stderr, "error: caught unhandled exception 0x%08lx\n", pExceptionRecord->ExceptionCode);
86 fflush(stderr);
88 _exit(pExceptionRecord->ExceptionCode);
91 # ifdef __MINGW32__
93 // http://www.programmingunlimited.net/siteexec/content.cgi?page=mingw-seh
94 // http://www.microsoft.com/msj/0197/exception/exception.aspx
95 EXCEPTION_DISPOSITION
96 exception_handler(struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
98 EXCEPTION_POINTERS ExceptionInfo = {ExceptionRecord, ContextRecord};
99 switch (exception_filter(&ExceptionInfo)) {
100 case EXCEPTION_EXECUTE_HANDLER:
101 return ExceptionExecuteHandler;
102 case EXCEPTION_CONTINUE_SEARCH:
103 return ExceptionContinueSearch;
104 case EXCEPTION_CONTINUE_EXECUTION:
105 return ExceptionContinueExecution;
106 default:
107 return ExceptionContinueSearch;
111 # define TRY __try1(exception_handler);
112 # define CATCH_ALL __except1;
114 # else
116 # define TRY __try {
117 # define CATCH_ALL } __except(exception_filter(GetExceptionInformation())) {}
119 # endif
121 #else
123 # define TRY
124 # define CATCH_ALL
126 #endif
129 static void
130 display(void)
132 const struct piglit_gl_test_config *test_config = glut_fw.gl_fw.test_config;
136 if (test_config->display)
137 glut_fw.result = test_config->display();
139 CATCH_ALL
141 if (piglit_automatic) {
142 glutDestroyWindow(glut_fw.window);
143 #ifdef FREEGLUT
144 /* Tell GLUT to clean up and exit, so that we can
145 * reasonably valgrind our testcases for memory
146 * leaks by the GL.
148 glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
149 GLUT_ACTION_GLUTMAINLOOP_RETURNS);
150 glutLeaveMainLoop();
151 #else
152 piglit_report_result(glut_fw.result);
153 #endif
157 static void
158 default_reshape_func(int w, int h)
160 if (piglit_automatic &&
161 (w != piglit_width ||
162 h != piglit_height)) {
163 printf("Got spurious window resize in automatic run "
164 "(%d,%d to %d,%d)\n", piglit_width, piglit_height, w, h);
165 piglit_report_result(PIGLIT_WARN);
168 piglit_width = w;
169 piglit_height = h;
171 glViewport(0, 0, w, h);
174 static void
175 error_func(const char *fmt, va_list ap)
177 vfprintf(stderr, fmt, ap);
178 fprintf(stderr, "\n");
179 piglit_report_result(PIGLIT_SKIP);
182 static void
183 init_glut(void)
185 const struct piglit_gl_test_config *test_config = glut_fw.gl_fw.test_config;
186 char *argv[] = {"piglit"};
187 int argc = 1;
188 unsigned flags = GLUT_RGB;
190 if (test_config->window_visual & PIGLIT_GL_VISUAL_RGBA)
191 flags |= GLUT_ALPHA;
192 if (test_config->window_visual & PIGLIT_GL_VISUAL_DEPTH)
193 flags |= GLUT_DEPTH;
194 if (test_config->window_visual & PIGLIT_GL_VISUAL_STENCIL)
195 flags |= GLUT_STENCIL;
196 if (test_config->window_visual & PIGLIT_GL_VISUAL_ACCUM)
197 flags |= GLUT_ACCUM;
199 if (test_config->window_visual & PIGLIT_GL_VISUAL_DOUBLE)
200 flags |= GLUT_DOUBLE;
201 else
202 flags |= GLUT_SINGLE;
205 * MacOSX GLUT.
207 * This will request a core profile. It will always return the highest
208 * version supported.
210 * See:
211 * /System/Library/Frameworks/GLUT.framework/Headers/glut.h
212 * https://developer.apple.com/opengl/capabilities/
214 #if GLUT_MACOSX_IMPLEMENTATION >= 4
215 if (test_config->supports_gl_core_version >= 31) {
216 flags |= GLUT_3_2_CORE_PROFILE;
218 #endif
220 glutInit(&argc, argv);
221 glutInitWindowPosition(0, 0);
222 glutInitWindowSize(test_config->window_width,
223 test_config->window_height);
224 glutInitDisplayMode(flags);
227 * FreeGLUT
229 #ifdef PIGLIT_USE_GLUT_INIT_ERROR_FUNC
230 glutInitErrorFunc(error_func);
231 #else
232 (void)error_func;
233 #endif
234 #ifdef GLUT_CORE_PROFILE
235 if (test_config->supports_gl_core_version) {
236 glutInitContextVersion(test_config->supports_gl_core_version / 10,
237 test_config->supports_gl_core_version % 10);
238 if (test_config->supports_gl_core_version >= 32) {
239 glutInitContextProfile(GLUT_CORE_PROFILE);
241 } else {
242 glutInitContextVersion(test_config->supports_gl_compat_version / 10,
243 test_config->supports_gl_compat_version % 10);
244 if (test_config->supports_gl_compat_version >= 32) {
245 glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);
249 int context_flags = 0;
250 /* There are no 3.1 core profiles -- the closest is 3.1 context without
251 * ARB_compatibility or a 3.2 core context --, and setting
252 * forward-compatible flag should ensure we don't get a 3.1 context w/
253 * ARB_compatibility.
255 if (test_config->require_forward_compatible_context ||
256 test_config->supports_gl_core_version == 31) {
257 context_flags |= GLUT_FORWARD_COMPATIBLE;
259 if (test_config->require_debug_context) {
260 context_flags |= GLUT_DEBUG;
262 if (context_flags) {
263 glutInitContextFlags(context_flags);
265 #endif
267 glut_fw.window = glutCreateWindow("Piglit");
269 glutDisplayFunc(display);
270 glutReshapeFunc(default_reshape_func);
271 glutKeyboardFunc(piglit_escape_exit_key);
273 #ifdef PIGLIT_USE_OPENGL
274 piglit_dispatch_default_init(PIGLIT_DISPATCH_GL);
275 #endif
278 static void
279 run_test(struct piglit_gl_framework *gl_fw,
280 int argc, char *argv[])
282 const struct piglit_gl_test_config *test_config = glut_fw.gl_fw.test_config;
284 if (test_config->init)
285 test_config->init(argc, argv);
287 glutMainLoop();
288 piglit_report_result(glut_fw.result);
291 static void
292 swap_buffers(struct piglit_gl_framework *gl_fw)
294 glutSwapBuffers();
297 static void
298 post_redisplay(struct piglit_gl_framework *gl_fw)
300 glutPostRedisplay();
303 static void
304 set_keyboard_func(struct piglit_gl_framework *gl_fw,
305 void (*func)(unsigned char key, int x, int y))
307 glutKeyboardFunc(func);
310 static void
311 set_reshape_func(struct piglit_gl_framework *gl_fw,
312 void (*func)(int w, int h))
314 glutReshapeFunc(func);
318 * Check that the context's actual version is no less than the
319 * requested version.
321 static bool
322 check_gl_version(const struct piglit_gl_test_config *test_config)
324 int actual_version = piglit_get_gl_version();
326 if (test_config->supports_gl_core_version) {
327 if (actual_version < test_config->supports_gl_core_version) {
328 printf("Test requires GL version %d.%d, but actual version is "
329 "%d.%d\n",
330 test_config->supports_gl_core_version / 10,
331 test_config->supports_gl_core_version % 10,
332 actual_version / 10,
333 actual_version % 10);
334 return false;
336 return true;
339 if (actual_version < test_config->supports_gl_compat_version) {
340 printf("Test requires GL version %d.%d, but actual version is "
341 "%d.%d\n",
342 test_config->supports_gl_compat_version / 10,
343 test_config->supports_gl_compat_version % 10,
344 actual_version / 10,
345 actual_version % 10);
346 return false;
349 if (piglit_is_core_profile &&
350 test_config->supports_gl_core_version == 0) {
351 /* We have a core profile context but the test needs a
352 * compat profile. We can't run the test.
354 printf("Test requires compat version %d.%d or later but "
355 "context is core profile %d.%d.\n",
356 test_config->supports_gl_compat_version / 10,
357 test_config->supports_gl_compat_version % 10,
358 actual_version / 10,
359 actual_version % 10);
360 return false;
363 return true;
366 struct piglit_gl_framework*
367 piglit_glut_framework_create(const struct piglit_gl_test_config *test_config)
369 bool ok = true;
371 #if !defined(GLUT_CORE_PROFILE) && \
372 (!defined(GLUT_MACOSX_IMPLEMENTATION) || GLUT_MACOSX_IMPLEMENTATION < 4)
373 if (!test_config->supports_gl_compat_version) {
374 printf("GLUT can create only GL compatibility contexts, "
375 "which the test does not support running under.\n");
376 piglit_report_result(PIGLIT_SKIP);
378 #endif
380 if (test_config->window_samples > 1) {
381 printf("GLUT doesn't support MSAA visuals.\n");
382 piglit_report_result(PIGLIT_SKIP);
385 ok = piglit_gl_framework_init(&glut_fw.gl_fw, test_config);
386 if (!ok)
387 return NULL;
389 init_glut();
391 /* Check if we actually have a core profile */
393 int actual_version = piglit_get_gl_version();
395 piglit_is_core_profile =
396 actual_version >= 31 &&
397 !piglit_is_extension_supported("GL_ARB_compatibility");
400 if (!check_gl_version(test_config))
401 piglit_report_result(PIGLIT_SKIP);
403 glut_fw.gl_fw.swap_buffers = swap_buffers;
404 glut_fw.gl_fw.run_test = run_test;
405 glut_fw.gl_fw.post_redisplay = post_redisplay;
406 glut_fw.gl_fw.set_keyboard_func = set_keyboard_func;
407 glut_fw.gl_fw.set_reshape_func = set_reshape_func;
408 glut_fw.gl_fw.destroy = destroy;
410 return &glut_fw.gl_fw;