12 #include "cgmath/cgmath.h"
16 static void display(void);
17 static void idle(void);
18 static void reshape(int x, int y);
19 static void keydown(unsigned char key, int x, int y);
20 static void keyup(unsigned char key, int x, int y);
21 static void skeydown(int key, int x, int y);
22 static void skeyup(int key, int x, int y);
23 static int translate_special(int skey);
24 static void mouse_button(int bn, int st, int x, int y);
25 static void mouse_motion(int x, int y);
26 static void sball_motion(int x, int y, int z);
27 static void sball_rotate(int x, int y, int z);
28 static void sball_button(int bn, int st);
29 static void recalc_sball_matrix(float *xform);
30 static unsigned int next_pow2(unsigned int x);
31 static void set_fullscreen(int fs);
32 static void set_vsync(int vsync);
35 unsigned int joy_bnstate, joy_bndiff, joy_bnpress;
38 {0, w, h, 16, w * 2, 5, 6, 5, 11, 5, 0, 0xf800, 0x7e0, 0x1f, 0xbadf00d, 2, 0}
39 static struct video_mode vmodes[] = {
40 MODE(320, 240), MODE(400, 300), MODE(512, 384), MODE(640, 480),
41 MODE(800, 600), MODE(1024, 768), MODE(1280, 960), MODE(1280, 1024),
42 MODE(1920, 1080), MODE(1600, 1200), MODE(1920, 1200)
44 static struct video_mode *cur_vmode;
46 static unsigned int num_pressed;
47 static unsigned char keystate[256];
49 static unsigned long start_time;
50 static unsigned int modkeys;
52 static int win_width, win_height;
53 static float win_aspect;
54 static unsigned int tex;
61 static void (*glx_swap_interval_ext)();
62 static void (*glx_swap_interval_sgi)();
66 static PROC wgl_swap_interval_ext;
70 static cgm_vec3 pos = {0, 0, 0};
71 static cgm_quat rot = {0, 0, 0, 1};
74 int main(int argc, char **argv)
76 glutInit(&argc, argv);
78 if(glutGet(GLUT_SCREEN_HEIGHT) <= 1024) {
79 glutInitWindowSize(640, 480);
81 glutInitWindowSize(1280, 960);
83 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
84 glutCreateWindow("Mindlapse");
86 glutDisplayFunc(display);
88 glutReshapeFunc(reshape);
89 glutKeyboardFunc(keydown);
90 glutKeyboardUpFunc(keyup);
91 glutSpecialFunc(skeydown);
92 glutSpecialUpFunc(skeyup);
93 glutMouseFunc(mouse_button);
94 glutMotionFunc(mouse_motion);
95 glutPassiveMotionFunc(mouse_motion);
96 glutSpaceballMotionFunc(sball_motion);
97 glutSpaceballRotateFunc(sball_rotate);
98 glutSpaceballButtonFunc(sball_button);
100 glutSetCursor(GLUT_CURSOR_NONE);
102 glEnable(GL_TEXTURE_2D);
103 glEnable(GL_CULL_FACE);
105 if(read_cpuid(&cpuid) == 0) {
109 if(!set_video_mode(match_video_mode(FB_WIDTH, FB_HEIGHT, FB_BPP), 1)) {
114 xdpy = glXGetCurrentDisplay();
115 xwin = glXGetCurrentDrawable();
117 if(!(glx_swap_interval_ext = glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"))) {
118 glx_swap_interval_sgi = glXGetProcAddress((unsigned char*)"glXSwapIntervalSGI");
122 wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT");
125 if(au_init() == -1) {
129 if(demo_init1(argc, argv) == -1) {
134 set_fullscreen(opt.fullscreen);
135 reshape(glutGet(GLUT_SCREEN_WIDTH), glutGet(GLUT_SCREEN_HEIGHT));
137 reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
140 if(demo_init2() == -1) {
143 atexit(demo_cleanup);
156 void demo_abort(void)
161 struct video_mode *video_modes(void)
166 int num_video_modes(void)
168 return sizeof vmodes / sizeof *vmodes;
171 struct video_mode *get_video_mode(int idx)
173 if(idx == VMODE_CURRENT) {
179 int match_video_mode(int xsz, int ysz, int bpp)
181 struct video_mode *vm = vmodes;
182 int i, count = num_video_modes();
184 for(i=0; i<count; i++) {
185 if(vm->xsz == xsz && vm->ysz == ysz && vm->bpp == bpp) {
193 static int tex_xsz, tex_ysz;
194 static uint32_t *convbuf;
195 static int convbuf_size;
197 void *set_video_mode(int idx, int nbuf)
199 struct video_mode *vm = vmodes + idx;
201 if(cur_vmode == vm) {
205 glGenTextures(1, &tex);
206 glBindTexture(GL_TEXTURE_2D, tex);
208 tex_xsz = next_pow2(vm->xsz);
209 tex_ysz = next_pow2(vm->ysz);
210 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_xsz, tex_ysz, 0, GL_RGBA,
211 GL_UNSIGNED_BYTE, 0);
212 if(opt.scaler == SCALER_LINEAR) {
213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
220 glMatrixMode(GL_TEXTURE);
222 glScalef((float)vm->xsz / tex_xsz, (float)vm->ysz / tex_ysz, 1);
224 if(vm->xsz * vm->ysz > convbuf_size) {
225 convbuf_size = vm->xsz * vm->ysz;
227 convbuf = malloc(convbuf_size * sizeof *convbuf);
230 if(demo_resizefb(vm->xsz, vm->ysz, vm->bpp) == -1) {
231 fprintf(stderr, "failed to allocate virtual framebuffer\n");
240 void wait_vsync(void)
244 void blit_frame(void *pixels, int vsync)
247 uint32_t *dptr = convbuf;
248 uint16_t *sptr = pixels;
249 static int prev_vsync = -1;
251 if(vsync != prev_vsync) {
256 demo_post_draw(pixels);
258 for(i=0; i<FB_WIDTH * FB_HEIGHT; i++) {
259 int r = UNPACK_R16(*sptr);
260 int g = UNPACK_G16(*sptr);
261 int b = UNPACK_B16(*sptr);
262 *dptr++ = PACK_RGB32(b, g, r);
266 glBindTexture(GL_TEXTURE_2D, tex);
267 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, FB_WIDTH, FB_HEIGHT, GL_RGBA,
268 GL_UNSIGNED_BYTE, convbuf);
270 glMatrixMode(GL_MODELVIEW);
272 if(win_aspect >= FB_ASPECT) {
273 glScalef(FB_ASPECT / win_aspect, 1, 1);
275 glScalef(1, win_aspect / FB_ASPECT, 1);
278 glClear(GL_COLOR_BUFFER_BIT);
292 assert(glGetError() == GL_NO_ERROR);
295 int kb_isdown(int key)
302 return keystate[KB_LALT] + keystate[KB_RALT];
305 return keystate[KB_LCTRL] + keystate[KB_RCTRL];
311 return keystate[key];
315 void init_timer(int res_hz)
319 void reset_timer(void)
321 start_time = glutGet(GLUT_ELAPSED_TIME);
324 unsigned long get_msec(void)
326 return glutGet(GLUT_ELAPSED_TIME) - start_time;
332 void sleep_msec(unsigned long msec)
340 void sleep_msec(unsigned long msec)
346 static void display(void)
348 recalc_sball_matrix(sball_matrix);
350 time_msec = get_msec();
354 static void idle(void)
359 static void reshape(int x, int y)
363 win_aspect = (float)x / (float)y;
364 glViewport(0, 0, x, y);
367 static void keydown(unsigned char key, int x, int y)
369 modkeys = glutGetModifiers();
371 if((key == '\n' || key == '\r') && (modkeys & GLUT_ACTIVE_ALT)) {
373 set_fullscreen(opt.fullscreen);
377 demo_keyboard(key, 1);
380 static void keyup(unsigned char key, int x, int y)
383 demo_keyboard(key, 0);
386 static void skeydown(int key, int x, int y)
388 if(key == GLUT_KEY_F5) {
389 opt.scaler = (opt.scaler + 1) % NUM_SCALERS;
391 if(opt.scaler == SCALER_LINEAR) {
392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
393 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
395 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
396 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
399 key = translate_special(key);
401 demo_keyboard(key, 1);
404 static void skeyup(int key, int x, int y)
406 key = translate_special(key);
408 demo_keyboard(key, 0);
411 static int translate_special(int skey)
424 case GLUT_KEY_PAGE_UP:
426 case GLUT_KEY_PAGE_DOWN:
433 if(skey >= GLUT_KEY_F1 && skey <= GLUT_KEY_F12) {
434 return KB_F1 + skey - GLUT_KEY_F1;
440 static void map_mouse_pos(int *xp, int *yp)
446 *xp = x * FB_WIDTH / win_width;
447 *yp = y * FB_HEIGHT / win_height;
450 static void mouse_button(int bn, int st, int x, int y)
454 map_mouse_pos(&x, &y);
459 case GLUT_LEFT_BUTTON:
462 case GLUT_RIGHT_BUTTON:
465 case GLUT_MIDDLE_BUTTON:
470 if(st == GLUT_DOWN) {
471 mouse_bmask |= 1 << bit;
473 mouse_bmask &= ~(1 << bit);
477 static void mouse_motion(int x, int y)
479 map_mouse_pos(&x, &y);
484 static void sball_motion(int x, int y, int z)
492 static void sball_rotate(int rx, int ry, int rz)
495 float s = (float)rsqrt(rx * rx + ry * ry + rz * rz);
496 cgm_qrotate(&rot, 0.001f / s, rx * s, ry * s, -rz * s);
500 static void sball_button(int bn, int st)
502 pos.x = pos.y = pos.z = 0;
503 rot.x = rot.y = rot.z = 0;
507 static void recalc_sball_matrix(float *xform)
509 cgm_mrotation_quat(xform, &rot);
516 static unsigned int next_pow2(unsigned int x)
527 static void set_fullscreen(int fs)
529 static int win_x, win_y;
532 win_x = glutGet(GLUT_WINDOW_WIDTH);
533 win_y = glutGet(GLUT_WINDOW_HEIGHT);
536 glutReshapeWindow(win_x, win_y);
541 static void set_vsync(int vsync)
543 vsync = vsync ? 1 : 0;
544 if(glx_swap_interval_ext) {
545 glx_swap_interval_ext(xdpy, xwin, vsync);
546 } else if(glx_swap_interval_sgi) {
547 glx_swap_interval_sgi(vsync);
552 static void set_vsync(int vsync)
554 if(wgl_swap_interval_ext) {
555 wgl_swap_interval_ext(vsync ? 1 : 0);