X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=src%2Fglut%2Fmain.c;fp=src%2Fglut%2Fmain.c;h=0e766bdc6860ebe0eeb52aa7606bb33a9b6bc255;hp=0000000000000000000000000000000000000000;hb=09e214b94e007964189222cca1e655f3aaefaf90;hpb=b2c24e9d5b637bb78d18a377d9957c07d0759030 diff --git a/src/glut/main.c b/src/glut/main.c new file mode 100644 index 0000000..0e766bd --- /dev/null +++ b/src/glut/main.c @@ -0,0 +1,521 @@ +#include +#include +#include +#include +#include "miniglut.h" +#include "demo.h" +#include "gfx.h" +#include "gfxutil.h" +#include "timer.h" +#include "audio.h" +#include "cfgopt.h" +#include "cgmath/cgmath.h" +#include "util.h" + +static void display(void); +static void idle(void); +static void reshape(int x, int y); +static void keydown(unsigned char key, int x, int y); +static void keyup(unsigned char key, int x, int y); +static void skeydown(int key, int x, int y); +static void skeyup(int key, int x, int y); +static int translate_special(int skey); +static void mouse_button(int bn, int st, int x, int y); +static void mouse_motion(int x, int y); +static void sball_motion(int x, int y, int z); +static void sball_rotate(int x, int y, int z); +static void sball_button(int bn, int st); +static void recalc_sball_matrix(float *xform); +static unsigned int next_pow2(unsigned int x); +static void set_fullscreen(int fs); +static void set_vsync(int vsync); + +int have_joy; +unsigned int joy_bnstate, joy_bndiff, joy_bnpress; + +#define MODE(w, h) \ + {0, w, h, 16, w * 2, 5, 6, 5, 11, 5, 0, 0xf800, 0x7e0, 0x1f, 0xbadf00d, 2, 0} +static struct video_mode vmodes[] = { + MODE(320, 240), MODE(400, 300), MODE(512, 384), MODE(640, 480), + MODE(800, 600), MODE(1024, 768), MODE(1280, 960), MODE(1280, 1024), + MODE(1920, 1080), MODE(1600, 1200), MODE(1920, 1200) +}; +static struct video_mode *cur_vmode; + +static unsigned int num_pressed; +static unsigned char keystate[256]; + +static unsigned long start_time; +static unsigned int modkeys; + +static int win_width, win_height; +static float win_aspect; +static unsigned int tex; + +#ifdef __unix__ +#include +static Display *xdpy; +static Window xwin; + +static void (*glx_swap_interval_ext)(); +static void (*glx_swap_interval_sgi)(); +#endif +#ifdef _WIN32 +#include +static PROC wgl_swap_interval_ext; +#endif + +static int use_sball; +static cgm_vec3 pos = {0, 0, 0}; +static cgm_quat rot = {0, 0, 0, 1}; + + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitWindowSize(800, 600); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("Mindlapse"); + + glutDisplayFunc(display); + glutIdleFunc(idle); + glutReshapeFunc(reshape); + glutKeyboardFunc(keydown); + glutKeyboardUpFunc(keyup); + glutSpecialFunc(skeydown); + glutSpecialUpFunc(skeyup); + glutMouseFunc(mouse_button); + glutMotionFunc(mouse_motion); + glutPassiveMotionFunc(mouse_motion); + glutSpaceballMotionFunc(sball_motion); + glutSpaceballRotateFunc(sball_rotate); + glutSpaceballButtonFunc(sball_button); + + glutSetCursor(GLUT_CURSOR_NONE); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_CULL_FACE); + + + if(!set_video_mode(match_video_mode(FB_WIDTH, FB_HEIGHT, FB_BPP), 1)) { + return 1; + } + +#ifdef __unix__ + xdpy = glXGetCurrentDisplay(); + xwin = glXGetCurrentDrawable(); + + if(!(glx_swap_interval_ext = glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"))) { + glx_swap_interval_sgi = glXGetProcAddress((unsigned char*)"glXSwapIntervalSGI"); + } +#endif +#ifdef _WIN32 + wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT"); +#endif + + if(au_init() == -1) { + return 1; + } + time_msec = 0; + if(demo_init(argc, argv) == -1) { + return 1; + } + atexit(demo_cleanup); + + if(opt.fullscreen) { + set_fullscreen(opt.fullscreen); + } + + reset_timer(); + + glutMainLoop(); + return 0; +} + +void demo_quit(void) +{ + exit(0); +} + +struct video_mode *video_modes(void) +{ + return vmodes; +} + +int num_video_modes(void) +{ + return sizeof vmodes / sizeof *vmodes; +} + +struct video_mode *get_video_mode(int idx) +{ + if(idx == VMODE_CURRENT) { + return cur_vmode; + } + return vmodes + idx; +} + +int match_video_mode(int xsz, int ysz, int bpp) +{ + struct video_mode *vm = vmodes; + int i, count = num_video_modes(); + + for(i=0; ixsz == xsz && vm->ysz == ysz && vm->bpp == bpp) { + return i; + } + vm++; + } + return -1; +} + +static int tex_xsz, tex_ysz; +static uint32_t *convbuf; +static int convbuf_size; + +void *set_video_mode(int idx, int nbuf) +{ + struct video_mode *vm = vmodes + idx; + + if(cur_vmode == vm) { + return vmem; + } + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + + tex_xsz = next_pow2(vm->xsz); + tex_ysz = next_pow2(vm->ysz); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_xsz, tex_ysz, 0, GL_RGBA, + GL_UNSIGNED_BYTE, 0); + if(opt.scaler == SCALER_LINEAR) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef((float)vm->xsz / tex_xsz, (float)vm->ysz / tex_ysz, 1); + + if(vm->xsz * vm->ysz > convbuf_size) { + convbuf_size = vm->xsz * vm->ysz; + free(convbuf); + convbuf = malloc(convbuf_size * sizeof *convbuf); + } + + if(demo_resizefb(vm->xsz, vm->ysz, vm->bpp) == -1) { + fprintf(stderr, "failed to allocate virtual framebuffer\n"); + return 0; + } + vmem = fb_pixels; + + cur_vmode = vm; + return vmem; +} + +void wait_vsync(void) +{ +} + +void blit_frame(void *pixels, int vsync) +{ + int i; + uint32_t *dptr = convbuf; + uint16_t *sptr = pixels; + static int prev_vsync = -1; + + if(vsync != prev_vsync) { + set_vsync(vsync); + prev_vsync = vsync; + } + + for(i=0; i= FB_ASPECT) { + glScalef(FB_ASPECT / win_aspect, 1, 1); + } else { + glScalef(1, win_aspect / FB_ASPECT, 1); + } + + glClear(GL_COLOR_BUFFER_BIT); + + glBegin(GL_QUADS); + glTexCoord2f(0, 1); + glVertex2f(-1, -1); + glTexCoord2f(1, 1); + glVertex2f(1, -1); + glTexCoord2f(1, 0); + glVertex2f(1, 1); + glTexCoord2f(0, 0); + glVertex2f(-1, 1); + glEnd(); + + glutSwapBuffers(); + assert(glGetError() == GL_NO_ERROR); +} + +int kb_isdown(int key) +{ + switch(key) { + case KB_ANY: + return num_pressed; + + case KB_ALT: + return keystate[KB_LALT] + keystate[KB_RALT]; + + case KB_CTRL: + return keystate[KB_LCTRL] + keystate[KB_RCTRL]; + } + + if(isalpha(key)) { + key = tolower(key); + } + return keystate[key]; +} + +/* timer */ +void init_timer(int res_hz) +{ +} + +void reset_timer(void) +{ + start_time = glutGet(GLUT_ELAPSED_TIME); +} + +unsigned long get_msec(void) +{ + return glutGet(GLUT_ELAPSED_TIME) - start_time; +} + +#ifdef _WIN32 +#include + +void sleep_msec(unsigned long msec) +{ + Sleep(msec); +} + +#else +#include + +void sleep_msec(unsigned long msec) +{ + usleep(msec * 1000); +} +#endif + +static void display(void) +{ + recalc_sball_matrix(sball_matrix); + + time_msec = get_msec(); + demo_draw(); +} + +static void idle(void) +{ + glutPostRedisplay(); +} + +static void reshape(int x, int y) +{ + win_width = x; + win_height = y; + win_aspect = (float)x / (float)y; + glViewport(0, 0, x, y); +} + +static void keydown(unsigned char key, int x, int y) +{ + modkeys = glutGetModifiers(); + + if((key == '\n' || key == '\r') && (modkeys & GLUT_ACTIVE_ALT)) { + opt.fullscreen ^= 1; + set_fullscreen(opt.fullscreen); + return; + } + keystate[key] = 1; + demo_keyboard(key, 1); +} + +static void keyup(unsigned char key, int x, int y) +{ + keystate[key] = 0; + demo_keyboard(key, 0); +} + +static void skeydown(int key, int x, int y) +{ + if(key == GLUT_KEY_F5) { + opt.scaler = (opt.scaler + 1) % NUM_SCALERS; + + if(opt.scaler == SCALER_LINEAR) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + } + key = translate_special(key); + keystate[key] = 1; + demo_keyboard(key, 1); +} + +static void skeyup(int key, int x, int y) +{ + key = translate_special(key); + keystate[key] = 0; + demo_keyboard(key, 0); +} + +static int translate_special(int skey) +{ + switch(skey) { + case 127: + return 127; + case GLUT_KEY_LEFT: + return KB_LEFT; + case GLUT_KEY_RIGHT: + return KB_RIGHT; + case GLUT_KEY_UP: + return KB_UP; + case GLUT_KEY_DOWN: + return KB_DOWN; + case GLUT_KEY_PAGE_UP: + return KB_PGUP; + case GLUT_KEY_PAGE_DOWN: + return KB_PGDN; + case GLUT_KEY_HOME: + return KB_HOME; + case GLUT_KEY_END: + return KB_END; + default: + if(skey >= GLUT_KEY_F1 && skey <= GLUT_KEY_F12) { + return KB_F1 + skey - GLUT_KEY_F1; + } + } + return 0; +} + +static void map_mouse_pos(int *xp, int *yp) +{ + int x = *xp; + int y = *yp; + + /* TODO */ + *xp = x * FB_WIDTH / win_width; + *yp = y * FB_HEIGHT / win_height; +} + +static void mouse_button(int bn, int st, int x, int y) +{ + map_mouse_pos(&x, &y); + mouse_x = x; + mouse_y = y; + + if(st == GLUT_DOWN) { + mouse_bmask |= 1 << bn; + } else { + mouse_bmask &= ~(1 << bn); + } +} + +static void mouse_motion(int x, int y) +{ + map_mouse_pos(&x, &y); + mouse_x = x; + mouse_y = y; +} + +static void sball_motion(int x, int y, int z) +{ + pos.x += x * 0.001f; + pos.y += y * 0.001f; + pos.z -= z * 0.001f; + +} + +static void sball_rotate(int rx, int ry, int rz) +{ + if(rx | ry | rz) { + float s = (float)rsqrt(rx * rx + ry * ry + rz * rz); + cgm_qrotate(&rot, 0.001f / s, rx * s, ry * s, -rz * s); + } +} + +static void sball_button(int bn, int st) +{ + pos.x = pos.y = pos.z = 0; + rot.x = rot.y = rot.z = 0; + rot.w = 1; +} + +static void recalc_sball_matrix(float *xform) +{ + cgm_mrotation_quat(xform, &rot); + xform[12] = pos.x; + xform[13] = pos.y; + xform[14] = pos.z; +} + + +static unsigned int next_pow2(unsigned int x) +{ + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x + 1; +} + +static void set_fullscreen(int fs) +{ + static int win_x, win_y; + + if(fs) { + win_x = glutGet(GLUT_WINDOW_WIDTH); + win_y = glutGet(GLUT_WINDOW_HEIGHT); + glutFullScreen(); + } else { + glutReshapeWindow(win_x, win_y); + } +} + +#ifdef __unix__ +static void set_vsync(int vsync) +{ + vsync = vsync ? 1 : 0; + if(glx_swap_interval_ext) { + glx_swap_interval_ext(xdpy, xwin, vsync); + } else if(glx_swap_interval_sgi) { + glx_swap_interval_sgi(vsync); + } +} +#endif +#ifdef WIN32 +static void set_vsync(int vsync) +{ + if(wgl_swap_interval_ext) { + wgl_swap_interval_ext(vsync ? 1 : 0); + } +} +#endif