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