]> git.tdb.fi Git - gldbg.git/blob - source/glwrap.c
cd1c328139e784f2a4bea80d90297e86401d4402
[gldbg.git] / source / glwrap.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <dlfcn.h>
6 #include <fcntl.h>
7 #include <signal.h>
8 #include "arraysize.h"
9 #include "breakpoint.h"
10 #include "functions.h"
11 #include "opengl.h"
12 #include "packet.h"
13
14 #define UNUSED __attribute__((unused))
15
16 static unsigned char breakpoints[N_FUNCS] = { };
17 static char break_any = 0;
18 static char hold = 0;
19 static char no_break = 0;
20
21 static const char *get_lib_names(void)
22 {
23         const char *env = getenv("GLWRAP_LIBS");
24         if(env)
25                 return env;
26         return "libGL.so.1";
27 }
28
29 void *glsym(const char *name)
30 {
31         static void **gl_libs = NULL;
32         unsigned i;
33
34         if(!gl_libs)
35         {
36                 char *lib_names = strdup(get_lib_names());
37                 unsigned n_libs = 1;
38                 unsigned j;
39
40                 for(i=0; lib_names[i]; ++i)
41                         if(lib_names[i]==':')
42                                 ++n_libs;
43
44                 gl_libs = (void **)malloc((n_libs+1)*sizeof(void *));
45                 i = 0;
46                 n_libs = 0;
47                 for(j=0;; ++j)
48                 {
49                         if(lib_names[j]==':' || lib_names[j]==0)
50                         {
51                                 int at_end = (lib_names[j]==0);
52                                 lib_names[j] = 0;
53
54                                 gl_libs[n_libs] = dlopen(lib_names+i, RTLD_NOW);
55                                 if(!gl_libs[n_libs])
56                                 {
57                                         fprintf(stderr, "Could not open %s: %s\n", lib_names+i, dlerror());
58                                         abort();
59                                 }
60
61                                 i = j+1;
62                                 ++n_libs;
63
64                                 if(at_end)
65                                         break;
66                         }
67                 }
68
69                 gl_libs[n_libs] = 0;
70                 free(lib_names);
71         }
72
73         for(i=0; gl_libs[i]; ++i)
74         {
75                 void *sym = dlsym(gl_libs[i], name);
76                 if(sym)
77                         return sym;
78         }
79
80         return NULL;
81 }
82
83 int get_out_fd(void)
84 {
85         static int fd = -1;
86
87         if(fd<0)
88         {
89                 const char *var = getenv("GLWRAP_FD");
90                 if(var)
91                         fd = strtol(var, NULL, 0);
92                 else
93                 {
94                         var = getenv("GLWRAP_FILE");
95                         if(var)
96                         {
97                                 fd = open(var, O_WRONLY|O_CREAT|O_TRUNC, 0644);
98                                 if(fd==-1)
99                                 {
100                                         fprintf(stderr, "Couldn't open dumpfile %s for output: %s", var, strerror(errno));
101                                         abort();
102                                 }
103                         }
104                         else
105                                 fd = 2;
106                 }
107         }
108
109         return fd;
110 }
111
112 int get_in_fd(void)
113 {
114         static int fd = -1;
115
116         if(fd<0)
117         {
118                 const char *var = getenv("GLWRAP_CTRL_FD");
119                 if(var)
120                         fd = strtol(var, NULL, 0);
121                 else
122                         fd = 0;
123         }
124
125         return fd;
126 }
127
128 static void receive_gldBreak(GlPacket *pkt)
129 {
130         unsigned short func;
131         unsigned char flags_set;
132         unsigned char flags_clr;
133
134         packet_read_short(pkt, (short *)&func);
135         packet_read_char(pkt, (char *)&flags_set);
136         packet_read_char(pkt, (char *)&flags_clr);
137
138         if(func)
139         {
140                 breakpoints[func] &= ~flags_clr;
141                 breakpoints[func] |= flags_set;
142         }
143         else
144                 break_any = flags_set;
145 }
146
147 static void receive_gldHold(GlPacket *pkt UNUSED)
148 {
149         hold = 1;
150 }
151
152 static void receive_gldQueryViewport(GlPacket *pkt UNUSED)
153 {
154         int viewport[4];
155
156         no_break = 1;
157         glGetIntegerv(GL_VIEWPORT, viewport);
158         no_break = 0;
159 }
160
161 static void receive_gldReadPixels(GlPacket *pkt)
162 {
163         GLint x, y;
164         GLsizei width, height;
165         GLenum format, type;
166         char *data;
167
168         packet_read_int(pkt, &x);
169         packet_read_int(pkt, &y);
170         packet_read_int(pkt, &width);
171         packet_read_int(pkt, &height);
172         packet_read_int(pkt, (int *)&format);
173         packet_read_int(pkt, (int *)&type);
174
175         data = (char *)malloc(width*height*typesize(type)*formatsize(format));
176         no_break = 1;
177         glReadPixels(x, y, width, height, format, type, data);
178         no_break = 0;
179         free(data);
180 }
181
182 static void receive(void)
183 {
184         GlPacket *pkt;
185
186         while((pkt = packet_receive(get_in_fd())))
187         {
188                 unsigned short func;
189
190                 packet_read_short(pkt, (short *)&func);
191                 switch(func)
192                 {
193                 case FUNC_GLDBREAK: receive_gldBreak(pkt); break;
194                 case FUNC_GLDHOLD: receive_gldHold(pkt); break;
195                 case FUNC_GLDQUERYVIEWPORT: receive_gldQueryViewport(pkt); break;
196                 case FUNC_GLDREADPIXELS: receive_gldReadPixels(pkt); break;
197                 default:;
198                 }
199         }
200 }
201
202 void tracepoint(unsigned short func, int flag)
203 {
204         int breakpoint;
205
206         if(no_break)
207                 return;
208
209         receive();
210
211         breakpoint = (breakpoints[func]|break_any)&flag;
212         if(breakpoint || hold)
213         {
214                 GlPacket *pkt;
215
216                 if(breakpoint)
217                 {
218                         pkt = packet_begin(FUNC_GLDBREAK);
219                         packet_write_short(pkt, func);
220                         packet_write_char(pkt, flag);
221                         packet_send(pkt, get_out_fd());
222                 }
223
224                 break_any = 0;
225
226                 while(1)
227                 {
228                         hold = 0;
229                         raise(SIGTRAP);
230                         receive();
231                         if(!hold)
232                                 break;
233                 }
234         }
235 }