1 /*
2 * gl_vidsdl.c -- SDL GL vid component
3 * Select window size and mode and init SDL in GL mode.
4 * $Id: gl_vidsdl.c 5776 2016-12-27 14:37:48Z sezero $
5 *
6 * Changed 7/11/04 by S.A.
7 * - Fixed fullscreen opengl mode, window sizes
8 * - Options are now: -fullscreen, -height, -width, -bpp
9 * - The "-mode" option has been removed
10 *
11 * Changed 7/01/06 by O.S
12 * - Added video modes enumeration via SDL
13 * - Added video mode changing on the fly.
14 *
15 * Copyright (C) 1996-1997 Id Software, Inc.
16 * Copyright (C) 1997-1998 Raven Software Corp.
17 * Copyright (C) 2004-2005 Steven Atkinson <stevenaaus@yahoo.com>
18 * Copyright (C) 2005-2016 O.Sezer <sezero@users.sourceforge.net>
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or (at
23 * your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful, but
26 * WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
28 *
29 * See the GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License along
32 * with this program; if not, write to the Free Software Foundation, Inc.,
33 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
34 */
35
36 #define __GL_FUNC_EXTERN
37
38 #include "quakedef.h"
39 #include "cfgfile.h"
40 #include "bgmusic.h"
41 #include "cdaudio.h"
42 #include "sdl_inc.h"
43 #include "filenames.h"
44
45 #define WARP_WIDTH 320
46 #define WARP_HEIGHT 200
47 #define MAXWIDTH 10000
48 #define MAXHEIGHT 10000
49 #define MIN_WIDTH 320
50 //#define MIN_HEIGHT 200
51 #define MIN_HEIGHT 240
52 #define MAX_DESC 33
53
54 typedef struct {
55 modestate_t type;
56 int width;
57 int height;
58 int modenum;
59 int fullscreen;
60 int bpp;
61 int halfscreen;
62 char modedesc[MAX_DESC];
63 } vmode_t;
64
65 typedef struct {
66 int width;
67 int height;
68 } stdmode_t;
69
70 #define RES_640X480 3
71 static const stdmode_t std_modes[] = {
72 // NOTE: keep this list in order
73 {320, 240}, // 0
74 {400, 300}, // 1
75 {512, 384}, // 2
76 {640, 480}, // 3 == RES_640X480, this is our default, below
77 // this is the lowresmodes region.
78 // either do not change its order,
79 // or change the above define, too
80 {800, 600}, // 4, RES_640X480 + 1
81 {1024, 768}, // 5, RES_640X480 + 2
82 {1280, 1024}, // 6
83 {1600, 1200} // 7
84 };
85
86 #define MAX_MODE_LIST 128
87 #define MAX_STDMODES (sizeof(std_modes) / sizeof(std_modes[0]))
88 #define NUM_LOWRESMODES (RES_640X480)
89 static vmode_t fmodelist[MAX_MODE_LIST+1]; // list of enumerated fullscreen modes
90 static vmode_t wmodelist[MAX_STDMODES +1]; // list of standart 4:3 windowed modes
91 static vmode_t *modelist; // modelist in use, points to one of the above lists
92
93 static int num_fmodes;
94 static int num_wmodes;
95 static int *nummodes;
96 static int bpp = 16;
97
98 #if defined(H2W)
99 # define WM_TITLEBAR_TEXT "HexenWorld"
100 # define WM_ICON_TEXT "HexenWorld"
101 //#elif defined(H2MP)
102 //# define WM_TITLEBAR_TEXT "Hexen II+"
103 //# define WM_ICON_TEXT "HEXEN2MP"
104 #else
105 # define WM_TITLEBAR_TEXT "Hexen II"
106 # define WM_ICON_TEXT "HEXEN2"
107 #endif
108
109 typedef struct {
110 int red,
111 green,
112 blue,
113 alpha,
114 depth,
115 stencil;
116 } attributes_t;
117 static attributes_t vid_attribs;
118
119 static const SDL_VideoInfo *vid_info;
120 static SDL_Surface *screen;
121 static qboolean vid_menu_fs;
122 static qboolean fs_toggle_works = true;
123
124 // vars for vid state
125 viddef_t vid; // global video state
126 modestate_t modestate = MS_UNINIT;
127 static int vid_default = -1; // modenum of 640x480 as a safe default
128 static int vid_modenum = -1; // current video mode, set after mode setting succeeds
129 static int vid_maxwidth = 640, vid_maxheight = 480;
130 static qboolean vid_conscale = false;
131 static int WRHeight, WRWidth;
132
133 static qboolean vid_initialized = false;
134 qboolean in_mode_set = false;
135
136 // cvar vid_mode must be set before calling
137 // VID_SetMode, VID_ChangeVideoMode or VID_Restart_f
138 static cvar_t vid_mode = {"vid_mode", "0", CVAR_NONE};
139 static cvar_t vid_config_consize = {"vid_config_consize", "640", CVAR_ARCHIVE};
140 static cvar_t vid_config_glx = {"vid_config_glx", "640", CVAR_ARCHIVE};
141 static cvar_t vid_config_gly = {"vid_config_gly", "480", CVAR_ARCHIVE};
142 static cvar_t vid_config_fscr= {"vid_config_fscr", "0", CVAR_ARCHIVE};
143 // cvars for compatibility with the software version
144 static cvar_t vid_config_swx = {"vid_config_swx", "320", CVAR_ARCHIVE};
145 static cvar_t vid_config_swy = {"vid_config_swy", "240", CVAR_ARCHIVE};
146
147 byte globalcolormap[VID_GRADES*256];
148 float RTint[256], GTint[256], BTint[256];
149 unsigned short d_8to16table[256];
150 unsigned int d_8to24table[256];
151 unsigned int d_8to24TranslucentTable[256];
152 unsigned char *inverse_pal;
153
154 // gl stuff
155 static void GL_Init (void);
156
157 #ifdef GL_DLSYM
158 static const char *gl_library;
159 #endif
160
161 static const char *gl_vendor;
162 static const char *gl_renderer;
163 static const char *gl_version;
164 static const char *gl_extensions;
165 qboolean is_3dfx = false;
166
167 GLint gl_max_size = 256;
168 static qboolean have_NPOT = false;
169 qboolean gl_tex_NPOT = false;
170 static cvar_t gl_texture_NPOT = {"gl_texture_NPOT", "0", CVAR_ARCHIVE};
171 GLfloat gl_max_anisotropy;
172 float gldepthmin, gldepthmax;
173
174 /* palettized textures */
175 static qboolean have8bit = false;
176 qboolean is8bit = false;
177 static cvar_t vid_config_gl8bit = {"vid_config_gl8bit", "0", CVAR_ARCHIVE};
178
179 /* Gamma stuff */
180 #define USE_GAMMA_RAMPS 0
181
182 /* 3dfx gamma hacks: see fx_gamma.c */
183 #define USE_3DFX_RAMPS 0
184 #if defined(USE_3DFXGAMMA)
185 #include "fx_gamma.h"
186 #endif
187
188 #if (USE_GAMMA_RAMPS) || (defined(USE_3DFXGAMMA) && (USE_3DFX_RAMPS))
189 static unsigned short orig_ramps[3][256];
190 #endif
191
192 static qboolean fx_gamma = false; // 3dfx-specific gamma control
193 static qboolean gammaworks = false; // whether hw-gamma works
194
195 // multitexturing
196 qboolean gl_mtexable = false;
197 static GLint num_tmus = 1;
198 static qboolean have_mtex = false;
199 static cvar_t gl_multitexture = {"gl_multitexture", "0", CVAR_ARCHIVE};
200
201 // multisampling
202 static int multisample = 0; // do not set this if SDL cannot multisample
203 static qboolean sdl_has_multisample = false;
204 static cvar_t vid_config_fsaa = {"vid_config_fsaa", "0", CVAR_ARCHIVE};
205
206 // stencil buffer
207 qboolean have_stencil = false;
208
209 // this is useless: things aren't like those in quake
210 //static qboolean fullsbardraw = false;
211
212 // menu drawing
213 static void VID_MenuDraw (void);
214 static void VID_MenuKey (int key);
215
216 // input stuff
217 static void ClearAllStates (void);
218 static int enable_mouse;
219 cvar_t _enable_mouse = {"_enable_mouse", "1", CVAR_ARCHIVE};
220
221
222 //====================================
223
GL_ParseExtensionList(const char * list,const char * name)224 static qboolean GL_ParseExtensionList (const char *list, const char *name)
225 {
226 const char *start;
227 const char *where, *terminator;
228
229 if (!list || !name || !*name)
230 return false;
231 if (strchr(name, ' ') != NULL)
232 return false; // extension names must not have spaces
233
234 start = list;
235 while (1) {
236 where = strstr (start, name);
237 if (!where)
238 break;
239 terminator = where + strlen (name);
240 if (where == start || where[-1] == ' ')
241 if (*terminator == ' ' || *terminator == '\0')
242 return true;
243 start = terminator;
244 }
245 return false;
246 }
247
248 //====================================
249
VID_LockBuffer(void)250 void VID_LockBuffer (void)
251 {
252 // nothing to do
253 }
254
VID_UnlockBuffer(void)255 void VID_UnlockBuffer (void)
256 {
257 // nothing to do
258 }
259
VID_HandlePause(qboolean paused)260 void VID_HandlePause (qboolean paused)
261 {
262 if (_enable_mouse.integer/* && (modestate == MS_WINDOWED)*/)
263 {
264 // for consistency, don't show pointer - S.A
265 if (paused)
266 {
267 IN_DeactivateMouse ();
268 // IN_ShowMouse ();
269 }
270 else
271 {
272 IN_ActivateMouse ();
273 // IN_HideMouse ();
274 }
275 }
276 }
277
278
279 //====================================
280
VID_SetIcon(void)281 static void VID_SetIcon (void)
282 {
283 /* from Kristian Duske: "AFAIK, the application icon must be present in
284 * Contents/Resources and it must be set in the Info.plist file. It will
285 * then be used by Finder and Dock as well as for individual windows
286 * unless overridden by a document icon. So SDL_WM_SetIcon() is probably
287 * not necessary, and will likely use a low-res image anyway." */
288 #if !defined(PLATFORM_OSX)
289
290 # include "xbm_icon.h" /* the xbm data */
291 SDL_Surface *icon;
292 SDL_Color color;
293 Uint8 *ptr;
294 int i, mask;
295
296 icon = SDL_CreateRGBSurface(SDL_SWSURFACE, hx2icon_width, hx2icon_height, 8, 0, 0, 0, 0);
297 if (icon == NULL)
298 return;
299
300 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, 0);
301
302 color.r = 255;
303 color.g = 255;
304 color.b = 255;
305 SDL_SetColors(icon, &color, 0, 1); /* just in case */
306 color.r = 192;
307 color.g = 0;
308 color.b = 0;
309 SDL_SetColors(icon, &color, 1, 1);
310
311 ptr = (Uint8 *)icon->pixels;
312 /* one bit represents a pixel, black or white: each
313 * byte in the xbm array contains data for 8 pixels. */
314 for (i = 0; i < (int) sizeof(hx2icon_bits); i++)
315 {
316 for (mask = 1; mask != 0x100; mask <<= 1)
317 {
318 *ptr = (hx2icon_bits[i] & mask) ? 1 : 0;
319 ptr++;
320 }
321 }
322
323 SDL_WM_SetIcon(icon, NULL);
324 SDL_FreeSurface(icon);
325 #endif /* !OSX */
326 }
327
VID_ConWidth(int modenum)328 static void VID_ConWidth (int modenum)
329 {
330 int w, h;
331
332 if (!vid_conscale)
333 {
334 Cvar_SetValueQuick (&vid_config_consize, modelist[modenum].width);
335 return;
336 }
337
338 w = vid_config_consize.integer;
339 w &= ~7; /* make it a multiple of eight */
340 if (w < MIN_WIDTH)
341 w = MIN_WIDTH;
342 else if (w > modelist[modenum].width)
343 w = modelist[modenum].width;
344
345 h = w * modelist[modenum].height / modelist[modenum].width;
346 if (h < 200 /* MIN_HEIGHT */ ||
347 h > modelist[modenum].height || w > modelist[modenum].width)
348 {
349 vid_conscale = false;
350 Cvar_SetValueQuick (&vid_config_consize, modelist[modenum].width);
351 return;
352 }
353 vid.width = vid.conwidth = w;
354 vid.height = vid.conheight = h;
355 if (w != modelist[modenum].width)
356 vid_conscale = true;
357 else vid_conscale = false;
358 }
359
VID_ChangeConsize(int dir)360 void VID_ChangeConsize (int dir)
361 {
362 int w, h;
363
364 switch (dir)
365 {
366 case -1: /* smaller text */
367 w = ((float)vid.conwidth/(float)vid.width + 0.05f) * vid.width; /* use 0.10f increment ?? */
368 w &= ~7; /* make it a multiple of eight */
369 if (w > modelist[vid_modenum].width)
370 w = modelist[vid_modenum].width;
371 break;
372
373 case 1: /* bigger text */
374 w = ((float)vid.conwidth/(float)vid.width - 0.05f) * vid.width;
375 w &= ~7; /* make it a multiple of eight */
376 if (w < MIN_WIDTH)
377 w = MIN_WIDTH;
378 break;
379
380 default: /* bad key */
381 return;
382 }
383
384 h = w * modelist[vid_modenum].height / modelist[vid_modenum].width;
385 if (h < 200)
386 return;
387 vid.width = vid.conwidth = w;
388 vid.height = vid.conheight = h;
389 Cvar_SetValueQuick (&vid_config_consize, vid.conwidth);
390 vid.recalc_refdef = 1;
391 if (vid.conwidth != modelist[vid_modenum].width)
392 vid_conscale = true;
393 else vid_conscale = false;
394 }
395
VID_ReportConsize(void)396 float VID_ReportConsize(void)
397 {
398 return (float)modelist[vid_modenum].width/vid.conwidth;
399 }
400
401
VID_SetMode(int modenum)402 static qboolean VID_SetMode (int modenum)
403 {
404 Uint32 flags;
405 int i, is_fullscreen;
406
407 in_mode_set = true;
408
409 //flags = (SDL_OPENGL|SDL_NOFRAME);
410 flags = (SDL_OPENGL);
411 if (vid_config_fscr.integer)
412 flags |= SDL_FULLSCREEN;
413
414 // setup the attributes
415 if (bpp >= 32)
416 {
417 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
418 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
419 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
420 SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
421 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );
422 SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );
423 }
424 else
425 {
426 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
427 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
428 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
429 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
430 }
431 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
432
433 if (multisample && !sdl_has_multisample)
434 {
435 multisample = 0;
436 Con_SafePrintf ("SDL ver < %d, multisampling disabled\n", SDL_VER_WITH_MULTISAMPLING);
437 }
438 if (multisample)
439 {
440 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
441 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multisample);
442 }
443
444 Con_SafePrintf ("Requested mode %d: %dx%dx%d\n", modenum, modelist[modenum].width, modelist[modenum].height, bpp);
445
446 VID_SetIcon();
447
448 screen = SDL_SetVideoMode (modelist[modenum].width, modelist[modenum].height, bpp, flags);
449 if (!screen)
450 {
451 if (!multisample)
452 {
453 Sys_Error ("Couldn't set video mode: %s", SDL_GetError());
454 }
455 else
456 {
457 Con_SafePrintf ("multisample window failed\n");
458 multisample = 0;
459 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
460 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multisample);
461 screen = SDL_SetVideoMode (modelist[modenum].width, modelist[modenum].height, bpp, flags);
462 if (!screen)
463 Sys_Error ("Couldn't set video mode: %s", SDL_GetError());
464 }
465 }
466
467 // set vid_modenum properly and adjust other vars
468 vid_modenum = modenum;
469 is_fullscreen = (screen->flags & SDL_FULLSCREEN) ? 1 : 0;
470 modestate = (is_fullscreen) ? MS_FULLDIB : MS_WINDOWED;
471 Cvar_SetValueQuick (&vid_config_glx, modelist[vid_modenum].width);
472 Cvar_SetValueQuick (&vid_config_gly, modelist[vid_modenum].height);
473 Cvar_SetValueQuick (&vid_config_fscr, is_fullscreen);
474 WRWidth = vid.width = vid.conwidth = modelist[modenum].width;
475 WRHeight = vid.height = vid.conheight = modelist[modenum].height;
476
477 // setup the effective console width
478 VID_ConWidth(modenum);
479
480 SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &i);
481 Con_SafePrintf ("Video Mode Set : %dx%dx%d\n", modelist[modenum].width, modelist[modenum].height, i);
482 if (multisample)
483 {
484 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &multisample);
485 Con_SafePrintf ("multisample buffer with %i samples\n", multisample);
486 }
487 Cvar_SetValueQuick (&vid_config_fsaa, multisample);
488
489 SDL_WM_SetCaption(WM_TITLEBAR_TEXT, WM_ICON_TEXT);
490
491 IN_HideMouse ();
492
493 in_mode_set = false;
494
495 return true;
496 }
497
498
499 //====================================
500
501 #if 0 /* No.. */
502 static void CheckSetGlobalPalette (void)
503 {
504 gl3DfxSetPaletteEXT_f gl3DfxSetPaletteEXT_fp;
505
506 if (GL_ParseExtensionList(gl_extensions, "3DFX_set_global_palette"))
507 {
508 gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) SDL_GL_GetProcAddress("gl3DfxSetPaletteEXT");
509 if (!gl3DfxSetPaletteEXT_fp)
510 gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) SDL_GL_GetProcAddress("3DFX_set_global_palette");
511 if (!gl3DfxSetPaletteEXT_fp)
512 return;
513 Con_SafePrintf("Found 3DFX_set_global_palette\n");
514 }
515 else if (GL_ParseExtensionList(gl_extensions, "POWERVR_set_global_palette"))
516 {
517 gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) SDL_GL_GetProcAddress("glSetGlobalPalettePOWERVR");
518 if (!gl3DfxSetPaletteEXT_fp)
519 gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) SDL_GL_GetProcAddress("POWERVR_set_global_palette");
520 if (!gl3DfxSetPaletteEXT_fp)
521 return;
522 Con_SafePrintf("Found POWERVR_set_global_palette\n");
523 }
524 else {
525 return;
526 }
527
528 have8bit = true;
529 if (!vid_config_gl8bit.integer)
530 return;
531 else
532 {
533 int i;
534 GLubyte table[256][4];
535 char *oldpal;
536
537 is8bit = true;
538 oldpal = (char *) d_8to24table;
539 for (i = 0; i < 256; i++) {
540 table[i][2] = *oldpal++;
541 table[i][1] = *oldpal++;
542 table[i][0] = *oldpal++;
543 table[i][3] = 255;
544 oldpal++;
545 }
546 glEnable_fp (GL_SHARED_TEXTURE_PALETTE_EXT);
547 gl3DfxSetPaletteEXT_fp ((GLuint *)table);
548 }
549 }
550 #endif /* #if 0 */
551
CheckSharedTexturePalette(void)552 static void CheckSharedTexturePalette (void)
553 {
554 glColorTableEXT_f glColorTableEXT_fp;
555
556 if (!GL_ParseExtensionList(gl_extensions, "GL_EXT_shared_texture_palette"))
557 return;
558
559 glColorTableEXT_fp = (glColorTableEXT_f) SDL_GL_GetProcAddress("glColorTableEXT");
560 if (glColorTableEXT_fp == NULL)
561 return;
562
563 have8bit = true;
564 Con_SafePrintf("Found GL_EXT_shared_texture_palette\n");
565 if (!vid_config_gl8bit.integer)
566 return;
567 else
568 {
569 int i;
570 char thePalette[256*3];
571 char *oldPalette, *newPalette;
572
573 is8bit = true;
574 oldPalette = (char *) d_8to24table;
575 newPalette = thePalette;
576 for (i = 0; i < 256; i++) {
577 *newPalette++ = *oldPalette++;
578 *newPalette++ = *oldPalette++;
579 *newPalette++ = *oldPalette++;
580 oldPalette++;
581 }
582
583 glEnable_fp (GL_SHARED_TEXTURE_PALETTE_EXT);
584 glColorTableEXT_fp (GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256,
585 GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
586 }
587 }
588
VID_Init8bitPalette(void)589 static void VID_Init8bitPalette (void)
590 {
591 have8bit = false;
592 is8bit = false;
593
594 /* Check for 8bit Extensions and initialize them */
595 CheckSharedTexturePalette();
596 #if 0 /* No.. */
597 if (!have8bit)
598 CheckSetGlobalPalette();
599 #endif
600
601 if (is8bit)
602 Con_SafePrintf("8-bit palettized textures enabled\n");
603 }
604
605
606 #if !defined(USE_3DFXGAMMA)
Init_3dfxGammaCtrl(void)607 static inline int Init_3dfxGammaCtrl (void) { return 0; }
Shutdown_3dfxGamma(void)608 static inline void Shutdown_3dfxGamma (void) { }
do3dfxGammaCtrl(float value)609 static inline int do3dfxGammaCtrl (float value) { return 0; }
glGetDeviceGammaRamp3DFX(void * arrays)610 static inline int glGetDeviceGammaRamp3DFX (void *arrays) { return 0; }
glSetDeviceGammaRamp3DFX(void * arrays)611 static inline int glSetDeviceGammaRamp3DFX (void *arrays) { return 0; }
VID_Check3dfxGamma(void)612 static inline qboolean VID_Check3dfxGamma (void) { return false; }
613 #else
VID_Check3dfxGamma(void)614 static qboolean VID_Check3dfxGamma (void)
615 {
616 int ret;
617
618 if (COM_CheckParm("-no3dfxgamma"))
619 return false;
620
621 /* refuse 3dfxgamma with DRI drivers */
622 if (!q_strncasecmp(gl_renderer, "Mesa DRI", 8) ||
623 !q_strncasecmp(gl_renderer, "Mesa Glide - DRI", 16))
624 return false;
625 #if 0
626 /* Daniel Borca's SAGE is not necessarily V1/2-only
627 * on Windows. it is V1/2-only on Linux, because it
628 * is not a DRI driver. */
629 if (!q_strncasecmp(gl_renderer, "SAGE Glide", 10))
630 return false;
631 #endif
632
633 #if USE_3DFX_RAMPS /* not recommended for Voodoo1, currently crashes */
634 ret = glGetDeviceGammaRamp3DFX(orig_ramps);
635 if (ret != 0)
636 {
637 Con_SafePrintf ("Using 3dfx glide3 specific gamma ramps\n");
638 return true;
639 }
640 #else
641 ret = Init_3dfxGammaCtrl();
642 if (ret > 0)
643 {
644 Con_SafePrintf ("Using 3dfx glide%d gamma controls\n", ret);
645 return true;
646 }
647 #endif
648 return false;
649 }
650 #endif /* USE_3DFXGAMMA */
651
VID_InitGamma(void)652 static void VID_InitGamma (void)
653 {
654 gammaworks = fx_gamma = false;
655 /* we don't have WGL_3DFX_gamma_control or an equivalent in unix.
656 * assuming is_3dfx means Voodoo1 or Voodoo2, this means we dont
657 * have hw-gamma. */
658 /* Here is an evil hack abusing the exposed Glide symbols: */
659 if (is_3dfx)
660 fx_gamma = VID_Check3dfxGamma();
661 if (!fx_gamma)
662 {
663 #if USE_GAMMA_RAMPS
664 gammaworks = (SDL_GetGammaRamp(orig_ramps[0], orig_ramps[1], orig_ramps[2]) == 0);
665 if (gammaworks)
666 gammaworks = (SDL_SetGammaRamp(orig_ramps[0], orig_ramps[1], orig_ramps[2]) == 0);
667 #else
668 gammaworks = (SDL_SetGamma(1, 1, 1) == 0);
669 #endif
670 }
671
672 if (!gammaworks && !fx_gamma)
673 Con_SafePrintf("gamma adjustment not available\n");
674 }
675
VID_ShutdownGamma(void)676 static void VID_ShutdownGamma (void)
677 {
678 #if USE_3DFX_RAMPS
679 if (fx_gamma) glSetDeviceGammaRamp3DFX(orig_ramps);
680 #else
681 /* if (fx_gamma) do3dfxGammaCtrl(1);*/
682 #endif
683 Shutdown_3dfxGamma();
684 #if USE_GAMMA_RAMPS /* restore hw-gamma */
685 if (gammaworks) SDL_SetGammaRamp(orig_ramps[0], orig_ramps[1], orig_ramps[2]);
686 #else
687 if (gammaworks) SDL_SetGamma (1,1,1);
688 #endif
689 }
690
VID_SetGamma(void)691 static void VID_SetGamma (void)
692 {
693 #if (!USE_GAMMA_RAMPS) || (!USE_3DFX_RAMPS)
694 float value = (v_gamma.value > (1.0 / GAMMA_MAX))?
695 (1.0 / v_gamma.value) : GAMMA_MAX;
696 #endif
697 #if USE_3DFX_RAMPS
698 if (fx_gamma) glSetDeviceGammaRamp3DFX(ramps);
699 #else
700 if (fx_gamma) do3dfxGammaCtrl(value);
701 #endif
702 #if USE_GAMMA_RAMPS
703 if (gammaworks) SDL_SetGammaRamp(ramps[0], ramps[1], ramps[2]);
704 #else
705 if (gammaworks) SDL_SetGamma(value,value,value);
706 #endif
707 }
708
VID_ShiftPalette(const unsigned char * palette)709 void VID_ShiftPalette (const unsigned char *palette)
710 {
711 VID_SetGamma();
712 }
713
714
CheckMultiTextureExtensions(void)715 static void CheckMultiTextureExtensions (void)
716 {
717 gl_mtexable = have_mtex = false;
718
719 if (COM_CheckParm("-nomtex"))
720 {
721 Con_SafePrintf("Multitexture extensions disabled\n");
722 }
723 else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_multitexture"))
724 {
725 Con_SafePrintf("ARB Multitexture extensions found\n");
726
727 glGetIntegerv_fp(GL_MAX_TEXTURE_UNITS_ARB, &num_tmus);
728 if (num_tmus < 2)
729 {
730 Con_SafePrintf("ignoring multitexture (%i TMUs)\n", (int) num_tmus);
731 return;
732 }
733
734 glMultiTexCoord2fARB_fp = (glMultiTexCoord2fARB_f) SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
735 glActiveTextureARB_fp = (glActiveTextureARB_f) SDL_GL_GetProcAddress("glActiveTextureARB");
736 if (glMultiTexCoord2fARB_fp == NULL || glActiveTextureARB_fp == NULL)
737 {
738 Con_SafePrintf ("Couldn't link to multitexture functions\n");
739 return;
740 }
741
742 have_mtex = true;
743 if (!gl_multitexture.integer)
744 {
745 Con_SafePrintf("ignoring multitexture (cvar disabled)\n");
746 return;
747 }
748
749 Con_SafePrintf("Found %i TMUs support\n", (int) num_tmus);
750 gl_mtexable = true;
751 glDisable_fp(GL_TEXTURE_2D);
752 glActiveTextureARB_fp(GL_TEXTURE0_ARB);
753 }
754 else
755 {
756 Con_SafePrintf("GL_ARB_multitexture not found\n");
757 }
758 }
759
CheckAnisotropyExtensions(void)760 static void CheckAnisotropyExtensions (void)
761 {
762 gl_max_anisotropy = 1;
763
764 Con_SafePrintf("Anisotropic filtering ");
765 if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_filter_anisotropic"))
766 {
767 GLfloat test1 = 0, test2 = 0;
768 GLuint tex;
769 glGetTexParameterfv_f glGetTexParameterfv_fp;
770
771 glGetTexParameterfv_fp = (glGetTexParameterfv_f) SDL_GL_GetProcAddress("glGetTexParameterfv");
772 if (glGetTexParameterfv_fp == NULL)
773 {
774 Con_SafePrintf("... can't check driver-lock status\n... ");
775 goto _skiptest;
776 }
777 // test to make sure we really have control over it
778 // 1.0 and 2.0 should always be legal values.
779 glGenTextures_fp(1, &tex);
780 glBindTexture_fp(GL_TEXTURE_2D, tex);
781 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
782 glGetTexParameterfv_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test1);
783 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
784 glGetTexParameterfv_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test2);
785 glDeleteTextures_fp(1, &tex);
786 if (test1 != 1 || test2 != 2)
787 {
788 Con_SafePrintf("driver-locked @ %.1f\n", test1);
789 }
790 else
791 {
792 _skiptest:
793 glGetFloatv_fp(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max_anisotropy);
794 if (gl_max_anisotropy < 2)
795 Con_SafePrintf("broken\n");
796 else Con_SafePrintf("found, max %.1f\n", gl_max_anisotropy);
797 }
798 }
799 else
800 {
801 Con_SafePrintf("not found\n");
802 }
803 }
804
CheckNonPowerOfTwoTextures(void)805 static void CheckNonPowerOfTwoTextures (void)
806 {
807 /* On Mac OS X, old Radeons lie about NPOT textures capability, they
808 * fallback to software with mipmap NPOT textures. see, e.g.:
809 * http://lists.apple.com/archives/mac-opengl/2006/Dec/msg00000.html
810 * http://lists.apple.com/archives/mac-opengl/2009/Oct/msg00040.html
811 * http://www.idevgames.com/forums/printthread.php?tid=3814&page=2
812 * MH says NVIDIA once did the same with their GeForce FX on Windows:
813 * http://forums.inside3d.com/viewtopic.php?f=10&t=4832
814 * Therefore, advertisement of this extension is an unreliable way of
815 * detecting the actual capability.
816 */
817 gl_tex_NPOT = have_NPOT = false;
818 if (GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_non_power_of_two"))
819 {
820 have_NPOT = true;
821 Con_SafePrintf("Found ARB_texture_non_power_of_two\n");
822 if (!gl_texture_NPOT.integer) {
823 Con_SafePrintf("ignoring texture_NPOT (cvar disabled)\n");
824 }
825 else {
826 gl_tex_NPOT = true;
827 }
828 }
829 else
830 {
831 Con_SafePrintf("GL_ARB_texture_non_power_of_two not found\n");
832 }
833 }
834
CheckStencilBuffer(void)835 static void CheckStencilBuffer (void)
836 {
837 have_stencil = !!vid_attribs.stencil;
838 }
839
840
841 #ifdef GL_DLSYM
GL_OpenLibrary(const char * name)842 static qboolean GL_OpenLibrary (const char *name)
843 {
844 int ret;
845 char gl_liblocal[MAX_OSPATH];
846
847 ret = SDL_GL_LoadLibrary(name);
848
849 if (ret == -1)
850 {
851 // In case of user-specified gl library, look for it under the
852 // installation directory, too: the user may forget providing
853 // a valid path information. In that case, make sure it doesnt
854 // contain any path information and exists in our own basedir,
855 // then try loading it
856 if (name != NULL &&
857 FIND_FIRST_DIRSEP(name) == NULL && !HAS_DRIVE_SPEC(name))
858 {
859 FS_MakePath_BUF (FS_BASEDIR, NULL, gl_liblocal, MAX_OSPATH, name);
860 if (! (Sys_FileType(gl_liblocal) & FS_ENT_FILE))
861 return false;
862
863 Con_SafePrintf ("Failed loading gl library %s\n"
864 "Trying to load %s\n", name, gl_liblocal);
865
866 ret = SDL_GL_LoadLibrary(gl_liblocal);
867 if (ret == -1)
868 return false;
869
870 Con_SafePrintf("Using GL library: %s\n", gl_liblocal);
871 return true;
872 }
873
874 return false;
875 }
876
877 if (name)
878 Con_SafePrintf("Using GL library: %s\n", name);
879 else
880 Con_SafePrintf("Using system GL library\n");
881
882 return true;
883 }
884 #endif /* GL_DLSYM */
885
886
887 #ifdef GL_DLSYM
GL_Init_Functions(void)888 static void GL_Init_Functions (void)
889 {
890 #define GL_FUNCTION(ret, func, params) \
891 do { \
892 func##_fp = (func##_f) SDL_GL_GetProcAddress(#func); \
893 if (func##_fp == NULL) \
894 Sys_Error("%s not found in GL library", #func); \
895 } while (0);
896 #define GL_FUNCTION_OPT(ret, func, params)
897 #include "gl_func.h"
898 }
899 #endif /* GL_DLSYM */
900
GL_ResetFunctions(void)901 static void GL_ResetFunctions (void)
902 {
903 #ifdef GL_DLSYM
904 #define GL_FUNCTION(ret, func, params) \
905 func##_fp = NULL;
906 #endif
907 #define GL_FUNCTION_OPT(ret, func, params) \
908 func##_fp = NULL;
909 #include "gl_func.h"
910
911 have_stencil = false;
912 gl_mtexable = false;
913 have_mtex = false;
914 have8bit = false;
915 is8bit = false;
916 have_NPOT = false;
917 gl_tex_NPOT = false;
918 }
919
920 /*
921 ===============
922 GL_Init
923 ===============
924 */
GL_Init(void)925 static void GL_Init (void)
926 {
927 #ifdef GL_DLSYM
928 // initialize gl function pointers
929 GL_Init_Functions();
930 #endif
931
932 // collect the visual attributes
933 memset (&vid_attribs, 0, sizeof(attributes_t));
934 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &vid_attribs.red);
935 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &vid_attribs.green);
936 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &vid_attribs.blue);
937 SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &vid_attribs.alpha);
938 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &vid_attribs.depth);
939 SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &vid_attribs.stencil);
940 Con_SafePrintf ("R:%d G:%d B:%d A:%d, Z:%d, S:%d\n",
941 vid_attribs.red, vid_attribs.green, vid_attribs.blue, vid_attribs.alpha,
942 vid_attribs.depth, vid_attribs.stencil);
943
944 gl_vendor = (const char *)glGetString_fp (GL_VENDOR);
945 Con_SafePrintf ("GL_VENDOR: %s\n", gl_vendor);
946 gl_renderer = (const char *)glGetString_fp (GL_RENDERER);
947 Con_SafePrintf ("GL_RENDERER: %s\n", gl_renderer);
948
949 gl_version = (const char *)glGetString_fp (GL_VERSION);
950 Con_SafePrintf ("GL_VERSION: %s\n", gl_version);
951 gl_extensions = (const char *)glGetString_fp (GL_EXTENSIONS);
952 Con_SafeDPrintf ("GL_EXTENSIONS: %s\n", gl_extensions);
953
954 glGetIntegerv_fp(GL_MAX_TEXTURE_SIZE, &gl_max_size);
955 if (gl_max_size < 256) // Refuse to work when less than 256
956 Sys_Error ("hardware capable of min. 256k opengl texture size needed");
957 Con_SafePrintf("OpenGL max.texture size: %i\n", (int) gl_max_size);
958
959 is_3dfx = false;
960 if (!q_strncasecmp(gl_renderer, "3dfx", 4) ||
961 !q_strncasecmp(gl_renderer, "SAGE Glide", 10) ||
962 !q_strncasecmp(gl_renderer, "Glide ", 6) || /* possible with Mesa 3.x/4.x/5.0.x */
963 !q_strncasecmp(gl_renderer, "Mesa Glide", 10))
964 {
965 // This should hopefully detect Voodoo1 and Voodoo2
966 // hardware and possibly Voodoo Rush.
967 // Voodoo Banshee, Voodoo3 and later are hw-accelerated
968 // by DRI in XFree86-4.x and should be: is_3dfx = false.
969 Con_SafePrintf("3dfx Voodoo found\n");
970 is_3dfx = true;
971 }
972
973 // if (!q_strncasecmp(gl_renderer, "PowerVR", 7))
974 // fullsbardraw = true;
975
976 CheckMultiTextureExtensions();
977 CheckAnisotropyExtensions();
978 CheckNonPowerOfTwoTextures();
979 CheckStencilBuffer();
980
981 glClearColor_fp (1,0,0,0);
982 glCullFace_fp(GL_FRONT);
983 glEnable_fp(GL_TEXTURE_2D);
984
985 glEnable_fp(GL_ALPHA_TEST);
986 glAlphaFunc_fp(GL_GREATER, 0.632); // 1 - e^-1 : replaced 0.666 to avoid clipping of smaller fonts/graphics
987 #if 0 /* causes side effects at least in 16 bpp. */
988 /* Get rid of Z-fighting for textures by offsetting the
989 * drawing of entity models compared to normal polygons.
990 * (See: R_DrawBrushModel.)
991 * (Only works if gl_ztrick is turned off) */
992 glPolygonOffset_fp(0.05f, 25.0f);
993 #endif /* #if 0 */
994 glPolygonMode_fp (GL_FRONT_AND_BACK, GL_FILL);
995 glShadeModel_fp (GL_FLAT);
996
997 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
998 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
999
1000 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1001 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1002
1003 glBlendFunc_fp (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1004
1005 // glTexEnvf_fp(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1006 glTexEnvf_fp(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1007
1008 if (multisample)
1009 {
1010 glEnable_fp (GL_MULTISAMPLE_ARB);
1011 Con_SafePrintf ("enabled %i sample fsaa\n", multisample);
1012 }
1013 }
1014
1015 /*
1016 =================
1017 GL_BeginRendering
1018 =================
1019 */
GL_BeginRendering(int * x,int * y,int * width,int * height)1020 void GL_BeginRendering (int *x, int *y, int *width, int *height)
1021 {
1022 *x = *y = 0;
1023 *width = WRWidth;
1024 *height = WRHeight;
1025
1026 // glViewport_fp (*x, *y, *width, *height);
1027 }
1028
1029
GL_EndRendering(void)1030 void GL_EndRendering (void)
1031 {
1032 if (!scr_skipupdate)
1033 SDL_GL_SwapBuffers();
1034
1035 // handle the mouse state when windowed if that's changed
1036 if (_enable_mouse.integer != enable_mouse /*&& modestate == MS_WINDOWED*/)
1037 {
1038 if (_enable_mouse.integer)
1039 IN_ActivateMouse ();
1040 else IN_DeactivateMouse ();
1041
1042 enable_mouse = _enable_mouse.integer;
1043 }
1044
1045 // if (fullsbardraw)
1046 // Sbar_Changed();
1047 }
1048
1049
1050 const int ColorIndex[16] = {
1051 0, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 199, 207, 223, 231
1052 };
1053
1054 const unsigned int ColorPercent[16] = {
1055 25, 51, 76, 102, 114, 127, 140, 153, 165, 178, 191, 204, 216, 229, 237, 247
1056 };
1057
1058 #define INVERSE_PALNAME "gfx/invpal.lmp"
ConvertTrueColorToPal(const unsigned char * true_color,const unsigned char * palette)1059 static int ConvertTrueColorToPal (const unsigned char *true_color, const unsigned char *palette)
1060 {
1061 int i;
1062 long min_dist;
1063 int min_index;
1064 long r, g, b;
1065
1066 min_dist = 256 * 256 + 256 * 256 + 256 * 256;
1067 min_index = -1;
1068 r = (long) true_color[0];
1069 g = (long) true_color[1];
1070 b = (long) true_color[2];
1071
1072 for (i = 0; i < 256; i++)
1073 {
1074 long palr, palg, palb, dist;
1075 long dr, dg, db;
1076
1077 palr = palette[3*i];
1078 palg = palette[3*i+1];
1079 palb = palette[3*i+2];
1080 dr = palr - r;
1081 dg = palg - g;
1082 db = palb - b;
1083 dist = dr * dr + dg * dg + db * db;
1084 if (dist < min_dist)
1085 {
1086 min_dist = dist;
1087 min_index = i;
1088 }
1089 }
1090 return min_index;
1091 }
1092
VID_CreateInversePalette(const unsigned char * palette)1093 static void VID_CreateInversePalette (const unsigned char *palette)
1094 {
1095 long r, g, b;
1096 long idx = 0;
1097 unsigned char true_color[3];
1098
1099 Con_SafePrintf ("Creating inverse palette\n");
1100
1101 for (r = 0; r < (1 << INVERSE_PAL_R_BITS); r++)
1102 {
1103 for (g = 0; g < (1 << INVERSE_PAL_G_BITS); g++)
1104 {
1105 for (b = 0; b < (1 << INVERSE_PAL_B_BITS); b++)
1106 {
1107 true_color[0] = (unsigned char)(r << (8 - INVERSE_PAL_R_BITS));
1108 true_color[1] = (unsigned char)(g << (8 - INVERSE_PAL_G_BITS));
1109 true_color[2] = (unsigned char)(b << (8 - INVERSE_PAL_B_BITS));
1110 inverse_pal[idx] = ConvertTrueColorToPal(true_color, palette);
1111 idx++;
1112 }
1113 }
1114 }
1115
1116 FS_CreatePath(FS_MakePath(FS_USERDIR, NULL, INVERSE_PALNAME));
1117 FS_WriteFile (INVERSE_PALNAME, inverse_pal, INVERSE_PAL_SIZE);
1118 }
1119
VID_InitPalette(const unsigned char * palette)1120 static void VID_InitPalette (const unsigned char *palette)
1121 {
1122 const unsigned char *pal;
1123 unsigned short r, g, b;
1124 unsigned short i, p, c;
1125 unsigned int v, *table;
1126 int mark;
1127
1128 #if ENDIAN_RUNTIME_DETECT
1129 switch (host_byteorder)
1130 {
1131 case BIG_ENDIAN: /* R G B A */
1132 MASK_r = 0xff000000;
1133 MASK_g = 0x00ff0000;
1134 MASK_b = 0x0000ff00;
1135 MASK_a = 0x000000ff;
1136 SHIFT_r = 24;
1137 SHIFT_g = 16;
1138 SHIFT_b = 8;
1139 SHIFT_a = 0;
1140 break;
1141 case LITTLE_ENDIAN: /* A B G R */
1142 MASK_r = 0x000000ff;
1143 MASK_g = 0x0000ff00;
1144 MASK_b = 0x00ff0000;
1145 MASK_a = 0xff000000;
1146 SHIFT_r = 0;
1147 SHIFT_g = 8;
1148 SHIFT_b = 16;
1149 SHIFT_a = 24;
1150 break;
1151 default:
1152 break;
1153 }
1154 MASK_rgb = (MASK_r|MASK_g|MASK_b);
1155 #endif /* ENDIAN_RUNTIME_DETECT */
1156
1157 //
1158 // 8 8 8 encoding
1159 //
1160 pal = palette;
1161 table = d_8to24table;
1162 for (i = 0; i < 256; i++)
1163 {
1164 r = pal[0];
1165 g = pal[1];
1166 b = pal[2];
1167 pal += 3;
1168
1169 v = (255 << SHIFT_a) + (r << SHIFT_r) + (g << SHIFT_g) + (b << SHIFT_b);
1170 *table++ = v;
1171 }
1172
1173 d_8to24table[255] &= MASK_rgb; // 255 is transparent
1174
1175 pal = palette;
1176 table = d_8to24TranslucentTable;
1177
1178 for (i = 0; i < 16; i++)
1179 {
1180 c = ColorIndex[i] * 3;
1181
1182 r = pal[c];
1183 g = pal[c + 1];
1184 b = pal[c + 2];
1185
1186 for (p = 0; p < 16; p++)
1187 {
1188 v = (ColorPercent[15 - p] << SHIFT_a) + (r << SHIFT_r) + (g << SHIFT_g) + (b << SHIFT_b);
1189 *table++ = v;
1190
1191 RTint[i*16 + p] = ((float)r) / ((float)ColorPercent[15-p]);
1192 GTint[i*16 + p] = ((float)g) / ((float)ColorPercent[15-p]);
1193 BTint[i*16 + p] = ((float)b) / ((float)ColorPercent[15-p]);
1194 }
1195 }
1196
1197 // Initialize the palettized textures data
1198 mark = Hunk_LowMark ();
1199 inverse_pal = (unsigned char *) FS_LoadHunkFile (INVERSE_PALNAME, NULL);
1200 if (inverse_pal != NULL && fs_filesize != INVERSE_PAL_SIZE)
1201 {
1202 Hunk_FreeToLowMark (mark);
1203 inverse_pal = NULL;
1204 }
1205 if (inverse_pal == NULL)
1206 {
1207 inverse_pal = (unsigned char *) Hunk_AllocName (INVERSE_PAL_SIZE + 1, INVERSE_PALNAME);
1208 VID_CreateInversePalette (palette);
1209 }
1210 }
1211
VID_SetPalette(const unsigned char * palette)1212 void VID_SetPalette (const unsigned char *palette)
1213 {
1214 // nothing to do
1215 }
1216
1217
1218 /*
1219 ===================================================================
1220
1221 MAIN WINDOW
1222
1223 ===================================================================
1224 */
1225
1226 /*
1227 ================
1228 ClearAllStates
1229 ================
1230 */
ClearAllStates(void)1231 static void ClearAllStates (void)
1232 {
1233 Key_ClearStates ();
1234 IN_ClearStates ();
1235 }
1236
1237 /*
1238 =================
1239 VID_ChangeVideoMode
1240 intended only as a callback for VID_Restart_f
1241 =================
1242 */
VID_ChangeVideoMode(int newmode)1243 static void VID_ChangeVideoMode (int newmode)
1244 {
1245 int temp;
1246
1247 if (!screen)
1248 return;
1249
1250 temp = scr_disabled_for_loading;
1251 scr_disabled_for_loading = true;
1252
1253 // restore gamma, reset gamma function pointers
1254 VID_ShutdownGamma();
1255 CDAudio_Pause ();
1256 BGM_Pause ();
1257 S_ClearBuffer ();
1258
1259 // Unload all textures and reset texture counts
1260 D_ClearOpenGLTextures(0);
1261 memset (lightmap_textures, 0, sizeof(lightmap_textures));
1262
1263 // reset all opengl function pointers
1264 GL_ResetFunctions();
1265
1266 // Avoid re-registering commands and re-allocating memory
1267 draw_reinit = true;
1268
1269 // temporarily disable input devices
1270 IN_DeactivateMouse();
1271 IN_ShowMouse ();
1272
1273 // Kill device and rendering contexts
1274 SDL_FreeSurface(screen);
1275 SDL_QuitSubSystem(SDL_INIT_VIDEO); // also unloads the opengl driver
1276
1277 // re-init sdl_video, set the mode and re-init opengl
1278 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
1279 Sys_Error ("Couldn't init video: %s", SDL_GetError());
1280 #ifdef GL_DLSYM
1281 if (!GL_OpenLibrary(gl_library))
1282 Sys_Error ("Unable to load GL library %s", (gl_library != NULL) ? gl_library : SDL_GetError());
1283 #endif
1284 VID_SetMode (newmode);
1285 // re-get the video info since we re-inited sdl_video
1286 vid_info = SDL_GetVideoInfo();
1287
1288 // Reload graphics wad file (Draw_PicFromWad writes glpic_t data (sizes,
1289 // texnums) right on top of the original pic data, so the pic data will
1290 // be dirty after gl textures are loaded the first time; we need to load
1291 // a clean version)
1292 W_LoadWadFile ("gfx.wad");
1293
1294 // Initialize extensions and default OpenGL parameters
1295 GL_Init();
1296 VID_InitGamma();
1297 VID_Init8bitPalette();
1298
1299 // Reload pre-map pics, fonts, console, etc
1300 Draw_Init();
1301 SCR_Init();
1302 // R_Init() stuff:
1303 R_InitParticleTexture();
1304 R_InitExtraTextures ();
1305 #if defined(H2W)
1306 R_InitNetgraphTexture();
1307 #endif /* H2W */
1308 Sbar_Init();
1309 vid.recalc_refdef = 1;
1310
1311 IN_ReInit ();
1312 ClearAllStates ();
1313 CDAudio_Resume ();
1314 BGM_Resume ();
1315
1316 // Reload model textures and player skins
1317 Mod_ReloadTextures();
1318 // rebuild the lightmaps
1319 GL_BuildLightmaps();
1320 // finished reloading all images
1321 draw_reinit = false;
1322 scr_disabled_for_loading = temp;
1323 // apply our gamma
1324 VID_ShiftPalette(NULL);
1325 }
1326
VID_Restart_f(void)1327 static void VID_Restart_f (void)
1328 {
1329 if (vid_mode.integer < 0 || vid_mode.integer >= *nummodes)
1330 {
1331 Con_Printf ("Bad video mode %d\n", vid_mode.integer);
1332 Cvar_SetValueQuick (&vid_mode, vid_modenum);
1333 return;
1334 }
1335
1336 Con_Printf ("Re-initializing video:\n");
1337 VID_ChangeVideoMode (vid_mode.integer);
1338 }
1339
sort_modes(const void * arg1,const void * arg2)1340 static int sort_modes (const void *arg1, const void *arg2)
1341 {
1342 const vmode_t *a1, *a2;
1343 a1 = (vmode_t *) arg1;
1344 a2 = (vmode_t *) arg2;
1345
1346 #if 0
1347 /* low to high bpp ? */
1348 if (a1->bpp != a2->bpp)
1349 return a1->bpp - a2->bpp;
1350 #endif
1351 /* lowres to highres */
1352 if (a1->width == a2->width)
1353 return a1->height - a2->height;
1354 return a1->width - a2->width;
1355 }
1356
VID_PrepareModes(SDL_Rect ** sdl_modes)1357 static void VID_PrepareModes (SDL_Rect **sdl_modes)
1358 {
1359 int i, j;
1360 qboolean not_multiple;
1361
1362 num_fmodes = 0;
1363 num_wmodes = 0;
1364
1365 // Add the standart 4:3 modes to the windowed modes list
1366 // In an unlikely case that we receive no fullscreen modes,
1367 // this will be our modes list (kind of...)
1368 for (i = 0; i < (int)MAX_STDMODES; i++)
1369 {
1370 wmodelist[num_wmodes].width = std_modes[i].width;
1371 wmodelist[num_wmodes].height = std_modes[i].height;
1372 wmodelist[num_wmodes].halfscreen = 0;
1373 wmodelist[num_wmodes].fullscreen = 0;
1374 wmodelist[num_wmodes].bpp = 16;
1375 q_snprintf (wmodelist[num_wmodes].modedesc, MAX_DESC,
1376 "%d x %d", std_modes[i].width, std_modes[i].height);
1377 num_wmodes++;
1378 }
1379
1380 // disaster scenario #1: no fullscreen modes. bind to the
1381 // windowed modes list. limit it to 640x480 max. because
1382 // we don't know the desktop dimensions
1383 if (sdl_modes == (SDL_Rect **)0)
1384 {
1385 no_fmodes:
1386 Con_SafePrintf ("No fullscreen video modes available\n");
1387 num_wmodes = RES_640X480 + 1;
1388 modelist = wmodelist;
1389 nummodes = &num_wmodes;
1390 vid_default = RES_640X480;
1391 Cvar_SetValueQuick (&vid_config_glx, modelist[vid_default].width);
1392 Cvar_SetValueQuick (&vid_config_gly, modelist[vid_default].height);
1393 return;
1394 }
1395
1396 // another disaster scenario (#2)
1397 if (sdl_modes == (SDL_Rect **)-1)
1398 { // Really should NOT HAVE happened! this return value is
1399 // for windowed modes! Since this means all resolutions
1400 // are supported, use our standart modes as modes list.
1401 Con_SafePrintf ("Unexpectedly received -1 from SDL_ListModes\n");
1402 vid_maxwidth = MAXWIDTH;
1403 vid_maxheight = MAXHEIGHT;
1404 // num_fmodes = -1;
1405 num_fmodes = num_wmodes;
1406 nummodes = &num_wmodes;
1407 modelist = wmodelist;
1408 vid_default = RES_640X480;
1409 Cvar_SetValueQuick (&vid_config_glx, modelist[vid_default].width);
1410 Cvar_SetValueQuick (&vid_config_gly, modelist[vid_default].height);
1411 return;
1412 }
1413
1414 #if 0
1415 // print the un-processed modelist as reported by SDL
1416 for (j = 0; sdl_modes[j]; ++j)
1417 {
1418 Con_SafePrintf ("%d x %d\n", sdl_modes[j]->w, sdl_modes[j]->h);
1419 }
1420 Con_SafePrintf ("Total %d entries\n", j);
1421 #endif
1422
1423 for (i = 0; sdl_modes[i] && num_fmodes < MAX_MODE_LIST; ++i)
1424 {
1425 // avoid multiple listings of the same dimension
1426 not_multiple = true;
1427 for (j = 0; j < num_fmodes; ++j)
1428 {
1429 if (fmodelist[j].width == sdl_modes[i]->w && fmodelist[j].height == sdl_modes[i]->h)
1430 {
1431 not_multiple = false;
1432 break;
1433 }
1434 }
1435
1436 // avoid resolutions < 320x240
1437 if (not_multiple && sdl_modes[i]->w >= MIN_WIDTH && sdl_modes[i]->h >= MIN_HEIGHT)
1438 {
1439 fmodelist[num_fmodes].width = sdl_modes[i]->w;
1440 fmodelist[num_fmodes].height = sdl_modes[i]->h;
1441 // FIXME: look at gl_vidnt.c and learn how to
1442 // really functionalize the halfscreen field?
1443 fmodelist[num_fmodes].halfscreen = 0;
1444 fmodelist[num_fmodes].fullscreen = 1;
1445 fmodelist[num_fmodes].bpp = 16;
1446 q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%d x %d", sdl_modes[i]->w, sdl_modes[i]->h);
1447 num_fmodes++;
1448 }
1449 }
1450
1451 if (!num_fmodes)
1452 goto no_fmodes;
1453
1454 // At his point, we have a list of valid fullscreen modes:
1455 // Let's bind to it and use it for windowed modes, as well.
1456 // The only downside is that if SDL doesn't report any low
1457 // resolutions to us, we shall not have any for windowed
1458 // rendering where they would be perfectly legitimate...
1459 // Since our fullscreen/windowed toggling is instant and
1460 // doesn't require a vid_restart, switching lists won't be
1461 // feasible, either. The -width/-height commandline args
1462 // remain as the user's trusty old friends here.
1463 nummodes = &num_fmodes;
1464 modelist = fmodelist;
1465
1466 // SDL versions older than 1.2.8 have sorting problems
1467 if (num_fmodes > 1)
1468 qsort(fmodelist, num_fmodes, sizeof fmodelist[0], sort_modes);
1469
1470 vid_maxwidth = fmodelist[num_fmodes-1].width;
1471 vid_maxheight = fmodelist[num_fmodes-1].height;
1472
1473 // find the 640x480 default resolution. this shouldn't fail
1474 // at all (for any adapter suporting the VGA/XGA legacy).
1475 for (i = 0; i < num_fmodes; i++)
1476 {
1477 if (fmodelist[i].width == 640 && fmodelist[i].height == 480)
1478 {
1479 vid_default = i;
1480 break;
1481 }
1482 }
1483
1484 if (vid_default < 0)
1485 {
1486 // No 640x480? Unexpected, at least today..
1487 // Easiest thing is to set the default mode
1488 // as the highest reported one.
1489 Con_SafePrintf ("WARNING: 640x480 not found in fullscreen modes\n"
1490 "Using the largest reported dimension as default\n");
1491 vid_default = num_fmodes;
1492 }
1493
1494 // limit the windowed (standart) modes list to desktop dimensions
1495 for (i = 0; i < num_wmodes; i++)
1496 {
1497 if (wmodelist[i].width > vid_maxwidth || wmodelist[i].height > vid_maxheight)
1498 break;
1499 }
1500 if (i < num_wmodes)
1501 num_wmodes = i;
1502
1503 Cvar_SetValueQuick (&vid_config_glx, modelist[vid_default].width);
1504 Cvar_SetValueQuick (&vid_config_gly, modelist[vid_default].height);
1505 }
1506
VID_ListModes_f(void)1507 static void VID_ListModes_f (void)
1508 {
1509 int i;
1510
1511 Con_Printf ("Maximum allowed mode: %d x %d\n", vid_maxwidth, vid_maxheight);
1512 Con_Printf ("Windowed modes enabled:\n");
1513 for (i = 0; i < num_wmodes; i++)
1514 Con_Printf ("%2d: %d x %d\n", i, wmodelist[i].width, wmodelist[i].height);
1515 Con_Printf ("Fullscreen modes enumerated:");
1516 if (num_fmodes)
1517 {
1518 Con_Printf ("\n");
1519 for (i = 0; i < num_fmodes; i++)
1520 Con_Printf ("%2d: %d x %d\n", i, fmodelist[i].width, fmodelist[i].height);
1521 }
1522 else
1523 {
1524 Con_Printf (" None\n");
1525 }
1526 }
1527
VID_NumModes_f(void)1528 static void VID_NumModes_f (void)
1529 {
1530 Con_Printf ("%d video modes in current list\n", *nummodes);
1531 }
1532
1533 /*
1534 ===================
1535 VID_Init
1536 ===================
1537 */
VID_Init(const unsigned char * palette)1538 void VID_Init (const unsigned char *palette)
1539 {
1540 #ifndef __MORPHOS__
1541 static char nvidia_env_vsync[32] = "__GL_SYNC_TO_VBLANK=1";
1542 static char fxmesa_env_fullscreen[32] = "MESA_GLX_FX=f";
1543 static char fxmesa_env_multitex[32] = "FX_DONT_FAKE_MULTITEX=1";
1544 static char fxglide_env_nosplash[32] = "FX_GLIDE_NO_SPLASH=1";
1545 #endif
1546 int i, temp, width, height;
1547 SDL_Rect **enumlist;
1548 const SDL_version *sdl_version;
1549 const char *read_vars[] = {
1550 "vid_config_fscr",
1551 "vid_config_gl8bit",
1552 "vid_config_fsaa",
1553 "vid_config_glx",
1554 "vid_config_gly",
1555 "vid_config_consize",
1556 "gl_texture_NPOT",
1557 "gl_multitexture",
1558 "gl_lightmapfmt" };
1559 #define num_readvars ( sizeof(read_vars)/sizeof(read_vars[0]) )
1560
1561 Cvar_RegisterVariable (&vid_config_gl8bit);
1562 Cvar_RegisterVariable (&vid_config_fsaa);
1563 Cvar_RegisterVariable (&vid_config_fscr);
1564 Cvar_RegisterVariable (&vid_config_swy);
1565 Cvar_RegisterVariable (&vid_config_swx);
1566 Cvar_RegisterVariable (&vid_config_gly);
1567 Cvar_RegisterVariable (&vid_config_glx);
1568 Cvar_RegisterVariable (&vid_config_consize);
1569 Cvar_RegisterVariable (&vid_mode);
1570 Cvar_RegisterVariable (&_enable_mouse);
1571 Cvar_RegisterVariable (&gl_texture_NPOT);
1572 Cvar_RegisterVariable (&gl_lightmapfmt);
1573 Cvar_RegisterVariable (&gl_multitexture);
1574
1575 Cmd_AddCommand ("vid_listmodes", VID_ListModes_f);
1576 Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
1577 Cmd_AddCommand ("vid_restart", VID_Restart_f);
1578
1579 VID_InitPalette (palette);
1580
1581 vid.numpages = 2;
1582
1583 // see if the SDL version we linked to is multisampling-capable
1584 sdl_version = SDL_Linked_Version();
1585 if (SDL_VERSIONNUM(sdl_version->major,sdl_version->minor,sdl_version->patch) >= SDL_VER_WITH_MULTISAMPLING)
1586 sdl_has_multisample = true;
1587
1588 #ifndef __MORPHOS__
1589 // enable vsync for nvidia geforce or newer - S.A
1590 if (COM_CheckParm("-sync") || COM_CheckParm("-vsync"))
1591 {
1592 putenv(nvidia_env_vsync);
1593 Con_SafePrintf ("Nvidia GL vsync enabled\n");
1594 }
1595
1596 // set fxMesa mode to fullscreen, don't let it cheat multitexturing
1597 putenv (fxmesa_env_fullscreen);
1598 putenv (fxmesa_env_multitex);
1599 // disable the 3dfx splash screen.
1600 putenv (fxglide_env_nosplash);
1601 #endif
1602
1603 // init sdl
1604 // the first check is actually unnecessary
1605 if ((SDL_WasInit(SDL_INIT_VIDEO)) == 0)
1606 {
1607 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
1608 Sys_Error ("Couldn't init video: %s", SDL_GetError());
1609 }
1610
1611 #ifdef GL_DLSYM
1612 i = COM_CheckParm("--gllibrary");
1613 if (i == 0)
1614 i = COM_CheckParm ("-gllibrary");
1615 if (i == 0)
1616 i = COM_CheckParm ("-g");
1617 if (i && i < com_argc - 1)
1618 gl_library = com_argv[i+1];
1619 else
1620 gl_library = NULL; // trust SDL's wisdom here
1621
1622 // load the opengl library
1623 if (!GL_OpenLibrary(gl_library))
1624 Sys_Error ("Unable to load GL library %s", (gl_library != NULL) ? gl_library : SDL_GetError());
1625 #endif
1626
1627 // this will contain the "best bpp" for the current display
1628 // make sure to re-retrieve it if you ever re-init sdl_video
1629 vid_info = SDL_GetVideoInfo();
1630
1631 // retrieve the list of fullscreen modes
1632 enumlist = SDL_ListModes(NULL, SDL_OPENGL|SDL_FULLSCREEN);
1633
1634 i = COM_CheckParm("-bpp");
1635 if (i && i < com_argc-1)
1636 {
1637 bpp = atoi(com_argv[i+1]);
1638 }
1639
1640 // prepare the modelists, find the actual modenum for vid_default
1641 VID_PrepareModes(enumlist);
1642
1643 // set vid_mode to our safe default first
1644 Cvar_SetValueQuick (&vid_mode, vid_default);
1645
1646 // perform an early read of config.cfg
1647 CFG_ReadCvars (read_vars, num_readvars);
1648
1649 // windowed mode is default
1650 // see if the user wants fullscreen
1651 if (COM_CheckParm("-fullscreen") || COM_CheckParm("-f"))
1652 {
1653 Cvar_SetQuick (&vid_config_fscr, "1");
1654 }
1655 else if (COM_CheckParm("-window") || COM_CheckParm("-w"))
1656 {
1657 Cvar_SetQuick (&vid_config_fscr, "0");
1658 }
1659
1660 if (vid_config_fscr.integer && !num_fmodes) // FIXME: see below, as well
1661 Sys_Error ("No fullscreen modes available at this color depth");
1662
1663 width = vid_config_glx.integer;
1664 height = vid_config_gly.integer;
1665
1666 if (vid_config_consize.integer != width)
1667 vid_conscale = true;
1668
1669 // user is always right ...
1670 i = COM_CheckParm("-width");
1671 if (i && i < com_argc-1)
1672 { // FIXME: this part doesn't know about a disaster case
1673 // like we aren't reported any fullscreen modes.
1674 width = atoi(com_argv[i+1]);
1675
1676 i = COM_CheckParm("-height");
1677 if (i && i < com_argc-1)
1678 height = atoi(com_argv[i+1]);
1679 else // proceed with 4/3 ratio
1680 height = 3 * width / 4;
1681 }
1682
1683 // user requested a mode either from the config or from the
1684 // command line
1685 // scan existing modes to see if this is already available
1686 // if not, add this as the last "valid" video mode and set
1687 // vid_mode to it only if it doesn't go beyond vid_maxwidth
1688 i = 0;
1689 while (i < *nummodes)
1690 {
1691 if (modelist[i].width == width && modelist[i].height == height)
1692 break;
1693 i++;
1694 }
1695 if (i < *nummodes)
1696 {
1697 Cvar_SetValueQuick (&vid_mode, i);
1698 }
1699 else if ( (width <= vid_maxwidth && width >= MIN_WIDTH &&
1700 height <= vid_maxheight && height >= MIN_HEIGHT) ||
1701 COM_CheckParm("-force") )
1702 {
1703 modelist[*nummodes].width = width;
1704 modelist[*nummodes].height = height;
1705 modelist[*nummodes].halfscreen = 0;
1706 modelist[*nummodes].fullscreen = 1;
1707 modelist[*nummodes].bpp = 16;
1708 q_snprintf (modelist[*nummodes].modedesc, MAX_DESC, "%d x %d (user mode)", width, height);
1709 Cvar_SetValueQuick (&vid_mode, *nummodes);
1710 (*nummodes)++;
1711 }
1712 else
1713 {
1714 Con_SafePrintf ("ignoring invalid -width and/or -height arguments\n");
1715 }
1716
1717 if (!vid_conscale)
1718 Cvar_SetValueQuick (&vid_config_consize, width);
1719
1720 // This will display a bigger hud and readable fonts at high
1721 // resolutions. The fonts will be somewhat distorted, though
1722 i = COM_CheckParm("-conwidth");
1723 if (i != 0 && i < com_argc-1)
1724 i = atoi(com_argv[i + 1]);
1725 else i = vid_config_consize.integer;
1726 if (i < MIN_WIDTH) i = MIN_WIDTH;
1727 else if (i > width) i = width;
1728 Cvar_SetValueQuick(&vid_config_consize, i);
1729 if (vid_config_consize.integer != width)
1730 vid_conscale = true;
1731
1732 multisample = vid_config_fsaa.integer;
1733 i = COM_CheckParm ("-fsaa");
1734 if (i && i < com_argc-1)
1735 multisample = atoi(com_argv[i+1]);
1736
1737 if (COM_CheckParm("-paltex"))
1738 Cvar_SetQuick (&vid_config_gl8bit, "1");
1739
1740 vid.maxwarpwidth = WARP_WIDTH;
1741 vid.maxwarpheight = WARP_HEIGHT;
1742 vid.colormap = host_colormap;
1743 vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
1744
1745 temp = scr_disabled_for_loading;
1746 scr_disabled_for_loading = true;
1747 //set the mode
1748 VID_SetMode (vid_mode.integer);
1749 ClearAllStates ();
1750
1751 GL_SetupLightmapFmt();
1752 GL_Init ();
1753 VID_InitGamma();
1754 VID_Init8bitPalette();
1755
1756 // lock the early-read cvars until Host_Init is finished
1757 for (i = 0; i < (int)num_readvars; i++)
1758 Cvar_LockVar (read_vars[i]);
1759
1760 vid_initialized = true;
1761 scr_disabled_for_loading = temp;
1762 vid.recalc_refdef = 1;
1763
1764 Con_SafePrintf ("Video initialized.\n");
1765
1766 vid_menudrawfn = VID_MenuDraw;
1767 vid_menukeyfn = VID_MenuKey;
1768
1769 // if (COM_CheckParm("-fullsbar"))
1770 // fullsbardraw = true;
1771 }
1772
1773
VID_Shutdown(void)1774 void VID_Shutdown (void)
1775 {
1776 VID_ShutdownGamma();
1777 SDL_QuitSubSystem(SDL_INIT_VIDEO);
1778 }
1779
1780
1781 /*
1782 ================
1783 VID_ToggleFullscreen
1784 Handles switching between fullscreen/windowed modes
1785 and brings the mouse to a proper state afterwards
1786 ================
1787 */
1788 extern qboolean menu_disabled_mouse;
VID_ToggleFullscreen(void)1789 void VID_ToggleFullscreen (void)
1790 {
1791 int is_fullscreen;
1792
1793 if (!fs_toggle_works)
1794 return;
1795 if (!num_fmodes)
1796 return;
1797 if (!screen)
1798 return;
1799
1800 S_ClearBuffer ();
1801
1802 // This doesn't seem to cause any trouble even
1803 // with is_3dfx == true and FX_GLX_MESA == f
1804 if (SDL_WM_ToggleFullScreen(screen) == 1)
1805 {
1806 is_fullscreen = (screen->flags & SDL_FULLSCREEN) ? 1 : 0;
1807 Cvar_SetValueQuick(&vid_config_fscr, is_fullscreen);
1808 modestate = (is_fullscreen) ? MS_FULLDIB : MS_WINDOWED;
1809 if (is_fullscreen)
1810 {
1811 // if (!_enable_mouse.integer)
1812 // Cvar_SetQuick (&_enable_mouse, "1");
1813 // activate mouse in fullscreen mode
1814 // in_sdl.c handles other non-moused cases
1815 if (menu_disabled_mouse)
1816 IN_ActivateMouse();
1817 }
1818 else
1819 { // windowed mode:
1820 // deactivate mouse if we are in menus
1821 if (menu_disabled_mouse)
1822 IN_DeactivateMouse();
1823 }
1824 // update the video menu option
1825 vid_menu_fs = (modestate != MS_WINDOWED);
1826 }
1827 else
1828 {
1829 fs_toggle_works = false;
1830 Con_Printf ("SDL_WM_ToggleFullScreen failed\n");
1831 }
1832 }
1833
1834
1835 #ifndef H2W /* unused in hexenworld */
D_ShowLoadingSize(void)1836 void D_ShowLoadingSize (void)
1837 {
1838 #if defined(DRAW_PROGRESSBARS)
1839 int cur_perc;
1840 static int prev_perc;
1841
1842 if (!vid_initialized)
1843 return;
1844
1845 cur_perc = loading_stage * 100;
1846 if (total_loading_size)
1847 cur_perc += current_loading_size * 100 / total_loading_size;
1848 if (cur_perc == prev_perc)
1849 return;
1850 prev_perc = cur_perc;
1851
1852 glDrawBuffer_fp (GL_FRONT);
1853
1854 SCR_DrawLoading();
1855
1856 glFlush_fp();
1857
1858 glDrawBuffer_fp (GL_BACK);
1859 #endif /* DRAW_PROGRESSBARS */
1860 }
1861 #endif
1862
1863
1864 //========================================================
1865 // Video menu stuff
1866 //========================================================
1867
1868 static int vid_menunum;
1869 static int vid_cursor;
1870 static qboolean want_fstoggle, need_apply;
1871 static qboolean vid_menu_firsttime = true;
1872
1873 enum {
1874 VID_FULLSCREEN, // make sure the fullscreen entry (0)
1875 VID_RESOLUTION, // is lower than resolution entry (1)
1876 VID_MULTISAMPLE,
1877 VID_MULTITEXTURE,
1878 VID_NPOT,
1879 VID_PALTEX,
1880 VID_BLANKLINE, // spacer line
1881 VID_RESET,
1882 VID_APPLY,
1883 VID_ITEMS
1884 };
1885
M_DrawYesNo(int x,int y,int on,int white)1886 static void M_DrawYesNo (int x, int y, int on, int white)
1887 {
1888 if (on)
1889 {
1890 if (white)
1891 M_PrintWhite (x, y, "yes");
1892 else
1893 M_Print (x, y, "yes");
1894 }
1895 else
1896 {
1897 if (white)
1898 M_PrintWhite (x, y, "no");
1899 else
1900 M_Print (x, y, "no");
1901 }
1902 }
1903
1904 /*
1905 ================
1906 VID_MenuDraw
1907 ================
1908 */
VID_MenuDraw(void)1909 static void VID_MenuDraw (void)
1910 {
1911 ScrollTitle("gfx/menu/title7.lmp");
1912
1913 if (vid_menu_firsttime)
1914 { // settings for entering the menu first time
1915 vid_menunum = vid_modenum;
1916 vid_menu_fs = (modestate != MS_WINDOWED);
1917 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
1918 vid_menu_firsttime = false;
1919 }
1920
1921 want_fstoggle = ( ((modestate == MS_WINDOWED) && vid_menu_fs) || ((modestate != MS_WINDOWED) && !vid_menu_fs) );
1922
1923 need_apply = (vid_menunum != vid_modenum) || want_fstoggle ||
1924 (have8bit && (is8bit != !!vid_config_gl8bit.integer)) ||
1925 (have_mtex && (gl_mtexable != !!gl_multitexture.integer)) ||
1926 (have_NPOT && (gl_tex_NPOT != !!gl_texture_NPOT.integer)) ||
1927 (multisample != vid_config_fsaa.integer);
1928
1929 M_Print (76, 92 + 8*VID_FULLSCREEN, "Fullscreen: ");
1930 M_DrawYesNo (76+12*8, 92 + 8*VID_FULLSCREEN, vid_menu_fs, !want_fstoggle);
1931
1932 M_Print (76, 92 + 8*VID_RESOLUTION, "Resolution: ");
1933 if (vid_menunum == vid_modenum)
1934 M_PrintWhite (76+12*8, 92 + 8*VID_RESOLUTION, modelist[vid_menunum].modedesc);
1935 else
1936 M_Print (76+12*8, 92 + 8*VID_RESOLUTION, modelist[vid_menunum].modedesc);
1937
1938 M_Print (76, 92 + 8*VID_MULTISAMPLE, "Antialiasing :");
1939 if (sdl_has_multisample)
1940 {
1941 if (multisample == vid_config_fsaa.integer)
1942 M_PrintWhite (76+16*8, 92 + 8*VID_MULTISAMPLE, va("%d",multisample));
1943 else
1944 M_Print (76+16*8, 92 + 8*VID_MULTISAMPLE, va("%d",multisample));
1945 }
1946 else
1947 M_PrintWhite (76+16*8, 92 + 8*VID_MULTISAMPLE, "Not found");
1948
1949 M_Print (76, 92 + 8*VID_MULTITEXTURE, "Multitexturing:");
1950 if (have_mtex)
1951 M_DrawYesNo (76+16*8, 92 + 8*VID_MULTITEXTURE, gl_multitexture.integer, (gl_mtexable == !!gl_multitexture.integer));
1952 else
1953 M_PrintWhite (76+16*8, 92 + 8*VID_MULTITEXTURE, "Not found");
1954
1955 M_Print (76, 92 + 8*VID_NPOT, "NPOT textures :");
1956 if (have_NPOT)
1957 M_DrawYesNo (76+16*8, 92 + 8*VID_NPOT, gl_texture_NPOT.integer, (gl_tex_NPOT == !!gl_texture_NPOT.integer));
1958 else
1959 M_PrintWhite (76+16*8, 92 + 8*VID_NPOT, "Not found");
1960
1961 M_Print (76, 92 + 8*VID_PALTEX, "8 bit textures:");
1962 if (have8bit)
1963 M_DrawYesNo (76+16*8, 92 + 8*VID_PALTEX, vid_config_gl8bit.integer, (is8bit == !!vid_config_gl8bit.integer));
1964 else
1965 M_PrintWhite (76+16*8, 92 + 8*VID_PALTEX, "Not found");
1966
1967 if (need_apply)
1968 {
1969 M_Print (76, 92 + 8*VID_RESET, "RESET CHANGES");
1970 M_Print (76, 92 + 8*VID_APPLY, "APPLY CHANGES");
1971 }
1972
1973 M_DrawCharacter (64, 92 + vid_cursor*8, 12+((int)(realtime*4)&1));
1974 }
1975
1976 /*
1977 ================
1978 VID_MenuKey
1979 ================
1980 */
VID_MenuKey(int key)1981 static void VID_MenuKey (int key)
1982 {
1983 switch (key)
1984 {
1985 case K_ESCAPE:
1986 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
1987 M_Menu_Options_f ();
1988 break;
1989
1990 case K_UPARROW:
1991 S_LocalSound ("raven/menu1.wav");
1992 vid_cursor--;
1993 if (vid_cursor < 0)
1994 {
1995 vid_cursor = (need_apply) ? VID_ITEMS-1 : VID_BLANKLINE-1;
1996 }
1997 else if (vid_cursor == VID_BLANKLINE)
1998 {
1999 vid_cursor--;
2000 }
2001 break;
2002
2003 case K_DOWNARROW:
2004 S_LocalSound ("raven/menu1.wav");
2005 vid_cursor++;
2006 if (vid_cursor >= VID_ITEMS)
2007 {
2008 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2009 break;
2010 }
2011 if (vid_cursor >= VID_BLANKLINE)
2012 {
2013 if (need_apply)
2014 {
2015 if (vid_cursor == VID_BLANKLINE)
2016 vid_cursor++;
2017 }
2018 else
2019 {
2020 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2021 }
2022 }
2023 break;
2024
2025 case K_ENTER:
2026 switch (vid_cursor)
2027 {
2028 case VID_RESET:
2029 vid_menu_fs = (modestate != MS_WINDOWED);
2030 vid_menunum = vid_modenum;
2031 multisample = vid_config_fsaa.integer;
2032 Cvar_SetValueQuick (&vid_config_gl8bit, is8bit);
2033 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2034 break;
2035 case VID_APPLY:
2036 if (need_apply)
2037 {
2038 Cvar_SetValueQuick(&vid_mode, vid_menunum);
2039 Cvar_SetValueQuick(&vid_config_fscr, vid_menu_fs);
2040 VID_Restart_f();
2041 }
2042 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2043 break;
2044 }
2045 return;
2046
2047 case K_LEFTARROW:
2048 switch (vid_cursor)
2049 {
2050 case VID_FULLSCREEN:
2051 vid_menu_fs = !vid_menu_fs;
2052 if (fs_toggle_works)
2053 VID_ToggleFullscreen();
2054 break;
2055 case VID_RESOLUTION:
2056 S_LocalSound ("raven/menu1.wav");
2057 vid_menunum--;
2058 if (vid_menunum < 0)
2059 vid_menunum = 0;
2060 break;
2061 case VID_MULTISAMPLE:
2062 if (!sdl_has_multisample)
2063 break;
2064 if (multisample <= 2)
2065 multisample = 0;
2066 else if (multisample <= 4)
2067 multisample = 2;
2068 else
2069 multisample = 4;
2070 break;
2071 case VID_MULTITEXTURE:
2072 if (have_mtex)
2073 Cvar_SetQuick (&gl_multitexture, gl_multitexture.integer ? "0" : "1");
2074 break;
2075 case VID_NPOT:
2076 if (have_NPOT)
2077 Cvar_SetQuick (&gl_texture_NPOT, gl_texture_NPOT.integer ? "0" : "1");
2078 break;
2079 case VID_PALTEX:
2080 if (have8bit)
2081 Cvar_SetQuick (&vid_config_gl8bit, vid_config_gl8bit.integer ? "0" : "1");
2082 break;
2083 }
2084 return;
2085
2086 case K_RIGHTARROW:
2087 switch (vid_cursor)
2088 {
2089 case VID_FULLSCREEN:
2090 vid_menu_fs = !vid_menu_fs;
2091 if (fs_toggle_works)
2092 VID_ToggleFullscreen();
2093 break;
2094 case VID_RESOLUTION:
2095 S_LocalSound ("raven/menu1.wav");
2096 vid_menunum++;
2097 if (vid_menunum >= *nummodes)
2098 vid_menunum = *nummodes - 1;
2099 break;
2100 case VID_MULTISAMPLE:
2101 if (!sdl_has_multisample)
2102 break;
2103 if (multisample < 2)
2104 multisample = 2;
2105 else if (multisample < 4)
2106 multisample = 4;
2107 else if (multisample < 8)
2108 multisample = 8;
2109 break;
2110 case VID_MULTITEXTURE:
2111 if (have_mtex)
2112 Cvar_SetQuick (&gl_multitexture, gl_multitexture.integer ? "0" : "1");
2113 break;
2114 case VID_NPOT:
2115 if (have_NPOT)
2116 Cvar_SetQuick (&gl_texture_NPOT, gl_texture_NPOT.integer ? "0" : "1");
2117 break;
2118 case VID_PALTEX:
2119 if (have8bit)
2120 Cvar_SetQuick (&vid_config_gl8bit, vid_config_gl8bit.integer ? "0" : "1");
2121 break;
2122 }
2123 return;
2124
2125 default:
2126 break;
2127 }
2128 }
2129
2130