1 /***************************************************************************
2 screen.cpp -- screen init
3 -------------------
4 created : Fri Aug 13 22:29:56 CEST 1999
5 copyright : (C) 1999, 2014 by Eric Espie, Bernhard Wymann
6 email : torcs@free.fr
7 version : $Id: screen.cpp,v 1.23.2.11 2014/05/23 08:38:32 berniw Exp $
8 ***************************************************************************/
9
10 /***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19 /** @file
20 Screen management.
21 @author bernhard Wymann, Eric Espie
22 @version $Id: screen.cpp,v 1.23.2.11 2014/05/23 08:38:32 berniw Exp $
23 */
24
25 #include <stdio.h>
26 #ifdef WIN32
27 #include <windows.h>
28 #endif
29 #include <GL/glut.h>
30 #include <math.h>
31 #ifndef WIN32
32 #include <unistd.h>
33 #else
34 #include <process.h>
35 #endif /* WIN32 */
36
37 #include <tgfclient.h>
38 #include <portability.h>
39 #include <musicplayer/musicplayer.h>
40 #include <portability.h>
41
42 #include "gui.h"
43 #include "fg_gm.h"
44 #include "glfeatures.h"
45
46 //#ifndef WIN32
47 //#define USE_RANDR_EXT
48 //#endif // WIN32
49
50 #ifdef USE_RANDR_EXT
51 #include <GL/glx.h>
52 #include <X11/Xlib.h>
53 #include <X11/Xatom.h>
54 #include <X11/keysym.h>
55 #include <X11/extensions/Xrandr.h>
56 #endif // USE_RANDR_EXT
57
58 static int GfScrWidth;
59 static int GfScrHeight;
60 static int GfViewWidth;
61 static int GfViewHeight;
62 static int GfScrCenX;
63 static int GfScrCenY;
64
65 static void *scrHandle = NULL;
66
67 static int usedGM = 0;
68 #if !defined(FREEGLUT) && !defined(WIN32)
69 static int usedFG = 0;
70 #endif
71
72 #ifdef USE_RANDR_EXT
73 static char **Res = NULL;
74 static int nbRes = 0;
75 #else // USE_RANDR_EXT
76 static char *Res[] = {"640x480", "800x600", "1024x768", "1152x768", "1152x864", "1200x854", "1200x960", "1280x720", "1280x1024", "1400x900", "1600x900", "1600x1200", "1680x1050", "1920x1200", "320x200"};
77 static const int nbRes = sizeof(Res) / sizeof(Res[0]);
78 #endif // USE_RANDR_EXT
79
80 static const char *Mode[] = {"Full-screen mode", "Window mode"};
81 static const char *VInit[] = {GFSCR_VAL_VINIT_COMPATIBLE, GFSCR_VAL_VINIT_BEST};
82 static const char *Depthlist[] = {"24", "32", "16"};
83
84 //static const int nbRes = sizeof(Res) / sizeof(Res[0]);
85 static const int nbMode = sizeof(Mode) / sizeof(Mode[0]);
86 static const int nbVInit = sizeof(VInit) / sizeof(VInit[0]);
87 static const int nbDepth = sizeof(Depthlist) / sizeof(Depthlist[0]);
88
89 static int curRes = 0;
90 static int curMode = 0;
91 static int curDepth = 0;
92 static int curVInit = 0;
93
94 static int curMaxFreq = 75;
95 #ifdef WIN32
96 static int MaxFreqId;
97 #endif
98
99 static int ResLabelId;
100 static int DepthLabelId;
101 static int ModeLabelId;
102 static int VInitLabelId;
103
104 static float LabelColor[] = {1.0, 0.0, 1.0, 1.0};
105
106
107 void
gfScreenInit(void)108 gfScreenInit(void)
109 {
110 #ifdef USE_RANDR_EXT
111 // Get display, screen and root window handles.
112 const char *displayname = getenv("DISPLAY");
113 if (displayname == NULL) {
114 displayname = strdup(":0.0");
115 }
116
117 Display *display = XOpenDisplay(displayname);
118
119 if( display != NULL) {
120 // If we have a display fill in the resolutions advertised by Xrandr.
121 int screen = DefaultScreen(display);
122 Window root = RootWindow(display, screen);
123
124 XRRScreenConfiguration *screenconfig = XRRGetScreenInfo (display, root);
125 if (screenconfig != NULL) {
126 int i, j, nsize;
127 XRRScreenSize *sizes = XRRConfigSizes(screenconfig, &nsize);
128
129 if (nsize > 0) {
130 // Check if 320x200, 640x480, 800x600 are available, construct a mode wish list.
131 int check_resx[] = {320, 640, 800};
132 int check_resy[] = {240, 480, 600};
133 bool mode_in_list[] = {false, false, false};
134 int add_modes = sizeof(check_resx)/sizeof(check_resx[0]);
135
136 for (i = 0; i < nsize; i++) {
137 for (j = 0; j < 3; j++) {
138 if ((mode_in_list[j] == false) && (sizes[i].width == check_resx[j])) {
139 if (sizes[i].height == check_resy[j]) {
140 // Mode already in list.
141 mode_in_list[j] = true;
142 add_modes--;
143 }
144 }
145 }
146 }
147
148 const int bufsize = 20;
149 char buffer[bufsize];
150 Res = (char**) malloc(sizeof(char *)*(nsize+add_modes));
151 int resx[nsize+add_modes];
152 int resy[nsize+add_modes];
153 for (i = 0; i < nsize+add_modes; i++) {
154 if (i < nsize) {
155 // Add mode from screenconfig (system).
156 snprintf(buffer, bufsize, "%dx%d", sizes[i].width, sizes[i].height);
157 Res[i] = strndup(buffer, bufsize);
158 resx[i] = sizes[i].width;
159 resy[i] = sizes[i].height;
160 } else {
161 // Add mode from wish list.
162 unsigned int j;
163 for (j = 0; j < sizeof(check_resx)/sizeof(check_resx[0]); j++) {
164 if (mode_in_list[j] == false) {
165 mode_in_list[j] = true;
166 snprintf(buffer, bufsize, "%dx%d", check_resx[j], check_resy[j]);
167 Res[i] = strndup(buffer, bufsize);
168 resx[i] = check_resx[j];
169 resy[i] = check_resy[j];
170 break;
171 }
172 }
173 }
174
175 // Stupid sorting (not much elements, don't worry).
176 int j;
177 for (j = i; j > 0; j--) {
178 if ((resx[j] < resx[j-1]) ||
179 (resx[j] == resx[j-1] && resy[j] < resy[j-1]))
180 {
181 int tx, ty;
182 char *tc;
183 tx = resx[j-1];
184 ty = resy[j-1];
185 resx[j-1] = resx[j];
186 resy[j-1] = resy[j];
187 resx[j] = tx;
188 resy[j] = ty;
189 tc = Res[j-1];
190 Res[j-1] = Res[j];
191 Res[j] = tc;
192 } else {
193 break;
194 }
195 }
196 }
197
198 nbRes = nsize + add_modes;
199 }
200
201 XRRFreeScreenConfigInfo(screenconfig);
202 }
203 XCloseDisplay(display);
204 }
205
206 if (Res == NULL || nbRes == 0) {
207 // We failed to get a handle to the display, so fill in some defaults.
208 GfOut("Failed to initialize resolutions for display '%s'", XDisplayName(displayname));
209 nbRes = 8;
210 Res = (char **) malloc(sizeof(char *)*nbRes);
211 Res[0] = strdup("640x480");
212 Res[1] = strdup("800x600");
213 Res[2] = strdup("1024x768");
214 Res[3] = strdup("1152x864");
215 Res[4] = strdup("1200x960");
216 Res[5] = strdup("1280x1024");
217 Res[6] = strdup("1600x1200");
218 Res[7] = strdup("320x200");
219 }
220 #endif // USE_RANDR_EXT
221 }
222
Reshape(int width,int height)223 static void Reshape(int width, int height)
224 {
225 glViewport( (width-GfViewWidth)/2, (height-GfViewHeight)/2, GfViewWidth, GfViewHeight);
226 glMatrixMode( GL_PROJECTION );
227 glLoadIdentity();
228 glOrtho( 0.0, 640.0, 0.0, 480.0, -1.0, 1.0 );
229 glMatrixMode( GL_MODELVIEW );
230 glLoadIdentity();
231
232 GfScrWidth = width;
233 GfScrHeight = height;
234 GfScrCenX = width / 2;
235 GfScrCenY = height / 2;
236 }
237
GfScrInit(int argc,char * argv[])238 void GfScrInit(int argc, char *argv[])
239 {
240 int Window;
241 int xw, yw;
242 int winX, winY;
243 void *handle;
244 int fullscreen;
245 int maxfreq;
246 int i, depth;
247 const int BUFSIZE = 1024;
248 char buf[BUFSIZE];
249
250 snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
251 handle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
252 xw = (int)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_X, (char*)NULL, 640);
253 yw = (int)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_Y, (char*)NULL, 480);
254 winX = (int)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_WIN_X, (char*)NULL, xw);
255 winY = (int)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_WIN_Y, (char*)NULL, yw);
256 depth = (int)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_BPP, (char*)NULL, 32);
257 maxfreq = (int)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_MAXREFRESH, (char*)NULL, 160);
258 GfViewWidth = xw;
259 GfViewHeight = yw;
260 GfScrCenX = xw / 2;
261 GfScrCenY = yw / 2;
262
263 // The fullscreen hack must be run before glutInit, such that glut gets the right screen size, etc.
264 const char* fscr = GfParmGetStr(handle, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, GFSCR_VAL_NO);
265 fullscreen = 0;
266 #if !defined(FREEGLUT) && !defined(WIN32)
267 if (strcmp(fscr, GFSCR_VAL_YES) == 0) { // Resize the screen
268 GfOut ("Freeglut not detected...\n");
269 for (i = maxfreq; i > 59; i--) {
270 snprintf(buf, BUFSIZE, "%dx%d:%d@%d", winX, winY, depth, i);
271 GfOut("Trying %s mode\n", buf);
272 fglutGameModeString(buf);
273 if (fglutEnterGameMode()) {
274 GfOut("OK done for %s\n", buf);
275 usedFG = 1;
276 break;
277 }
278 }
279 }
280 #endif
281
282 const char* vinit = GfParmGetStr(handle, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, GFSCR_VAL_VINIT_COMPATIBLE);
283
284 glutInit(&argc, argv);
285
286 // Depending on "video mode init" setting try to get the best mode or try to get a mode in a safe way...
287 // This is a workaround for driver/glut/glx bug, which lie about the capabilites of the visual.
288
289 if (strcmp(vinit, GFSCR_VAL_VINIT_BEST) == 0) {
290
291 // Try to get "best" videomode, z-buffer >= 24bit, visual with alpha channel,
292 // antialiasing support.
293
294 int visualDepthBits = 24;
295 bool visualSupportsMultisample = true;
296 bool visualSupportsAlpha = true;
297
298 glutInitDisplayString("rgba double depth>=24 samples alpha");
299
300 if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE)) {
301 // Failed, try without antialiasing support.
302 visualDepthBits = 24;
303 visualSupportsMultisample = false;
304 visualSupportsAlpha = true;
305 glutInitDisplayString("rgba double depth>=24 alpha");
306 }
307
308 if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE)) {
309 // Failed, try without alpha channel.
310 visualDepthBits = 24;
311 visualSupportsMultisample = true;
312 visualSupportsAlpha = false;
313 glutInitDisplayString("rgb double depth>=24 samples");
314 }
315
316 if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE)) {
317 // Failed, try without antialiasing and alpha support.
318 visualDepthBits = 24;
319 visualSupportsMultisample = false;
320 visualSupportsAlpha = false;
321 glutInitDisplayString("rgb double depth>=24");
322 }
323
324 if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE)) {
325 // Failed, try without 24 bit z-Buffer and without antialiasing.
326 visualDepthBits = 16;
327 visualSupportsMultisample = false;
328 visualSupportsAlpha = true;
329 glutInitDisplayString("rgba double depth>=16 alpha");
330 }
331
332 if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE)) {
333 // Failed, try without 24 bit z-Buffer, without antialiasing and without alpha.
334 visualDepthBits = 16;
335 visualSupportsMultisample = false;
336 visualSupportsAlpha = false;
337 glutInitDisplayString("rgb double depth>=16");
338 }
339
340 printf("Visual Properties Report\n");
341 printf("------------------------\n");
342
343 if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE)) {
344 // All failed.
345 printf("The minimum display requirements are not fulfilled.\n");
346 printf("We need a double buffered RGB visual with a 16 bit depth buffer at least.\n");
347 // Try fallback as last resort.
348 printf("Trying generic initialization, fallback.\n");
349 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
350 } else {
351 // We have got a mode, report the properties.
352 printf("z-buffer depth: %d (%s)\n", visualDepthBits, visualDepthBits < 24 ? "bad" : "good");
353 printf("multisampling : %s\n", visualSupportsMultisample ? "available" : "no");
354 printf("alpha bits : %s\n", visualSupportsAlpha ? "available" : "no");
355 if (visualDepthBits < 24) {
356 // Show a hint if the z-buffer depth is not optimal.
357 printf("The z-buffer resolution is below 24 bit, you will experience rendering\n");
358 printf("artefacts. Try to improve the setup of your graphics board or look\n");
359 printf("for an alternate driver.\n");
360 }
361 }
362 } else {
363 // Compatibility mode.
364 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
365 printf("Visual Properties Report\n");
366 printf("------------------------\n");
367 printf("Compatibility mode, properties unknown.\n");
368 }
369
370
371 if (strcmp(fscr, GFSCR_VAL_YES) == 0) {
372 for (i = maxfreq; i > 59; i--) {
373 snprintf(buf, BUFSIZE, "%dx%d:%d@%d", winX, winY, depth, i);
374 glutGameModeString(buf);
375 GfOut("2 - Trying %s mode\n", buf);
376 if (glutGameModeGet(GLUT_GAME_MODE_POSSIBLE)) {
377 GfOut("2- %s mode Possible\n", buf);
378 glutEnterGameMode();
379 if (glutGameModeGet(GLUT_GAME_MODE_DISPLAY_CHANGED)) {
380 GfOut("Use GameMode %s\n", buf);
381 usedGM = 1;
382 fullscreen = 1;
383 break;
384 } else {
385 glutLeaveGameMode();
386 }
387 }
388 }
389 }
390
391 if (!fullscreen) {
392 /* Give an initial size and position so user doesn't have to place window */
393 glutInitWindowPosition(0, 0);
394 glutInitWindowSize(winX, winY);
395 Window = glutCreateWindow(argv[0]);
396 if (!Window) {
397 printf("Error, couldn't open window\n");
398 GfScrShutdown();
399 exit(1);
400 }
401 }
402
403 if ((strcmp(fscr, GFSCR_VAL_YES) == 0) && (!fullscreen)) {
404 /* glutVideoResize(0, 0, winX, winY); */
405 glutFullScreen();
406 }
407
408 GfParmReleaseHandle(handle);
409
410 glutReshapeFunc( Reshape );
411
412 checkGLFeatures();
413 }
414
415 /** Shutdown the screen
416 @ingroup screen
417 @return none
418 */
GfScrShutdown(void)419 void GfScrShutdown(void)
420 {
421 if (usedGM) {
422 glutLeaveGameMode();
423 }
424 #if !defined(FREEGLUT) && !defined(WIN32)
425 if (usedFG) {
426 fglutLeaveGameMode();
427 }
428 #endif
429
430 #ifdef USE_RANDR_EXT
431 int i;
432 for (i = 0; i < nbRes; i++) {
433 free(Res[i]);
434 }
435 free(Res);
436 #endif // USE_RANDR_EXT
437 }
438
439
440 /** Get the screen and viewport sizes.
441 @ingroup screen
442 @param scrw address of screen with
443 @param scrh address of screen height
444 @param vieww address of viewport with
445 @param viewh address of viewport height
446 @return none
447 */
GfScrGetSize(int * scrw,int * scrh,int * vieww,int * viewh)448 void GfScrGetSize(int *scrw, int *scrh, int *vieww, int *viewh)
449 {
450 *scrw = GfScrWidth;
451 *scrh = GfScrHeight;
452 *vieww = GfViewWidth;
453 *viewh = GfViewHeight;
454 }
455
456 static void
saveParams(void)457 saveParams(void)
458 {
459 int x, y, bpp;
460
461 sscanf(Res[curRes], "%dx%d", &x, &y);
462 sscanf(Depthlist[curDepth], "%d", &bpp);
463
464 const int BUFSIZE = 1024;
465 char buf[BUFSIZE];
466 snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
467 void *paramHdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
468
469 GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_X, (char*)NULL, x);
470 GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_Y, (char*)NULL, y);
471 GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_WIN_X, (char*)NULL, x);
472 GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_WIN_Y, (char*)NULL, y);
473 GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_BPP, (char*)NULL, bpp);
474 GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_MAXREFRESH, (char*)NULL, curMaxFreq);
475
476 GfParmSetStr(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, VInit[curVInit]);
477
478 if (curMode == 0) {
479 GfParmSetStr(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, "yes");
480 } else {
481 GfParmSetStr(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, "no");
482 }
483 GfParmWriteFile(NULL, paramHdle, "Screen");
484 GfParmReleaseHandle(paramHdle);
485 }
486
487
488 void
GfScrReinit(void *)489 GfScrReinit(void * /* dummy */)
490 {
491 int retcode = 0;
492 static const int CMDSIZE = 1024;
493 char cmd[CMDSIZE];
494
495 stopMenuMusic();
496
497 #ifndef WIN32
498 const char *arg[8];
499 int curArg;
500 #endif
501
502 saveParams();
503
504 #ifdef WIN32
505 snprintf(cmd, CMDSIZE, "%swtorcs.exe", GetLibDir());
506 int i;
507 for (i = 0; i < CMDSIZE && cmd[i] != NULL; i++) {
508 if (cmd[i] == '/') {
509 cmd[i] = '\\';
510 }
511 }
512
513 char cmdarg[CMDSIZE];
514 snprintf(cmdarg, CMDSIZE, "\"%swtorcs.exe\"", GetLibDir());
515 for (i = 0; i < CMDSIZE && cmdarg[i] != NULL; i++) {
516 if (cmdarg[i] == '/') {
517 cmdarg[i] = '\\';
518 }
519 }
520
521 retcode = execlp(cmd, cmdarg, (const char *)NULL);
522 #else
523 GfScrShutdown();
524
525 snprintf (cmd, CMDSIZE, "%storcs-bin", GetLibDir ());
526 memset (arg, 0, sizeof (arg));
527 curArg = 0;
528 if (GfuiMouseHW) {
529 arg[curArg++] = "-m";
530 }
531
532 if (strlen(GetLocalDir ())) {
533 arg[curArg++] = "-l";
534 arg[curArg++] = GetLocalDir();
535 }
536
537 if (strlen(GetLibDir ())) {
538 arg[curArg++] = "-L";
539 arg[curArg++] = GetLibDir ();
540 }
541
542 if (strlen(GetDataDir ())) {
543 arg[curArg++] = "-D";
544 arg[curArg++] = GetDataDir ();
545 }
546
547 switch (curArg) {
548 case 0:
549 retcode = execlp (cmd, cmd, (const char *)NULL);
550 break;
551 case 1:
552 retcode = execlp (cmd, cmd, arg[0], (const char *)NULL);
553 break;
554 case 2:
555 retcode = execlp (cmd, cmd, arg[0], arg[1], (const char *)NULL);
556 break;
557 case 3:
558 retcode = execlp (cmd, cmd, arg[0], arg[1], arg[2], (const char *)NULL);
559 break;
560 case 4:
561 retcode = execlp (cmd, cmd, arg[0], arg[1], arg[2], arg[3], (const char *)NULL);
562 break;
563 case 5:
564 retcode = execlp (cmd, cmd, arg[0], arg[1], arg[2], arg[3], arg[4], (const char *)NULL);
565 break;
566 case 6:
567 retcode = execlp (cmd, cmd, arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], (const char *)NULL);
568 break;
569 case 7:
570 retcode = execlp (cmd, cmd, arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], (const char *)NULL);
571 break;
572 case 8:
573 retcode = execlp (cmd, cmd, arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7], (const char *)NULL);
574 break;
575 }
576
577
578 #endif
579 if (retcode) {
580 perror("torcs");
581 exit(1);
582 }
583 }
584
585 static void
updateLabelText(void)586 updateLabelText(void)
587 {
588 GfuiLabelSetText (scrHandle, ResLabelId, Res[curRes]);
589 GfuiLabelSetText (scrHandle, DepthLabelId, Depthlist[curDepth]);
590 GfuiLabelSetText (scrHandle, ModeLabelId, Mode[curMode]);
591 #ifdef WIN32
592 const int BUFSIZE = 1024;
593 char buf[BUFSIZE];
594
595 snprintf(buf, BUFSIZE, "%d", curMaxFreq);
596 GfuiEditboxSetString(scrHandle, MaxFreqId, buf);
597 #endif
598 GfuiLabelSetText (scrHandle, VInitLabelId, VInit[curVInit]);
599 }
600
601 static void
ResPrevNext(void * vdelta)602 ResPrevNext(void *vdelta)
603 {
604 long delta = (long)vdelta;
605 curRes += (int)delta;
606 if (curRes < 0) {
607 curRes = nbRes - 1;
608 } else {
609 if (curRes >= nbRes) {
610 curRes = 0;
611 }
612 }
613 updateLabelText();
614 }
615
616 static void
DepthPrevNext(void * vdelta)617 DepthPrevNext(void *vdelta)
618 {
619 long delta = (long)vdelta;
620
621 curDepth += (int)delta;
622 if (curDepth < 0) {
623 curDepth = nbDepth - 1;
624 } else {
625 if (curDepth >= nbDepth) {
626 curDepth = 0;
627 }
628 }
629 updateLabelText();
630 }
631
632 static void
ModePrevNext(void * vdelta)633 ModePrevNext(void *vdelta)
634 {
635 long delta = (long)vdelta;
636
637 curMode += (int)delta;
638 if (curMode < 0) {
639 curMode = nbMode - 1;
640 } else {
641 if (curMode >= nbMode) {
642 curMode = 0;
643 }
644 }
645 updateLabelText();
646 }
647
648
649 static void
VInitPrevNext(void * vdelta)650 VInitPrevNext(void *vdelta)
651 {
652 long delta = (long)vdelta;
653
654 curVInit += (int)delta;
655 if (curVInit < 0) {
656 curVInit = nbVInit - 1;
657 } else {
658 if (curVInit >= nbVInit) {
659 curVInit = 0;
660 }
661 }
662 updateLabelText();
663 }
664
665
666 static void
initFromConf(void)667 initFromConf(void)
668 {
669 int x, y, bpp;
670 int i;
671 const int BUFSIZE = 1024;
672 char buf[BUFSIZE];
673
674 snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
675 void *paramHdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
676
677 x = (int)GfParmGetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_X, NULL, 640);
678 y = (int)GfParmGetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_Y, NULL, 480);
679
680 snprintf(buf, BUFSIZE, "%dx%d", x, y);
681 for (i = 0; i < nbRes; i++) {
682 if (!strcmp(buf, Res[i])) {
683 curRes = i;
684 break;
685 }
686 }
687
688 if (!strcmp("yes", GfParmGetStr(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, "yes"))) {
689 curMode = 0;
690 } else {
691 curMode = 1;
692 }
693
694 curVInit = 0;
695 const char *tmp = GfParmGetStr(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, GFSCR_VAL_VINIT_COMPATIBLE);
696 for (i = 0; i < nbVInit; i++) {
697 if (strcmp(VInit[i], tmp) == 0) {
698 curVInit = i;
699 break;
700 }
701 }
702
703 bpp = (int)GfParmGetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_BPP, NULL, 24);
704 snprintf(buf, BUFSIZE, "%d", bpp);
705 for (i = 0; i < nbDepth; i++) {
706 if (!strcmp(buf, Depthlist[i])) {
707 curDepth = i;
708 break;
709 }
710 }
711
712 curMaxFreq = (int)GfParmGetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_MAXREFRESH, NULL, curMaxFreq);
713 GfParmReleaseHandle(paramHdle);
714 }
715
716 #ifdef WIN32
717 static void
ChangeMaxFreq(void *)718 ChangeMaxFreq(void * /* dummy */)
719 {
720 char *val;
721 const int BUFSIZE = 1024;
722 char buf[BUFSIZE];
723
724 val = GfuiEditboxGetString(scrHandle, MaxFreqId);
725 curMaxFreq = (int)strtol(val, (char **)NULL, 0);
726 snprintf(buf, BUFSIZE, "%d", curMaxFreq);
727 GfuiEditboxSetString(scrHandle, MaxFreqId, buf);
728 }
729 #endif
730
731 static void
onActivate(void *)732 onActivate(void * /* dummy */)
733 {
734 initFromConf();
735 updateLabelText();
736 }
737
738
739 /** Create and activate the video options menu screen.
740 @ingroup screen
741 @param precMenu previous menu to return to
742 */
743 void *
GfScrMenuInit(void * precMenu)744 GfScrMenuInit(void *precMenu)
745 {
746 int y, x1, x2;
747
748 #ifndef WIN32
749 const int yoffset1 = 30, yoffset2 = 60;
750 #else // WIN32
751 const int yoffset1 = 30, yoffset2 = 40;
752 #endif // WIN32
753
754 if (scrHandle) return scrHandle;
755
756 scrHandle = GfuiScreenCreateEx((float*)NULL, NULL, onActivate, NULL, (tfuiCallback)NULL, 1);
757 GfuiTitleCreate(scrHandle, "Screen configuration", 0);
758 GfuiScreenAddBgImg(scrHandle, "data/img/splash-graphic.png");
759
760 x1 = 200;
761 x2 = 440;
762 y = 400;
763 GfuiLabelCreate(scrHandle,
764 "Screen Resolution",
765 GFUI_FONT_LARGE,
766 320, y, GFUI_ALIGN_HC_VB,
767 0);
768
769 y -= yoffset1; //30;
770 GfuiGrButtonCreate(scrHandle,
771 "data/img/arrow-left.png",
772 "data/img/arrow-left.png",
773 "data/img/arrow-left.png",
774 "data/img/arrow-left-pushed.png",
775 x1, y, GFUI_ALIGN_HC_VB, 0,
776 (void*)-1, ResPrevNext,
777 NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
778 GfuiAddSKey(scrHandle, GLUT_KEY_LEFT, "Previous Resolution", (void*)-1, ResPrevNext, NULL);
779
780 ResLabelId = GfuiLabelCreate(scrHandle,
781 "",
782 GFUI_FONT_LARGE_C,
783 320, y, GFUI_ALIGN_HC_VB,
784 30);
785 GfuiLabelSetColor(scrHandle, ResLabelId, LabelColor);
786
787 GfuiGrButtonCreate(scrHandle,
788 "data/img/arrow-right.png",
789 "data/img/arrow-right.png",
790 "data/img/arrow-right.png",
791 "data/img/arrow-right-pushed.png",
792 x2, y, GFUI_ALIGN_HC_VB, 0,
793 (void*)1, ResPrevNext,
794 NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
795 GfuiAddSKey(scrHandle, GLUT_KEY_RIGHT, "Next Resolution", (void*)1, ResPrevNext, NULL);
796
797 y -= yoffset2; //60;
798 GfuiLabelCreate(scrHandle,
799 "Color Depth",
800 GFUI_FONT_LARGE,
801 320, y, GFUI_ALIGN_HC_VB,
802 0);
803 y -= yoffset1; //30;
804 GfuiGrButtonCreate(scrHandle,
805 "data/img/arrow-left.png",
806 "data/img/arrow-left.png",
807 "data/img/arrow-left.png",
808 "data/img/arrow-left-pushed.png",
809 x1, y, GFUI_ALIGN_HC_VB, 0,
810 (void*)-1, DepthPrevNext,
811 NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
812
813 DepthLabelId = GfuiLabelCreate(scrHandle,
814 "",
815 GFUI_FONT_LARGE_C,
816 320, y, GFUI_ALIGN_HC_VB,
817 30);
818 GfuiLabelSetColor(scrHandle, DepthLabelId, LabelColor);
819
820 GfuiGrButtonCreate(scrHandle,
821 "data/img/arrow-right.png",
822 "data/img/arrow-right.png",
823 "data/img/arrow-right.png",
824 "data/img/arrow-right-pushed.png",
825 x2, y, GFUI_ALIGN_HC_VB, 0,
826 (void*)1, DepthPrevNext,
827 NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
828
829 y -= yoffset2; //60;
830 GfuiLabelCreate(scrHandle,
831 "Display Mode",
832 GFUI_FONT_LARGE,
833 320, y, GFUI_ALIGN_HC_VB,
834 0);
835
836 y -= yoffset1; //30;
837 GfuiGrButtonCreate(scrHandle,
838 "data/img/arrow-left.png",
839 "data/img/arrow-left.png",
840 "data/img/arrow-left.png",
841 "data/img/arrow-left-pushed.png",
842 x1, y, GFUI_ALIGN_HC_VB, 0,
843 (void*)-1, ModePrevNext,
844 NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
845
846 ModeLabelId = GfuiLabelCreate(scrHandle,
847 "",
848 GFUI_FONT_LARGE_C,
849 320, y, GFUI_ALIGN_HC_VB,
850 30);
851 GfuiLabelSetColor(scrHandle, ModeLabelId, LabelColor);
852
853 GfuiGrButtonCreate(scrHandle,
854 "data/img/arrow-right.png",
855 "data/img/arrow-right.png",
856 "data/img/arrow-right.png",
857 "data/img/arrow-right-pushed.png",
858 x2, y, GFUI_ALIGN_HC_VB, 0,
859 (void*)1, ModePrevNext,
860 NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
861 GfuiAddKey(scrHandle, 'f', "Display Mode", (void*)1, ModePrevNext, NULL);
862
863 #ifdef WIN32
864 y -= yoffset2; //60;
865 GfuiLabelCreate(scrHandle,
866 "Max Frequency",
867 GFUI_FONT_LARGE,
868 320, y, GFUI_ALIGN_HC_VB,
869 0);
870 y -= yoffset1; //30;
871 MaxFreqId = GfuiEditboxCreate(scrHandle, "", GFUI_FONT_MEDIUM_C,
872 275, y, 0, 8, NULL, (tfuiCallback)NULL, ChangeMaxFreq);
873 #endif
874
875 y -= yoffset2; //60;
876 GfuiLabelCreate(scrHandle,
877 "Video Mode Initialization",
878 GFUI_FONT_LARGE,
879 320, y, GFUI_ALIGN_HC_VB,
880 0);
881 y -= yoffset1; //30;
882 GfuiGrButtonCreate(scrHandle,
883 "data/img/arrow-left.png",
884 "data/img/arrow-left.png",
885 "data/img/arrow-left.png",
886 "data/img/arrow-left-pushed.png",
887 x1, y, GFUI_ALIGN_HC_VB, 0,
888 (void*)-1, VInitPrevNext,
889 NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
890
891 VInitLabelId = GfuiLabelCreate(scrHandle,
892 "",
893 GFUI_FONT_LARGE_C,
894 320, y, GFUI_ALIGN_HC_VB,
895 30);
896 GfuiLabelSetColor(scrHandle, VInitLabelId, LabelColor);
897
898 GfuiGrButtonCreate(scrHandle,
899 "data/img/arrow-right.png",
900 "data/img/arrow-right.png",
901 "data/img/arrow-right.png",
902 "data/img/arrow-right-pushed.png",
903 x2, y, GFUI_ALIGN_HC_VB, 0,
904 (void*)1, VInitPrevNext,
905 NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
906
907
908 GfuiAddKey(scrHandle, 13, "Apply Mode", NULL, GfScrReinit, NULL);
909 GfuiButtonCreate(scrHandle, "Apply", GFUI_FONT_LARGE, 210, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
910 NULL, GfScrReinit, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
911
912 GfuiAddKey(scrHandle, 27, "Cancel", precMenu, GfuiScreenActivate, NULL);
913 GfuiButtonCreate(scrHandle, "Back", GFUI_FONT_LARGE, 430, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
914 precMenu, GfuiScreenActivate, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
915
916 return scrHandle;
917 }
918
919
920
GfuiGlutExtensionSupported(const char * str)921 int GfuiGlutExtensionSupported(const char *str)
922 {
923 return glutExtensionSupported(str);
924 }
925