X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=glaze-gl.c;h=e7dd728c058b53f31b2ba2f0f73fdb128781512d;hb=acb1372fca12d1df8bead92eb2ab16dbc98b9c6c;hp=453d4606f2be1320b009630bf1e041960b190afc;hpb=f427658599546afd1fa19c31f25001ada8c0667d;p=glaze diff --git a/glaze-gl.c b/glaze-gl.c index 453d460..e7dd728 100644 --- a/glaze-gl.c +++ b/glaze-gl.c @@ -31,6 +31,8 @@ void *libgl_handle; void *wrapper_handle; +#define STRNCMP_LITERAL(str, literal) strncmp (str, literal, sizeof (literal) - 1) + static void open_libgl_handle (void) { @@ -78,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); } @@ -104,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) @@ -114,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 * \