removed clang-format and clang_complete files from the repo
[dosdemo] / src / glut / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <assert.h>
5 #include "miniglut.h"
6 #include "demo.h"
7 #include "gfx.h"
8 #include "gfxutil.h"
9 #include "timer.h"
10 #include "audio.h"
11 #include "cfgopt.h"
12 #include "cgmath/cgmath.h"
13 #include "util.h"
14 #include "cpuid.h"
15
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);
33
34 int have_joy;
35 unsigned int joy_bnstate, joy_bndiff, joy_bnpress;
36
37 #define MODE(w, h)      \
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)
43 };
44 static struct video_mode *cur_vmode;
45
46 static unsigned int num_pressed;
47 static unsigned char keystate[256];
48
49 static unsigned long start_time;
50 static unsigned int modkeys;
51
52 static int win_width, win_height;
53 static float win_aspect;
54 static unsigned int tex;
55
56 #ifdef __unix__
57 #include <GL/glx.h>
58 static Display *xdpy;
59 static Window xwin;
60
61 static void (*glx_swap_interval_ext)();
62 static void (*glx_swap_interval_sgi)();
63 #endif
64 #ifdef _WIN32
65 #include <windows.h>
66 static PROC wgl_swap_interval_ext;
67 #endif
68
69 static int use_sball;
70 static cgm_vec3 pos = {0, 0, 0};
71 static cgm_quat rot = {0, 0, 0, 1};
72
73
74 int main(int argc, char **argv)
75 {
76         glutInit(&argc, argv);
77
78         if(glutGet(GLUT_SCREEN_HEIGHT) <= 1024) {
79                 glutInitWindowSize(640, 480);
80         } else {
81                 glutInitWindowSize(1280, 960);
82         }
83         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
84         glutCreateWindow("Mindlapse");
85
86         glutDisplayFunc(display);
87         glutIdleFunc(idle);
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);
99
100         glutSetCursor(GLUT_CURSOR_NONE);
101
102         glEnable(GL_TEXTURE_2D);
103         glEnable(GL_CULL_FACE);
104
105         if(read_cpuid(&cpuid) == 0) {
106                 print_cpuid(&cpuid);
107         }
108
109         if(!set_video_mode(match_video_mode(FB_WIDTH, FB_HEIGHT, FB_BPP), 1)) {
110                 return 1;
111         }
112
113 #ifdef __unix__
114         xdpy = glXGetCurrentDisplay();
115         xwin = glXGetCurrentDrawable();
116
117         if(!(glx_swap_interval_ext = glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"))) {
118                 glx_swap_interval_sgi = glXGetProcAddress((unsigned char*)"glXSwapIntervalSGI");
119         }
120 #endif
121 #ifdef _WIN32
122         wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT");
123 #endif
124
125         if(au_init() == -1) {
126                 return 1;
127         }
128         time_msec = 0;
129         if(demo_init1(argc, argv) == -1) {
130                 return 1;
131         }
132
133         if(opt.fullscreen) {
134                 set_fullscreen(opt.fullscreen);
135                 reshape(glutGet(GLUT_SCREEN_WIDTH), glutGet(GLUT_SCREEN_HEIGHT));
136         } else {
137                 reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
138         }
139
140         if(demo_init2() == -1) {
141                 return 1;
142         }
143         atexit(demo_cleanup);
144
145         reset_timer();
146
147         glutMainLoop();
148         return 0;
149 }
150
151 void demo_quit(void)
152 {
153         exit(0);
154 }
155
156 void demo_abort(void)
157 {
158         abort();
159 }
160
161 struct video_mode *video_modes(void)
162 {
163         return vmodes;
164 }
165
166 int num_video_modes(void)
167 {
168         return sizeof vmodes / sizeof *vmodes;
169 }
170
171 struct video_mode *get_video_mode(int idx)
172 {
173         if(idx == VMODE_CURRENT) {
174                 return cur_vmode;
175         }
176         return vmodes + idx;
177 }
178
179 int match_video_mode(int xsz, int ysz, int bpp)
180 {
181         struct video_mode *vm = vmodes;
182         int i, count = num_video_modes();
183
184         for(i=0; i<count; i++) {
185                 if(vm->xsz == xsz && vm->ysz == ysz && vm->bpp == bpp) {
186                         return i;
187                 }
188                 vm++;
189         }
190         return -1;
191 }
192
193 static int tex_xsz, tex_ysz;
194 static uint32_t *convbuf;
195 static int convbuf_size;
196
197 void *set_video_mode(int idx, int nbuf)
198 {
199         struct video_mode *vm = vmodes + idx;
200
201         if(cur_vmode == vm) {
202                 return vmem;
203         }
204
205         glGenTextures(1, &tex);
206         glBindTexture(GL_TEXTURE_2D, tex);
207
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);
215         } else {
216                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
217                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
218         }
219
220         glMatrixMode(GL_TEXTURE);
221         glLoadIdentity();
222         glScalef((float)vm->xsz / tex_xsz, (float)vm->ysz / tex_ysz, 1);
223
224         if(vm->xsz * vm->ysz > convbuf_size) {
225                 convbuf_size = vm->xsz * vm->ysz;
226                 free(convbuf);
227                 convbuf = malloc(convbuf_size * sizeof *convbuf);
228         }
229
230         if(demo_resizefb(vm->xsz, vm->ysz, vm->bpp) == -1) {
231                 fprintf(stderr, "failed to allocate virtual framebuffer\n");
232                 return 0;
233         }
234         vmem = fb_pixels;
235
236         cur_vmode = vm;
237         return vmem;
238 }
239
240 void wait_vsync(void)
241 {
242 }
243
244 void blit_frame(void *pixels, int vsync)
245 {
246         int i;
247         uint32_t *dptr = convbuf;
248         uint16_t *sptr = pixels;
249         static int prev_vsync = -1;
250
251         if(vsync != prev_vsync) {
252                 set_vsync(vsync);
253                 prev_vsync = vsync;
254         }
255
256         demo_post_draw(pixels);
257
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);
263                 sptr++;
264         }
265
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);
269
270         glMatrixMode(GL_MODELVIEW);
271         glLoadIdentity();
272         if(win_aspect >= FB_ASPECT) {
273                 glScalef(FB_ASPECT / win_aspect, 1, 1);
274         } else {
275                 glScalef(1, win_aspect / FB_ASPECT, 1);
276         }
277
278         glClear(GL_COLOR_BUFFER_BIT);
279
280         glBegin(GL_QUADS);
281         glTexCoord2f(0, 1);
282         glVertex2f(-1, -1);
283         glTexCoord2f(1, 1);
284         glVertex2f(1, -1);
285         glTexCoord2f(1, 0);
286         glVertex2f(1, 1);
287         glTexCoord2f(0, 0);
288         glVertex2f(-1, 1);
289         glEnd();
290
291         glutSwapBuffers();
292         assert(glGetError() == GL_NO_ERROR);
293 }
294
295 int kb_isdown(int key)
296 {
297         switch(key) {
298         case KB_ANY:
299                 return num_pressed;
300
301         case KB_ALT:
302                 return keystate[KB_LALT] + keystate[KB_RALT];
303
304         case KB_CTRL:
305                 return keystate[KB_LCTRL] + keystate[KB_RCTRL];
306         }
307
308         if(isalpha(key)) {
309                 key = tolower(key);
310         }
311         return keystate[key];
312 }
313
314 /* timer */
315 void init_timer(int res_hz)
316 {
317 }
318
319 void reset_timer(void)
320 {
321         start_time = glutGet(GLUT_ELAPSED_TIME);
322 }
323
324 unsigned long get_msec(void)
325 {
326         return glutGet(GLUT_ELAPSED_TIME) - start_time;
327 }
328
329 #ifdef _WIN32
330 #include <windows.h>
331
332 void sleep_msec(unsigned long msec)
333 {
334         Sleep(msec);
335 }
336
337 #else
338 #include <unistd.h>
339
340 void sleep_msec(unsigned long msec)
341 {
342         usleep(msec * 1000);
343 }
344 #endif
345
346 static void display(void)
347 {
348         recalc_sball_matrix(sball_matrix);
349
350         time_msec = get_msec();
351         demo_draw();
352 }
353
354 static void idle(void)
355 {
356         glutPostRedisplay();
357 }
358
359 static void reshape(int x, int y)
360 {
361         win_width = x;
362         win_height = y;
363         win_aspect = (float)x / (float)y;
364         glViewport(0, 0, x, y);
365 }
366
367 static void keydown(unsigned char key, int x, int y)
368 {
369         modkeys = glutGetModifiers();
370
371         if((key == '\n' || key == '\r') && (modkeys & GLUT_ACTIVE_ALT)) {
372                 opt.fullscreen ^= 1;
373                 set_fullscreen(opt.fullscreen);
374                 return;
375         }
376         keystate[key] = 1;
377         demo_keyboard(key, 1);
378 }
379
380 static void keyup(unsigned char key, int x, int y)
381 {
382         keystate[key] = 0;
383         demo_keyboard(key, 0);
384 }
385
386 static void skeydown(int key, int x, int y)
387 {
388         if(key == GLUT_KEY_F5) {
389                 opt.scaler = (opt.scaler + 1) % NUM_SCALERS;
390
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);
394                 } else {
395                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
396                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
397                 }
398         }
399         key = translate_special(key);
400         keystate[key] = 1;
401         demo_keyboard(key, 1);
402 }
403
404 static void skeyup(int key, int x, int y)
405 {
406         key = translate_special(key);
407         keystate[key] = 0;
408         demo_keyboard(key, 0);
409 }
410
411 static int translate_special(int skey)
412 {
413         switch(skey) {
414         case 127:
415                 return 127;
416         case GLUT_KEY_LEFT:
417                 return KB_LEFT;
418         case GLUT_KEY_RIGHT:
419                 return KB_RIGHT;
420         case GLUT_KEY_UP:
421                 return KB_UP;
422         case GLUT_KEY_DOWN:
423                 return KB_DOWN;
424         case GLUT_KEY_PAGE_UP:
425                 return KB_PGUP;
426         case GLUT_KEY_PAGE_DOWN:
427                 return KB_PGDN;
428         case GLUT_KEY_HOME:
429                 return KB_HOME;
430         case GLUT_KEY_END:
431                 return KB_END;
432         default:
433                 if(skey >= GLUT_KEY_F1 && skey <= GLUT_KEY_F12) {
434                         return KB_F1 + skey - GLUT_KEY_F1;
435                 }
436         }
437         return 0;
438 }
439
440 static void map_mouse_pos(int *xp, int *yp)
441 {
442         int x = *xp;
443         int y = *yp;
444
445         /* TODO */
446         *xp = x * FB_WIDTH / win_width;
447         *yp = y * FB_HEIGHT / win_height;
448 }
449
450 static void mouse_button(int bn, int st, int x, int y)
451 {
452         int bit;
453
454         map_mouse_pos(&x, &y);
455         mouse_x = x;
456         mouse_y = y;
457
458         switch(bn) {
459         case GLUT_LEFT_BUTTON:
460                 bit = 0;
461                 break;
462         case GLUT_RIGHT_BUTTON:
463                 bit = 1;
464                 break;
465         case GLUT_MIDDLE_BUTTON:
466                 bit = 2;
467                 break;
468         }
469
470         if(st == GLUT_DOWN) {
471                 mouse_bmask |= 1 << bit;
472         } else {
473                 mouse_bmask &= ~(1 << bit);
474         }
475 }
476
477 static void mouse_motion(int x, int y)
478 {
479         map_mouse_pos(&x, &y);
480         mouse_x = x;
481         mouse_y = y;
482 }
483
484 static void sball_motion(int x, int y, int z)
485 {
486         pos.x += x * 0.001f;
487         pos.y += y * 0.001f;
488         pos.z -= z * 0.001f;
489
490 }
491
492 static void sball_rotate(int rx, int ry, int rz)
493 {
494         if(rx | ry | 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);
497         }
498 }
499
500 static void sball_button(int bn, int st)
501 {
502         pos.x = pos.y = pos.z = 0;
503         rot.x = rot.y = rot.z = 0;
504         rot.w = 1;
505 }
506
507 static void recalc_sball_matrix(float *xform)
508 {
509         cgm_mrotation_quat(xform, &rot);
510         xform[12] = pos.x;
511         xform[13] = pos.y;
512         xform[14] = pos.z;
513 }
514
515
516 static unsigned int next_pow2(unsigned int x)
517 {
518         x--;
519         x |= x >> 1;
520         x |= x >> 2;
521         x |= x >> 4;
522         x |= x >> 8;
523         x |= x >> 16;
524         return x + 1;
525 }
526
527 static void set_fullscreen(int fs)
528 {
529         static int win_x, win_y;
530
531         if(fs) {
532                 win_x = glutGet(GLUT_WINDOW_WIDTH);
533                 win_y = glutGet(GLUT_WINDOW_HEIGHT);
534                 glutFullScreen();
535         } else {
536                 glutReshapeWindow(win_x, win_y);
537         }
538 }
539
540 #ifdef __unix__
541 static void set_vsync(int vsync)
542 {
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);
548         }
549 }
550 #endif
551 #ifdef WIN32
552 static void set_vsync(int vsync)
553 {
554         if(wgl_swap_interval_ext) {
555                 wgl_swap_interval_ext(vsync ? 1 : 0);
556         }
557 }
558 #endif