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