nuclear@20: /* SimplyGL window system module for SDL */ nuclear@20: /* link-with: `sdl-config --libs` */ nuclear@20: nuclear@20: #include "config.h" nuclear@20: nuclear@20: #ifdef USE_WSYS_MODULE_SDL nuclear@20: nuclear@20: #include nuclear@20: #include "sgl.h" nuclear@20: #include "wsys.h" nuclear@20: nuclear@20: nuclear@20: nuclear@20: static int init(void); nuclear@20: static void shutdown(void); nuclear@20: nuclear@20: /* video mode switching */ nuclear@20: static int set_vidmode(int xsz, int ysz); nuclear@20: static int get_vidmode(int *xsz, int *ysz); nuclear@20: nuclear@20: /* create/destroy windows */ nuclear@20: static int create_window(int xsz, int ysz, unsigned int flags); nuclear@20: static void close_window(int wid); nuclear@20: nuclear@20: /* window management */ nuclear@20: static int set_active(int wid); nuclear@20: static int set_title(const char *str); nuclear@20: static void redisplay(void); nuclear@20: static void swap_buffers(void); nuclear@20: nuclear@20: static int get_modifiers(void); nuclear@20: nuclear@20: /* event handling and friends */ nuclear@20: static void set_event(int idx, int enable); nuclear@20: static int process_events(void); nuclear@20: static int handle_event(SDL_Event *ev); nuclear@20: nuclear@20: nuclear@20: static struct wsys_module ws = { nuclear@20: "sdl", 6, nuclear@20: init, nuclear@20: shutdown, nuclear@20: set_vidmode, nuclear@20: get_vidmode, nuclear@20: create_window, nuclear@20: close_window, nuclear@20: set_active, nuclear@20: set_title, nuclear@20: redisplay, nuclear@20: swap_buffers, nuclear@20: get_modifiers, nuclear@20: set_event, nuclear@20: process_events, nuclear@20: 0 nuclear@20: }; nuclear@20: nuclear@20: static int must_redisplay = 1; nuclear@20: static int win_width, win_height; nuclear@20: static unsigned int sdl_flags; nuclear@20: nuclear@20: nuclear@20: void sgl_register_sdl(void) nuclear@20: { nuclear@20: sgl_register_module(&ws); nuclear@20: } nuclear@20: nuclear@20: nuclear@20: static int init(void) nuclear@20: { nuclear@20: return SDL_Init(SDL_INIT_VIDEO); nuclear@20: } nuclear@20: nuclear@20: static void shutdown(void) nuclear@20: { nuclear@20: SDL_Quit(); nuclear@20: } nuclear@20: nuclear@20: /* video mode switching */ nuclear@20: static int set_vidmode(int xsz, int ysz) nuclear@20: { nuclear@20: return 0; /* TODO */ nuclear@20: } nuclear@20: nuclear@20: static int get_vidmode(int *xsz, int *ysz) nuclear@20: { nuclear@20: return 0; /* TODO */ nuclear@20: } nuclear@20: nuclear@20: /* create/destroy windows */ nuclear@20: static int create_window(int xsz, int ysz, unsigned int flags) nuclear@20: { nuclear@20: void (*func)(); nuclear@20: nuclear@20: SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); nuclear@20: SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); nuclear@20: SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); nuclear@20: nuclear@20: if(flags & SGL_DOUBLE) { nuclear@20: SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); nuclear@20: } nuclear@20: if(flags & SGL_DEPTH) { nuclear@20: SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); nuclear@20: } nuclear@20: if(flags & SGL_STENCIL) { nuclear@20: SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); nuclear@20: } nuclear@20: if(flags & SGL_STEREO) { nuclear@20: SDL_GL_SetAttribute(SDL_GL_STEREO, 1); nuclear@20: } nuclear@20: if(flags & SGL_MULTISAMPLE) { nuclear@20: SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); nuclear@20: SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); nuclear@20: } nuclear@20: nuclear@20: sdl_flags = SDL_OPENGL | SDL_RESIZABLE; nuclear@20: nuclear@20: if(!SDL_SetVideoMode(xsz, ysz, 32, sdl_flags)) { nuclear@20: return -1; nuclear@20: } nuclear@20: win_width = xsz; nuclear@20: win_height = ysz; nuclear@20: set_title("OpenGL/SDL"); nuclear@20: nuclear@20: if((func = sgl_get_callback(SGL_CREATE))) { nuclear@20: func(0); nuclear@20: } nuclear@20: if((func = sgl_get_callback(SGL_RESHAPE))) { nuclear@20: func(xsz, ysz); nuclear@20: } nuclear@20: nuclear@20: return 0; nuclear@20: } nuclear@20: nuclear@20: static void close_window(int wid) nuclear@20: { nuclear@20: SDL_Quit(); nuclear@20: } nuclear@20: nuclear@20: /* window management */ nuclear@20: static int set_active(int wid) nuclear@20: { nuclear@20: return 0; /* only one window is supported in SDL */ nuclear@20: } nuclear@20: nuclear@20: static int set_title(const char *str) nuclear@20: { nuclear@20: SDL_WM_SetCaption(str, str); nuclear@20: return 0; nuclear@20: } nuclear@20: nuclear@20: static void redisplay(void) nuclear@20: { nuclear@20: must_redisplay = 1; nuclear@20: } nuclear@20: nuclear@20: static void swap_buffers(void) nuclear@20: { nuclear@20: SDL_GL_SwapBuffers(); nuclear@20: } nuclear@20: nuclear@20: static int get_modifiers(void) nuclear@20: { nuclear@20: int mod = 0; nuclear@20: SDLMod sdlmod = SDL_GetModState(); nuclear@20: nuclear@20: if(sdlmod & (KMOD_LSHIFT | KMOD_RSHIFT)) { nuclear@20: mod |= SGL_MOD_SHIFT; nuclear@20: } nuclear@20: if(sdlmod & (KMOD_LCTRL | KMOD_RCTRL)) { nuclear@20: mod |= SGL_MOD_CONTROL; nuclear@20: } nuclear@20: if(sdlmod & (KMOD_LALT | KMOD_RALT)) { nuclear@20: mod |= SGL_MOD_ALT; nuclear@20: } nuclear@20: return mod; nuclear@20: } nuclear@20: nuclear@20: /* event handling and friends */ nuclear@20: static void set_event(int idx, int enable) nuclear@20: { nuclear@20: /* no need to do anything for SDL */ nuclear@20: } nuclear@20: nuclear@20: static int process_events(void) nuclear@20: { nuclear@20: int got_event; nuclear@20: SDL_Event ev; nuclear@20: sgl_idle_callback_t idle = sgl_get_callback(SGL_IDLE); nuclear@20: sgl_display_callback_t disp = sgl_get_callback(SGL_DISPLAY); nuclear@20: nuclear@20: if(must_redisplay && disp) { nuclear@20: disp(); nuclear@20: must_redisplay = 0; nuclear@20: } nuclear@20: nuclear@20: if(idle) { nuclear@20: got_event = SDL_PollEvent(&ev); nuclear@20: } else { nuclear@20: if(!SDL_WaitEvent(&ev)) { nuclear@20: return -1; nuclear@20: } nuclear@20: got_event = 1; nuclear@20: } nuclear@20: nuclear@20: if(got_event) { nuclear@20: do { nuclear@20: if(handle_event(&ev) == -1) { nuclear@20: return -1; nuclear@20: } nuclear@20: } while(SDL_PollEvent(&ev)); nuclear@20: } nuclear@20: nuclear@20: if(idle) { nuclear@20: idle(); nuclear@20: } nuclear@20: nuclear@20: return 0; nuclear@20: } nuclear@20: nuclear@20: static int handle_event(SDL_Event *ev) nuclear@20: { nuclear@20: void (*func)(); nuclear@20: nuclear@20: switch(ev->type) { nuclear@20: case SDL_VIDEORESIZE: nuclear@20: /* XXX this'll fuck up big time on windows, will lose the gl state! */ nuclear@20: SDL_SetVideoMode(ev->resize.w, ev->resize.h, 32, sdl_flags); nuclear@20: nuclear@20: if((func = sgl_get_callback(SGL_RESHAPE)) && nuclear@20: (ev->resize.w != win_width || ev->resize.h != win_height)) { nuclear@20: win_width = ev->resize.w; nuclear@20: win_height = ev->resize.h; nuclear@20: nuclear@20: func(win_width, win_height); nuclear@20: } nuclear@20: break; nuclear@20: nuclear@20: case SDL_VIDEOEXPOSE: nuclear@20: must_redisplay = 1; nuclear@20: break; nuclear@20: nuclear@20: case SDL_KEYDOWN: nuclear@20: case SDL_KEYUP: nuclear@20: if((func = sgl_get_callback(SGL_KEYBOARD))) { nuclear@20: func(ev->key.keysym.sym, ev->key.state == SDL_PRESSED); nuclear@20: } nuclear@20: break; nuclear@20: nuclear@20: case SDL_MOUSEBUTTONDOWN: nuclear@20: case SDL_MOUSEBUTTONUP: nuclear@20: if((func = sgl_get_callback(SGL_MOUSE))) { nuclear@20: func(ev->button.which - 1, ev->button.state == SDL_PRESSED, ev->button.x, ev->button.y); nuclear@20: } nuclear@20: break; nuclear@20: nuclear@20: case SDL_MOUSEMOTION: nuclear@20: if(ev->motion.state) { nuclear@20: func = sgl_get_callback(SGL_MOTION); nuclear@20: } else { nuclear@20: func = sgl_get_callback(SGL_PASSIVE); nuclear@20: } nuclear@20: nuclear@20: if(func) { nuclear@20: func(ev->motion.x, ev->motion.y); nuclear@20: } nuclear@20: break; nuclear@20: nuclear@20: case SDL_QUIT: nuclear@20: return -1; nuclear@20: } nuclear@20: nuclear@20: return 0; nuclear@20: } nuclear@20: nuclear@20: #else nuclear@20: int sgl_wsys_sdl_silence_the_fucking_empty_file_warnings; nuclear@20: #endif /* USE_WSYS_MODULE_SDL */