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@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
37typedef 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
56static 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
64static 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
103XIC (*pXCreateIC)(XIM,...) = NULL;
104char *(*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
115static 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
130static int x11_load_refcount = 0;
131
132void 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. */
164int 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