diff src/video/x11/SDL_x11dyn.c @ 1168:045f186426e1

Dynamically load X11 libraries like we currently do for alsa, esd, etc. This allows you to run an SDL program on a system without Xlib, since it'll just report the x11 target unavailable at runtime.
author Ryan C. Gordon <icculus@icculus.org>
date Sat, 05 Nov 2005 19:53:37 +0000
parents
children f84c6f1397cd
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/x11/SDL_x11dyn.c	Sat Nov 05 19:53:37 2005 +0000
@@ -0,0 +1,127 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2004 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+
+/*#define DEBUG_DYNAMIC_X11 1*/
+
+#include "SDL_x11dyn.h"
+
+#ifdef DEBUG_DYNAMIC_X11
+#include <stdio.h>
+#endif
+
+#ifdef X11_DYNAMIC
+#include <dlfcn.h>
+#include "SDL_name.h"
+#include "SDL_loadso.h"
+static const char *x11_library = X11_DYNAMIC;
+static void *x11_handle = NULL;
+static const char *x11ext_library = X11EXT_DYNAMIC;
+static void *x11ext_handle = NULL;
+
+static void *X11_GetSym(const char *fnname, int *rc)
+{
+	void *fn = NULL;
+	if (*rc) {  /* haven't already failed on a previous lookup? */
+		fn = SDL_LoadFunction(x11_handle, fnname);
+		#if DEBUG_DYNAMIC_X11
+		if (fn != NULL)
+			printf("X11: Found '%s' in libX11 (%p)\n", fnname, fn);
+		#endif
+
+		if (fn == NULL) {  /* not found? Check libX11ext ... */
+			fn = SDL_LoadFunction(x11ext_handle, fnname);
+			#if DEBUG_DYNAMIC_X11
+			if (fn != NULL)
+				printf("X11: Found '%s' in libXext (%p)\n", fnname, fn);
+			else
+				printf("X11: Symbol '%s' NOT FOUND!\n", fnname);
+			#endif
+		}
+		*rc = (fn != NULL);
+	}
+
+	return fn;
+}
+#endif  /* defined X11_DYNAMIC */
+
+/* Define all the function pointers... */
+#define SDL_X11_SYM(ret,fn,params) ret (*p##fn) params = NULL;
+#include "SDL_x11sym.h"
+#undef SDL_X11_SYM
+
+static int x11_load_refcount = 0;
+
+void SDL_X11_UnloadSymbols(void)
+{
+	/* Don't actually unload if more than one module is using the libs... */
+	if (x11_load_refcount > 0) {
+		if (--x11_load_refcount == 0) {
+			/* set all the function pointers to NULL. */
+			#define SDL_X11_SYM(ret,fn,params) p##fn = NULL;
+			#include "SDL_x11sym.h"
+			#undef SDL_X11_SYM
+
+			#ifdef X11_DYNAMIC
+			if (x11_handle != NULL) {
+				SDL_UnloadObject(x11_handle);
+				x11_handle = NULL;
+			}
+			if (x11ext_handle != NULL) {
+				SDL_UnloadObject(x11ext_handle);
+				x11ext_handle = NULL;
+			}
+			#endif
+		}
+	}
+}
+
+/* returns non-zero if all needed symbols were loaded. */
+int SDL_X11_LoadSymbols(void)
+{
+	int rc = 1;
+
+    /* deal with multiple modules (dga, x11, etc) needing these symbols... */
+	if (x11_load_refcount++ == 0) {
+		#ifdef X11_DYNAMIC
+			x11_handle = SDL_LoadObject(x11_library);
+			x11ext_handle = SDL_LoadObject(x11ext_library);
+			if ((x11_handle != NULL) && (x11ext_handle != NULL)) {
+				#define SDL_X11_SYM(r,fn,arg) p##fn = X11_GetSym(#fn, &rc);
+				#include "SDL_x11sym.h"
+				#undef SDL_X11_SYM
+			}
+
+			if (!rc)
+				SDL_X11_UnloadSymbols();  /* in case one of these loaded... */
+
+		#else
+			#define SDL_X11_SYM(r,fn,arg) p##fn = fn;
+			#include "SDL_x11sym.h"
+			#undef SDL_X11_SYM
+		#endif
+	}
+
+	return rc;
+}
+
+/* end of SDL_x11dyn.c ... */
+