1 /*
2  * gl_viddos.c -- DOS OpenGL (based on gl_vidsdl.c and gl_vidnt.c)
3  *
4  * Copyright (C) 1996-1997  Id Software, Inc.
5  * Copyright (C) 1997-1998  Raven Software Corp.
6  * Copyright (C) 2015-2016  O.Sezer <sezero@users.sourceforge.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 #define	__GL_FUNC_EXTERN
25 
26 #include "quakedef.h"
27 #include "cfgfile.h"
28 #include "bgmusic.h"
29 #include "cdaudio.h"
30 #include <unistd.h>
31 #include "filenames.h"
32 
33 #include "gl_dos.h"
34 #include "sys_dxe.h"
35 
36 /* DOSGL interface */
37 int  (*DOSGL_InitCtx ) (int *width, int *height, int *bpp);
38 void (*DOSGL_Shutdown) (void);
39 void (*DOSGL_EndFrame) (void);
40 void * (*DOSGL_GetProcAddress) (const char *);
41 const char * (*DOSGL_APIName) (void);
42 
43 #define WARP_WIDTH		320
44 #define WARP_HEIGHT		200
45 #define MAXWIDTH		10000
46 #define MAXHEIGHT		10000
47 #define MIN_WIDTH		320
48 //#define MIN_HEIGHT		200
49 #define MIN_HEIGHT		240
50 #define MAX_DESC		33
51 
52 typedef struct {
53 	int			width;
54 	int			height;
55 	int			modenum;
56 	int			bpp;
57 	int			halfscreen;
58 	char		modedesc[MAX_DESC];
59 } vmode_t;
60 
61 typedef struct {
62 	int	width;
63 	int	height;
64 } stdmode_t;
65 
66 #define RES_640X480	3
67 static const stdmode_t	std_modes[] = {
68 // NOTE: keep this list in order
69 	{320, 240},	// 0
70 	{400, 300},	// 1
71 	{512, 384},	// 2
72 	{640, 480},	// 3 == RES_640X480, this is our default
73 	{800, 600},
74 	{856, 480},	// GR_RESOLUTION_856x480
75 	{960, 720},	// GR_RESOLUTION_960x720
76 	{1024,768},
77 	{1280,1024},
78 	{1600,1200}
79 };
80 
81 #define MAX_MODE_LIST	20
82 #define MAX_STDMODES	(sizeof(std_modes) / sizeof(std_modes[0]))
83 static vmode_t	modelist[MAX_MODE_LIST+1];
84 
85 static int	nummodes;
86 static int	bpp = 16;
87 
88 typedef struct {
89 	int	red,
90 		green,
91 		blue,
92 		alpha,
93 		depth,
94 		stencil;
95 } attributes_t;
96 static attributes_t	vid_attribs;
97 
98 // vars for vid state
99 viddef_t	vid;			// global video state
100 modestate_t	modestate = MS_UNINIT;
101 static int	vid_default = -1;	// modenum of 640x480 as a safe default
102 static int	vid_modenum = -1;	// current video mode, set after mode setting succeeds
103 static int	vid_maxwidth = 640, vid_maxheight = 480;
104 static qboolean	vid_conscale = false;
105 static int	WRHeight, WRWidth;
106 
107 static qboolean	vid_initialized = false;
108 qboolean	in_mode_set = false;
109 
110 // cvar vid_mode must be set before calling
111 // VID_SetMode, VID_ChangeVideoMode or VID_Restart_f
112 static cvar_t	vid_mode = {"vid_mode", "0", CVAR_NONE};
113 static cvar_t	vid_config_consize = {"vid_config_consize", "640", CVAR_ARCHIVE};
114 static cvar_t	vid_config_glx = {"vid_config_glx", "640", CVAR_ARCHIVE};
115 static cvar_t	vid_config_gly = {"vid_config_gly", "480", CVAR_ARCHIVE};
116 // cvars for compatibility with the software version
117 static cvar_t	vid_nopageflip = {"vid_nopageflip", "0", CVAR_ARCHIVE};
118 static cvar_t	_vid_wait_override = {"_vid_wait_override", "0", CVAR_ARCHIVE};
119 static cvar_t	_vid_default_mode = {"_vid_default_mode", "0", CVAR_ARCHIVE};
120 
121 byte		globalcolormap[VID_GRADES*256];
122 float		RTint[256], GTint[256], BTint[256];
123 unsigned short	d_8to16table[256];
124 unsigned int	d_8to24table[256];
125 unsigned int	d_8to24TranslucentTable[256];
126 unsigned char	*inverse_pal;
127 
128 // gl stuff
129 static void GL_Init (void);
130 
131 #ifdef GL_DLSYM
132 static const char	*gl_library;
133 #endif
134 static void		*gl_handle;
135 
136 static const char	*gl_vendor;
137 static const char	*gl_renderer;
138 static const char	*gl_version;
139 static const char	*gl_extensions;
140 qboolean	is_3dfx = false;
141 
142 GLint		gl_max_size = 256;
143 static qboolean	have_NPOT = false;
144 qboolean	gl_tex_NPOT = false;
145 static cvar_t	gl_texture_NPOT = {"gl_texture_NPOT", "0", CVAR_ARCHIVE};
146 GLfloat		gl_max_anisotropy;
147 float		gldepthmin, gldepthmax;
148 
149 // palettized textures
150 static qboolean	have8bit = false;
151 qboolean	is8bit = false;
152 static cvar_t	vid_config_gl8bit = {"vid_config_gl8bit", "0", CVAR_ARCHIVE};
153 
154 /* Gamma stuff */
155 #define	USE_GAMMA_RAMPS			0
156 
157 /* 3dfx gamma hacks: see fx_gamma.c */
158 #define	USE_3DFX_RAMPS			0
159 #if defined(USE_3DFXGAMMA)
160 #include "fx_gamma.h"
161 #endif
162 
163 #if (USE_GAMMA_RAMPS) || (defined(USE_3DFXGAMMA) && (USE_3DFX_RAMPS))
164 static unsigned short	orig_ramps[3][256];
165 #endif
166 
167 static qboolean	fx_gamma   = false;	// 3dfx-specific gamma control
168 static qboolean	gammaworks = false;	// whether hw-gamma works
169 
170 // multitexturing
171 qboolean	gl_mtexable = false;
172 static GLint	num_tmus = 1;
173 static qboolean	have_mtex = false;
174 static cvar_t	gl_multitexture = {"gl_multitexture", "0", CVAR_ARCHIVE};
175 
176 // stencil buffer
177 qboolean	have_stencil = false;
178 
179 // this is useless: things aren't like those in quake
180 //static qboolean	fullsbardraw = false;
181 
182 // menu drawing
183 static void VID_MenuDraw (void);
184 static void VID_MenuKey (int key);
185 
186 // input stuff
187 static void ClearAllStates (void);
188 cvar_t		_enable_mouse = {"_enable_mouse", "1", CVAR_ARCHIVE};
189 
190 
191 //====================================
192 
GL_ParseExtensionList(const char * list,const char * name)193 static qboolean GL_ParseExtensionList (const char *list, const char *name)
194 {
195 	const char	*start;
196 	const char	*where, *terminator;
197 
198 	if (!list || !name || !*name)
199 		return false;
200 	if (strchr(name, ' ') != NULL)
201 		return false;	// extension names must not have spaces
202 
203 	start = list;
204 	while (1) {
205 		where = strstr (start, name);
206 		if (!where)
207 			break;
208 		terminator = where + strlen (name);
209 		if (where == start || where[-1] == ' ')
210 			if (*terminator == ' ' || *terminator == '\0')
211 				return true;
212 		start = terminator;
213 	}
214 	return false;
215 }
216 
217 //====================================
218 
VID_LockBuffer(void)219 void VID_LockBuffer (void)
220 {
221 // nothing to do
222 }
223 
VID_UnlockBuffer(void)224 void VID_UnlockBuffer (void)
225 {
226 // nothing to do
227 }
228 
VID_HandlePause(qboolean paused)229 void VID_HandlePause (qboolean paused)
230 {
231 	if (paused)	IN_DeactivateMouse ();
232 	else		IN_ActivateMouse ();
233 }
234 
235 //====================================
236 
VID_ConWidth(int modenum)237 static void VID_ConWidth (int modenum)
238 {
239 	int	w, h;
240 
241 	if (!vid_conscale)
242 	{
243 		Cvar_SetValueQuick (&vid_config_consize, modelist[modenum].width);
244 		return;
245 	}
246 
247 	w = vid_config_consize.integer;
248 	w &= ~7; /* make it a multiple of eight */
249 	if (w < MIN_WIDTH)
250 		w = MIN_WIDTH;
251 	else if (w > modelist[modenum].width)
252 		w = modelist[modenum].width;
253 
254 	h = w * modelist[modenum].height / modelist[modenum].width;
255 	if (h < 200 /* MIN_HEIGHT */ ||
256 	    h > modelist[modenum].height || w > modelist[modenum].width)
257 	{
258 		vid_conscale = false;
259 		Cvar_SetValueQuick (&vid_config_consize, modelist[modenum].width);
260 		return;
261 	}
262 	vid.width = vid.conwidth = w;
263 	vid.height = vid.conheight = h;
264 	if (w != modelist[modenum].width)
265 		vid_conscale = true;
266 	else	vid_conscale = false;
267 }
268 
VID_ChangeConsize(int dir)269 void VID_ChangeConsize (int dir)
270 {
271 	int	w, h;
272 
273 	switch (dir)
274 	{
275 	case -1: /* smaller text */
276 		w = ((float)vid.conwidth/(float)vid.width + 0.05f) * vid.width; /* use 0.10f increment ?? */
277 		w &= ~7; /* make it a multiple of eight */
278 		if (w > modelist[vid_modenum].width)
279 			w = modelist[vid_modenum].width;
280 		break;
281 
282 	case 1: /* bigger text */
283 		w = ((float)vid.conwidth/(float)vid.width - 0.05f) * vid.width;
284 		w &= ~7; /* make it a multiple of eight */
285 		if (w < MIN_WIDTH)
286 			w = MIN_WIDTH;
287 		break;
288 
289 	default:	/* bad key */
290 		return;
291 	}
292 
293 	h = w * modelist[vid_modenum].height / modelist[vid_modenum].width;
294 	if (h < 200)
295 		return;
296 	vid.width = vid.conwidth = w;
297 	vid.height = vid.conheight = h;
298 	Cvar_SetValueQuick (&vid_config_consize, vid.conwidth);
299 	vid.recalc_refdef = 1;
300 	if (vid.conwidth != modelist[vid_modenum].width)
301 		vid_conscale = true;
302 	else	vid_conscale = false;
303 }
304 
VID_ReportConsize(void)305 float VID_ReportConsize(void)
306 {
307 	return (float)modelist[vid_modenum].width/vid.conwidth;
308 }
309 
310 
VID_SetMode(int modenum)311 static qboolean VID_SetMode (int modenum)
312 {
313 	int	width, height;
314 
315 	in_mode_set = true;
316 
317 	width = modelist[modenum].width;
318 	height = modelist[modenum].height;
319 	Con_SafePrintf ("Requested mode %d: %dx%dx%d\n", modenum, width, height, bpp);
320 
321 	if (DOSGL_InitCtx(&width, &height, &bpp) < 0)
322 		Sys_Error("DOSGL: Failed creating context.");
323 
324 	// set vid_modenum properly and adjust other vars
325 	vid_modenum = modenum;
326 	modestate = MS_FULLDIB;
327 	Cvar_SetValueQuick (&vid_config_glx, modelist[vid_modenum].width);
328 	Cvar_SetValueQuick (&vid_config_gly, modelist[vid_modenum].height);
329 	WRWidth = vid.width = vid.conwidth = modelist[modenum].width;
330 	WRHeight = vid.height = vid.conheight = modelist[modenum].height;
331 
332 	// setup the effective console width
333 	VID_ConWidth(modenum);
334 
335 	Con_SafePrintf ("Video Mode Set : %dx%dx%d\n", width, height, bpp);
336 
337 	in_mode_set = false;
338 
339 	return true;
340 }
341 
342 
343 //====================================
344 
345 #if 0 /* No.. */
346 static void CheckSetGlobalPalette (void)
347 {
348 	gl3DfxSetPaletteEXT_f gl3DfxSetPaletteEXT_fp;
349 
350 	if (GL_ParseExtensionList(gl_extensions, "3DFX_set_global_palette"))
351 	{
352 		gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) DOSGL_GetProcAddress("gl3DfxSetPaletteEXT");
353 		if (!gl3DfxSetPaletteEXT_fp)
354 			gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) DOSGL_GetProcAddress("3DFX_set_global_palette");
355 		if (!gl3DfxSetPaletteEXT_fp)
356 			return;
357 		Con_SafePrintf("Found 3DFX_set_global_palette\n");
358 	}
359 	else if (GL_ParseExtensionList(gl_extensions, "POWERVR_set_global_palette"))
360 	{
361 		gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) DOSGL_GetProcAddress("glSetGlobalPalettePOWERVR");
362 		if (!gl3DfxSetPaletteEXT_fp)
363 			gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) DOSGL_GetProcAddress("POWERVR_set_global_palette");
364 		if (!gl3DfxSetPaletteEXT_fp)
365 			return;
366 		Con_SafePrintf("Found POWERVR_set_global_palette\n");
367 	}
368 	else {
369 		return;
370 	}
371 
372 	have8bit = true;
373 	if (!vid_config_gl8bit.integer)
374 		return;
375 	else
376 	{
377 		int i;
378 		GLubyte table[256][4];
379 		char *oldpal;
380 
381 		is8bit = true;
382 		oldpal = (char *) d_8to24table;
383 		for (i = 0; i < 256; i++) {
384 			table[i][2] = *oldpal++;
385 			table[i][1] = *oldpal++;
386 			table[i][0] = *oldpal++;
387 			table[i][3] = 255;
388 			oldpal++;
389 		}
390 		glEnable_fp (GL_SHARED_TEXTURE_PALETTE_EXT);
391 		gl3DfxSetPaletteEXT_fp ((GLuint *)table);
392 	}
393 }
394 #endif /* #if 0 */
395 
CheckSharedTexturePalette(void)396 static void CheckSharedTexturePalette (void)
397 {
398 	glColorTableEXT_f glColorTableEXT_fp;
399 
400 	if (!GL_ParseExtensionList(gl_extensions, "GL_EXT_shared_texture_palette"))
401 		return;
402 
403 	glColorTableEXT_fp = (glColorTableEXT_f) DOSGL_GetProcAddress("glColorTableEXT");
404 	if (glColorTableEXT_fp == NULL)
405 		return;
406 
407 	have8bit = true;
408 	Con_SafePrintf("Found GL_EXT_shared_texture_palette\n");
409 	if (!vid_config_gl8bit.integer)
410 		return;
411 	else
412 	{
413 		int i;
414 		char thePalette[256*3];
415 		char *oldPalette, *newPalette;
416 
417 		is8bit = true;
418 		oldPalette = (char *) d_8to24table;
419 		newPalette = thePalette;
420 		for (i = 0; i < 256; i++) {
421 			*newPalette++ = *oldPalette++;
422 			*newPalette++ = *oldPalette++;
423 			*newPalette++ = *oldPalette++;
424 			oldPalette++;
425 		}
426 
427 		glEnable_fp (GL_SHARED_TEXTURE_PALETTE_EXT);
428 		glColorTableEXT_fp (GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256,
429 					GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
430 	}
431 }
432 
VID_Init8bitPalette(void)433 static void VID_Init8bitPalette (void)
434 {
435 	have8bit = false;
436 	is8bit = false;
437 
438 	/* Check for 8bit Extensions and initialize them */
439 	CheckSharedTexturePalette();
440 #if 0	/* No.. */
441 	if (!have8bit)
442 		CheckSetGlobalPalette();
443 #endif
444 
445 	if (is8bit)
446 		Con_SafePrintf("8-bit palettized textures enabled\n");
447 }
448 
449 
450 #if !defined(USE_3DFXGAMMA)
Init_3dfxGammaCtrl(void)451 static inline int Init_3dfxGammaCtrl (void)		{ return 0; }
Shutdown_3dfxGamma(void)452 static inline void Shutdown_3dfxGamma (void)		{ }
do3dfxGammaCtrl(float value)453 static inline int do3dfxGammaCtrl (float value)			{ return 0; }
glGetDeviceGammaRamp3DFX(void * arrays)454 static inline int glGetDeviceGammaRamp3DFX (void *arrays)	{ return 0; }
glSetDeviceGammaRamp3DFX(void * arrays)455 static inline int glSetDeviceGammaRamp3DFX (void *arrays)	{ return 0; }
VID_Check3dfxGamma(void)456 static inline qboolean VID_Check3dfxGamma (void)	{ return false; }
457 #else
VID_Check3dfxGamma(void)458 static qboolean VID_Check3dfxGamma (void)
459 {
460 	int		ret;
461 
462 	if (COM_CheckParm("-no3dfxgamma"))
463 		return false;
464 
465 #if USE_3DFX_RAMPS /* not recommended for Voodoo1, currently crashes */
466 	ret = glGetDeviceGammaRamp3DFX(orig_ramps);
467 	if (ret != 0)
468 	{
469 		Con_SafePrintf ("Using 3dfx glide3 specific gamma ramps\n");
470 		return true;
471 	}
472 #else
473 	ret = Init_3dfxGammaCtrl();
474 	if (ret > 0)
475 	{
476 		Con_SafePrintf ("Using 3dfx glide%d gamma controls\n", ret);
477 		return true;
478 	}
479 #endif
480 	return false;
481 }
482 #endif	/* USE_3DFXGAMMA */
483 
VID_InitGamma(void)484 static void VID_InitGamma (void)
485 {
486 	gammaworks = fx_gamma = false;
487 	/* we don't have WGL_3DFX_gamma_control or an equivalent in dos. */
488 	/* Here is an evil hack abusing the exposed Glide symbols: */
489 	if (is_3dfx)
490 		fx_gamma = VID_Check3dfxGamma();
491 
492 	if (!gammaworks && !fx_gamma)
493 		Con_SafePrintf("gamma adjustment not available\n");
494 }
495 
VID_ShutdownGamma(void)496 static void VID_ShutdownGamma (void)
497 {
498 #if USE_3DFX_RAMPS
499 	if (fx_gamma) glSetDeviceGammaRamp3DFX(orig_ramps);
500 #else
501 /*	if (fx_gamma) do3dfxGammaCtrl(1);*/
502 #endif
503 	Shutdown_3dfxGamma();
504 }
505 
VID_SetGamma(void)506 static void VID_SetGamma (void)
507 {
508 #if (!USE_GAMMA_RAMPS) || (!USE_3DFX_RAMPS)
509 	float	value = (v_gamma.value > (1.0 / GAMMA_MAX))?
510 			(1.0 / v_gamma.value) : GAMMA_MAX;
511 #endif
512 #if USE_3DFX_RAMPS
513 	if (fx_gamma) glSetDeviceGammaRamp3DFX(ramps);
514 #else
515 	if (fx_gamma) do3dfxGammaCtrl(value);
516 #endif
517 }
518 
VID_ShiftPalette(const unsigned char * palette)519 void VID_ShiftPalette (const unsigned char *palette)
520 {
521 	VID_SetGamma();
522 }
523 
524 
CheckMultiTextureExtensions(void)525 static void CheckMultiTextureExtensions (void)
526 {
527 	gl_mtexable = have_mtex = false;
528 
529 	if (COM_CheckParm("-nomtex"))
530 	{
531 		Con_SafePrintf("Multitexture extensions disabled\n");
532 	}
533 	else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_multitexture"))
534 	{
535 		Con_SafePrintf("ARB Multitexture extensions found\n");
536 
537 		glGetIntegerv_fp(GL_MAX_TEXTURE_UNITS_ARB, &num_tmus);
538 		if (num_tmus < 2)
539 		{
540 			Con_SafePrintf("ignoring multitexture (%i TMUs)\n", (int) num_tmus);
541 			return;
542 		}
543 
544 		glMultiTexCoord2fARB_fp = (glMultiTexCoord2fARB_f) DOSGL_GetProcAddress("glMultiTexCoord2fARB");
545 		glActiveTextureARB_fp = (glActiveTextureARB_f) DOSGL_GetProcAddress("glActiveTextureARB");
546 		if (glMultiTexCoord2fARB_fp == NULL || glActiveTextureARB_fp == NULL)
547 		{
548 			Con_SafePrintf ("Couldn't link to multitexture functions\n");
549 			return;
550 		}
551 
552 		have_mtex = true;
553 		if (!gl_multitexture.integer)
554 		{
555 			Con_SafePrintf("ignoring multitexture (cvar disabled)\n");
556 			return;
557 		}
558 
559 		Con_SafePrintf("Found %i TMUs support\n", (int) num_tmus);
560 		gl_mtexable = true;
561 		glDisable_fp(GL_TEXTURE_2D);
562 		glActiveTextureARB_fp(GL_TEXTURE0_ARB);
563 	}
564 	else
565 	{
566 		Con_SafePrintf("GL_ARB_multitexture not found\n");
567 	}
568 }
569 
CheckAnisotropyExtensions(void)570 static void CheckAnisotropyExtensions (void)
571 {
572 	gl_max_anisotropy = 1;
573 
574 	Con_SafePrintf("Anisotropic filtering ");
575 	if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_filter_anisotropic"))
576 	{
577 		GLfloat test1 = 0, test2 = 0;
578 		GLuint tex;
579 		glGetTexParameterfv_f glGetTexParameterfv_fp;
580 
581 		glGetTexParameterfv_fp = (glGetTexParameterfv_f) DOSGL_GetProcAddress("glGetTexParameterfv");
582 		if (glGetTexParameterfv_fp == NULL)
583 		{
584 			Con_SafePrintf("... can't check driver-lock status\n... ");
585 			goto _skiptest;
586 		}
587 		// test to make sure we really have control over it
588 		// 1.0 and 2.0 should always be legal values.
589 		glGenTextures_fp(1, &tex);
590 		glBindTexture_fp(GL_TEXTURE_2D, tex);
591 		glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
592 		glGetTexParameterfv_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test1);
593 		glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
594 		glGetTexParameterfv_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test2);
595 		glDeleteTextures_fp(1, &tex);
596 		if (test1 != 1 || test2 != 2)
597 		{
598 			Con_SafePrintf("driver-locked @ %.1f\n", test1);
599 		}
600 		else
601 		{
602 		_skiptest:
603 			glGetFloatv_fp(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max_anisotropy);
604 			if (gl_max_anisotropy < 2)
605 				Con_SafePrintf("broken\n");
606 			else	Con_SafePrintf("found, max %.1f\n", gl_max_anisotropy);
607 		}
608 	}
609 	else
610 	{
611 		Con_SafePrintf("not found\n");
612 	}
613 }
614 
CheckNonPowerOfTwoTextures(void)615 static void CheckNonPowerOfTwoTextures (void)
616 {
617 	gl_tex_NPOT = have_NPOT = false;
618 	if (GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_non_power_of_two"))
619 	{
620 		have_NPOT = true;
621 		Con_SafePrintf("Found ARB_texture_non_power_of_two\n");
622 		if (!gl_texture_NPOT.integer) {
623 			Con_SafePrintf("ignoring texture_NPOT (cvar disabled)\n");
624 		}
625 		else {
626 			gl_tex_NPOT = true;
627 		}
628 	}
629 	else
630 	{
631 		Con_SafePrintf("GL_ARB_texture_non_power_of_two not found\n");
632 	}
633 }
634 
CheckStencilBuffer(void)635 static void CheckStencilBuffer (void)
636 {
637 	have_stencil = !!vid_attribs.stencil;
638 }
639 
640 
DOSGL_Init(void)641 static void DOSGL_Init (void)
642 {
643 	int rc = -1;
644 
645 	if (rc < 0) rc = DMESA_LoadAPI (gl_handle);
646 	if (rc < 0) rc = SAGE_LoadAPI (gl_handle);
647 	if (rc < 0) rc = FXMESA_LoadAPI (gl_handle);
648 	if (rc < 0) {
649 		Sys_Error("Unable to find a supported API for DOSGL.");
650 	}
651 	Con_SafePrintf("DOSGL: driver using %s API.\n", DOSGL_APIName());
652 }
653 
654 #ifdef GL_DLSYM
GL_OpenLibrary(const char * name)655 static qboolean GL_OpenLibrary (const char *name)
656 {
657 	Con_SafePrintf("Loading OpenGL library %s\n", name);
658 
659 	// open the library
660 	if (!(gl_handle = Sys_dlopen(name, false)))
661 	{
662 		Con_SafePrintf("Unable to dlopen %s\n", name);
663 		return false;
664 	}
665 
666 	return true;
667 }
668 
GL_CloseLibrary(void)669 static void GL_CloseLibrary (void)
670 {
671 	// clear the DOSGL function pointers
672 	DOSGL_InitCtx  = NULL;
673 	DOSGL_Shutdown = NULL;
674 	DOSGL_EndFrame = NULL;
675 	DOSGL_GetProcAddress = NULL;
676 	DOSGL_APIName = NULL;
677 
678 	// free the library
679 	if (gl_handle != NULL)
680 	{
681 		Sys_dlclose(gl_handle);
682 		gl_handle = NULL;
683 	}
684 }
685 #endif	/* GL_DLSYM */
686 
687 
688 #ifdef GL_DLSYM
GL_Init_Functions(void)689 static void GL_Init_Functions (void)
690 {
691 #define GL_FUNCTION(ret, func, params)				\
692     do {							\
693 	func##_fp = (func##_f) Sys_dlsym(gl_handle, "_"#func);	\
694 	if (func##_fp == NULL)					\
695 		Sys_Error("%s not found in GL library", "_"#func);	\
696     } while (0);
697 #define GL_FUNCTION_OPT(ret, func, params)
698 #include "gl_func.h"
699 }
700 #endif	/* GL_DLSYM */
701 
GL_ResetFunctions(void)702 static void GL_ResetFunctions (void)
703 {
704 #ifdef	GL_DLSYM
705 #define GL_FUNCTION(ret, func, params)	\
706 	func##_fp = NULL;
707 #endif
708 #define GL_FUNCTION_OPT(ret, func, params) \
709 	func##_fp = NULL;
710 #include "gl_func.h"
711 
712 	have_stencil = false;
713 	gl_mtexable = false;
714 	have_mtex = false;
715 	have8bit = false;
716 	is8bit = false;
717 	have_NPOT = false;
718 	gl_tex_NPOT = false;
719 }
720 
721 /*
722 ===============
723 GL_Init
724 ===============
725 */
GL_Init(void)726 static void GL_Init (void)
727 {
728 #ifdef GL_DLSYM
729 	// initialize gl function pointers
730 	GL_Init_Functions();
731 #endif
732 
733 	// collect the visual attributes
734 	memset (&vid_attribs, 0, sizeof(attributes_t));
735 	glGetIntegerv_fp(GL_RED_BITS, &vid_attribs.red);
736 	glGetIntegerv_fp(GL_GREEN_BITS, &vid_attribs.green);
737 	glGetIntegerv_fp(GL_BLUE_BITS, &vid_attribs.blue);
738 	glGetIntegerv_fp(GL_ALPHA_BITS, &vid_attribs.alpha);
739 	glGetIntegerv_fp(GL_DEPTH_BITS, &vid_attribs.depth);
740 	glGetIntegerv_fp(GL_STENCIL_BITS, &vid_attribs.stencil);
741 	Con_SafePrintf ("R:%d G:%d B:%d A:%d, Z:%d, S:%d\n",
742 			vid_attribs.red, vid_attribs.green, vid_attribs.blue, vid_attribs.alpha,
743 			vid_attribs.depth, vid_attribs.stencil);
744 
745 	gl_vendor = (const char *)glGetString_fp (GL_VENDOR);
746 	Con_SafePrintf ("GL_VENDOR: %s\n", gl_vendor);
747 	gl_renderer = (const char *)glGetString_fp (GL_RENDERER);
748 	Con_SafePrintf ("GL_RENDERER: %s\n", gl_renderer);
749 
750 	gl_version = (const char *)glGetString_fp (GL_VERSION);
751 	Con_SafePrintf ("GL_VERSION: %s\n", gl_version);
752 	gl_extensions = (const char *)glGetString_fp (GL_EXTENSIONS);
753 	Con_SafeDPrintf ("GL_EXTENSIONS: %s\n", gl_extensions);
754 
755 	glGetIntegerv_fp(GL_MAX_TEXTURE_SIZE, &gl_max_size);
756 	if (gl_max_size < 256)	// Refuse to work when less than 256
757 		Sys_Error ("hardware capable of min. 256k opengl texture size needed");
758 	Con_SafePrintf("OpenGL max.texture size: %i\n", (int) gl_max_size);
759 
760 	is_3dfx = false;
761 	if (!q_strncasecmp(gl_renderer, "3dfx", 4)	  ||
762 	    !q_strncasecmp(gl_renderer, "SAGE Glide", 10) ||
763 	    !q_strncasecmp(gl_renderer, "Glide ", 6)	  || /* possible with Mesa 3.x/4.x/5.0.x */
764 	    !q_strncasecmp(gl_renderer, "Mesa Glide", 10))
765 	{
766 		Con_SafePrintf("3dfx Voodoo found\n");
767 		is_3dfx = true;
768 	}
769 
770 	CheckMultiTextureExtensions();
771 	CheckAnisotropyExtensions();
772 	CheckNonPowerOfTwoTextures();
773 	CheckStencilBuffer();
774 
775 	glClearColor_fp (1,0,0,0);
776 	glCullFace_fp(GL_FRONT);
777 	glEnable_fp(GL_TEXTURE_2D);
778 
779 	glEnable_fp(GL_ALPHA_TEST);
780 	glAlphaFunc_fp(GL_GREATER, 0.632); // 1 - e^-1 : replaced 0.666 to avoid clipping of smaller fonts/graphics
781 #if 0 /* causes side effects at least in 16 bpp.  */
782 	/* Get rid of Z-fighting for textures by offsetting the
783 	 * drawing of entity models compared to normal polygons.
784 	 * (See: R_DrawBrushModel.)
785 	 * (Only works if gl_ztrick is turned off) */
786 	glPolygonOffset_fp(0.05f, 25.0f);
787 #endif /* #if 0 */
788 	glPolygonMode_fp (GL_FRONT_AND_BACK, GL_FILL);
789 	glShadeModel_fp (GL_FLAT);
790 
791 	glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
792 	glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
793 
794 	glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
795 	glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
796 
797 	glBlendFunc_fp (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
798 
799 //	glTexEnvf_fp(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
800 	glTexEnvf_fp(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
801 }
802 
803 /*
804 =================
805 GL_BeginRendering
806 =================
807 */
GL_BeginRendering(int * x,int * y,int * width,int * height)808 void GL_BeginRendering (int *x, int *y, int *width, int *height)
809 {
810 	*x = *y = 0;
811 	*width = WRWidth;
812 	*height = WRHeight;
813 }
814 
815 
GL_EndRendering(void)816 void GL_EndRendering (void)
817 {
818 	if (!scr_skipupdate)
819 	{
820 		DOSGL_EndFrame();
821 	}
822 }
823 
824 
825 const int ColorIndex[16] = {
826 	0, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 199, 207, 223, 231
827 };
828 
829 const unsigned int ColorPercent[16] = {
830 	25, 51, 76, 102, 114, 127, 140, 153, 165, 178, 191, 204, 216, 229, 237, 247
831 };
832 
833 #define	INVERSE_PALNAME	"gfx/invpal.lmp"
ConvertTrueColorToPal(const unsigned char * true_color,const unsigned char * palette)834 static int ConvertTrueColorToPal (const unsigned char *true_color, const unsigned char *palette)
835 {
836 	int	i;
837 	long	min_dist;
838 	int	min_index;
839 	long	r, g, b;
840 
841 	min_dist = 256 * 256 + 256 * 256 + 256 * 256;
842 	min_index = -1;
843 	r = (long) true_color[0];
844 	g = (long) true_color[1];
845 	b = (long) true_color[2];
846 
847 	for (i = 0; i < 256; i++)
848 	{
849 		long palr, palg, palb, dist;
850 		long dr, dg, db;
851 
852 		palr = palette[3*i];
853 		palg = palette[3*i+1];
854 		palb = palette[3*i+2];
855 		dr = palr - r;
856 		dg = palg - g;
857 		db = palb - b;
858 		dist = dr * dr + dg * dg + db * db;
859 		if (dist < min_dist)
860 		{
861 			min_dist = dist;
862 			min_index = i;
863 		}
864 	}
865 	return min_index;
866 }
867 
VID_CreateInversePalette(const unsigned char * palette)868 static void VID_CreateInversePalette (const unsigned char *palette)
869 {
870 	long	r, g, b;
871 	long	idx = 0;
872 	unsigned char	true_color[3];
873 
874 	Con_SafePrintf ("Creating inverse palette\n");
875 
876 	for (r = 0; r < (1 << INVERSE_PAL_R_BITS); r++)
877 	{
878 		for (g = 0; g < (1 << INVERSE_PAL_G_BITS); g++)
879 		{
880 			for (b = 0; b < (1 << INVERSE_PAL_B_BITS); b++)
881 			{
882 				true_color[0] = (unsigned char)(r << (8 - INVERSE_PAL_R_BITS));
883 				true_color[1] = (unsigned char)(g << (8 - INVERSE_PAL_G_BITS));
884 				true_color[2] = (unsigned char)(b << (8 - INVERSE_PAL_B_BITS));
885 				inverse_pal[idx] = ConvertTrueColorToPal(true_color, palette);
886 				idx++;
887 			}
888 		}
889 	}
890 
891 	FS_CreatePath(FS_MakePath(FS_USERDIR, NULL, INVERSE_PALNAME));
892 	FS_WriteFile (INVERSE_PALNAME, inverse_pal, INVERSE_PAL_SIZE);
893 }
894 
VID_InitPalette(const unsigned char * palette)895 static void VID_InitPalette (const unsigned char *palette)
896 {
897 	const unsigned char	*pal;
898 	unsigned short	r, g, b;
899 	unsigned short	i, p, c;
900 	unsigned int	v, *table;
901 	int		mark;
902 
903 #if ENDIAN_RUNTIME_DETECT
904 	switch (host_byteorder)
905 	{
906 	case BIG_ENDIAN:	/* R G B A */
907 		MASK_r	=	0xff000000;
908 		MASK_g	=	0x00ff0000;
909 		MASK_b	=	0x0000ff00;
910 		MASK_a	=	0x000000ff;
911 		SHIFT_r	=	24;
912 		SHIFT_g	=	16;
913 		SHIFT_b	=	8;
914 		SHIFT_a	=	0;
915 		break;
916 	case LITTLE_ENDIAN:	/* A B G R */
917 		MASK_r	=	0x000000ff;
918 		MASK_g	=	0x0000ff00;
919 		MASK_b	=	0x00ff0000;
920 		MASK_a	=	0xff000000;
921 		SHIFT_r	=	0;
922 		SHIFT_g	=	8;
923 		SHIFT_b	=	16;
924 		SHIFT_a	=	24;
925 		break;
926 	default:
927 		break;
928 	}
929 	MASK_rgb	=	(MASK_r|MASK_g|MASK_b);
930 #endif	/* ENDIAN_RUNTIME_DETECT */
931 
932 //
933 // 8 8 8 encoding
934 //
935 	pal = palette;
936 	table = d_8to24table;
937 	for (i = 0; i < 256; i++)
938 	{
939 		r = pal[0];
940 		g = pal[1];
941 		b = pal[2];
942 		pal += 3;
943 
944 		v = (255 << SHIFT_a) + (r << SHIFT_r) + (g << SHIFT_g) + (b << SHIFT_b);
945 		*table++ = v;
946 	}
947 
948 	d_8to24table[255] &= MASK_rgb;	// 255 is transparent
949 
950 	pal = palette;
951 	table = d_8to24TranslucentTable;
952 
953 	for (i = 0; i < 16; i++)
954 	{
955 		c = ColorIndex[i] * 3;
956 
957 		r = pal[c];
958 		g = pal[c + 1];
959 		b = pal[c + 2];
960 
961 		for (p = 0; p < 16; p++)
962 		{
963 			v = (ColorPercent[15 - p] << SHIFT_a) + (r << SHIFT_r) + (g << SHIFT_g) + (b << SHIFT_b);
964 			*table++ = v;
965 
966 			RTint[i*16 + p] = ((float)r) / ((float)ColorPercent[15-p]);
967 			GTint[i*16 + p] = ((float)g) / ((float)ColorPercent[15-p]);
968 			BTint[i*16 + p] = ((float)b) / ((float)ColorPercent[15-p]);
969 		}
970 	}
971 
972 	// Initialize the palettized textures data
973 	mark = Hunk_LowMark ();
974 	inverse_pal = (unsigned char *) FS_LoadHunkFile (INVERSE_PALNAME, NULL);
975 	if (inverse_pal != NULL && fs_filesize != INVERSE_PAL_SIZE)
976 	{
977 		Hunk_FreeToLowMark (mark);
978 		inverse_pal = NULL;
979 	}
980 	if (inverse_pal == NULL)
981 	{
982 		inverse_pal = (unsigned char *) Hunk_AllocName (INVERSE_PAL_SIZE + 1, INVERSE_PALNAME);
983 		VID_CreateInversePalette (palette);
984 	}
985 }
986 
VID_SetPalette(const unsigned char * palette)987 void VID_SetPalette (const unsigned char *palette)
988 {
989 // nothing to do
990 }
991 
992 
993 /*
994 ===================================================================
995 
996 MAIN WINDOW
997 
998 ===================================================================
999 */
1000 
1001 /*
1002 ================
1003 ClearAllStates
1004 ================
1005 */
ClearAllStates(void)1006 static void ClearAllStates (void)
1007 {
1008 	Key_ClearStates ();
1009 	IN_ClearStates ();
1010 }
1011 
1012 /*
1013 =================
1014 VID_ChangeVideoMode
1015 intended only as a callback for VID_Restart_f
1016 =================
1017 */
VID_ChangeVideoMode(int newmode)1018 static void VID_ChangeVideoMode (int newmode)
1019 {
1020 	int	temp;
1021 
1022 	temp = scr_disabled_for_loading;
1023 	scr_disabled_for_loading = true;
1024 
1025 	// restore gamma, reset gamma function pointers
1026 	VID_ShutdownGamma();
1027 	CDAudio_Pause ();
1028 	BGM_Pause ();
1029 	S_ClearBuffer ();
1030 
1031 	// Unload all textures and reset texture counts
1032 	D_ClearOpenGLTextures(0);
1033 	memset (lightmap_textures, 0, sizeof(lightmap_textures));
1034 
1035 	// reset all opengl function pointers
1036 	GL_ResetFunctions();
1037 
1038 	// Avoid re-registering commands and re-allocating memory
1039 	draw_reinit = true;
1040 
1041 	// temporarily disable input devices
1042 	IN_DeactivateMouse();
1043 
1044 	// Kill device and rendering contexts
1045 	DOSGL_Shutdown();
1046 
1047 	VID_SetMode (newmode);
1048 
1049 	// Reload graphics wad file (Draw_PicFromWad writes glpic_t data (sizes,
1050 	// texnums) right on top of the original pic data, so the pic data will
1051 	// be dirty after gl textures are loaded the first time; we need to load
1052 	// a clean version)
1053 	W_LoadWadFile ("gfx.wad");
1054 
1055 	// Initialize extensions and default OpenGL parameters
1056 	GL_Init();
1057 	VID_InitGamma();
1058 	VID_Init8bitPalette();
1059 
1060 	// Reload pre-map pics, fonts, console, etc
1061 	Draw_Init();
1062 	SCR_Init();
1063 	// R_Init() stuff:
1064 	R_InitParticleTexture();
1065 	R_InitExtraTextures ();
1066 #if defined(H2W)
1067 	R_InitNetgraphTexture();
1068 #endif	/* H2W */
1069 	Sbar_Init();
1070 	vid.recalc_refdef = 1;
1071 
1072 	ClearAllStates ();
1073 	CDAudio_Resume ();
1074 	BGM_Resume ();
1075 
1076 	// Reload model textures and player skins
1077 	Mod_ReloadTextures();
1078 	// rebuild the lightmaps
1079 	GL_BuildLightmaps();
1080 	// finished reloading all images
1081 	draw_reinit = false;
1082 	scr_disabled_for_loading = temp;
1083 	// apply our gamma
1084 	VID_ShiftPalette(NULL);
1085 }
1086 
VID_Restart_f(void)1087 static void VID_Restart_f (void)
1088 {
1089 	if (vid_mode.integer < 0 || vid_mode.integer >= nummodes)
1090 	{
1091 		Con_Printf ("Bad video mode %d\n", vid_mode.integer);
1092 		Cvar_SetValueQuick (&vid_mode, vid_modenum);
1093 		return;
1094 	}
1095 
1096 	Con_Printf ("Re-initializing video:\n");
1097 	VID_ChangeVideoMode (vid_mode.integer);
1098 }
1099 
VID_PrepareModes(void)1100 static void VID_PrepareModes (void)
1101 {
1102 	int	i;
1103 
1104 	nummodes = 0;
1105 
1106 	// Add the standart 4:3 modes to the windowed modes list
1107 	// In an unlikely case that we receive no fullscreen modes,
1108 	// this will be our modes list (kind of...)
1109 	for (i = 0; i < (int)MAX_STDMODES; i++)
1110 	{
1111 		modelist[nummodes].width = std_modes[i].width;
1112 		modelist[nummodes].height = std_modes[i].height;
1113 		modelist[nummodes].halfscreen = 0;
1114 		modelist[nummodes].bpp = 16;
1115 		q_snprintf (modelist[nummodes].modedesc, MAX_DESC,
1116 				"%d x %d", std_modes[i].width, std_modes[i].height);
1117 		nummodes++;
1118 	}
1119 
1120 	vid_maxwidth = modelist[nummodes-1].width;
1121 	vid_maxheight = modelist[nummodes-1].height;
1122 	vid_default = RES_640X480;
1123 
1124 	Cvar_SetValueQuick (&vid_config_glx, modelist[vid_default].width);
1125 	Cvar_SetValueQuick (&vid_config_gly, modelist[vid_default].height);
1126 }
1127 
VID_ListModes_f(void)1128 static void VID_ListModes_f (void)
1129 {
1130 	int	i;
1131 
1132 	Con_Printf ("Maximum allowed mode: %d x %d\n", vid_maxwidth, vid_maxheight);
1133 	Con_Printf ("Supported modes:\n");
1134 	for (i = 0; i < nummodes; i++)
1135 		Con_Printf ("%2d:  %d x %d\n", i, modelist[i].width, modelist[i].height);
1136 }
1137 
VID_NumModes_f(void)1138 static void VID_NumModes_f (void)
1139 {
1140 	Con_Printf ("%d video modes in current list\n", nummodes);
1141 }
1142 
1143 /*
1144 ===================
1145 VID_Init
1146 ===================
1147 */
VID_Init(const unsigned char * palette)1148 void	VID_Init (const unsigned char *palette)
1149 {
1150 	static char fxmesa_env_multitex[32] = "FX_DONT_FAKE_MULTITEX=1";
1151 	static char fxglide_env_nosplash[32] = "FX_GLIDE_NO_SPLASH=1";
1152 	int	i, temp, width, height;
1153 	const char	*read_vars[] = {
1154 				"vid_config_gl8bit",
1155 				"vid_config_glx",
1156 				"vid_config_gly",
1157 				"vid_config_consize",
1158 				"gl_texture_NPOT",
1159 				"gl_multitexture",
1160 				"gl_lightmapfmt" };
1161 #define num_readvars	( sizeof(read_vars)/sizeof(read_vars[0]) )
1162 
1163 	Cvar_RegisterVariable (&vid_config_gl8bit);
1164 	Cvar_RegisterVariable (&vid_config_gly);
1165 	Cvar_RegisterVariable (&vid_config_glx);
1166 	Cvar_RegisterVariable (&vid_config_consize);
1167 	Cvar_RegisterVariable (&vid_mode);
1168 	Cvar_RegisterVariable (&_enable_mouse);
1169 	Cvar_RegisterVariable (&gl_texture_NPOT);
1170 	Cvar_RegisterVariable (&gl_lightmapfmt);
1171 	Cvar_RegisterVariable (&gl_multitexture);
1172 	Cvar_RegisterVariable (&vid_nopageflip);
1173 	Cvar_RegisterVariable (&_vid_wait_override);
1174 	Cvar_RegisterVariable (&_vid_default_mode);
1175 
1176 	Cmd_AddCommand ("vid_listmodes", VID_ListModes_f);
1177 	Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
1178 	Cmd_AddCommand ("vid_restart", VID_Restart_f);
1179 
1180 	VID_InitPalette (palette);
1181 
1182 	vid.numpages = 2;
1183 
1184 	// don't let fxMesa cheat multitexturing
1185 	putenv (fxmesa_env_multitex);
1186 	// disable the 3dfx splash screen.
1187 	putenv (fxglide_env_nosplash);
1188 
1189 #ifdef GL_DLSYM
1190 	i = COM_CheckParm("-gllibrary");
1191 	if (i == 0)
1192 		i = COM_CheckParm ("-g");
1193 	if (i && i < com_argc - 1)
1194 		gl_library = com_argv[i+1];
1195 	else
1196 		gl_library = "gl.dxe";
1197 
1198 	// load the opengl library
1199 	if (!GL_OpenLibrary(gl_library))
1200 		Sys_Error ("Unable to load GL library %s", gl_library);
1201 #endif
1202 	DOSGL_Init();
1203 
1204 	i = COM_CheckParm("-bpp");
1205 	if (i && i < com_argc-1)
1206 	{
1207 		bpp = atoi(com_argv[i+1]);
1208 	}
1209 
1210 	// prepare the modelists, find the actual modenum for vid_default
1211 	VID_PrepareModes();
1212 
1213 	// set vid_mode to our safe default first
1214 	Cvar_SetValueQuick (&vid_mode, vid_default);
1215 
1216 	// perform an early read of config.cfg
1217 	CFG_ReadCvars (read_vars, num_readvars);
1218 
1219 	width = vid_config_glx.integer;
1220 	height = vid_config_gly.integer;
1221 
1222 	if (vid_config_consize.integer != width)
1223 		vid_conscale = true;
1224 
1225 	// user is always right ...
1226 	i = COM_CheckParm("-width");
1227 	if (i && i < com_argc-1)
1228 	{	// FIXME: this part doesn't know about a disaster case
1229 		// like we aren't reported any fullscreen modes.
1230 		width = atoi(com_argv[i+1]);
1231 
1232 		i = COM_CheckParm("-height");
1233 		if (i && i < com_argc-1)
1234 			height = atoi(com_argv[i+1]);
1235 		else	// proceed with 4/3 ratio
1236 			height = 3 * width / 4;
1237 	}
1238 
1239 	// user requested a mode either from the config or from the
1240 	// command line
1241 	// scan existing modes to see if this is already available
1242 	// if not, add this as the last "valid" video mode and set
1243 	// vid_mode to it only if it doesn't go beyond vid_maxwidth
1244 	i = 0;
1245 	while (i < nummodes)
1246 	{
1247 		if (modelist[i].width == width && modelist[i].height == height)
1248 			break;
1249 		i++;
1250 	}
1251 	if (i < nummodes)
1252 	{
1253 		Cvar_SetValueQuick (&vid_mode, i);
1254 	}
1255 	else if ( (width <= vid_maxwidth && width >= MIN_WIDTH &&
1256 		   height <= vid_maxheight && height >= MIN_HEIGHT) ||
1257 		  COM_CheckParm("-force") )
1258 	{
1259 		modelist[nummodes].width = width;
1260 		modelist[nummodes].height = height;
1261 		modelist[nummodes].halfscreen = 0;
1262 		modelist[nummodes].bpp = 16;
1263 		q_snprintf (modelist[nummodes].modedesc, MAX_DESC, "%d x %d (user mode)", width, height);
1264 		Cvar_SetValueQuick (&vid_mode, nummodes);
1265 		nummodes++;
1266 	}
1267 	else
1268 	{
1269 		Con_SafePrintf ("ignoring invalid -width and/or -height arguments\n");
1270 	}
1271 
1272 	if (!vid_conscale)
1273 		Cvar_SetValueQuick (&vid_config_consize, width);
1274 
1275 	// This will display a bigger hud and readable fonts at high
1276 	// resolutions. The fonts will be somewhat distorted, though
1277 	i = COM_CheckParm("-conwidth");
1278 	if (i != 0 && i < com_argc-1)
1279 		i = atoi(com_argv[i + 1]);
1280 	else	i = vid_config_consize.integer;
1281 	if (i < MIN_WIDTH)	i = MIN_WIDTH;
1282 	else if (i > width)	i = width;
1283 	Cvar_SetValueQuick(&vid_config_consize, i);
1284 	if (vid_config_consize.integer != width)
1285 		vid_conscale = true;
1286 
1287 	if (COM_CheckParm("-paltex"))
1288 		Cvar_SetQuick (&vid_config_gl8bit, "1");
1289 
1290 	vid.maxwarpwidth = WARP_WIDTH;
1291 	vid.maxwarpheight = WARP_HEIGHT;
1292 	vid.colormap = host_colormap;
1293 	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
1294 
1295 	temp = scr_disabled_for_loading;
1296 	scr_disabled_for_loading = true;
1297 	// disable printing to terminal
1298 	Cvar_SetROM ("sys_nostdout", "1");
1299 	//set the mode
1300 	VID_SetMode (vid_mode.integer);
1301 	ClearAllStates ();
1302 
1303 	GL_SetupLightmapFmt();
1304 	GL_Init ();
1305 	VID_InitGamma();
1306 	VID_Init8bitPalette();
1307 
1308 	// lock the early-read cvars until Host_Init is finished
1309 	for (i = 0; i < (int)num_readvars; i++)
1310 		Cvar_LockVar (read_vars[i]);
1311 
1312 	vid_initialized = true;
1313 	scr_disabled_for_loading = temp;
1314 	vid.recalc_refdef = 1;
1315 
1316 	Con_SafePrintf ("Video initialized.\n");
1317 
1318 	vid_menudrawfn = VID_MenuDraw;
1319 	vid_menukeyfn = VID_MenuKey;
1320 }
1321 
1322 
VID_Shutdown(void)1323 void	VID_Shutdown (void)
1324 {
1325 	VID_ShutdownGamma();
1326 	if (DOSGL_Shutdown)
1327 		DOSGL_Shutdown ();
1328 #ifdef GL_DLSYM
1329 	GL_CloseLibrary();
1330 #endif
1331 }
1332 
1333 
1334 /*
1335 ================
1336 VID_ToggleFullscreen
1337 Handles switching between fullscreen/windowed modes
1338 and brings the mouse to a proper state afterwards
1339 ================
1340 */
VID_ToggleFullscreen(void)1341 void VID_ToggleFullscreen (void)
1342 {
1343 	// always fullscreen in DOS
1344 }
1345 
1346 
1347 #ifndef H2W /* unused in hexenworld */
D_ShowLoadingSize(void)1348 void D_ShowLoadingSize (void)
1349 {
1350 #if defined(DRAW_PROGRESSBARS)
1351 	int cur_perc;
1352 	static int prev_perc;
1353 
1354 	if (!vid_initialized)
1355 		return;
1356 
1357 	cur_perc = loading_stage * 100;
1358 	if (total_loading_size)
1359 		cur_perc += current_loading_size * 100 / total_loading_size;
1360 	if (cur_perc == prev_perc)
1361 		return;
1362 	prev_perc = cur_perc;
1363 
1364 	glDrawBuffer_fp (GL_FRONT);
1365 
1366 	SCR_DrawLoading();
1367 
1368 	glFlush_fp();
1369 
1370 	glDrawBuffer_fp (GL_BACK);
1371 #endif	/* DRAW_PROGRESSBARS */
1372 }
1373 #endif
1374 
1375 
1376 //========================================================
1377 // Video menu stuff
1378 //========================================================
1379 
1380 static int	vid_menunum;
1381 static int	vid_cursor;
1382 static qboolean	need_apply;
1383 static qboolean	vid_menu_firsttime = true;
1384 
1385 enum {
1386 	VID_RESOLUTION,
1387 	VID_MULTITEXTURE,
1388 	VID_NPOT,
1389 	VID_PALTEX,
1390 	VID_BLANKLINE,	// spacer line
1391 	VID_RESET,
1392 	VID_APPLY,
1393 	VID_ITEMS
1394 };
1395 
M_DrawYesNo(int x,int y,int on,int white)1396 static void M_DrawYesNo (int x, int y, int on, int white)
1397 {
1398 	if (on)
1399 	{
1400 		if (white)
1401 			M_PrintWhite (x, y, "yes");
1402 		else
1403 			M_Print (x, y, "yes");
1404 	}
1405 	else
1406 	{
1407 		if (white)
1408 			M_PrintWhite (x, y, "no");
1409 		else
1410 			M_Print (x, y, "no");
1411 	}
1412 }
1413 
1414 /*
1415 ================
1416 VID_MenuDraw
1417 ================
1418 */
VID_MenuDraw(void)1419 static void VID_MenuDraw (void)
1420 {
1421 	ScrollTitle("gfx/menu/title7.lmp");
1422 
1423 	if (vid_menu_firsttime)
1424 	{	// settings for entering the menu first time
1425 		vid_menunum = vid_modenum;
1426 		vid_cursor = 0;
1427 		vid_menu_firsttime = false;
1428 	}
1429 
1430 	need_apply = (vid_menunum != vid_modenum) ||
1431 			(have_mtex && (gl_mtexable != !!gl_multitexture.integer)) ||
1432 			(have_NPOT && (gl_tex_NPOT != !!gl_texture_NPOT.integer)) ||
1433 			(have8bit && (is8bit != !!vid_config_gl8bit.integer));
1434 
1435 	M_Print (76, 92 + 8*VID_RESOLUTION, "Resolution: ");
1436 	if (vid_menunum == vid_modenum)
1437 		M_PrintWhite (76+12*8, 92 + 8*VID_RESOLUTION, modelist[vid_menunum].modedesc);
1438 	else
1439 		M_Print (76+12*8, 92 + 8*VID_RESOLUTION, modelist[vid_menunum].modedesc);
1440 
1441 	M_Print (76, 92 + 8*VID_MULTITEXTURE, "Multitexturing:");
1442 	if (have_mtex)
1443 		M_DrawYesNo (76+16*8, 92 + 8*VID_MULTITEXTURE, gl_multitexture.integer, (gl_mtexable == !!gl_multitexture.integer));
1444 	else
1445 		M_PrintWhite (76+16*8, 92 + 8*VID_MULTITEXTURE, "Not found");
1446 
1447 	M_Print (76, 92 + 8*VID_NPOT, "NPOT textures :");
1448 	if (have_NPOT)
1449 		M_DrawYesNo (76+16*8, 92 + 8*VID_NPOT, gl_texture_NPOT.integer, (gl_tex_NPOT == !!gl_texture_NPOT.integer));
1450 	else
1451 		M_PrintWhite (76+16*8, 92 + 8*VID_NPOT, "Not found");
1452 
1453 	M_Print (76, 92 + 8*VID_PALTEX, "8 bit textures:");
1454 	if (have8bit)
1455 		M_DrawYesNo (76+16*8, 92 + 8*VID_PALTEX, vid_config_gl8bit.integer, (is8bit == !!vid_config_gl8bit.integer));
1456 	else
1457 		M_PrintWhite (76+16*8, 92 + 8*VID_PALTEX, "Not found");
1458 
1459 	if (need_apply)
1460 	{
1461 		M_Print (76, 92 + 8*VID_RESET, "RESET CHANGES");
1462 		M_Print (76, 92 + 8*VID_APPLY, "APPLY CHANGES");
1463 	}
1464 
1465 	M_DrawCharacter (64, 92 + vid_cursor*8, 12+((int)(realtime*4)&1));
1466 }
1467 
1468 /*
1469 ================
1470 VID_MenuKey
1471 ================
1472 */
VID_MenuKey(int key)1473 static void VID_MenuKey (int key)
1474 {
1475 	switch (key)
1476 	{
1477 	case K_ESCAPE:
1478 		vid_cursor = 0;
1479 		M_Menu_Options_f ();
1480 		break;
1481 
1482 	case K_UPARROW:
1483 		S_LocalSound ("raven/menu1.wav");
1484 		vid_cursor--;
1485 		if (vid_cursor < 0)
1486 		{
1487 			vid_cursor = (need_apply) ? VID_ITEMS-1 : VID_BLANKLINE-1;
1488 		}
1489 		else if (vid_cursor == VID_BLANKLINE)
1490 		{
1491 			vid_cursor--;
1492 		}
1493 		break;
1494 
1495 	case K_DOWNARROW:
1496 		S_LocalSound ("raven/menu1.wav");
1497 		vid_cursor++;
1498 		if (vid_cursor >= VID_ITEMS)
1499 		{
1500 			vid_cursor = 0;
1501 			break;
1502 		}
1503 		if (vid_cursor >= VID_BLANKLINE)
1504 		{
1505 			if (need_apply)
1506 			{
1507 				if (vid_cursor == VID_BLANKLINE)
1508 					vid_cursor++;
1509 			}
1510 			else
1511 			{
1512 				vid_cursor = 0;
1513 			}
1514 		}
1515 		break;
1516 
1517 	case K_ENTER:
1518 		switch (vid_cursor)
1519 		{
1520 		case VID_RESET:
1521 			vid_menunum = vid_modenum;
1522 			Cvar_SetValueQuick (&vid_config_gl8bit, is8bit);
1523 			vid_cursor = 0;
1524 			break;
1525 		case VID_APPLY:
1526 			if (need_apply)
1527 			{
1528 				Cvar_SetValueQuick(&vid_mode, vid_menunum);
1529 				VID_Restart_f();
1530 			}
1531 			vid_cursor = 0;
1532 			break;
1533 		}
1534 		return;
1535 
1536 	case K_LEFTARROW:
1537 		switch (vid_cursor)
1538 		{
1539 		case VID_RESOLUTION:
1540 			S_LocalSound ("raven/menu1.wav");
1541 			vid_menunum--;
1542 			if (vid_menunum < 0)
1543 				vid_menunum = 0;
1544 			break;
1545 		case VID_MULTITEXTURE:
1546 			if (have_mtex)
1547 				Cvar_SetQuick (&gl_multitexture, gl_multitexture.integer ? "0" : "1");
1548 			break;
1549 		case VID_NPOT:
1550 			if (have_NPOT)
1551 				Cvar_SetQuick (&gl_texture_NPOT, gl_texture_NPOT.integer ? "0" : "1");
1552 			break;
1553 		case VID_PALTEX:
1554 			if (have8bit)
1555 				Cvar_SetQuick (&vid_config_gl8bit, vid_config_gl8bit.integer ? "0" : "1");
1556 			break;
1557 		}
1558 		return;
1559 
1560 	case K_RIGHTARROW:
1561 		switch (vid_cursor)
1562 		{
1563 		case VID_RESOLUTION:
1564 			S_LocalSound ("raven/menu1.wav");
1565 			vid_menunum++;
1566 			if (vid_menunum >= nummodes)
1567 				vid_menunum = nummodes - 1;
1568 			break;
1569 		case VID_MULTITEXTURE:
1570 			if (have_mtex)
1571 				Cvar_SetQuick (&gl_multitexture, gl_multitexture.integer ? "0" : "1");
1572 			break;
1573 		case VID_NPOT:
1574 			if (have_NPOT)
1575 				Cvar_SetQuick (&gl_texture_NPOT, gl_texture_NPOT.integer ? "0" : "1");
1576 			break;
1577 		case VID_PALTEX:
1578 			if (have8bit)
1579 				Cvar_SetQuick (&vid_config_gl8bit, vid_config_gl8bit.integer ? "0" : "1");
1580 			break;
1581 		}
1582 		return;
1583 
1584 	default:
1585 		break;
1586 	}
1587 }
1588 
1589