/* * 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 <string.h> #include <ctype.h> #include "glxclient.h" #include <xcb/glx.h> #include <X11/Xlib-xcb.h> _X_HIDDEN void __glX_send_client_info(struct glx_display *glx_dpy) { const unsigned ext_length = strlen("GLX_ARB_create_context"); const unsigned prof_length = strlen("_profile"); char *gl_extension_string; int gl_extension_length; xcb_connection_t *c; Bool any_screen_has_ARB_create_context = False; Bool any_screen_has_ARB_create_context_profile = False; unsigned i; static const uint32_t gl_versions[] = { 1, 4, }; static const uint32_t gl_versions_profiles[] = { 1, 4, 0x00000000, }; static const char glx_extensions[] = "GLX_ARB_create_context GLX_ARB_create_context_profile"; /* There are three possible flavors of the client info structure that the * client could send to the server. The version sent depends on the * combination of GLX versions and extensions supported by the client and * the server. * * Server supports Client sends * ---------------------------------------------------------------------- * GLX version = 1.0 Nothing. * * GLX version >= 1.1 struct GLXClientInfo * * GLX version >= 1.4 and * GLX_ARB_create_context struct glXSetClientInfoARB * * GLX version >= 1.4 and * GLX_ARB_create_context_profile struct glXSetClientInfo2ARB * * GLX_ARB_create_context and GLX_ARB_create_context_profile use FBConfigs, * and these only exist in GLX 1.4 or with GLX_SGIX_fbconfig. I can't * imagine an implementation that supports GLX_SGIX_fbconfig and * GLX_ARB_create_context but not GLX 1.4. Making GLX 1.4 a hard * requirement in this case does not seem like a limitation. * * This library currently only supports struct GLXClientInfo. */ if (glx_dpy->majorVersion == 1 && glx_dpy->minorVersion == 0) return; /* Determine whether any screen on the server supports either of the * create-context extensions. */ for (i = 0; i < ScreenCount(glx_dpy->dpy); i++) { struct glx_screen *src = glx_dpy->screens[i]; const char *haystack = src->serverGLXexts; while (haystack != NULL) { char *match = strstr(haystack, "GLX_ARB_create_context"); if (match == NULL) break; match += ext_length; switch (match[0]) { case '\0': case ' ': any_screen_has_ARB_create_context = True; break; case '_': if (strncmp(match, "_profile", prof_length) == 0 && (match[prof_length] == '\0' || match[prof_length] == ' ')) { any_screen_has_ARB_create_context_profile = True; match += prof_length; } break; } haystack = match; } } gl_extension_string = __glXGetClientGLExtensionString(); if (gl_extension_string == NULL) { return; } gl_extension_length = strlen(gl_extension_string) + 1; c = XGetXCBConnection(glx_dpy->dpy); /* Depending on the GLX verion and the available extensions on the server, * send the correct "flavor" of protocol to the server. * * THE ORDER IS IMPORTANT. We want to send the most recent version of the * protocol that the server can support. */ if (glx_dpy->majorVersion == 1 && glx_dpy->minorVersion == 4 && any_screen_has_ARB_create_context_profile) { xcb_glx_set_client_info_2arb(c, GLX_MAJOR_VERSION, GLX_MINOR_VERSION, sizeof(gl_versions_profiles) / (3 * sizeof(gl_versions_profiles[0])), gl_extension_length, strlen(glx_extensions) + 1, gl_versions_profiles, gl_extension_string, glx_extensions); } else if (glx_dpy->majorVersion == 1 && glx_dpy->minorVersion == 4 && any_screen_has_ARB_create_context) { xcb_glx_set_client_info_arb(c, GLX_MAJOR_VERSION, GLX_MINOR_VERSION, sizeof(gl_versions) / (2 * sizeof(gl_versions[0])), gl_extension_length, strlen(glx_extensions) + 1, gl_versions, gl_extension_string, glx_extensions); } else { xcb_glx_client_info(c, GLX_MAJOR_VERSION, GLX_MINOR_VERSION, gl_extension_length, gl_extension_string); } free(gl_extension_string); }