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