]> git.tdb.fi Git - gldbg.git/blob - source/glwrap.c
bf05214b8a09d7ee844d5567626b395b2066f1db
[gldbg.git] / source / glwrap.c
1 /* $Id$
2
3 This file is part of gldbg
4 Copyright © 2009  Mikko Rasa, Mikkosoft Productions
5 Distributed under the GPL
6 */
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <dlfcn.h>
12 #include <sys/uio.h>
13 #include <X11/Xlib.h>
14 #include <GL/gl.h>
15 #include <GL/glx.h>
16 #include "arraysize.h"
17 #include "functions.h"
18
19 static inline void *glsym(const char *sym)
20 {
21         static void *libgl = NULL;
22         if(!libgl)
23         {
24                 const char *libgl_name = getenv("GLWRAP_LIBGL");
25                 if(!libgl_name)
26                         libgl_name = "libGL.so";
27                 libgl = dlopen(libgl_name, RTLD_NOW);
28                 if(!libgl)
29                 {
30                         fprintf(stderr, "Could not open %s: %s\n", libgl_name, dlerror());
31                         abort();
32                 }
33         }
34
35         return dlsym(libgl, sym);
36 }
37
38 static char *buffer = 0;
39 static char *write_pos;
40 static struct iovec *iovecs = 0;
41 static struct iovec *cur_vec;
42 static unsigned length;
43
44 static inline void next_vec()
45 {
46         if(write_pos!=cur_vec->iov_base)
47         {
48                 cur_vec->iov_len = write_pos-(char *)cur_vec->iov_base;
49                 length += cur_vec->iov_len;
50                 ++cur_vec;
51                 cur_vec->iov_base = write_pos;
52         }
53 }
54
55 static inline void write_bytes(const char *ptr, unsigned size)
56 {
57         unsigned i;
58         for(i=0; i<size; ++i)
59                 *write_pos++ = *ptr++;
60 }
61
62 static inline void write_char(char v)
63 {
64         *write_pos++ = v;
65 }
66
67 static inline void write_short(short v)
68 {
69         write_bytes((char *)&v, sizeof(short));
70 }
71
72 static inline void write_int(int v)
73 {
74         write_bytes((char *)&v, sizeof(int));
75 }
76
77 static inline void write_long(long v)
78 {
79         write_bytes((char *)&v, sizeof(long));
80 }
81
82 static inline void write_long_long(long long v)
83 {
84         write_bytes((char *)&v, sizeof(long long));
85 }
86
87 static inline void write_float(float v)
88 {
89         write_bytes((char *)&v, sizeof(float));
90 }
91
92 static inline void write_double(double v)
93 {
94         write_bytes((char *)&v, sizeof(double));
95 }
96
97 static inline void write_pointer(const void *p)
98 {
99         write_bytes((char *)&p, sizeof(void *));
100 }
101
102 static inline void write_data(const void *data, unsigned size)
103 {
104         if(data)
105         {
106                 write_int(size);
107                 next_vec();
108                 cur_vec->iov_base = (void *)data;
109                 cur_vec->iov_len = size;
110                 length += size;
111                 ++cur_vec;
112                 cur_vec->iov_base = write_pos;
113         }
114         else
115                 write_int(0);
116 }
117
118 static inline void write_string(const char *s)
119 {
120         write_data(s, strlen(s)+1);
121 }
122
123 static inline void write_string_array(const char **sa, unsigned size)
124 {
125         unsigned i;
126         size /= sizeof(const char *);
127         write_int(size);
128         for(i=0; i<size; ++i)
129                 write_string(sa[i]);
130 }
131
132 static inline void begin_packet(int func)
133 {
134         if(!buffer)
135                 buffer = (char *)malloc(1024);
136         if(!iovecs)
137                 iovecs = (struct iovec *)malloc(16*sizeof(struct iovec));
138         write_pos = buffer;
139         cur_vec = iovecs;
140         cur_vec->iov_base = write_pos;
141         length = 0;
142         write_int(0);
143         write_short(func);
144 }
145
146 static inline void send_packet()
147 {
148         static int fd = -1;
149         if(fd<0)
150         {
151                 const char *var = getenv("GLWRAP_FD");
152                 if(var)
153                         fd = strtol(var, NULL, 0);
154                 else
155                         fd = 2;
156         }
157         next_vec();
158         write_pos = buffer;
159         write_int(length);
160         writev(fd, iovecs, cur_vec-iovecs);
161 }
162
163 GLenum cur_error = GL_NO_ERROR;
164
165 static void check_error()
166 {
167         GLenum (*orig_glGetError)() = 0;
168         GLenum code;
169         if(!orig_glGetError)
170                 orig_glGetError = glsym("glGetError");
171         code = orig_glGetError();
172         if(code!=GL_NO_ERROR)
173         {
174                 begin_packet(FUNC_GLDERROR);
175                 write_int(code);
176                 send_packet();
177                 if(cur_error==GL_NO_ERROR)
178                         cur_error = code;
179         }
180 }
181
182 GLenum APIENTRY glGetError()
183 {
184         GLenum ret = cur_error;
185         cur_error = GL_NO_ERROR;
186         begin_packet(FUNC_GLGETERROR);
187         write_int(ret);
188         send_packet();
189         return ret;
190 }
191
192 void (*glXGetProcAddress(const GLubyte *procname))(void)
193 {
194         void *handle = 0;
195         void (*ret)() = 0;
196
197         if(glsym((const char *)procname))
198         {
199                 handle = dlopen(NULL, RTLD_LAZY);
200                 ret = dlsym(handle, (const char *)procname);
201         }
202
203         begin_packet(FUNC_GLXGETPROCADDRESS);
204         write_pointer(ret);
205         write_string((const char *)procname);
206         send_packet();
207
208         return ret;
209 }
210
211 void (*glXGetProcAddressARB(const GLubyte *))(void) __attribute__((alias("glXGetProcAddress")));
212
213 #include "glwrap.funcs"