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#include <string.h> 25#include <ctype.h> 26 27#include "glxclient.h" 28#include <xcb/glx.h> 29#include <X11/Xlib-xcb.h> 30 31_X_HIDDEN void 32__glX_send_client_info(struct glx_display *glx_dpy) 33{ 34 const unsigned ext_length = strlen("GLX_ARB_create_context"); 35 const unsigned prof_length = strlen("_profile"); 36 char *gl_extension_string; 37 int gl_extension_length; 38 xcb_connection_t *c; 39 Bool any_screen_has_ARB_create_context = False; 40 Bool any_screen_has_ARB_create_context_profile = False; 41 unsigned i; 42 static const uint32_t gl_versions[] = { 43 1, 4, 44 }; 45 static const uint32_t gl_versions_profiles[] = { 46 1, 4, 0x00000000, 47 }; 48 static const char glx_extensions[] = 49 "GLX_ARB_create_context GLX_ARB_create_context_profile"; 50 51 /* There are three possible flavors of the client info structure that the 52 * client could send to the server. The version sent depends on the 53 * combination of GLX versions and extensions supported by the client and 54 * the server. 55 * 56 * Server supports Client sends 57 * ---------------------------------------------------------------------- 58 * GLX version = 1.0 Nothing. 59 * 60 * GLX version >= 1.1 struct GLXClientInfo 61 * 62 * GLX version >= 1.4 and 63 * GLX_ARB_create_context struct glXSetClientInfoARB 64 * 65 * GLX version >= 1.4 and 66 * GLX_ARB_create_context_profile struct glXSetClientInfo2ARB 67 * 68 * GLX_ARB_create_context and GLX_ARB_create_context_profile use FBConfigs, 69 * and these only exist in GLX 1.4 or with GLX_SGIX_fbconfig. I can't 70 * imagine an implementation that supports GLX_SGIX_fbconfig and 71 * GLX_ARB_create_context but not GLX 1.4. Making GLX 1.4 a hard 72 * requirement in this case does not seem like a limitation. 73 * 74 * This library currently only supports struct GLXClientInfo. 75 */ 76 77 if (glx_dpy->majorVersion == 1 && glx_dpy->minorVersion == 0) 78 return; 79 80 /* Determine whether any screen on the server supports either of the 81 * create-context extensions. 82 */ 83 for (i = 0; i < ScreenCount(glx_dpy->dpy); i++) { 84 struct glx_screen *src = glx_dpy->screens[i]; 85 86 const char *haystack = src->serverGLXexts; 87 while (haystack != NULL) { 88 char *match = strstr(haystack, "GLX_ARB_create_context"); 89 90 if (match == NULL) 91 break; 92 93 match += ext_length; 94 95 switch (match[0]) { 96 case '\0': 97 case ' ': 98 any_screen_has_ARB_create_context = True; 99 break; 100 101 case '_': 102 if (strncmp(match, "_profile", prof_length) == 0 103 && (match[prof_length] == '\0' 104 || match[prof_length] == ' ')) { 105 any_screen_has_ARB_create_context_profile = True; 106 match += prof_length; 107 } 108 break; 109 } 110 111 haystack = match; 112 } 113 } 114 115 gl_extension_string = __glXGetClientGLExtensionString(); 116 if (gl_extension_string == NULL) { 117 return; 118 } 119 120 gl_extension_length = strlen(gl_extension_string) + 1; 121 122 c = XGetXCBConnection(glx_dpy->dpy); 123 124 /* Depending on the GLX verion and the available extensions on the server, 125 * send the correct "flavor" of protocol to the server. 126 * 127 * THE ORDER IS IMPORTANT. We want to send the most recent version of the 128 * protocol that the server can support. 129 */ 130 if (glx_dpy->majorVersion == 1 && glx_dpy->minorVersion == 4 131 && any_screen_has_ARB_create_context_profile) { 132 xcb_glx_set_client_info_2arb(c, 133 GLX_MAJOR_VERSION, GLX_MINOR_VERSION, 134 sizeof(gl_versions_profiles) 135 / (3 * sizeof(gl_versions_profiles[0])), 136 gl_extension_length, 137 strlen(glx_extensions) + 1, 138 gl_versions_profiles, 139 gl_extension_string, 140 glx_extensions); 141 } else if (glx_dpy->majorVersion == 1 && glx_dpy->minorVersion == 4 142 && any_screen_has_ARB_create_context) { 143 xcb_glx_set_client_info_arb(c, 144 GLX_MAJOR_VERSION, GLX_MINOR_VERSION, 145 sizeof(gl_versions) 146 / (2 * sizeof(gl_versions[0])), 147 gl_extension_length, 148 strlen(glx_extensions) + 1, 149 gl_versions, 150 gl_extension_string, 151 glx_extensions); 152 } else { 153 xcb_glx_client_info(c, 154 GLX_MAJOR_VERSION, GLX_MINOR_VERSION, 155 gl_extension_length, 156 gl_extension_string); 157 } 158 159 free(gl_extension_string); 160} 161