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