Home | History | Annotate | Download | only in glx
      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