]> git.tdb.fi Git - gldbg.git/blobdiff - source/glwrap.c
Send as much of a packet as possible before calling the original function
[gldbg.git] / source / glwrap.c
index 79d6404d2a34b21cf9cfeb3bfb045e6ecb7bda0b..4c17edfca772755f16a983253e96d37cf3ef0de6 100644 (file)
@@ -1,44 +1,89 @@
 /* $Id$
 
 This file is part of gldbg
-Copyright © 2009  Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the GPL
 */
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 #include <dlfcn.h>
+#include <fcntl.h>
 #include <sys/uio.h>
-#include <X11/Xlib.h>
-#include <GL/gl.h>
-#include <GL/glx.h>
-#include "arraysize.h"
-#include "functions.h"
 
-static inline void *glsym(const char *sym)
+#define INTERNAL __attribute__((visibility("internal")))
+
+INTERNAL inline const char *get_lib_names(void)
 {
-       static void *libgl = NULL;
-       if(!libgl)
+       const char *env = getenv("GLWRAP_LIBS");
+       if(env)
+               return env;
+       return "libGL.so";
+}
+
+INTERNAL inline void *glsym(const char *name)
+{
+       static void **gl_libs = NULL;
+       unsigned i;
+
+       if(!gl_libs)
        {
-               libgl = dlopen("libGL.so", RTLD_NOW);
-               if(!libgl)
+               char *lib_names = strdup(get_lib_names());
+               unsigned n_libs = 1;
+               unsigned j;
+
+               for(i=0; lib_names[i]; ++i)
+                       if(lib_names[i]==':')
+                               ++n_libs;
+
+               gl_libs = (void **)malloc((n_libs+1)*sizeof(void *));
+               i = 0;
+               n_libs = 0;
+               for(j=0;; ++j)
                {
-                       fprintf(stderr, "Could not open libGL: %s\n", dlerror());
-                       abort();
+                       if(lib_names[j]==':' || lib_names[j]==0)
+                       {
+                               int at_end = (lib_names[j]==0);
+                               lib_names[j] = 0;
+
+                               gl_libs[n_libs] = dlopen(lib_names+i, RTLD_NOW);
+                               if(!gl_libs[n_libs])
+                               {
+                                       fprintf(stderr, "Could not open %s: %s\n", lib_names+i, dlerror());
+                                       abort();
+                               }
+
+                               i = j+1;
+                               ++n_libs;
+
+                               if(at_end)
+                                       break;
+                       }
                }
+
+               gl_libs[n_libs] = 0;
+               free(lib_names);
+       }
+
+       for(i=0; gl_libs[i]; ++i)
+       {
+               void *sym = dlsym(gl_libs[i], name);
+               if(sym)
+                       return sym;
        }
 
-       return dlsym(libgl, sym);
+       return NULL;
 }
 
-static char *buffer = 0;
-static char *write_pos;
-static struct iovec *iovecs = 0;
-static struct iovec *cur_vec;
-static unsigned length;
+INTERNAL char *buffer = 0;
+INTERNAL char *write_pos;
+INTERNAL struct iovec *iovecs = 0;
+INTERNAL struct iovec *cur_vec;
+INTERNAL unsigned length;
 
-static inline void next_vec()
+INTERNAL inline void next_vec(void)
 {
        if(write_pos!=cur_vec->iov_base)
        {
@@ -49,59 +94,54 @@ static inline void next_vec()
        }
 }
 
-static inline void write_bytes(const char *ptr, unsigned size)
+INTERNAL inline void write_bytes(const char *ptr, unsigned size)
 {
        unsigned i;
        for(i=0; i<size; ++i)
                *write_pos++ = *ptr++;
 }
 
-static inline void write_char(char v)
+INTERNAL inline void write_char(char v)
 {
        *write_pos++ = v;
 }
 
-static inline void write_short(short v)
+INTERNAL inline void write_short(short v)
 {
        write_bytes((char *)&v, sizeof(short));
 }
 
-static inline void write_int(int v)
+INTERNAL inline void write_int(int v)
 {
        write_bytes((char *)&v, sizeof(int));
 }
 
-static inline void write_long(long v)
+INTERNAL inline void write_long(long v)
 {
        write_bytes((char *)&v, sizeof(long));
 }
 
