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 Library General Public
      7     License as published by the Free Software Foundation; either
      8     version 2 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     Library General Public License for more details.
     14 
     15     You should have received a copy of the GNU Library General Public
     16     License along with this library; if not, write to the Free
     17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 #define DEBUG_DYNAMIC_X11 0
     25 
     26 #include "SDL_x11dyn.h"
     27 
     28 #if DEBUG_DYNAMIC_X11
     29 #include <stdio.h>
     30 #endif
     31 
     32 #ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
     33 
     34 #include "SDL_name.h"
     35 #include "SDL_loadso.h"
     36 
     37 typedef struct
     38 {
     39     void *lib;
     40     const char *libname;
     41 } x11dynlib;
     42 
     43 #ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC
     44 #define SDL_VIDEO_DRIVER_X11_DYNAMIC NULL
     45 #endif
     46 #ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT
     47 #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT NULL
     48 #endif
     49 #ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER
     50 #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER NULL
     51 #endif
     52 #ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR
     53 #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR NULL
     54 #endif
     55 
     56 static x11dynlib x11libs[] =
     57 {
     58     { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC },
     59     { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT },
     60     { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER },
     61     { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR },
     62 };
     63 
     64 static void *X11_GetSym(const char *fnname, int *rc)
     65 {
     66 	void *fn = NULL;
     67 	int i;
     68 	for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
     69 		if (x11libs[i].lib != NULL)
     70 		{
     71 			fn = SDL_LoadFunction(x11libs[i].lib, fnname);
     72 			if (fn != NULL)
     73 				break;
     74 		}
     75 	}
     76 
     77 	#if DEBUG_DYNAMIC_X11
     78 	if (fn != NULL)
     79 		printf("X11: Found '%s' in %s (%p)\n", fnname, x11libs[i].libname, *fn);
     80 	else
     81 		printf("X11: Symbol '%s' NOT FOUND!\n", fnname);
     82 	#endif
     83 
     84 	if (fn == NULL)
     85 		*rc = 0;  /* kill this module. */
     86 
     87 	return fn;
     88 }
     89 
     90 
     91 /* Define all the function pointers and wrappers... */
     92 #define SDL_X11_MODULE(modname)
     93 #define SDL_X11_SYM(rc,fn,params,args,ret) \
     94 	static rc (*p##fn) params = NULL; \
     95 	rc fn params { ret p##fn args ; }
     96 #include "SDL_x11sym.h"
     97 #undef SDL_X11_MODULE
     98 #undef SDL_X11_SYM
     99 #endif  /* SDL_VIDEO_DRIVER_X11_DYNAMIC */
    100 
    101 /* Annoying varargs entry point... */
    102 #ifdef X_HAVE_UTF8_STRING
    103 XIC (*pXCreateIC)(XIM,...) = NULL;
    104 char *(*pXGetICValues)(XIC, ...) = NULL;
    105 #endif
    106 
    107 /* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */
    108 #define SDL_X11_MODULE(modname) int SDL_X11_HAVE_##modname = 1;
    109 #define SDL_X11_SYM(rc,fn,params,args,ret)
    110 #include "SDL_x11sym.h"
    111 #undef SDL_X11_MODULE
    112 #undef SDL_X11_SYM
    113 
    114 
    115 static void *SDL_XGetRequest_workaround(Display* dpy, CARD8 type, size_t len)
    116 {
    117 	xReq *req;
    118 	WORD64ALIGN
    119 	if (dpy->bufptr + len > dpy->bufmax)
    120 		_XFlush(dpy);
    121 	dpy->last_req = dpy->bufptr;
    122 	req = (xReq*)dpy->bufptr;
    123 	req->reqType = type;
    124 	req->length = len / 4;
    125 	dpy->bufptr += len;
    126 	dpy->request++;
    127 	return req;
    128 }
    129 
    130 static int x11_load_refcount = 0;
    131 
    132 void SDL_X11_UnloadSymbols(void)
    133 {
    134 	#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
    135 	/* Don't actually unload if more than one module is using the libs... */
    136 	if (x11_load_refcount > 0) {
    137 		if (--x11_load_refcount == 0) {
    138 			int i;
    139 
    140 			/* set all the function pointers to NULL. */
    141 			#define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 1;
    142 			#define SDL_X11_SYM(rc,fn,params,args,ret) p##fn = NULL;
    143 			#include "SDL_x11sym.h"
    144 			#undef SDL_X11_MODULE
    145 			#undef SDL_X11_SYM
    146 
    147 			#ifdef X_HAVE_UTF8_STRING
    148 			pXCreateIC = NULL;
    149 			pXGetICValues = NULL;
    150 			#endif
    151 
    152 			for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
    153 				if (x11libs[i].lib != NULL) {
    154 					SDL_UnloadObject(x11libs[i].lib);
    155 					x11libs[i].lib = NULL;
    156 				}
    157 			}
    158 		}
    159 	}
    160 	#endif
    161 }
    162 
    163 /* returns non-zero if all needed symbols were loaded. */
    164 int SDL_X11_LoadSymbols(void)
    165 {
    166 	int rc = 1;  /* always succeed if not using Dynamic X11 stuff. */
    167 
    168 	#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
    169 	/* deal with multiple modules (dga, x11, etc) needing these symbols... */
    170 	if (x11_load_refcount++ == 0) {
    171 		int i;
    172 		int *thismod = NULL;
    173 		for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
    174 			if (x11libs[i].libname != NULL) {
    175 				x11libs[i].lib = SDL_LoadObject(x11libs[i].libname);
    176 			}
    177 		}
    178 		#define SDL_X11_MODULE(modname) thismod = &SDL_X11_HAVE_##modname;
    179 		#define SDL_X11_SYM(rc,fn,params,args,ret) \
    180             p##fn = (rc(*)params) X11_GetSym(#fn, thismod);
    181 		#include "SDL_x11sym.h"
    182 		#undef SDL_X11_MODULE
    183 		#undef SDL_X11_SYM
    184 
    185 		#ifdef X_HAVE_UTF8_STRING
    186 		pXCreateIC = (XIC(*)(XIM,...)) X11_GetSym("XCreateIC",
    187 		                                          &SDL_X11_HAVE_UTF8);
    188 		pXGetICValues = (char * (*)(XIC,...)) X11_GetSym("XGetICValues",
    189 		                                                 &SDL_X11_HAVE_UTF8);
    190 		#endif
    191 
    192 		/*
    193 		 * In case we're built with newer Xlib headers, we need to make sure
    194 		 *  that _XGetRequest() is available, even on older systems.
    195 		 *  Otherwise, various Xlib macros we use will call a NULL pointer.
    196 		 */
    197 		if (!SDL_X11_HAVE_XGETREQUEST) {
    198 			p_XGetRequest = SDL_XGetRequest_workaround;
    199 		}
    200 
    201 		if (SDL_X11_HAVE_BASEXLIB) {  /* all required symbols loaded. */
    202 			SDL_ClearError();
    203 			XInitThreads();
    204 		} else {
    205 			SDL_X11_UnloadSymbols();  /* in case something got loaded... */
    206 			rc = 0;
    207 		}
    208 	}
    209 	#else
    210 		#if DEBUG_DYNAMIC_X11
    211 		printf("X11: No dynamic X11 support in this build of SDL.\n");
    212 		#endif
    213 		#ifdef X_HAVE_UTF8_STRING
    214 		pXCreateIC = XCreateIC;
    215 		pXGetICValues = XGetICValues;
    216 		#endif
    217 	#endif
    218 
    219 	return rc;
    220 }
    221 
    222 /* end of SDL_x11dyn.c ... */
    223 
    224