16ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick/*
26ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * Copyright © 2011 Intel Corporation
36ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick *
46ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * Permission is hereby granted, free of charge, to any person obtaining a
56ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * copy of this software and associated documentation files (the "Software"),
66ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * to deal in the Software without restriction, including without limitation
76ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * and/or sell copies of the Software, and to permit persons to whom the
96ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * Software is furnished to do so, subject to the following conditions:
106ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick *
116ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * The above copyright notice and this permission notice (including the next
126ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * paragraph) shall be included in all copies or substantial portions of the
136ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * Software.
146ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick *
156ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
196ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
206ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
216ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick * DEALINGS IN THE SOFTWARE.
226ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick */
236ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
246ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick#include <string.h>
256ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick#include <ctype.h>
266ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
276ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick#include "glxclient.h"
286ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick#include <xcb/glx.h>
296ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick#include <X11/Xlib-xcb.h>
306ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
316ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick_X_HIDDEN void
326ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick__glX_send_client_info(struct glx_display *glx_dpy)
336ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick{
346ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   const unsigned ext_length = strlen("GLX_ARB_create_context");
356ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   const unsigned prof_length = strlen("_profile");
366ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   char *gl_extension_string;
376ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   int gl_extension_length;
386ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   xcb_connection_t *c;
396ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   Bool any_screen_has_ARB_create_context = False;
406ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   Bool any_screen_has_ARB_create_context_profile = False;
416ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   unsigned i;
426ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   static const uint32_t gl_versions[] = {
436ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      1, 4,
446ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   };
456ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   static const uint32_t gl_versions_profiles[] = {
466ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      1, 4, 0x00000000,
476ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   };
486ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   static const char glx_extensions[] =
496ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      "GLX_ARB_create_context GLX_ARB_create_context_profile";
506ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
516ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   /* There are three possible flavors of the client info structure that the
526ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * client could send to the server.  The version sent depends on the
536ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * combination of GLX versions and extensions supported by the client and
546ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * the server.
556ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    *
566ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * Server supports                  Client sends
576ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * ----------------------------------------------------------------------
586ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * GLX version = 1.0                Nothing.
596ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    *
606ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * GLX version >= 1.1               struct GLXClientInfo
616ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    *
626ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * GLX version >= 1.4 and
636ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * GLX_ARB_create_context           struct glXSetClientInfoARB
646ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    *
656ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * GLX version >= 1.4 and
666ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * GLX_ARB_create_context_profile   struct glXSetClientInfo2ARB
676ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    *
686ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * GLX_ARB_create_context and GLX_ARB_create_context_profile use FBConfigs,
696ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * and these only exist in GLX 1.4 or with GLX_SGIX_fbconfig.  I can't
706ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * imagine an implementation that supports GLX_SGIX_fbconfig and
716ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * GLX_ARB_create_context but not GLX 1.4.  Making GLX 1.4 a hard
726ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * requirement in this case does not seem like a limitation.
736ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    *
746ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * This library currently only supports struct GLXClientInfo.
756ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    */
766ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
776ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   if (glx_dpy->majorVersion == 1 && glx_dpy->minorVersion == 0)
786ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      return;
796ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
806ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   /* Determine whether any screen on the server supports either of the
816ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * create-context extensions.
826ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    */
836ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   for (i = 0; i < ScreenCount(glx_dpy->dpy); i++) {
846ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      struct glx_screen *src = glx_dpy->screens[i];
856ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
866ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      const char *haystack = src->serverGLXexts;
876ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      while (haystack != NULL) {
886ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	 char *match = strstr(haystack, "GLX_ARB_create_context");
896ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
906ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	 if (match == NULL)
916ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	    break;
926ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
936ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	 match += ext_length;
946ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
956ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	 switch (match[0]) {
966ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	 case '\0':
976ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	 case ' ':
986ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	    any_screen_has_ARB_create_context = True;
996ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	    break;
1006ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
1016ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	 case '_':
1026ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	    if (strncmp(match, "_profile", prof_length) == 0
1036ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick		    && (match[prof_length] == '\0'
1046ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick			|| match[prof_length] == ' ')) {
1056ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	       any_screen_has_ARB_create_context_profile = True;
1066ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	       match += prof_length;
1076ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	    }
1086ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	    break;
1096ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	 }
1106ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
1116ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	 haystack = match;
1126ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      }
1136ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   }
1146ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
1156ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   gl_extension_string = __glXGetClientGLExtensionString();
116d530745169282469b2dd8221629ef948ff31bcf3Juha-Pekka Heikkila   if (gl_extension_string == NULL) {
117d530745169282469b2dd8221629ef948ff31bcf3Juha-Pekka Heikkila      return;
118d530745169282469b2dd8221629ef948ff31bcf3Juha-Pekka Heikkila   }
119d530745169282469b2dd8221629ef948ff31bcf3Juha-Pekka Heikkila
1206ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   gl_extension_length = strlen(gl_extension_string) + 1;
1216ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
1226ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   c = XGetXCBConnection(glx_dpy->dpy);
1236ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
1246ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   /* Depending on the GLX verion and the available extensions on the server,
1256ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * send the correct "flavor" of protocol to the server.
1266ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    *
1276ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * THE ORDER IS IMPORTANT.  We want to send the most recent version of the
1286ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    * protocol that the server can support.
1296ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick    */
1306ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   if (glx_dpy->majorVersion == 1 && glx_dpy->minorVersion == 4
1316ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick       && any_screen_has_ARB_create_context_profile) {
1326ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      xcb_glx_set_client_info_2arb(c,
1336ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  GLX_MAJOR_VERSION, GLX_MINOR_VERSION,
1346ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				   sizeof(gl_versions_profiles)
1356ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				   / (3 * sizeof(gl_versions_profiles[0])),
1366ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  gl_extension_length,
1376ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  strlen(glx_extensions) + 1,
1386ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  gl_versions_profiles,
1396ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  gl_extension_string,
1406ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  glx_extensions);
1416ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   } else if (glx_dpy->majorVersion == 1 && glx_dpy->minorVersion == 4
1426ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick	      && any_screen_has_ARB_create_context) {
1436ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      xcb_glx_set_client_info_arb(c,
1446ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  GLX_MAJOR_VERSION, GLX_MINOR_VERSION,
1456ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  sizeof(gl_versions)
1466ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  / (2 * sizeof(gl_versions[0])),
1476ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  gl_extension_length,
1486ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  strlen(glx_extensions) + 1,
1496ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  gl_versions,
1506ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  gl_extension_string,
1516ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick				  glx_extensions);
1526882381a2efbdf06b7002d11468c94b9964c2bc8Eric Anholt   } else {
1536ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick      xcb_glx_client_info(c,
1546ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick			  GLX_MAJOR_VERSION, GLX_MINOR_VERSION,
1556ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick			  gl_extension_length,
1566ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick			  gl_extension_string);
1576ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick   }
1586ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick
1597c7b7b068b1d0dc8e14b87dab5dbd4108f874f74Matt Turner   free(gl_extension_string);
1606ccda72bf87a27844f8b9807fc080984f48af1cfIan Romanick}
161