X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=glaze-gl.c;h=e7dd728c058b53f31b2ba2f0f73fdb128781512d;hb=acb1372fca12d1df8bead92eb2ab16dbc98b9c6c;hp=b6e7d72d3f8f9317a4ae03136f73b1ff9f444fa7;hpb=2b7630a8f3277a568695fc59996c8bad34261454;p=glaze diff --git a/glaze-gl.c b/glaze-gl.c index b6e7d72..e7dd728 100644 --- a/glaze-gl.c +++ b/glaze-gl.c @@ -24,27 +24,48 @@ #include #include +#include + +#include void *libgl_handle; void *wrapper_handle; +#define STRNCMP_LITERAL(str, literal) strncmp (str, literal, sizeof (literal) - 1) + static void open_libgl_handle (void) { - const char *path; + const char *libgl_path; if (libgl_handle) return; - path = getenv ("GLAZE_LIBGL"); - if (path == NULL) { - fprintf (stderr, "GLAZE_LIBGL unset. Please set to path of real libGL.so under glaze.\n"); - exit (1); + libgl_path = getenv ("GLAZE_LIBGL"); + + if (libgl_path == NULL) { + +#if GLAZE_BITS == 32 + libgl_path = getenv ("GLAZE_LIBGL_32_AUTO"); +#elif GLAZE_BITS == 64 + libgl_path = getenv ("GLAZE_LIBGL_64_AUTO"); +#endif + + if (libgl_path == NULL) { + fprintf (stderr, + "Error: Failed to detect OpenGL library.\n" + "Please set GLAZE_LIBGL to path of real libGL.so\n"); + exit (1); + } + + setenv ("GLAZE_LIBGL", libgl_path, 1); } - libgl_handle = dlopen (path, RTLD_LAZY | RTLD_GLOBAL); + dlerror(); + libgl_handle = dlopen (libgl_path, RTLD_LAZY | RTLD_GLOBAL); if (libgl_handle == NULL) { - fprintf (stderr, "Error: Failed to dlopen %s\n", path); + fprintf (stderr, "glaze_init: Error: Failed to dlopen %s: %s\n", + libgl_path, dlerror()); exit (1); } } @@ -59,7 +80,7 @@ open_wrapper_handle (void) path = getenv ("GLAZE_WRAPPER"); if (path == NULL) { - fprintf (stderr, "GLAZE_WRAPPER unset. Please set to path of real libGL.so under glaze.\n"); + fprintf (stderr, "GLAZE_WRAPPER unset. Please set to path of Glaze-using wrapper library.\n"); exit (1); } @@ -85,8 +106,29 @@ glaze_init (void) static void * resolve (const char *name) { + static int before_first_gl_call = 1; void *symbol; + if (before_first_gl_call && + 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); + } + } + before_first_gl_call = 0; + } + /* The wrapper gets first choice on all symbols. */ symbol = dlsym (wrapper_handle, name); if (symbol) @@ -95,6 +137,84 @@ resolve (const char *name) return dlsym (libgl_handle, name); } +void +(*glXGetProcAddress (const unsigned char *name))(void); + +void +(*glXGetProcAddress (const unsigned char *name))(void) +{ + static int first_call = 1; + static typeof (&glXGetProcAddress) wrapper_glXGetProcAddress; + static typeof (&glXGetProcAddress) libgl_glXGetProcAddress; + void *symbol; + + /* On the first call, check if the wrapper provides an + * implementation of this function. */ + if (first_call) { + wrapper_glXGetProcAddress = dlsym (wrapper_handle, + "glXGetProcAddress"); + libgl_glXGetProcAddress = dlsym (libgl_handle, + "glXGetProcAddress"); + first_call = 0; + } + + /* If the wrapper implements glXGetProcAddress itself, then it + * had better know best what to do. Just let it. */ + if (wrapper_glXGetProcAddress) + return wrapper_glXGetProcAddress (name); + + /* Otherwise, we need to resolve the name. + * + * The wrapper gets first choice on all symbols. */ + symbol = dlsym (wrapper_handle, (char *) name); + if (symbol) + return symbol; + + /* The wrapper doesn't care, so defer to the underlying + * glXGetProcAddress */ + return libgl_glXGetProcAddress (name); + +} + +void +(*glXGetProcAddressARB (const unsigned char *name))(void); + +void +(*glXGetProcAddressARB (const unsigned char *name))(void) +{ + static int first_call = 1; + static typeof (&glXGetProcAddressARB) wrapper_glXGetProcAddressARB; + static typeof (&glXGetProcAddressARB) libgl_glXGetProcAddressARB; + void *symbol; + + /* On the first call, check if the wrapper provides an + * implementation of this function. */ + if (first_call) { + wrapper_glXGetProcAddressARB = dlsym (wrapper_handle, + "glXGetProcAddressARB"); + libgl_glXGetProcAddressARB = dlsym (libgl_handle, + "glXGetProcAddressARB"); + first_call = 0; + } + + /* If the wrapper implements glXGetProcAddressARB itself, then + * it had better know best what to do. Just let it. */ + if (wrapper_glXGetProcAddressARB) + return wrapper_glXGetProcAddressARB (name); + + /* Otherwise, we need to resolve the name. + * + * The wrapper gets first choice on all symbols. */ + symbol = dlsym (wrapper_handle, (char *) name); + if (symbol) + return symbol; + + /* The wrapper doesn't care, so defer to the underlying + * glXGetProcAddressARB */ + return libgl_glXGetProcAddressARB (name); + +} + #define GLAZE_API(name) \ void * name() __attribute__((ifunc(#name "_resolver"))); \ static void * \