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)