X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=glaze-gl.c;h=04f288ee97473791fdf40d3a1adfca230d75c9fc;hb=f5afe7a34b5f7adc8451f01db92be1de5f0830af;hp=d4ad33f77023415466f76febc3ce5c62c8437f44;hpb=fded9f20d5f5c92bd5af051117327816dda0238e;p=glaze diff --git a/glaze-gl.c b/glaze-gl.c index d4ad33f..04f288e 100644 --- a/glaze-gl.c +++ b/glaze-gl.c @@ -27,51 +27,11 @@ #include #include -#include void *libgl_handle; void *wrapper_handle; -/* Is the given elf program 32 or 64 bit? - * - * Note: This function returns -1 if 'filename' cannot - * be opened as a valid ELF file. - */ -static int -elf_bits (const char *filename) -{ - Elf *elf; - GElf_Ehdr ehdr; - int fd, class; - - fd = open (filename, O_RDONLY, 0); - if (fd < 0) - return -1; - - if (elf_version (EV_CURRENT ) == EV_NONE) - return -1; - - elf = elf_begin (fd, ELF_C_READ, NULL); - if (elf == NULL) - return -1; - - if (elf_kind (elf) != ELF_K_ELF) - return -1; - - if (gelf_getehdr (elf, &ehdr) == NULL) - return -1; - - class = gelf_getclass (elf); - - switch (class) { - case ELFCLASS32: - return 32; - case ELFCLASS64: - return 64; - default: - return -1; - } -} +#define STRNCMP_LITERAL(str, literal) strncmp (str, literal, sizeof (literal) - 1) static void open_libgl_handle (void) @@ -84,22 +44,14 @@ open_libgl_handle (void) libgl_path = getenv ("GLAZE_LIBGL"); if (libgl_path == NULL) { - Dl_info info; - int bits; - if (dladdr (open_libgl_handle, &info) == 0) { - fprintf (stderr, "Internal error: Failed to lookup filename of glaze library with dladdr.\n"); - exit (1); - } - - bits = elf_bits (info.dli_fname); +#if GLAZE_BITS == 32 + libgl_path = getenv ("GLAZE_LIBGL_32_AUTO"); +#elif GLAZE_BITS == 64 + libgl_path = getenv ("GLAZE_LIBGL_64_AUTO"); +#endif - if (bits == 32) - libgl_path = getenv ("GLAZE_LIBGL_32_AUTO"); - if (bits == 64) - libgl_path = getenv ("GLAZE_LIBGL_64_AUTO"); - - 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"); @@ -128,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); } @@ -154,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) @@ -164,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 * \