]> git.cworth.org Git - glaze/blobdiff - glaze-gl.c
Add specs/README
[glaze] / glaze-gl.c
index d4ad33f77023415466f76febc3ce5c62c8437f44..e7dd728c058b53f31b2ba2f0f73fdb128781512d 100644 (file)
 #include <string.h>
 
 #include <fcntl.h>
-#include <gelf.h>
 
 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,20 +44,12 @@ 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 (bits == 32)
-                       libgl_path = getenv ("GLAZE_LIBGL_32_AUTO");
-               if (bits == 64)
-                       libgl_path = getenv ("GLAZE_LIBGL_64_AUTO");
+#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,
@@ -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 *                                                          \