nuclear@7: /* SimplyGL window system module for GLUT */ nuclear@7: /* link-with: -lglut */ nuclear@10: /* mac-framework: -framework GLUT */ nuclear@7: nuclear@7: #include "config.h" nuclear@7: nuclear@7: #ifdef USE_WSYS_MODULE_GLUT nuclear@7: nuclear@12: #include nuclear@7: #include nuclear@7: #ifndef __APPLE__ nuclear@7: #include nuclear@7: #ifdef FREEGLUT nuclear@7: #include nuclear@7: #endif /* freeglut */ nuclear@7: nuclear@7: #else /* apple */ nuclear@7: #include nuclear@7: #endif nuclear@7: nuclear@7: #include "sgl.h" nuclear@7: #include "wsys.h" nuclear@7: nuclear@7: struct window { nuclear@7: int id; nuclear@7: struct window *next; nuclear@7: }; nuclear@7: nuclear@7: static int init(void); nuclear@7: static void shutdown(void); nuclear@7: nuclear@7: /* video mode switching */ nuclear@7: static int set_vidmode(int xsz, int ysz); nuclear@7: static int get_vidmode(int *xsz, int *ysz); nuclear@7: nuclear@7: /* create/destroy windows */ nuclear@7: static int create_window(int xsz, int ysz, unsigned int flags); nuclear@7: static void close_window(int id); nuclear@7: nuclear@7: /* window management */ nuclear@7: static int set_active(int id); nuclear@7: static int set_title(const char *str); nuclear@7: static void redisplay(void); nuclear@7: static void swap_buffers(void); nuclear@7: nuclear@7: static int get_modifiers(void); nuclear@7: nuclear@7: /* event handling and friends */ nuclear@7: static void set_event(int idx, int enable); nuclear@7: static int process_events(void); nuclear@7: nuclear@7: /* callbacks */ nuclear@7: static void disp_cb(void); nuclear@7: static void reshape_cb(int x, int y); nuclear@7: static void keyb_down_cb(unsigned char c, int x, int y); nuclear@7: static void keyb_up_cb(unsigned char c, int x, int y); nuclear@7: static void special_down_cb(int c, int x, int y); nuclear@7: static void special_up_cb(int c, int x, int y); nuclear@7: static void mouse_cb(int bn, int state, int x, int y); nuclear@7: static void motion_cb(int x, int y); nuclear@7: static void passive_cb(int x, int y); nuclear@7: static void idle_cb(void); nuclear@7: nuclear@7: nuclear@7: static struct wsys_module ws = { nuclear@7: "glut", 1, nuclear@7: init, nuclear@7: shutdown, nuclear@7: set_vidmode, nuclear@7: get_vidmode, nuclear@7: create_window, nuclear@7: close_window, nuclear@7: set_active, nuclear@7: set_title, nuclear@7: redisplay, nuclear@7: swap_buffers, nuclear@7: get_modifiers, nuclear@7: set_event, nuclear@7: process_events, nuclear@7: 0 nuclear@7: }; nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: static jmp_buf jbuf; nuclear@7: #endif nuclear@7: nuclear@7: static struct window *winlist; nuclear@7: nuclear@7: nuclear@7: /* this is the only exported function, everything else should be static */ nuclear@7: void sgl_register_glut(void) nuclear@7: { nuclear@7: sgl_register_module(&ws); nuclear@7: } nuclear@7: nuclear@7: static int init(void) nuclear@7: { nuclear@7: char *argv[] = { "simplygl", 0 }; nuclear@7: int argc = 1; nuclear@7: nuclear@7: glutInit(&argc, argv); nuclear@7: return 0; nuclear@7: } nuclear@7: nuclear@7: static void shutdown(void) nuclear@7: { nuclear@7: struct window *win = winlist; nuclear@7: nuclear@7: while(win) { nuclear@7: int id = win->id; nuclear@7: win = win->next; nuclear@7: nuclear@7: close_window(id); nuclear@7: } nuclear@7: winlist = 0; nuclear@7: } nuclear@7: nuclear@7: static int set_vidmode(int xsz, int ysz) nuclear@7: { nuclear@7: /* TODO */ nuclear@7: return 0; nuclear@7: } nuclear@7: nuclear@7: static int get_vidmode(int *xsz, int *ysz) nuclear@7: { nuclear@7: /* TODO */ nuclear@7: return 0; nuclear@7: } nuclear@7: nuclear@7: static int create_window(int xsz, int ysz, unsigned int flags) nuclear@7: { nuclear@7: struct window *win; nuclear@7: unsigned int glut_flags = GLUT_RGBA; nuclear@7: nuclear@7: if(flags & SGL_DOUBLE) { nuclear@7: glut_flags |= GLUT_DOUBLE; nuclear@7: } nuclear@7: if(flags & SGL_DEPTH) { nuclear@7: glut_flags |= GLUT_DEPTH; nuclear@7: } nuclear@7: if(flags & SGL_STENCIL) { nuclear@7: glut_flags |= GLUT_STENCIL; nuclear@7: } nuclear@7: if(flags & SGL_STEREO) { nuclear@7: glut_flags |= GLUT_STEREO; nuclear@7: } nuclear@7: if(flags & SGL_MULTISAMPLE) { nuclear@7: glut_flags |= GLUT_MULTISAMPLE; nuclear@7: } nuclear@7: nuclear@7: if(!(win = malloc(sizeof *win))) { nuclear@7: return -1; nuclear@7: } nuclear@7: nuclear@7: glutInitDisplayMode(glut_flags); nuclear@7: glutInitWindowSize(xsz, ysz); nuclear@7: if((win->id = glutCreateWindow("OpenGL/GLUT")) <= 0) { nuclear@7: free(win); nuclear@7: return -1; nuclear@7: } nuclear@7: nuclear@7: win->next = winlist; nuclear@7: winlist = win; nuclear@7: return win->id; nuclear@7: } nuclear@7: nuclear@7: static void close_window(int id) nuclear@7: { nuclear@7: struct window dummy, *win, *prev; nuclear@7: nuclear@7: dummy.next = win = winlist; nuclear@7: prev = &dummy; nuclear@7: nuclear@7: while(win) { nuclear@7: if(win->id == id) { nuclear@7: prev->next = win->next; nuclear@7: free(win); nuclear@7: break; nuclear@7: } nuclear@13: prev = win; nuclear@7: win = win->next; nuclear@7: } nuclear@7: nuclear@7: glutDestroyWindow(id); nuclear@7: } nuclear@7: nuclear@7: static int set_active(int id) nuclear@7: { nuclear@7: glutSetWindow(id); nuclear@7: return 0; nuclear@7: } nuclear@7: nuclear@7: static int set_title(const char *str) nuclear@7: { nuclear@7: glutSetWindowTitle(str); nuclear@7: glutSetIconTitle(str); nuclear@7: return 0; nuclear@7: } nuclear@7: nuclear@7: static void redisplay(void) nuclear@7: { nuclear@7: glutPostRedisplay(); nuclear@7: } nuclear@7: nuclear@7: static void swap_buffers(void) nuclear@7: { nuclear@7: glutSwapBuffers(); nuclear@7: } nuclear@7: nuclear@7: static int get_modifiers(void) nuclear@7: { nuclear@7: return glutGetModifiers(); nuclear@7: } nuclear@7: nuclear@7: static void set_event(int idx, int enable) nuclear@7: { nuclear@7: switch(idx) { nuclear@7: case SGL_DISPLAY: nuclear@7: glutDisplayFunc(enable ? disp_cb : 0); nuclear@7: break; nuclear@7: case SGL_RESHAPE: nuclear@7: glutReshapeFunc(enable ? reshape_cb : 0); nuclear@7: break; nuclear@7: case SGL_KEYBOARD: nuclear@7: glutKeyboardFunc(enable ? keyb_down_cb : 0); nuclear@7: glutKeyboardUpFunc(enable ? keyb_up_cb : 0); nuclear@7: glutSpecialFunc(enable ? special_down_cb : 0); nuclear@7: glutSpecialUpFunc(enable ? special_up_cb : 0); nuclear@7: break; nuclear@7: case SGL_MOUSE: nuclear@7: glutMouseFunc(enable ? mouse_cb : 0); nuclear@7: break; nuclear@7: case SGL_MOTION: nuclear@7: glutMotionFunc(enable ? motion_cb : 0); nuclear@7: break; nuclear@7: case SGL_PASSIVE: nuclear@7: glutPassiveMotionFunc(enable ? passive_cb : 0); nuclear@7: break; nuclear@7: case SGL_IDLE: nuclear@7: glutIdleFunc(enable ? idle_cb : 0); nuclear@7: break; nuclear@7: default: nuclear@7: break; nuclear@7: } nuclear@7: } nuclear@7: nuclear@7: static int process_events(void) nuclear@7: { nuclear@7: #ifdef FREEGLUT nuclear@7: glutMainLoopEvent(); nuclear@7: #else nuclear@7: if(setjmp(jbuf) == 0) { nuclear@7: glutMainLoop(); nuclear@7: } nuclear@7: /* ok ... what happens is any callback that kicks in will set the idle func nuclear@7: * if it's not set, and then the idle func will longjmp right back here... nuclear@7: */ nuclear@7: #endif nuclear@7: return 0; nuclear@7: } nuclear@7: nuclear@7: static void disp_cb(void) nuclear@7: { nuclear@7: sgl_display_callback_t func = sgl_get_callback(SGL_DISPLAY); nuclear@7: func(); nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: glutIdleFunc(idle_cb); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: static void reshape_cb(int x, int y) nuclear@7: { nuclear@7: sgl_reshape_callback_t func = sgl_get_callback(SGL_RESHAPE); nuclear@7: func(x, y); nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: glutIdleFunc(idle_cb); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: static void keyb_down_cb(unsigned char c, int x, int y) nuclear@7: { nuclear@7: sgl_keyboard_callback_t func = sgl_get_callback(SGL_KEYBOARD); nuclear@7: func((int)c, 1); nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: glutIdleFunc(idle_cb); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: static void keyb_up_cb(unsigned char c, int x, int y) nuclear@7: { nuclear@7: sgl_keyboard_callback_t func = sgl_get_callback(SGL_KEYBOARD); nuclear@7: func((int)c, 0); nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: glutIdleFunc(idle_cb); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: static void special_down_cb(int c, int x, int y) nuclear@7: { nuclear@7: sgl_keyboard_callback_t func = sgl_get_callback(SGL_KEYBOARD); nuclear@7: func(c, 1); nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: glutIdleFunc(idle_cb); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: static void special_up_cb(int c, int x, int y) nuclear@7: { nuclear@7: sgl_keyboard_callback_t func = sgl_get_callback(SGL_KEYBOARD); nuclear@7: func(c, 0); nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: glutIdleFunc(idle_cb); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: static void mouse_cb(int bn, int state, int x, int y) nuclear@7: { nuclear@7: sgl_mouse_callback_t func = sgl_get_callback(SGL_MOUSE); nuclear@7: func(0, bn, state, x, y); nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: glutIdleFunc(idle_cb); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: static void motion_cb(int x, int y) nuclear@7: { nuclear@7: sgl_motion_callback_t func = sgl_get_callback(SGL_MOTION); nuclear@7: func(0, x, y); nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: glutIdleFunc(idle_cb); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: static void passive_cb(int x, int y) nuclear@7: { nuclear@7: sgl_passive_callback_t func = sgl_get_callback(SGL_PASSIVE); nuclear@7: func(0, x, y); nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: glutIdleFunc(idle_cb); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: static void idle_cb(void) nuclear@7: { nuclear@7: sgl_idle_callback_t func = sgl_get_callback(SGL_IDLE); nuclear@7: if(func) { nuclear@7: func(); nuclear@7: #ifndef FREEGLUT nuclear@7: } else { nuclear@7: /* this was just the longjmp trick so restore the lack of idle func */ nuclear@7: glutIdleFunc(0); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@7: #ifndef FREEGLUT nuclear@7: longjmp(jbuf, 0); nuclear@7: #endif nuclear@7: } nuclear@7: nuclear@8: #else nuclear@8: int sgl_wsys_glut_silence_the_fucking_empty_file_warnings; nuclear@7: #endif /* USE_WSYS_MODULE_GLUT */