1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 #if defined (__unix__)
21 #include <dlfcn.h> // ELF dl loader
22 #include <sys/stat.h>
23 #endif
24
25 #include "client.h"
26 #include "qmenu.h"
27
28 extern cvar_t *vid_ref;
29 extern cvar_t *vid_fullscreen;
30 #if 1
31 extern cvar_t *vid_gamma;
32 #endif
33 cvar_t *gl_lightmap_saturation;
34 cvar_t *gl_lightmap_texture_saturation;
35
36 #if defined (__unix__)
37 static cvar_t *gl_driver;
38 #else
39 static cvar_t *gl_finish;
40 #endif
41 static cvar_t *gl_mode;
42 static cvar_t *gl_texturemode;
43
44 #if defined (__unix__)
45 /*
46 * ====================================================================
47 * REF stuff ... Used to dynamically load the menu with only
48 * those vid_ref's that are present on this system
49 * ====================================================================
50 */
51 /* this will have to be updated if ref's are added/removed from ref_t */
52 #define NUMBER_OF_REFS 2
53
54 /* all the refs should be initially set to 0 */
55 static char *refs[NUMBER_OF_REFS + 1] = {0};
56
57 /* make all these have illegal values, as they will be redefined */
58 static int REF_GLX = NUMBER_OF_REFS;
59 static int REF_SDLGL = NUMBER_OF_REFS;
60
61 static int GL_REF_START = NUMBER_OF_REFS;
62
63 typedef struct {
64 char menuname[32];
65 char realname[32];
66 int *pointer;
67 } ref_t;
68
69 static const ref_t possible_refs[NUMBER_OF_REFS] =
70 {
71 {"X11 OpenGL", "gl", &REF_GLX},
72 {"SDL OpenGL", "sdl", &REF_SDLGL}
73 };
74
75 /*
76 * ============ VID_CheckRefExists
77 *
78 * Checks to see if the given ref_NAME.so exists. Placed here to avoid
79 * complicating other code if the library .so files ever have their names
80 * changed. ============
81 */
82 qboolean
VID_CheckRefExists(const char * ref)83 VID_CheckRefExists(const char *ref)
84 {
85 char fn[MAX_OSPATH];
86 char *path;
87 struct stat st;
88
89 #if defined(LIBDIR)
90 path = LIBDIR;
91 #elif defined(DATADIR)
92 path = Cvar_Get("basedir", DATADIR, CVAR_NOSET)->string;
93 #else
94 path = Cvar_Get("basedir", ".", CVAR_NOSET)->string;
95 #endif
96 Com_sprintf(fn, sizeof(fn), "%s/vid_%s.so", path, ref);
97
98 if (stat(fn, &st) == 0)
99 return true;
100 else
101 return false;
102 }
103 #endif
104
105 /*
106 ====================================================================
107
108 MENU INTERACTION
109
110 ====================================================================
111 */
112
113 #if defined (__unix__)
114 #define OPENGL_MENU 0
115 #endif
116
117 static menuframework_s s_opengl_menu;
118 static menuframework_s *s_current_menu;
119 static int s_current_menu_index;
120
121 static menulist_s s_mode_list;
122 #if defined (__unix__)
123 static menulist_s s_ref_list[2];
124 #else
125 static menulist_s s_finish_box;
126 #endif
127 static menuslider_s s_brightness_slider;
128 static menulist_s s_fs_box;
129 static menulist_s s_texture_mode;
130 static menuslider_s s_lightmap_saturation;
131 static menuslider_s s_lightmap_texture_saturation;
132 static menuaction_s s_apply_action;
133
134 #if defined (__unix__)
DriverCallback(void * unused)135 static void DriverCallback( void *unused )
136 {
137 s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue;
138 s_current_menu = &s_opengl_menu;
139 s_current_menu_index = 1;
140 }
141 #endif
142
BrightnessCallback(void * s)143 static void BrightnessCallback( void *s )
144 {
145 #if 1
146 float gamma = (0.8 - (s_brightness_slider.curvalue * 0.1 - 0.5)) + 0.5;
147
148 Cvar_SetValue( "vid_gamma", gamma );
149 #else
150 Cvar_SetValue("vid_gamma", s_brightness_slider.curvalue * 0.1);
151 #endif
152 }
153
ApplyChanges(void * unused)154 static void ApplyChanges( void *unused )
155 {
156 #if defined (__unix__)
157 int ref;
158 /*
159 * must use an if here (instead of a switch), since the REF_'s are
160 * now variables * and not #DEFINE's (constants)
161 */
162 ref = s_ref_list[s_current_menu_index].curvalue;
163 if (ref == REF_GLX) {
164 Cvar_Set("vid_ref", "gl");
165 Cvar_Get("gl_driver", GL_DRIVER_LIB, CVAR_ARCHIVE);
166 if (gl_driver->modified)
167 vid_ref->modified = true;
168 }
169 if (ref == REF_SDLGL) {
170 Cvar_Set("vid_ref", "sdl");
171 Cvar_Get("gl_driver", GL_DRIVER_LIB, CVAR_ARCHIVE);
172 if (gl_driver->modified)
173 vid_ref->modified = true;
174 }
175
176 /*
177 ** make values consistent
178 */
179 s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue;
180 #else
181 Cvar_SetValue( "gl_finish", s_finish_box.curvalue );
182 #endif
183 Cvar_SetValue( "vid_fullscreen", s_fs_box.curvalue );
184 Cvar_SetValue( "gl_mode", s_mode_list.curvalue );
185
186 if (s_texture_mode.curvalue == 0)
187 Cvar_Set("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST"); //Bilinear
188 else if (s_texture_mode.curvalue == 1)
189 Cvar_Set("gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR"); //Trilinear
190
191 Cvar_SetValue("gl_lightmap_saturation", s_lightmap_saturation.curvalue * 0.1);
192 Cvar_SetValue("gl_lightmap_texture_saturation", s_lightmap_texture_saturation.curvalue * 0.1);
193
194 M_ForceMenuOff();
195 }
196
197 /* Knightmare */
TextureMode(void)198 int TextureMode(void)
199 {
200 char *texmode = Cvar_VariableString("gl_texturemode");
201
202 if (!Q_strcasecmp(texmode, "GL_LINEAR_MIPMAP_NEAREST"))
203 return 0;
204 else
205 return 1;
206 }
207
LightMapSaturation(void * unused)208 static void LightMapSaturation(void *unused)
209 {
210 Cvar_SetValue("gl_lightmap_saturation",
211 s_lightmap_saturation.curvalue / 10);
212 }
213
LightMapTextureSaturation(void * unused)214 static void LightMapTextureSaturation(void *unused)
215 {
216 Cvar_SetValue("gl_lightmap_texture_saturation",
217 s_lightmap_texture_saturation.curvalue / 10);
218 }
219
220 /*
221 ** VID_MenuInit
222 */
VID_MenuInit(void)223 void VID_MenuInit( void )
224 {
225 int i, y;
226 #if defined (__unix__)
227 int counter;
228 #endif
229
230 static const char *resolutions[] =
231 {
232 "320 x 240 [0]",
233 "400 x 300 [1]",
234 "512 x 384 [2]",
235 "640 x 480 [3]",
236 "800 x 600 [4]",
237 "960 x 720 [5]",
238 "1024 x 768 [6]",
239 "1152 x 864 [7]",
240 "1280 x 1024 [8]",
241 "1600 x 1200 [9]",
242 "2048 x 1536 [10]",
243 "640 x 400 [11]",
244 "800 x 500 [12]",
245 "1024 x 480 [13]",
246 "1024 x 640 [14]",
247 "1152 x 768 [15]",
248 "1152 x 854 [16]",
249 "1280 x 800 [17]",
250 "1280 x 854 [18]",
251 "1280 x 960 [19]",
252 "1680 x 1050 [20]",
253 "1920 x 1200 [21]",
254 NULL
255 };
256 static const char *mip_names[] =
257 {
258 "Bilinear ",
259 "Trilinear",
260 NULL
261 };
262 static const char *yesno_names[] =
263 {
264 "No",
265 "Yes",
266 NULL
267 };
268
269 #if defined (__unix__)
270 /* make sure these are invalided before showing the menu again */
271 REF_GLX = NUMBER_OF_REFS;
272 REF_SDLGL = NUMBER_OF_REFS;
273
274
275 GL_REF_START = NUMBER_OF_REFS;
276
277 /* now test to see which ref's are present */
278 i = counter = 0;
279 while (i < NUMBER_OF_REFS) {
280 if (VID_CheckRefExists(possible_refs[i].realname)) {
281 *(possible_refs[i].pointer) = counter;
282
283 /* free any previous string */
284 if (refs[i])
285 Q_free(refs[i]);
286 refs[counter] = strdup(possible_refs[i].menuname);
287
288 /*
289 * * if we reach the 3rd item in the list, this
290 * indicates that a * GL ref has been found; this
291 * will change if more software * modes are added to
292 * the possible_ref's array
293 */
294 if (i == 3)
295 GL_REF_START = counter;
296
297 counter++;
298 }
299 i++;
300 }
301 refs[counter] = (char *)0;
302
303 if ( !gl_driver )
304 gl_driver = Cvar_Get( "gl_driver", GL_DRIVER_LIB, CVAR_ARCHIVE );
305 #else
306 if ( !gl_finish )
307 gl_finish = Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE );
308 #endif
309 if ( !gl_mode )
310 gl_mode = Cvar_Get( "gl_mode", "4", CVAR_ARCHIVE );
311 if (!gl_texturemode)
312 gl_texturemode = Cvar_Get("gl_texturemode",
313 "GL_LINEAR_MIPMAP_NEAREST",
314 CVAR_ARCHIVE);
315
316 if ( !gl_lightmap_saturation )
317 gl_lightmap_saturation = Cvar_Get( "gl_lightmap_saturation", "1", CVAR_ARCHIVE );
318
319 if ( !gl_lightmap_texture_saturation )
320 gl_lightmap_texture_saturation = Cvar_Get( "gl_lightmap_texture_saturation", "1", CVAR_ARCHIVE );
321
322 s_mode_list.curvalue = gl_mode->value;
323 if (s_mode_list.curvalue < 0)
324 s_mode_list.curvalue = 4;
325
326 #if defined (__unix__)
327 if ( strcmp( vid_ref->string, "sdl" ) == 0 ) {
328 s_current_menu_index = OPENGL_MENU;
329 s_ref_list[s_current_menu_index].curvalue = REF_SDLGL;
330 }
331 else if ( strcmp( vid_ref->string, "gl" ) == 0 ) {
332 s_current_menu_index = OPENGL_MENU;
333 s_ref_list[s_current_menu_index].curvalue = REF_GLX;
334 }
335 #endif
336 s_opengl_menu.x = viddef.width * 0.50;
337 s_opengl_menu.y = 0;
338 s_opengl_menu.nitems = 0;
339
340 for ( i = 0; i < 2; i++ ) {
341 y = 0;
342 #if defined (__unix__)
343 s_ref_list[i].generic.type = MTYPE_SPINCONTROL;
344 s_ref_list[i].generic.name = "VIDEO DRIVER";
345 s_ref_list[i].generic.x = 0;
346 s_ref_list[i].generic.y = y;
347 s_ref_list[i].generic.callback = DriverCallback;
348 s_ref_list[i].itemnames = (const char **)refs;
349 #endif
350 s_mode_list.generic.type = MTYPE_SPINCONTROL;
351 s_mode_list.generic.name = "RESOLUTION";
352 s_mode_list.generic.x = 0;
353 s_mode_list.generic.y = y += (MENU_FONT_SIZE+2);
354 s_mode_list.itemnames = resolutions;
355 s_mode_list.generic.statusbar =
356 " ^1^sSet 'gl_mode' to -1 and use 'vid_width'/'vid_height' for custom resolutions.";
357
358 s_fs_box.generic.type = MTYPE_SPINCONTROL;
359 s_fs_box.generic.x = 0;
360 s_fs_box.generic.y = y += (MENU_FONT_SIZE+2);
361 s_fs_box.generic.name = "FULLSCREEN";
362 s_fs_box.itemnames = yesno_names;
363 s_fs_box.curvalue = vid_fullscreen->value;
364
365 s_brightness_slider.generic.type = MTYPE_SLIDER;
366 s_brightness_slider.generic.x = 0;
367 s_brightness_slider.generic.y = y += 2*(MENU_FONT_SIZE+2);
368 s_brightness_slider.generic.name = "BRIGHTNESS";
369 s_brightness_slider.generic.callback = BrightnessCallback;
370 #if 1
371 s_brightness_slider.minvalue = 5;
372 s_brightness_slider.maxvalue = 13;
373 s_brightness_slider.curvalue = (1.3 - vid_gamma->value + 0.5) * 10;
374 #else
375 s_brightness_slider.minvalue = 1;
376 s_brightness_slider.maxvalue = 8;
377 s_brightness_slider.curvalue = Cvar_VariableValue("vid_gamma") * 10;
378 #endif
379 s_texture_mode.generic.type = MTYPE_SPINCONTROL;
380 s_texture_mode.generic.x = 0;
381 s_texture_mode.generic.y = y += (MENU_FONT_SIZE+2);
382 s_texture_mode.generic.name = "TEXTURE MODE";
383 s_texture_mode.curvalue = TextureMode();
384 s_texture_mode.itemnames = mip_names;
385
386 s_lightmap_saturation.generic.type = MTYPE_SLIDER;
387 s_lightmap_saturation.generic.x = 0;
388 s_lightmap_saturation.generic.y = y+=(MENU_FONT_SIZE+2);
389 s_lightmap_saturation.generic.name = "LIGHT MAP SATURATION";
390 s_lightmap_saturation.generic.callback = LightMapSaturation;
391 s_lightmap_saturation.minvalue = 0;
392 s_lightmap_saturation.maxvalue = 10;
393 s_lightmap_saturation.curvalue = gl_lightmap_saturation->value * 10;
394 s_lightmap_saturation.generic.statusbar = "^3Lightmap saturation";
395
396 s_lightmap_texture_saturation.generic.type = MTYPE_SLIDER;
397 s_lightmap_texture_saturation.generic.x = 0;
398 s_lightmap_texture_saturation.generic.y = y+=(MENU_FONT_SIZE+2);
399 s_lightmap_texture_saturation.generic.name = "LIGHT MAP TEXTURE SATURATION";
400 s_lightmap_texture_saturation.generic.callback = LightMapTextureSaturation;
401 s_lightmap_texture_saturation.minvalue = 0;
402 s_lightmap_texture_saturation.maxvalue = 10;
403 s_lightmap_texture_saturation.curvalue = gl_lightmap_texture_saturation->value * 10;
404 s_lightmap_texture_saturation.generic.statusbar =
405 "^3Lightmap texture saturation, requires vid_restart.";
406
407 #if defined _WIN32
408 s_finish_box.generic.type = MTYPE_SPINCONTROL;
409 s_finish_box.generic.x = 0;
410 s_finish_box.generic.y = y += (MENU_FONT_SIZE+2);
411 s_finish_box.generic.name = "SYNC EVERY FRAME";
412 s_finish_box.curvalue = gl_finish->value;
413 s_finish_box.itemnames = yesno_names;
414 #endif
415
416 s_apply_action.generic.type = MTYPE_ACTION;
417 s_apply_action.generic.name = "APPLY";
418 s_apply_action.generic.x = 0;
419 s_apply_action.generic.y = y += 3*(MENU_FONT_SIZE+2);
420 s_apply_action.generic.callback = ApplyChanges;
421 }
422
423 #if defined (__unix__)
424 Menu_AddItem( &s_opengl_menu, ( void * ) &s_ref_list[OPENGL_MENU]);
425 #endif
426 Menu_AddItem( &s_opengl_menu, ( void * ) &s_mode_list);
427 Menu_AddItem( &s_opengl_menu, ( void * ) &s_fs_box);
428 Menu_AddItem( &s_opengl_menu, ( void * ) &s_brightness_slider);
429 Menu_AddItem( &s_opengl_menu, ( void * ) &s_texture_mode);
430 Menu_AddItem( &s_opengl_menu, ( void * ) &s_lightmap_saturation);
431 Menu_AddItem( &s_opengl_menu, ( void * ) &s_lightmap_texture_saturation);
432 #if defined _WIN32
433 Menu_AddItem( &s_opengl_menu, ( void * ) &s_finish_box );
434 #endif
435 Menu_AddItem( &s_opengl_menu, ( void * ) &s_apply_action);
436
437 Menu_Center( &s_opengl_menu );
438 s_opengl_menu.x -= MENU_FONT_SIZE;
439 }
440
441 #if defined (__unix__)
442 /*
443 * ================ VID_MenuShutdown ================
444 */
VID_MenuShutdown(void)445 void VID_MenuShutdown(void)
446 {
447 int i;
448
449 for (i = 0; i < NUMBER_OF_REFS; i++) {
450 if (refs[i])
451 Q_free(refs[i]);
452 }
453 }
454 #endif
455
456 /*
457 ================
458 VID_MenuDraw
459 ================
460 */
VID_MenuDraw(void)461 void VID_MenuDraw (void)
462 {
463
464 s_current_menu = &s_opengl_menu;
465
466 /*
467 ** draw the banner
468 */
469 M_Banner("m_banner_video");
470
471 /*
472 ** move cursor to a reasonable starting position
473 */
474 Menu_AdjustCursor( s_current_menu, 1 );
475
476 /*
477 ** draw the menu
478 */
479 Menu_Draw( s_current_menu );
480 }
481
482 /*
483 ================
484 VID_MenuKey
485 ================
486 */
VID_MenuKey(int key)487 const char *VID_MenuKey( int key )
488 {
489
490 menuframework_s *m = s_current_menu;
491 static const char *sound = "misc/menu1.wav";
492
493 switch ( key ) {
494 case K_ESCAPE:
495 M_PopMenu();
496 return NULL;
497 case K_UPARROW:
498 m->cursor--;
499 Menu_AdjustCursor( m, -1 );
500 break;
501 case K_DOWNARROW:
502 m->cursor++;
503 Menu_AdjustCursor( m, 1 );
504 break;
505 case K_LEFTARROW:
506 Menu_SlideItem( m, -1 );
507 break;
508 case K_RIGHTARROW:
509 Menu_SlideItem( m, 1 );
510 break;
511 case K_ENTER:
512 if ( !Menu_SelectItem( m ) )
513 ApplyChanges( NULL );
514 break;
515 }
516
517 return sound;
518 }
519
520
521