X-Git-Url: https://git.cworth.org/git?p=glaze;a=blobdiff_plain;f=glaze-gl.c;h=8c3a82d883e4c2055e960fc5ba9d3eaada3913f5;hp=e7dd728c058b53f31b2ba2f0f73fdb128781512d;hb=HEAD;hpb=caa8d546aea211396beaebf6f811314ff5979c14 diff --git a/glaze-gl.c b/glaze-gl.c index e7dd728..8c3a82d 100644 --- a/glaze-gl.c +++ b/glaze-gl.c @@ -29,7 +29,8 @@ #include void *libgl_handle; -void *wrapper_handle; +void **wrapper_handles; +int num_wrapper_handles; #define STRNCMP_LITERAL(str, literal) strncmp (str, literal, sizeof (literal) - 1) @@ -51,7 +52,7 @@ open_libgl_handle (void) libgl_path = getenv ("GLAZE_LIBGL_64_AUTO"); #endif - if (libgl_path == NULL) { + if (libgl_path == NULL || strlen (libgl_path) == 0) { fprintf (stderr, "Error: Failed to detect OpenGL library.\n" "Please set GLAZE_LIBGL to path of real libGL.so\n"); @@ -70,12 +71,34 @@ open_libgl_handle (void) } } +/* Count the number of types 'chr' appears in 'str' */ +static int +count_chars (const char *str, char chr) +{ + int count = 0; + const char *s = str; + + while (1) { + s = strchr (s, chr); + if (s == NULL) + break; + count++; + s++; + if (*s == '\0') + break; + } + + return count; +} + static void -open_wrapper_handle (void) +open_wrapper_handles (void) { const char *path; + char *path_copy, *wrapper, *save; + int i; - if (wrapper_handle) + if (wrapper_handles) return; path = getenv ("GLAZE_WRAPPER"); @@ -84,13 +107,37 @@ open_wrapper_handle (void) exit (1); } + num_wrapper_handles = count_chars (path, ':') + 1; + + wrapper_handles = malloc (num_wrapper_handles * sizeof (void*)); + if (wrapper_handles == NULL) { + fprintf (stderr, "Out of memory\n"); + exit (1); + } + + /* Clear dlerror state. */ dlerror (); - wrapper_handle = dlopen (path, RTLD_LAZY); - if (wrapper_handle == NULL) { - const char *error = dlerror(); - fprintf (stderr, "Error: Failed to dlopen %s: %s\n", path, error); + + path_copy = strdup (path); + if (path_copy == NULL) { + fprintf (stderr, "Out of memory\n"); exit (1); } + + for (i = 0, wrapper = strtok_r (path_copy, ":", &save); + i < num_wrapper_handles; + i++, wrapper = strtok_r (NULL, ":", &save)) + { + wrapper_handles[i] = dlopen (wrapper, RTLD_LAZY); + if (wrapper_handles[i] == NULL) { + const char *error = dlerror(); + fprintf (stderr, "Error: Failed to dlopen %s: %s\n", + wrapper, error); + exit (1); + } + } + + free (path_copy); } static void @@ -100,7 +147,59 @@ static void glaze_init (void) { open_libgl_handle (); - open_wrapper_handle (); + open_wrapper_handles (); +} + +static void +call_first_gl_call_callbacks (void) +{ + char *callbacks = getenv ("GLAZE_FIRST_GL_CALL_CALLBACK"); + char *name, *names, *save; + void (*callback) (void); + int i; + + if (callbacks == NULL) + return; + + names = strdup (callbacks); + if (names == NULL) { + fprintf (stderr, "Out of memory\n"); + exit (1); + } + + for (name = strtok_r (names, ":", &save); + name; + name = strtok_r (NULL, ":", &save)) + { + for (i = 0; i < num_wrapper_handles; i++) { + callback = dlsym (wrapper_handles[i], name); + if (callback) { + (callback) (); + goto NEXT_NAME; + } + } + fprintf (stderr, "Error: Failed to find function %s " + "in any GLAZE_WRAPPER library.\n", name); + NEXT_NAME: + ; + } + + free (names); +} + +static void * +find_symbol_in_glaze_wrappers (const char *name) +{ + void *symbol; + int i; + + for (i = 0; i < num_wrapper_handles; i++) { + symbol = dlsym (wrapper_handles[i], name); + if (symbol) + return symbol; + } + + return NULL; } static void * @@ -113,24 +212,13 @@ resolve (const char *name) STRNCMP_LITERAL (name, "gl") == 0 && STRNCMP_LITERAL (name, "glX") != 0) { - char *callback_name = getenv ("GLAZE_FIRST_GL_CALL_CALLBACK"); - if (callback_name) { - void (*callback) (void) = dlsym (wrapper_handle, - callback_name); - if (callback) { - (callback) (); - } else { - fprintf (stderr, - "Error: Failed to find function %s " - "in GLAZE_WRAPPER library.\n", - callback_name); - } - } + call_first_gl_call_callbacks (); + before_first_gl_call = 0; } - /* The wrapper gets first choice on all symbols. */ - symbol = dlsym (wrapper_handle, name); + /* The wrappers get first choice on all symbols. */ + symbol = find_symbol_in_glaze_wrappers (name); if (symbol) return symbol; @@ -151,8 +239,8 @@ void /* On the first call, check if the wrapper provides an * implementation of this function. */ if (first_call) { - wrapper_glXGetProcAddress = dlsym (wrapper_handle, - "glXGetProcAddress"); + wrapper_glXGetProcAddress = + find_symbol_in_glaze_wrappers ("glXGetProcAddress"); libgl_glXGetProcAddress = dlsym (libgl_handle, "glXGetProcAddress"); first_call = 0; @@ -165,8 +253,8 @@ void /* Otherwise, we need to resolve the name. * - * The wrapper gets first choice on all symbols. */ - symbol = dlsym (wrapper_handle, (char *) name); + * The wrappers get first choice on all symbols. */ + symbol = find_symbol_in_glaze_wrappers ((char *) name); if (symbol) return symbol; @@ -190,8 +278,8 @@ void /* On the first call, check if the wrapper provides an * implementation of this function. */ if (first_call) { - wrapper_glXGetProcAddressARB = dlsym (wrapper_handle, - "glXGetProcAddressARB"); + wrapper_glXGetProcAddressARB = + find_symbol_in_glaze_wrappers ("glXGetProcAddressARB"); libgl_glXGetProcAddressARB = dlsym (libgl_handle, "glXGetProcAddressARB"); first_call = 0; @@ -204,8 +292,8 @@ void /* Otherwise, we need to resolve the name. * - * The wrapper gets first choice on all symbols. */ - symbol = dlsym (wrapper_handle, (char *) name); + * The wrappers get first choice on all symbols. */ + symbol = find_symbol_in_glaze_wrappers ((char *) name); if (symbol) return symbol;