-static inline void write_ulong(unsigned long v)
-{
-       write_bytes((char *)&v, sizeof(unsigned long));
-}
-
-static inline void write_longlong(long long v)
+INTERNAL inline void write_long_long(long long v)
 {
        write_bytes((char *)&v, sizeof(long long));
 }
 
-static inline void write_float(float v)
+INTERNAL inline void write_float(float v)
 {
        write_bytes((char *)&v, sizeof(float));
 }
 
-static inline void write_double(double v)
+INTERNAL inline void write_double(double v)
 {
        write_bytes((char *)&v, sizeof(double));
 }
 
-static inline void write_pointer(const void *p)
+INTERNAL inline void write_pointer(const void *p)
 {
        write_bytes((char *)&p, sizeof(void *));
 }
 
-static inline void write_data(const void *data, unsigned size)
+INTERNAL inline void write_data(const void *data, unsigned size)
 {
        if(data)
        {
@@ -117,37 +157,40 @@ static inline void write_data(const void *data, unsigned size)
                write_int(0);
 }
 
-static inline void write_string(const unsigned char *s)
+INTERNAL inline void write_string(const char *s)
 {
        write_data(s, strlen(s)+1);
 }
 
-static inline void write_string_array(const unsigned char **sa, unsigned size)
+INTERNAL inline void write_string_array(const char **sa, unsigned size)
 {
        unsigned i;
-       size /= sizeof(const unsigned char *);
+       size /= sizeof(const char *);
        write_int(size);
        for(i=0; i<size; ++i)
                write_string(sa[i]);
 }
 
-static inline void begin_packet(int func)
+INTERNAL inline void begin_packet(int func)
 {
        if(!buffer)
                buffer = (char *)malloc(1024);
        if(!iovecs)
                iovecs = (struct iovec *)malloc(16*sizeof(struct iovec));
+
        write_pos = buffer;
        cur_vec = iovecs;
        cur_vec->iov_base = write_pos;
        length = 0;
+
        write_int(0);
        write_short(func);
 }
 
-static inline void send_packet()
+INTERNAL inline int get_out_fd(void)
 {
        static int fd = -1;
+
        if(fd<0)
        {
                const char *var = getenv("GLWRAP_FD");
@@ -156,52 +199,29 @@ static inline void send_packet()
                else
                        fd = 2;
        }
-       next_vec();
-       write_pos = buffer;
-       write_int(length);
-       writev(fd, iovecs, cur_vec-iovecs);
-}
-
-GLenum cur_error = GL_NO_ERROR;
 
-static void check_error()
-{
-       GLenum (*orig_glGetError)() = 0;
-       GLenum code;
-       if(!orig_glGetError)
-               orig_glGetError = glsym("glGetError");
-       code = orig_glGetError();
-       if(code!=GL_NO_ERROR)
-       {
-               begin_packet(FUNC_GLDERROR);
-               write_int(code);
-               send_packet();
-               if(cur_error==GL_NO_ERROR)
-                       cur_error = code;
-       }
+       return fd;
 }
 
-GLenum APIENTRY glGetError()
+INTERNAL inline void send_partial_packet(void)
 {
-       GLenum ret = cur_error;
-       cur_error = GL_NO_ERROR;
-       begin_packet(FUNC_GLGETERROR);
-       write_int(ret);
-       send_packet();
-       return ret;
+       next_vec();
+       write_pos = buffer;
+       write_int(length|0x80000000);
+       writev(get_out_fd(), iovecs, cur_vec-iovecs);
+
+       write_pos = buffer;
+       cur_vec = iovecs;
+       cur_vec->iov_base = write_pos;
+       length = 0;
+
+       write_int(0);
 }
 
-void (*glXGetProcAddress(const GLubyte *procname))(void)
+INTERNAL inline void send_packet(void)
 {
-       void *handle = dlopen(NULL, RTLD_LAZY);
-       void (*ret)() = dlsym(handle, (const char *)procname);
-       begin_packet(FUNC_GLXGETPROCADDRESS);
-       write_pointer(ret);
-       write_string(procname);
-       send_packet();
-       return ret;
+       next_vec();
+       write_pos = buffer;
+       write_int(length);
+       writev(get_out_fd(), iovecs, cur_vec-iovecs);
 }
-
-void (*glXGetProcAddressARB(const GLubyte *))(void) __attribute__((alias("glXGetProcAddress")));
-
-#include "glwrap.funcs"