/* Copyright © 2011 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include #include "piglit-util-gl.h" #include "piglit-glx-util.h" #include "common.h" PFNGLXGETCURRENTDISPLAYEXTPROC __piglit_glXGetCurrentDisplayEXT = NULL; PFNGLXQUERYCONTEXTINFOEXTPROC __piglit_glXQueryContextInfoEXT = NULL; PFNGLXGETCONTEXTIDEXTPROC __piglit_glXGetContextIDEXT = NULL; PFNGLXIMPORTCONTEXTEXTPROC __piglit_glXImportContextEXT = NULL; PFNGLXFREECONTEXTEXTPROC __piglit_glXFreeContextEXT = NULL; #define ADD_FUNC(name) PIGLIT_GLX_PROC(__piglit_##name, name) static const struct piglit_glx_proc_reference procedures[] = { ADD_FUNC(glXGetCurrentDisplayEXT), ADD_FUNC(glXQueryContextInfoEXT), ADD_FUNC(glXGetContextIDEXT), ADD_FUNC(glXImportContextEXT), ADD_FUNC(glXFreeContextEXT), }; Display *dpy = NULL; XVisualInfo *visinfo = NULL; GLXContext directCtx = NULL; GLXContextID directID = None; GLXContext indirectCtx = NULL; GLXContextID indirectID = None; int glx_error_code = -1; int x_error_code = Success; int piglit_height = 50; int piglit_width = 50; static int (*old_handler)(Display *, XErrorEvent *); static int x_error_handler(Display *dpy, XErrorEvent *e) { x_error_code = e->error_code; glx_error_code = piglit_glx_get_error(dpy, e); return 0; } void GLX_EXT_import_context_setup_for_child(void) { dpy = piglit_get_glx_display(); old_handler = XSetErrorHandler(x_error_handler); } void GLX_EXT_import_context_setup(void) { const char *vendor; dpy = piglit_get_glx_display(); /* NVIDIA incorrectly only list the extension in the client * extensions list. If the extension is available for applications * to use, it is supposed to be included in the list returned by * glXQueryExtensionsString. * * The glXImportContextEXT manual page is somewhat clear on this * topic: * * "If _glxextstring(EXT_import_context) is included in the string * returned by glXQueryExtensionsString, when called with argument * GLX_EXTENSIONS, extension EXT_import_context is supported." * * The text is a little weird because the only parameters to * glXQueryExtensionsString are the display and the screen. */ vendor = glXGetClientString(dpy, GLX_VENDOR); if (strcmp("NVIDIA Corporation", vendor) == 0) { const char *const client_extensions = glXGetClientString(dpy, GLX_EXTENSIONS); if (!piglit_is_extension_in_string(client_extensions, "GLX_EXT_import_context")) { fprintf(stderr, "Test requires GLX_EXT_import_context.\n"); piglit_report_result(PIGLIT_SKIP); } } else { piglit_require_glx_extension(dpy, "GLX_EXT_import_context"); } piglit_glx_get_all_proc_addresses(procedures, ARRAY_SIZE(procedures)); visinfo = piglit_get_glx_visual(dpy); directCtx = glXCreateContext(dpy, visinfo, NULL, True); if (directCtx == NULL) { fprintf(stderr, "Could not create initial direct-rendering context.\n"); piglit_report_result(PIGLIT_FAIL); } if (!glXIsDirect(dpy, directCtx)) { glXDestroyContext(dpy, directCtx); directCtx = NULL; } indirectCtx = glXCreateContext(dpy, visinfo, NULL, False); if (indirectCtx == NULL) { fprintf(stderr, "Could not create initial indirect-rendering " "context.\n"); piglit_report_result(PIGLIT_FAIL); } piglit_glx_get_error(dpy, NULL); old_handler = XSetErrorHandler(x_error_handler); } void GLX_EXT_import_context_teardown(void) { if (directCtx != NULL) { glXDestroyContext(dpy, directCtx); directCtx = NULL; } if (indirectCtx != NULL) { glXDestroyContext(dpy, indirectCtx); indirectCtx = NULL; } XFree(visinfo); visinfo = NULL; XSetErrorHandler(old_handler); } void get_context_IDs(void) { directID = None; if (directCtx != NULL) { directID = glXGetContextIDEXT(directCtx); } indirectID = None; if (indirectCtx != NULL) { indirectID = glXGetContextIDEXT(indirectCtx); } } const char *context_mode_name(enum context_mode mode) { switch (mode) { case direct_rendering: return "direct-rendering"; case indirect_rendering: return "indirect-rendering"; case invalid: return "invalid"; default: assert(!"Should not get here."); piglit_report_result(PIGLIT_FAIL); } return ""; } bool try_import_context(GLXContextID id, enum context_mode mode) { const int expected_glx_error = (mode == invalid) ? GLXBadContext : -1; bool pass = true; GLXContext ctx = glXImportContextEXT(dpy, id); XSync(dpy, 0); switch (mode) { case direct_rendering: if (ctx != NULL) { fprintf(stderr, "Could import direct-rendering context, " "but should have failed.\n"); pass = false; } break; case indirect_rendering: if (ctx == NULL) { fprintf(stderr, "Could not import indirect-rendering context, " "but should have succeeded.\n"); pass = false; } break; case invalid: if (ctx != NULL) { fprintf(stderr, "Could import invalid context (0x%08x), " "but should have failed.\n", (int) id); pass = false; } break; } assert(mode != invalid || expected_glx_error != -1); pass = validate_glx_error_code(Success, expected_glx_error) && pass; if (!pass) fprintf(stderr, "Context ID = 0x%08x.\n", (int) id); if (ctx != NULL) glXFreeContextEXT(dpy, ctx); return pass; } bool validate_glx_error_code(int expected_x_error, int expected_glx_error) { bool pass = true; if (expected_glx_error == -1 && expected_x_error == Success && (glx_error_code != -1 || x_error_code != Success)) { fprintf(stderr, "X error %d (%s (%d)) was generated, but " "no error was expected.\n", x_error_code, piglit_glx_error_string(glx_error_code), glx_error_code); pass = false; } if (expected_glx_error != -1 && glx_error_code != expected_glx_error) { fprintf(stderr, "X error %d (%s (%d)) was generated, but " "%s (%d) was expected.\n", x_error_code, piglit_glx_error_string(glx_error_code), glx_error_code, piglit_glx_error_string(expected_glx_error), expected_glx_error); pass = false; } else if (expected_x_error != Success && x_error_code != expected_x_error) { fprintf(stderr, "X error %d (%s (%d)) was generated, but " "X error %d was expected.\n", x_error_code, piglit_glx_error_string(glx_error_code), glx_error_code, expected_x_error); pass = false; } x_error_code = Success; glx_error_code = -1; return pass; }