Home | History | Annotate | Download | only in x11
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 #include "SDL_x11video.h"
     25 #include "../../events/SDL_events_c.h"
     26 #include "SDL_x11dga_c.h"
     27 #include "SDL_x11gl_c.h"
     28 
     29 #if defined(__IRIX__)
     30 /* IRIX doesn't have a GL library versioning system */
     31 #define DEFAULT_OPENGL	"libGL.so"
     32 #elif defined(__MACOSX__)
     33 #define DEFAULT_OPENGL	"/usr/X11R6/lib/libGL.1.dylib"
     34 #elif defined(__QNXNTO__)
     35 #define DEFAULT_OPENGL	"libGL.so.3"
     36 #elif defined(__OpenBSD__)
     37 #define DEFAULT_OPENGL	"libGL.so.4.0"
     38 #else
     39 #define DEFAULT_OPENGL	"libGL.so.1"
     40 #endif
     41 
     42 #ifndef GLX_ARB_multisample
     43 #define GLX_ARB_multisample
     44 #define GLX_SAMPLE_BUFFERS_ARB             100000
     45 #define GLX_SAMPLES_ARB                    100001
     46 #endif
     47 
     48 /* GLX_EXT_visual_rating stuff that might not be in the system headers... */
     49 #ifndef GLX_VISUAL_CAVEAT_EXT
     50 #define GLX_VISUAL_CAVEAT_EXT              0x20
     51 #endif
     52 #ifndef GLX_NONE_EXT
     53 #define GLX_NONE_EXT                       0x8000
     54 #endif
     55 #ifndef GLX_SLOW_VISUAL_EXT
     56 #define GLX_SLOW_VISUAL_EXT                0x8001
     57 #endif
     58 #ifndef GLX_NON_CONFORMANT_VISUAL_EXT
     59 #define GLX_NON_CONFORMANT_VISUAL_EXT      0x800D
     60 #endif
     61 
     62 
     63 #if SDL_VIDEO_OPENGL_GLX
     64 static int glXExtensionSupported(_THIS, const char *extension)
     65 {
     66 	const char *extensions;
     67 	const char *start;
     68 	const char *where, *terminator;
     69 
     70 	/* Extension names should not have spaces. */
     71 	where = SDL_strchr(extension, ' ');
     72 	if ( where || *extension == '\0' ) {
     73 	      return 0;
     74 	}
     75 
     76 	extensions = this->gl_data->glXQueryExtensionsString(GFX_Display,SDL_Screen);
     77 	/* It takes a bit of care to be fool-proof about parsing the
     78 	 * OpenGL extensions string. Don't be fooled by sub-strings, etc.
     79 	 */
     80 
     81 	/* http://bugs.debian.org/537487 */
     82 	if (extensions == NULL) {
     83 	      return 0;
     84 	}
     85 
     86 	start = extensions;
     87 
     88 	for (;;) {
     89 		where = SDL_strstr(start, extension);
     90 		if (!where) break;
     91 
     92 		terminator = where + strlen(extension);
     93 		if (where == start || *(where - 1) == ' ')
     94 	        if (*terminator == ' ' || *terminator == '\0') return 1;
     95 
     96 		start = terminator;
     97 	}
     98 	return 0;
     99 }
    100 #endif /* SDL_VIDEO_OPENGL_GLX */
    101 
    102 XVisualInfo *X11_GL_GetVisual(_THIS)
    103 {
    104 #if SDL_VIDEO_OPENGL_GLX
    105 	/* 64 seems nice. */
    106 	int attribs[64];
    107 	int i;
    108 
    109 	/* load the gl driver from a default path */
    110 	if ( ! this->gl_config.driver_loaded ) {
    111 	        /* no driver has been loaded, use default (ourselves) */
    112 	        if ( X11_GL_LoadLibrary(this, NULL) < 0 ) {
    113 		        return NULL;
    114 		}
    115 	}
    116 
    117 	/* See if we already have a window which we must use */
    118 	if ( SDL_windowid ) {
    119 		XWindowAttributes a;
    120 		XVisualInfo vi_in;
    121 		int out_count;
    122 
    123 		XGetWindowAttributes(SDL_Display, SDL_Window, &a);
    124 		vi_in.screen = SDL_Screen;
    125 		vi_in.visualid = XVisualIDFromVisual(a.visual);
    126 		glx_visualinfo = XGetVisualInfo(SDL_Display,
    127 	                     VisualScreenMask|VisualIDMask, &vi_in, &out_count);
    128 		return glx_visualinfo;
    129 	}
    130 
    131         /* Setup our GLX attributes according to the gl_config. */
    132 	i = 0;
    133 	attribs[i++] = GLX_RGBA;
    134 	attribs[i++] = GLX_RED_SIZE;
    135 	attribs[i++] = this->gl_config.red_size;
    136 	attribs[i++] = GLX_GREEN_SIZE;
    137 	attribs[i++] = this->gl_config.green_size;
    138 	attribs[i++] = GLX_BLUE_SIZE;
    139 	attribs[i++] = this->gl_config.blue_size;
    140 
    141 	if( this->gl_config.alpha_size ) {
    142 		attribs[i++] = GLX_ALPHA_SIZE;
    143 		attribs[i++] = this->gl_config.alpha_size;
    144 	}
    145 
    146 	if( this->gl_config.double_buffer ) {
    147 		attribs[i++] = GLX_DOUBLEBUFFER;
    148 	}
    149 
    150 	attribs[i++] = GLX_DEPTH_SIZE;
    151 	attribs[i++] = this->gl_config.depth_size;
    152 
    153 	if( this->gl_config.stencil_size ) {
    154 		attribs[i++] = GLX_STENCIL_SIZE;
    155 		attribs[i++] = this->gl_config.stencil_size;
    156 	}
    157 
    158 	if( this->gl_config.accum_red_size ) {
    159 		attribs[i++] = GLX_ACCUM_RED_SIZE;
    160 		attribs[i++] = this->gl_config.accum_red_size;
    161 	}
    162 
    163 	if( this->gl_config.accum_green_size ) {
    164 		attribs[i++] = GLX_ACCUM_GREEN_SIZE;
    165 		attribs[i++] = this->gl_config.accum_green_size;
    166 	}
    167 
    168 	if( this->gl_config.accum_blue_size ) {
    169 		attribs[i++] = GLX_ACCUM_BLUE_SIZE;
    170 		attribs[i++] = this->gl_config.accum_blue_size;
    171 	}
    172 
    173 	if( this->gl_config.accum_alpha_size ) {
    174 		attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
    175 		attribs[i++] = this->gl_config.accum_alpha_size;
    176 	}
    177 
    178 	if( this->gl_config.stereo ) {
    179 		attribs[i++] = GLX_STEREO;
    180 	}
    181 
    182 	if( this->gl_config.multisamplebuffers ) {
    183 		attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
    184 		attribs[i++] = this->gl_config.multisamplebuffers;
    185 	}
    186 
    187 	if( this->gl_config.multisamplesamples ) {
    188 		attribs[i++] = GLX_SAMPLES_ARB;
    189 		attribs[i++] = this->gl_config.multisamplesamples;
    190 	}
    191 
    192 	if( this->gl_config.accelerated >= 0 &&
    193 	    glXExtensionSupported(this, "GLX_EXT_visual_rating") ) {
    194 		attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
    195 		attribs[i++] = GLX_NONE_EXT;
    196 	}
    197 
    198 #ifdef GLX_DIRECT_COLOR /* Try for a DirectColor visual for gamma support */
    199 	if ( !SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) {
    200 		attribs[i++] = GLX_X_VISUAL_TYPE;
    201 		attribs[i++] = GLX_DIRECT_COLOR;
    202 	}
    203 #endif
    204 	attribs[i++] = None;
    205 
    206  	glx_visualinfo = this->gl_data->glXChooseVisual(GFX_Display,
    207 						  SDL_Screen, attribs);
    208 #ifdef GLX_DIRECT_COLOR
    209 	if( !glx_visualinfo && !SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) { /* No DirectColor visual?  Try again.. */
    210 		attribs[i-3] = None;
    211  		glx_visualinfo = this->gl_data->glXChooseVisual(GFX_Display,
    212 						  SDL_Screen, attribs);
    213 	}
    214 #endif
    215 	if( !glx_visualinfo ) {
    216 		SDL_SetError( "Couldn't find matching GLX visual");
    217 		return NULL;
    218 	}
    219 /*
    220 	printf("Found GLX visual 0x%x\n", glx_visualinfo->visualid);
    221 */
    222 	return glx_visualinfo;
    223 #else
    224 	SDL_SetError("X11 driver not configured with OpenGL");
    225 	return NULL;
    226 #endif
    227 }
    228 
    229 int X11_GL_CreateWindow(_THIS, int w, int h)
    230 {
    231 	int retval;
    232 #if SDL_VIDEO_OPENGL_GLX
    233 	XSetWindowAttributes attributes;
    234 	unsigned long mask;
    235 	unsigned long black;
    236 
    237 	black = (glx_visualinfo->visual == DefaultVisual(SDL_Display,
    238 						 	SDL_Screen))
    239 	       	? BlackPixel(SDL_Display, SDL_Screen) : 0;
    240 	attributes.background_pixel = black;
    241 	attributes.border_pixel = black;
    242 	attributes.colormap = SDL_XColorMap;
    243 	mask = CWBackPixel | CWBorderPixel | CWColormap;
    244 
    245 	SDL_Window = XCreateWindow(SDL_Display, WMwindow,
    246 			0, 0, w, h, 0, glx_visualinfo->depth,
    247 			InputOutput, glx_visualinfo->visual,
    248 			mask, &attributes);
    249 	if ( !SDL_Window ) {
    250 		SDL_SetError("Could not create window");
    251 		return -1;
    252 	}
    253 	retval = 0;
    254 #else
    255 	SDL_SetError("X11 driver not configured with OpenGL");
    256 	retval = -1;
    257 #endif
    258 	return(retval);
    259 }
    260 
    261 int X11_GL_CreateContext(_THIS)
    262 {
    263 	int retval;
    264 #if SDL_VIDEO_OPENGL_GLX
    265 
    266 	/* We do this to create a clean separation between X and GLX errors. */
    267 	XSync( SDL_Display, False );
    268 	glx_context = this->gl_data->glXCreateContext(GFX_Display,
    269 				     glx_visualinfo, NULL, True);
    270 	XSync( GFX_Display, False );
    271 
    272 	if ( glx_context == NULL ) {
    273 		SDL_SetError("Could not create GL context");
    274 		return(-1);
    275 	}
    276 	if ( X11_GL_MakeCurrent(this) < 0 ) {
    277 		return(-1);
    278 	}
    279 	gl_active = 1;
    280 
    281 	if ( !glXExtensionSupported(this, "GLX_SGI_swap_control") ) {
    282 		this->gl_data->glXSwapIntervalSGI = NULL;
    283 	}
    284 	if ( !glXExtensionSupported(this, "GLX_MESA_swap_control") ) {
    285 		this->gl_data->glXSwapIntervalMESA = NULL;
    286 	}
    287 	if ( !glXExtensionSupported(this, "GLX_EXT_swap_control") ) {
    288 		this->gl_data->glXSwapIntervalEXT = NULL;
    289 	}
    290 
    291 	if ( this->gl_config.swap_control >= 0 ) {
    292 		int rc = -1;
    293 		if ( this->gl_data->glXSwapIntervalEXT ) {
    294 			rc = this->gl_data->glXSwapIntervalEXT(GFX_Display, SDL_Window,
    295 					this->gl_config.swap_control);
    296 		} else if ( this->gl_data->glXSwapIntervalMESA ) {
    297 			rc = this->gl_data->glXSwapIntervalMESA(this->gl_config.swap_control);
    298 		} else if ( this->gl_data->glXSwapIntervalSGI ) {
    299 			rc = this->gl_data->glXSwapIntervalSGI(this->gl_config.swap_control);
    300 		}
    301 		if (rc == 0) {
    302 			this->gl_data->swap_interval = this->gl_config.swap_control;
    303 		}
    304 	}
    305 #else
    306 	SDL_SetError("X11 driver not configured with OpenGL");
    307 #endif
    308 	if ( gl_active ) {
    309 		retval = 0;
    310 	} else {
    311 		retval = -1;
    312 	}
    313 	return(retval);
    314 }
    315 
    316 void X11_GL_Shutdown(_THIS)
    317 {
    318 #if SDL_VIDEO_OPENGL_GLX
    319 	/* Clean up OpenGL */
    320 	if( glx_context ) {
    321 		this->gl_data->glXMakeCurrent(GFX_Display, None, NULL);
    322 
    323 		if (glx_context != NULL)
    324 			this->gl_data->glXDestroyContext(GFX_Display, glx_context);
    325 
    326 		glx_context = NULL;
    327 	}
    328 	gl_active = 0;
    329 #endif /* SDL_VIDEO_OPENGL_GLX */
    330 }
    331 
    332 #if SDL_VIDEO_OPENGL_GLX
    333 
    334 /* Make the current context active */
    335 int X11_GL_MakeCurrent(_THIS)
    336 {
    337 	int retval;
    338 
    339 	retval = 0;
    340 	if ( ! this->gl_data->glXMakeCurrent(GFX_Display,
    341 	                                     SDL_Window, glx_context) ) {
    342 		SDL_SetError("Unable to make GL context current");
    343 		retval = -1;
    344 	}
    345 	XSync( GFX_Display, False );
    346 
    347 	/* More Voodoo X server workarounds... Grr... */
    348 	SDL_Lock_EventThread();
    349 	X11_CheckDGAMouse(this);
    350 	SDL_Unlock_EventThread();
    351 
    352 	return(retval);
    353 }
    354 
    355 /* Get attribute data from glX. */
    356 int X11_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
    357 {
    358 	int retval = -1;
    359 	int unsupported = 0;
    360 	int glx_attrib = None;
    361 
    362 	switch( attrib ) {
    363 	    case SDL_GL_RED_SIZE:
    364 		glx_attrib = GLX_RED_SIZE;
    365 		break;
    366 	    case SDL_GL_GREEN_SIZE:
    367 		glx_attrib = GLX_GREEN_SIZE;
    368 		break;
    369 	    case SDL_GL_BLUE_SIZE:
    370 		glx_attrib = GLX_BLUE_SIZE;
    371 		break;
    372 	    case SDL_GL_ALPHA_SIZE:
    373 		glx_attrib = GLX_ALPHA_SIZE;
    374 		break;
    375 	    case SDL_GL_DOUBLEBUFFER:
    376 		glx_attrib = GLX_DOUBLEBUFFER;
    377 		break;
    378 	    case SDL_GL_BUFFER_SIZE:
    379 		glx_attrib = GLX_BUFFER_SIZE;
    380 		break;
    381 	    case SDL_GL_DEPTH_SIZE:
    382 		glx_attrib = GLX_DEPTH_SIZE;
    383 		break;
    384 	    case SDL_GL_STENCIL_SIZE:
    385 		glx_attrib = GLX_STENCIL_SIZE;
    386 		break;
    387 	    case SDL_GL_ACCUM_RED_SIZE:
    388 		glx_attrib = GLX_ACCUM_RED_SIZE;
    389 		break;
    390 	    case SDL_GL_ACCUM_GREEN_SIZE:
    391 		glx_attrib = GLX_ACCUM_GREEN_SIZE;
    392 		break;
    393 	    case SDL_GL_ACCUM_BLUE_SIZE:
    394 		glx_attrib = GLX_ACCUM_BLUE_SIZE;
    395 		break;
    396 	    case SDL_GL_ACCUM_ALPHA_SIZE:
    397 		glx_attrib = GLX_ACCUM_ALPHA_SIZE;
    398 		break;
    399 	    case SDL_GL_STEREO:
    400 		glx_attrib = GLX_STEREO;
    401 		break;
    402  	    case SDL_GL_MULTISAMPLEBUFFERS:
    403  		glx_attrib = GLX_SAMPLE_BUFFERS_ARB;
    404  		break;
    405  	    case SDL_GL_MULTISAMPLESAMPLES:
    406  		glx_attrib = GLX_SAMPLES_ARB;
    407  		break;
    408  	    case SDL_GL_ACCELERATED_VISUAL:
    409 		if ( glXExtensionSupported(this, "GLX_EXT_visual_rating") ) {
    410 			glx_attrib = GLX_VISUAL_CAVEAT_EXT;
    411 			retval = this->gl_data->glXGetConfig(GFX_Display, glx_visualinfo, glx_attrib, value);
    412 			if ( *value == GLX_SLOW_VISUAL_EXT ) {
    413 				*value = SDL_FALSE;
    414 			} else {
    415 				*value = SDL_TRUE;
    416 			}
    417 			return retval;
    418 		} else {
    419 			unsupported = 1;
    420 		}
    421 		break;
    422 	    case SDL_GL_SWAP_CONTROL:
    423 		if ( ( this->gl_data->glXSwapIntervalEXT ) ||
    424 		     ( this->gl_data->glXSwapIntervalMESA ) ||
    425 		     ( this->gl_data->glXSwapIntervalSGI ) ) {
    426 			*value = this->gl_data->swap_interval;
    427 			return 0;
    428 		} else {
    429 			unsupported = 1;
    430 		}
    431 		break;
    432 	    default:
    433 			unsupported = 1;
    434 			break;
    435 	}
    436 
    437 	if (unsupported) {
    438 		SDL_SetError("OpenGL attribute is unsupported on this system");
    439 	} else {
    440 		retval = this->gl_data->glXGetConfig(GFX_Display, glx_visualinfo, glx_attrib, value);
    441 	}
    442 	return retval;
    443 }
    444 
    445 void X11_GL_SwapBuffers(_THIS)
    446 {
    447 	this->gl_data->glXSwapBuffers(GFX_Display, SDL_Window);
    448 }
    449 
    450 #endif /* SDL_VIDEO_OPENGL_GLX */
    451 
    452 #define OPENGL_REQUIRS_DLOPEN
    453 #if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
    454 #include <dlfcn.h>
    455 #define GL_LoadObject(X)	dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
    456 #define GL_LoadFunction		dlsym
    457 #define GL_UnloadObject		dlclose
    458 #else
    459 #define GL_LoadObject	SDL_LoadObject
    460 #define GL_LoadFunction	SDL_LoadFunction
    461 #define GL_UnloadObject	SDL_UnloadObject
    462 #endif
    463 
    464 void X11_GL_UnloadLibrary(_THIS)
    465 {
    466 #if SDL_VIDEO_OPENGL_GLX
    467 	if ( this->gl_config.driver_loaded ) {
    468 
    469 		GL_UnloadObject(this->gl_config.dll_handle);
    470 
    471 		this->gl_data->glXGetProcAddress = NULL;
    472 		this->gl_data->glXChooseVisual = NULL;
    473 		this->gl_data->glXCreateContext = NULL;
    474 		this->gl_data->glXDestroyContext = NULL;
    475 		this->gl_data->glXMakeCurrent = NULL;
    476 		this->gl_data->glXSwapBuffers = NULL;
    477 		this->gl_data->glXSwapIntervalSGI = NULL;
    478 		this->gl_data->glXSwapIntervalMESA = NULL;
    479 		this->gl_data->glXSwapIntervalEXT = NULL;
    480 
    481 		this->gl_config.dll_handle = NULL;
    482 		this->gl_config.driver_loaded = 0;
    483 	}
    484 #endif
    485 }
    486 
    487 #if SDL_VIDEO_OPENGL_GLX
    488 
    489 /* Passing a NULL path means load pointers from the application */
    490 int X11_GL_LoadLibrary(_THIS, const char* path)
    491 {
    492 	void* handle = NULL;
    493 
    494 	if ( gl_active ) {
    495 		SDL_SetError("OpenGL context already created");
    496 		return -1;
    497 	}
    498 
    499 	if ( path == NULL ) {
    500 		path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
    501 		if ( path == NULL ) {
    502 			path = DEFAULT_OPENGL;
    503 		}
    504 	}
    505 
    506 	handle = GL_LoadObject(path);
    507 	if ( handle == NULL ) {
    508 #if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
    509 		SDL_SetError("Failed loading %s", path);
    510 #else
    511 		/* SDL_LoadObject() will call SDL_SetError() for us. */
    512 #endif
    513 		return -1;
    514 	}
    515 
    516 	/* Unload the old driver and reset the pointers */
    517 	X11_GL_UnloadLibrary(this);
    518 
    519 	/* Save the handle for X11_GL_GetProcAddress() */
    520 	this->gl_config.dll_handle = handle;
    521 
    522 	/* Load new function pointers */
    523 	this->gl_data->glXGetProcAddress =
    524 		(void *(*)(const GLubyte *)) GL_LoadFunction(handle, "glXGetProcAddressARB");
    525 	this->gl_data->glXChooseVisual =
    526 		(XVisualInfo *(*)(Display *, int, int *)) X11_GL_GetProcAddress(this, "glXChooseVisual");
    527 	this->gl_data->glXCreateContext =
    528 		(GLXContext (*)(Display *, XVisualInfo *, GLXContext, int)) X11_GL_GetProcAddress(this, "glXCreateContext");
    529 	this->gl_data->glXDestroyContext =
    530 		(void (*)(Display *, GLXContext)) X11_GL_GetProcAddress(this, "glXDestroyContext");
    531 	this->gl_data->glXMakeCurrent =
    532 		(int (*)(Display *, GLXDrawable, GLXContext)) X11_GL_GetProcAddress(this, "glXMakeCurrent");
    533 	this->gl_data->glXSwapBuffers =
    534 		(void (*)(Display *, GLXDrawable)) X11_GL_GetProcAddress(this, "glXSwapBuffers");
    535 	this->gl_data->glXGetConfig =
    536 		(int (*)(Display *, XVisualInfo *, int, int *)) X11_GL_GetProcAddress(this, "glXGetConfig");
    537 	this->gl_data->glXQueryExtensionsString =
    538 		(const char *(*)(Display *, int)) X11_GL_GetProcAddress(this, "glXQueryExtensionsString");
    539 	this->gl_data->glXSwapIntervalSGI =
    540 		(int (*)(int)) X11_GL_GetProcAddress(this, "glXSwapIntervalSGI");
    541 	this->gl_data->glXSwapIntervalMESA =
    542 		(GLint (*)(unsigned)) X11_GL_GetProcAddress(this, "glXSwapIntervalMESA");
    543 	this->gl_data->glXSwapIntervalEXT =
    544 		(int (*)(Display*,GLXDrawable,int)) X11_GL_GetProcAddress(this, "glXSwapIntervalEXT");
    545 
    546 	if ( (this->gl_data->glXChooseVisual == NULL) ||
    547 	     (this->gl_data->glXCreateContext == NULL) ||
    548 	     (this->gl_data->glXDestroyContext == NULL) ||
    549 	     (this->gl_data->glXMakeCurrent == NULL) ||
    550 	     (this->gl_data->glXSwapBuffers == NULL) ||
    551 	     (this->gl_data->glXGetConfig == NULL) ||
    552 	     (this->gl_data->glXQueryExtensionsString == NULL)) {
    553 		GL_UnloadObject(this->gl_config.dll_handle);
    554 		this->gl_config.dll_handle = NULL;
    555 		SDL_SetError("Could not retrieve OpenGL functions");
    556 		return -1;
    557 	}
    558 
    559 	this->gl_config.driver_loaded = 1;
    560 	if ( path ) {
    561 		SDL_strlcpy(this->gl_config.driver_path, path,
    562 			SDL_arraysize(this->gl_config.driver_path));
    563 	} else {
    564 		*this->gl_config.driver_path = '\0';
    565 	}
    566 	return 0;
    567 }
    568 
    569 void *X11_GL_GetProcAddress(_THIS, const char* proc)
    570 {
    571 	if ( this->gl_data->glXGetProcAddress ) {
    572 		return this->gl_data->glXGetProcAddress((const GLubyte *)proc);
    573 	}
    574 	return GL_LoadFunction(this->gl_config.dll_handle, proc);
    575 }
    576 
    577 #endif /* SDL_VIDEO_OPENGL_GLX */
    578