sgl
changeset 5:0570e27e5ebc
pretty much done with the basic functionality and GLX shit
author | John Tsiombikas <nuclear@siggraph.org> |
---|---|
date | Fri, 13 May 2011 07:49:47 +0300 |
parents | 648f8604d2b2 |
children | 0cb438c86b98 |
files | Makefile.in include/sgl.h src/cb.c src/log.c src/sgl.c src/wsys.h src/wsys_x11.c tests/simple/Makefile tests/simple/simple.c tests/tests-makefile |
diffstat | 10 files changed, 348 insertions(+), 87 deletions(-) [+] |
line diff
1.1 --- a/Makefile.in Thu May 12 11:04:10 2011 +0300 1.2 +++ b/Makefile.in Fri May 13 07:49:47 2011 +0300 1.3 @@ -8,7 +8,7 @@ 1.4 somajor = 0 1.5 sominor = 0 1.6 1.7 -lib_so_unix = $(soname).$(minor) 1.8 +lib_so_unix = $(soname).$(sominor) 1.9 lib_so_mac = libsgl.dylib 1.10 1.11 sharedopt_unix = -shared -Wl,-soname,$(soname) 1.12 @@ -23,6 +23,7 @@ 1.13 AR = ar 1.14 CC = gcc 1.15 CFLAGS = -pedantic -Wall -g -fPIC -Iinclude -Isrc 1.16 +LDFLAGS = -lX11 1.17 1.18 .PHONY: all 1.19 all: $(lib_so) $(lib_a) 1.20 @@ -31,7 +32,7 @@ 1.21 $(AR) rcs $@ $(obj) 1.22 1.23 $(lib_so): $(obj) 1.24 - $(CC) $(sharedopt_$(sys)) -o $@ $(obj) 1.25 + $(CC) $(sharedopt_$(sys)) -o $@ $(obj) $(LDFLAGS) 1.26 1.27 -include $(dep) 1.28
2.1 --- a/include/sgl.h Thu May 12 11:04:10 2011 +0300 2.2 +++ b/include/sgl.h Fri May 13 07:49:47 2011 +0300 2.3 @@ -21,8 +21,14 @@ 2.4 SGL_NUM_CALLBACKS 2.5 }; 2.6 2.7 +enum { 2.8 + SGL_LEFT_BUTTON, 2.9 + SGL_MIDDLE_BUTTON, 2.10 + SGL_RIGHT_BUTTON 2.11 +}; 2.12 + 2.13 int sgl_init(void); 2.14 -void sgl_shutdown(void); 2.15 +void sgl_quit(void); 2.16 2.17 int sgl_set_video_mode(int xsz, int ysz); 2.18 int sgl_get_video_mode(int *xsz, int *ysz); 2.19 @@ -33,8 +39,11 @@ 2.20 int sgl_set_active(int id); 2.21 int sgl_set_title(const char *str); 2.22 2.23 +void sgl_redisplay(void); 2.24 +void sgl_swap_buffers(void); 2.25 + 2.26 int sgl_process_events(void); 2.27 -int sgl_event_loop(void); 2.28 +void sgl_event_loop(void); 2.29 2.30 int sgl_push_callbacks(void); 2.31 int sgl_pop_callbacks(void);
3.1 --- a/src/cb.c Thu May 12 11:04:10 2011 +0300 3.2 +++ b/src/cb.c Fri May 13 07:49:47 2011 +0300 3.3 @@ -48,9 +48,15 @@ 3.4 notify_wsys(); 3.5 } 3.6 3.7 -void sgl_callback(int idx, void (*func)()) 3.8 +void sgl_set_callback(int idx, void (*func)()) 3.9 { 3.10 + struct wsys_module *ws; 3.11 + 3.12 cb->func[idx] = func; 3.13 + 3.14 + if((ws = sgl_wsys_module())) { 3.15 + ws->set_event(idx, func != 0); 3.16 + } 3.17 } 3.18 3.19 void (*sgl_get_callback(int idx))()
4.1 --- a/src/log.c Thu May 12 11:04:10 2011 +0300 4.2 +++ b/src/log.c Fri May 13 07:49:47 2011 +0300 4.3 @@ -17,5 +17,7 @@ 4.4 vfprintf(fp, fmt, ap); 4.5 va_end(ap); 4.6 4.7 - fclose(fp); 4.8 + if(fp != stderr) { 4.9 + fclose(fp); 4.10 + } 4.11 }
5.1 --- a/src/sgl.c Thu May 12 11:04:10 2011 +0300 5.2 +++ b/src/sgl.c Fri May 13 07:49:47 2011 +0300 5.3 @@ -1,13 +1,13 @@ 5.4 #include "sgl.h" 5.5 #include "wsys.h" 5.6 5.7 -void sgl_register_modules(void); 5.8 +void sgl_modules_init(void); 5.9 5.10 static struct wsys_module *ws; 5.11 5.12 int sgl_init(void) 5.13 { 5.14 - sgl_register_modules(); 5.15 + sgl_modules_init(); 5.16 sgl_sort_modules(); 5.17 5.18 if(!(ws = sgl_wsys_module())) { 5.19 @@ -16,7 +16,7 @@ 5.20 return ws->init(); 5.21 } 5.22 5.23 -void sgl_shutdown(void) 5.24 +void sgl_quit(void) 5.25 { 5.26 ws->shutdown(); 5.27 } 5.28 @@ -51,7 +51,22 @@ 5.29 return ws->set_title(str); 5.30 } 5.31 5.32 +void sgl_redisplay(void) 5.33 +{ 5.34 + ws->redisplay(); 5.35 +} 5.36 + 5.37 +void sgl_swap_buffers(void) 5.38 +{ 5.39 + ws->swap_buffers(); 5.40 +} 5.41 + 5.42 int sgl_process_events(void) 5.43 { 5.44 return ws->process_events(); 5.45 } 5.46 + 5.47 +void sgl_event_loop(void) 5.48 +{ 5.49 + while(ws->process_events() == 0); 5.50 +}
6.1 --- a/src/wsys.h Thu May 12 11:04:10 2011 +0300 6.2 +++ b/src/wsys.h Fri May 13 07:49:47 2011 +0300 6.3 @@ -17,12 +17,12 @@ 6.4 int (*set_active)(int); 6.5 int (*set_title)(const char*); 6.6 6.7 + void (*redisplay)(void); 6.8 + void (*swap_buffers)(void); 6.9 + 6.10 void (*set_event)(int idx, int enable); 6.11 int (*process_events)(void); 6.12 6.13 - void (*redisplay)(void); 6.14 - void (*swap_buffers)(void); 6.15 - 6.16 struct wsys_module *next; 6.17 }; 6.18
7.1 --- a/src/wsys_x11.c Thu May 12 11:04:10 2011 +0300 7.2 +++ b/src/wsys_x11.c Fri May 13 07:49:47 2011 +0300 7.3 @@ -5,10 +5,14 @@ 7.4 #include "wsys.h" 7.5 #include "log.h" 7.6 7.7 + 7.8 struct window { 7.9 Window win; 7.10 GLXContext ctx; 7.11 + int width, height; 7.12 + int mapped; 7.13 long evmask; 7.14 + int redisp_pending; 7.15 struct window *next; 7.16 }; 7.17 7.18 @@ -27,6 +31,8 @@ 7.19 7.20 /* window management */ 7.21 static int set_active(int id); 7.22 +static struct window *find_window(int id); 7.23 +static int activate_window(struct window *win); 7.24 static int set_title(const char *str); 7.25 static void redisplay(void); 7.26 static void swap_buffers(void); 7.27 @@ -36,7 +42,8 @@ 7.28 static void clear_bits(long *mask, long bits); 7.29 static void set_event(int idx, int enable); 7.30 static int process_events(void); 7.31 - 7.32 +static int handle_event(XEvent *xev); 7.33 +static int translate_keysym(KeySym sym); 7.34 7.35 static struct wsys_module ws = { 7.36 "x11-glx", 0, 7.37 @@ -60,7 +67,7 @@ 7.38 static int scr; 7.39 static Atom xa_wm_prot, xa_wm_del_win; 7.40 static struct window *winlist; 7.41 -static struct window *active_win; 7.42 +static struct window *active_win, *prev_active; 7.43 7.44 /* this is the only exported function, everything else should be static */ 7.45 void sgl_register_x11(void) 7.46 @@ -70,7 +77,13 @@ 7.47 7.48 static int init(void) 7.49 { 7.50 + if(dpy) { 7.51 + sgl_log("warning: double init\n"); 7.52 + return 0; 7.53 + } 7.54 + 7.55 winlist = 0; 7.56 + active_win = prev_active = 0; 7.57 7.58 if(!(dpy = XOpenDisplay(0))) { 7.59 sgl_log("failed to open X display: %s\n", XDisplayName(0)); 7.60 @@ -87,6 +100,10 @@ 7.61 7.62 static void shutdown(void) 7.63 { 7.64 + if(!dpy) { 7.65 + return; 7.66 + } 7.67 + 7.68 while(winlist) { 7.69 struct window *win = winlist; 7.70 winlist = winlist->next; 7.71 @@ -171,9 +188,13 @@ 7.72 7.73 wnode->win = win; 7.74 wnode->ctx = ctx; 7.75 + wnode->width = xsz; 7.76 + wnode->height = ysz; 7.77 + wnode->mapped = 0; 7.78 wnode->evmask = evmask; 7.79 + wnode->redisp_pending = 1; 7.80 wnode->next = winlist; 7.81 - winlist->next = wnode; 7.82 + winlist = wnode; 7.83 7.84 if(!active_win) { 7.85 set_active(win); 7.86 @@ -261,22 +282,37 @@ 7.87 7.88 static int set_active(int id) 7.89 { 7.90 + struct window *win = find_window(id); 7.91 + if(!win) { 7.92 + sgl_log("no such window: %d\n", id); 7.93 + return -1; 7.94 + } 7.95 + /* only the user calls this, so don't revert this selection */ 7.96 + prev_active = win; 7.97 + return activate_window(win); 7.98 +} 7.99 + 7.100 +static struct window *find_window(int id) 7.101 +{ 7.102 struct window *win = winlist; 7.103 7.104 while(win) { 7.105 if(win->win == id) { 7.106 - if(glXMakeCurrent(dpy, win->win, win->ctx) == False) { 7.107 - sgl_log("failed to activate window %d\n", id); 7.108 - return -1; 7.109 - } 7.110 - active_win = win; 7.111 - return 0; 7.112 + return win; 7.113 } 7.114 win = win->next; 7.115 } 7.116 + return 0; 7.117 +} 7.118 7.119 - sgl_log("no such window: %d\n", id); 7.120 - return -1; 7.121 +static int activate_window(struct window *win) 7.122 +{ 7.123 + if(glXMakeCurrent(dpy, win->win, win->ctx) == False) { 7.124 + sgl_log("failed to activate window %d\n", (int)win->win); 7.125 + return -1; 7.126 + } 7.127 + active_win = win; 7.128 + return 0; 7.129 } 7.130 7.131 static int set_title(const char *str) 7.132 @@ -300,7 +336,7 @@ 7.133 7.134 static void swap_buffers(void) 7.135 { 7.136 - glXSwapBuffers(dpy, active_win->ctx); 7.137 + glXSwapBuffers(dpy, active_win->win); 7.138 } 7.139 7.140 static void set_bits(long *mask, long bits) 7.141 @@ -350,76 +386,163 @@ 7.142 { 7.143 XEvent xev; 7.144 void (*func)(); 7.145 - int state; 7.146 + struct window *win; 7.147 7.148 + prev_active = active_win; 7.149 + 7.150 + win = winlist; 7.151 + while(win) { 7.152 + if(win->redisp_pending && (func = sgl_get_callback(SGL_DISPLAY))) { 7.153 + activate_window(win); 7.154 + func(); 7.155 + win->redisp_pending = 0; 7.156 + } 7.157 + win = win->next; 7.158 + } 7.159 + 7.160 + func = sgl_get_callback(SGL_IDLE); 7.161 + if(!func) { 7.162 + XNextEvent(dpy, &xev); 7.163 + XPutBackEvent(dpy, &xev); 7.164 + } 7.165 + 7.166 + /* process all pending events... */ 7.167 while(XPending(dpy)) { 7.168 XNextEvent(dpy, &xev); 7.169 + if(handle_event(&xev) == -1) { 7.170 + return -1; 7.171 + } 7.172 7.173 - switch(xev.type) { 7.174 - case Expose: 7.175 - if(xev.xexpose.count == 0) { 7.176 - if((func = sgl_get_callback(SGL_DISPLAY))) { 7.177 - func(); 7.178 - active_win->redisp_pending = 0; 7.179 + if(!dpy) { 7.180 + return -1; 7.181 + } 7.182 + } 7.183 + 7.184 + if(func) { 7.185 + /* ... and then call the idle function */ 7.186 + func(); 7.187 + } 7.188 + 7.189 + activate_window(prev_active); 7.190 + return 0; 7.191 +} 7.192 + 7.193 +/* returns 0, or -1 when the last window gets closed */ 7.194 +static int handle_event(XEvent *xev) 7.195 +{ 7.196 + int state; 7.197 + struct window *win; 7.198 + void (*func)(); 7.199 + 7.200 + if((win = find_window(xev->xany.window))) { 7.201 + activate_window(win); 7.202 + } else { 7.203 + return 0; 7.204 + } 7.205 + 7.206 + switch(xev->type) { 7.207 + case MapNotify: 7.208 + active_win->mapped = 1; 7.209 + break; 7.210 + 7.211 + case UnmapNotify: 7.212 + active_win->mapped = 0; 7.213 + break; 7.214 + 7.215 + case Expose: 7.216 + if(active_win->mapped && xev->xexpose.count == 0) { 7.217 + if((func = sgl_get_callback(SGL_DISPLAY))) { 7.218 + func(); 7.219 + active_win->redisp_pending = 0; 7.220 + } 7.221 + } 7.222 + break; 7.223 + 7.224 + case MotionNotify: 7.225 + if(xev->xmotion.state) { 7.226 + func = sgl_get_callback(SGL_MOTION); 7.227 + } else { 7.228 + func = sgl_get_callback(SGL_PASSIVE); 7.229 + } 7.230 + if(func) { 7.231 + func(xev->xmotion.x, xev->xmotion.y); 7.232 + } 7.233 + break; 7.234 + 7.235 + case ButtonPress: 7.236 + if(1) { 7.237 + state = 1; 7.238 + } else { 7.239 + case ButtonRelease: 7.240 + state = 0; 7.241 + } 7.242 + if((func = sgl_get_callback(SGL_MOUSE))) { 7.243 + int bn = xev->xbutton.button - 1; 7.244 + func(bn, state, xev->xbutton.x, xev->xbutton.y); 7.245 + } 7.246 + break; 7.247 + 7.248 + case KeyPress: 7.249 + if(1) { 7.250 + state = 1; 7.251 + } else { 7.252 + case KeyRelease: 7.253 + state = 0; 7.254 + } 7.255 + if((func = sgl_get_callback(SGL_KEYBOARD))) { 7.256 + KeySym sym = XLookupKeysym(&xev->xkey, 0); 7.257 + func(translate_keysym(sym), state); 7.258 + } 7.259 + break; 7.260 + 7.261 + case ConfigureNotify: 7.262 + if((func = sgl_get_callback(SGL_RESHAPE))) { 7.263 + if(xev->xconfigure.width != active_win->width || xev->xconfigure.height != active_win->height) { 7.264 + active_win->width = xev->xconfigure.width; 7.265 + active_win->height = xev->xconfigure.height; 7.266 + 7.267 + func(xev->xconfigure.width, xev->xconfigure.height); 7.268 + } 7.269 + } 7.270 + break; 7.271 + 7.272 + case ClientMessage: 7.273 + if(xev->xclient.message_type == xa_wm_prot) { 7.274 + if(xev->xclient.data.l[0] == xa_wm_del_win) { 7.275 + close_window(active_win->win); 7.276 + if(!active_win) { 7.277 + return -1; 7.278 } 7.279 } 7.280 - break; 7.281 + } 7.282 + break; 7.283 7.284 - case MotionNotify: 7.285 - if(xev.xmotion.state) { 7.286 - func = sgl_get_callback(SGL_MOTION); 7.287 - } else { 7.288 - func = sgl_get_callback(SGL_PASSIVE); 7.289 - } 7.290 - if(func) { 7.291 - func(xev.xmotion.x, xev.xmotion.y); 7.292 - } 7.293 - break; 7.294 + default: 7.295 + break; 7.296 + } 7.297 7.298 - case ButtonPress: 7.299 - if(1) { 7.300 - state = 1; 7.301 - } else { 7.302 - case ButtonRelease: 7.303 - state = 0; 7.304 - } 7.305 - if((func = sgl_get_callback(SGL_MOUSE))) { 7.306 - int bn = xev.xbutton.button - 1; 7.307 - func(bn, state, xev.xbutton.x, xev.xbutton.y); 7.308 - } 7.309 - break; 7.310 - 7.311 - case KeyPress: 7.312 - if(1) { 7.313 - state = 1; 7.314 - } else { 7.315 - case KeyRelease: 7.316 - state = 0; 7.317 - } 7.318 - if((func = sgl_get_callback(SGL_KEYBOARD))) { 7.319 - KeySym sym = XLookupKeysym(xev.xkey, 0); 7.320 - func(sym, state); 7.321 - /* XXX */ 7.322 - } 7.323 - break; 7.324 - 7.325 - case ConfigureNotify: 7.326 - if((func = sgl_get_callback(SGL_RESHAPE))) { 7.327 - func(xev.xconfigure.width, xev.xconfigure.height); 7.328 - } 7.329 - break; 7.330 - } 7.331 - 7.332 - case ClientMessage: 7.333 - if(xev.xclient.message_type == xa_wm_prot) { 7.334 - if(xev.xclient.data.l[0] == xa_wm_del_win) { 7.335 - close_window(active_win->win); 7.336 - if(!active_win) { 7.337 - return 1; 7.338 - } 7.339 - } 7.340 - } 7.341 - break; 7.342 - } 7.343 return 0; 7.344 } 7.345 + 7.346 +static int translate_keysym(KeySym sym) 7.347 +{ 7.348 + if(sym < 256) { 7.349 + return sym; 7.350 + } 7.351 + 7.352 + switch(sym) { 7.353 + case XK_BackSpace: 7.354 + return '\b'; 7.355 + case XK_Tab: 7.356 + return '\t'; 7.357 + case XK_Linefeed: 7.358 + return '\r'; 7.359 + case XK_Return: 7.360 + return '\n'; 7.361 + case XK_Escape: 7.362 + return 27; 7.363 + default: 7.364 + break; 7.365 + } 7.366 + return (int)sym; 7.367 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/tests/simple/Makefile Fri May 13 07:49:47 2011 +0300 8.3 @@ -0,0 +1,1 @@ 8.4 +../tests-makefile 8.5 \ No newline at end of file
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/tests/simple/simple.c Fri May 13 07:49:47 2011 +0300 9.3 @@ -0,0 +1,83 @@ 9.4 +#include <stdio.h> 9.5 +#include <ctype.h> 9.6 +#include <GL/gl.h> 9.7 +#include "sgl.h" 9.8 + 9.9 +void disp(void); 9.10 +void reshape(int x, int y); 9.11 +void keyb(int key, int state); 9.12 +void mouse(int bn, int state, int x, int y); 9.13 +void motion(int x, int y); 9.14 + 9.15 + 9.16 +int main(void) 9.17 +{ 9.18 + if(sgl_init() == -1) { 9.19 + return 1; 9.20 + } 9.21 + 9.22 + sgl_create_window(640, 480, SGL_DOUBLE | SGL_DEPTH); 9.23 + 9.24 + sgl_set_callback(SGL_DISPLAY, disp); 9.25 + sgl_set_callback(SGL_RESHAPE, reshape); 9.26 + sgl_set_callback(SGL_KEYBOARD, keyb); 9.27 + sgl_set_callback(SGL_MOUSE, mouse); 9.28 + sgl_set_callback(SGL_MOTION, motion); 9.29 + 9.30 + sgl_event_loop(); 9.31 + sgl_quit(); 9.32 + return 0; 9.33 +} 9.34 + 9.35 + 9.36 +void disp(void) 9.37 +{ 9.38 + printf("redisplay\n"); 9.39 + 9.40 + glClearColor(0.2, 0.2, 0.2, 1); 9.41 + glClear(GL_COLOR_BUFFER_BIT); 9.42 + 9.43 + glBegin(GL_QUADS); 9.44 + glColor3f(1, 0, 0); 9.45 + glVertex2f(-1, -1); 9.46 + glColor3f(0, 1, 0); 9.47 + glVertex2f(1, -1); 9.48 + glColor3f(0, 0, 1); 9.49 + glVertex2f(1, 1); 9.50 + glColor3f(1, 1, 0); 9.51 + glVertex2f(-1, 1); 9.52 + glEnd(); 9.53 + 9.54 + sgl_swap_buffers(); 9.55 +} 9.56 + 9.57 +void reshape(int x, int y) 9.58 +{ 9.59 + printf("reshape: %dx%d\n", x, y); 9.60 + glViewport(0, 0, x, y); 9.61 +} 9.62 + 9.63 +void keyb(int key, int state) 9.64 +{ 9.65 + char *ststr = state ? "pressed" : "released"; 9.66 + 9.67 + if(key < 0xff && isprint(key)) { 9.68 + printf("keyboard: '%c' %s\n", (char)key, ststr); 9.69 + } else { 9.70 + printf("keyboard: %x %s\n", key, ststr); 9.71 + } 9.72 + 9.73 + if(key == 27) { 9.74 + sgl_quit(); 9.75 + } 9.76 +} 9.77 + 9.78 +void mouse(int bn, int state, int x, int y) 9.79 +{ 9.80 + printf("mouse: button%d %s (ptr: %d %d)\n", bn, state ? "pressed" : "released", x, y); 9.81 +} 9.82 + 9.83 +void motion(int x, int y) 9.84 +{ 9.85 + printf("mouse dragged to: (%d %d)\n", x, y); 9.86 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/tests/tests-makefile Fri May 13 07:49:47 2011 +0300 10.3 @@ -0,0 +1,21 @@ 10.4 +name = $(shell pwd | sed 's/.*\///') 10.5 +bin = $(name) 10.6 +src = $(wildcard *.c) 10.7 +obj = $(src:.c=.o) 10.8 + 10.9 +sgldir = ../.. 10.10 + 10.11 +CC = gcc 10.12 +CFLAGS = -pedantic -Wall -g -I$(sgldir)/include 10.13 +LDFLAGS = -L. -Wl,-rpath=. -lsgl -lGL -lGLU -lm 10.14 + 10.15 +$(bin): $(obj) libsgl.so 10.16 + $(CC) -o $@ $(obj) $(LDFLAGS) 10.17 + 10.18 +libsgl.so: $(sgldir)/libsgl.so.0.0 10.19 + ln -s $< $@.0 10.20 + ln -s $< $@ 10.21 + 10.22 +.PHONY: clean 10.23 +clean: 10.24 + rm -f $(obj) $(bin)