1 /*
2 * gl_vidnt.c -- NT GL vid component
3 * $Id: gl_vidnt.c 6029 2018-04-04 05:56:12Z sezero $
4 *
5 * Copyright (C) 1996-1997 Id Software, Inc.
6 * Copyright (C) 1997-1998 Raven Software Corp.
7 * Copyright (C) 2005-2016 O.Sezer <sezero@users.sourceforge.net>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 * See the GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #define __GL_FUNC_EXTERN
26
27 #include "quakedef.h"
28 #include "winquake.h"
29 #include <mmsystem.h>
30 #include "cfgfile.h"
31 #include "bgmusic.h"
32 #include "cdaudio.h"
33 #include "resource.h"
34 #include "wgl_func.h"
35
36 #define WARP_WIDTH 320
37 #define WARP_HEIGHT 200
38 #define MAXWIDTH 10000
39 #define MAXHEIGHT 10000
40 #define MIN_WIDTH 320
41 //#define MIN_HEIGHT 200
42 #define MIN_HEIGHT 240
43 #define MAX_DESC 33
44 #define MAX_NUMBPP 8
45
46 typedef struct {
47 modestate_t type;
48 int width;
49 int height;
50 int modenum;
51 int dib;
52 int fullscreen;
53 int bpp;
54 int halfscreen;
55 char modedesc[MAX_DESC];
56 } vmode_t;
57
58 typedef struct {
59 int width;
60 int height;
61 } stdmode_t;
62
63 #define RES_640X480 3
64 static const stdmode_t std_modes[] = {
65 // NOTE: keep this list in order
66 {320, 240}, // 0
67 {400, 300}, // 1
68 {512, 384}, // 2
69 {640, 480}, // 3 == RES_640X480, this is our default, below
70 // this is the lowresmodes region.
71 // either do not change its order,
72 // or change the above define, too
73 {800, 600}, // 4, RES_640X480 + 1
74 {1024, 768}, // 5, RES_640X480 + 2
75 {1280, 1024}, // 6
76 {1600, 1200} // 7
77 };
78
79 #define MAX_MODE_LIST 128
80 #define MAX_STDMODES (sizeof(std_modes) / sizeof(std_modes[0]))
81 #define NUM_LOWRESMODES (RES_640X480)
82 static vmode_t fmodelist[MAX_MODE_LIST+1]; // list of enumerated fullscreen modes
83 static vmode_t wmodelist[MAX_STDMODES +1]; // list of standart 4:3 windowed modes
84 static vmode_t *modelist; // modelist in use, points to one of the above lists
85 static int bpplist[MAX_NUMBPP][2];
86
87 static int num_fmodes;
88 static int num_wmodes;
89 static int *nummodes;
90 static vmode_t badmode;
91
92 #if defined(H2W)
93 #define WM_CLASSNAME "HexenWorld"
94 #define WM_WINDOWNAME "HexenWorld"
95 #else
96 #define WM_CLASSNAME "HexenII"
97 #define WM_WINDOWNAME "HexenII"
98 #endif
99
100 static HGLRC baseRC;
101 static HDC maindc;
102 static DEVMODE gdevmode;
103 static qboolean classregistered;
104 HWND mainwindow;
105 static HICON hIcon;
106 static int DIBWidth, DIBHeight;
107 static RECT WindowRect;
108 int window_center_x, window_center_y, window_x, window_y, window_width, window_height;
109 RECT window_rect;
110 static LONG WindowStyle, ExWindowStyle;
111 qboolean DDActive;
112
113 static PIXELFORMATDESCRIPTOR pfd =
114 {
115 sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
116 1, // version number
117 PFD_DRAW_TO_WINDOW // support window
118 | PFD_SUPPORT_OPENGL // support OpenGL
119 | PFD_DOUBLEBUFFER , // double buffered
120 PFD_TYPE_RGBA, // RGBA type
121 24, // 24-bit color depth
122 0, 0, 0, 0, 0, 0, // color bits ignored
123 0, // no alpha buffer
124 0, // shift bit ignored
125 0, // no accumulation buffer
126 0, 0, 0, 0, // accum bits ignored
127 32, // 32-bit z-buffer
128 0, // no stencil buffer
129 0, // no auxiliary buffer
130 PFD_MAIN_PLANE, // main layer
131 0, // reserved
132 0, 0, 0 // layer masks ignored
133 };
134
135 typedef struct {
136 int red,
137 green,
138 blue,
139 alpha,
140 depth,
141 stencil;
142 } attributes_t;
143 static attributes_t vid_attribs;
144
145 // main vid functions
146 static LRESULT WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
147 static void AppActivate(BOOL fActive, BOOL minimize);
148 static void VID_UpdateWindowStatus (void);
149 static const char *VID_GetModeDescription (int mode);
150
151 // vars for vid state
152 viddef_t vid; // global video state
153 modestate_t modestate = MS_UNINIT;
154 static int vid_default = MODE_WINDOWED;
155 static int vid_modenum = NO_MODE; // current video mode, set after mode setting succeeds
156 static int vid_deskwidth, vid_deskheight, vid_deskbpp, vid_deskmode;
157 static qboolean vid_conscale = false;
158
159 static qboolean vid_initialized = false;
160 static qboolean vid_canalttab = false;
161 static qboolean vid_wassuspended = false;
162
163 // cvar vid_mode must be set before calling
164 // VID_SetMode, VID_ChangeVideoMode or VID_Restart_f
165 static cvar_t vid_mode = {"vid_mode", "0", CVAR_NONE};
166 static cvar_t vid_config_consize = {"vid_config_consize", "640", CVAR_ARCHIVE};
167 static cvar_t vid_config_glx = {"vid_config_glx", "640", CVAR_ARCHIVE};
168 static cvar_t vid_config_gly = {"vid_config_gly", "480", CVAR_ARCHIVE};
169 static cvar_t vid_config_bpp = {"vid_config_bpp", "16", CVAR_ARCHIVE};
170 static cvar_t vid_config_fscr= {"vid_config_fscr", "1", CVAR_ARCHIVE};
171 // cvars for compatibility with the software version
172 static cvar_t vid_wait = {"vid_wait", "-1", CVAR_ARCHIVE};
173 static cvar_t vid_maxpages = {"vid_maxpages", "3", CVAR_ARCHIVE};
174 static cvar_t vid_nopageflip = {"vid_nopageflip", "1", CVAR_ARCHIVE};
175 // Note that 0 is MODE_WINDOWED
176 // Note that 3 is MODE_FULLSCREEN_DEFAULT
177 static cvar_t _vid_default_mode = {"_vid_default_mode", "0", CVAR_ARCHIVE};
178 static cvar_t _vid_default_mode_win = {"_vid_default_mode_win", "3", CVAR_ARCHIVE};
179 static cvar_t vid_stretch_by_2 = {"vid_stretch_by_2", "1", CVAR_ARCHIVE};
180 static cvar_t vid_config_x = {"vid_config_x", "800", CVAR_ARCHIVE};
181 static cvar_t vid_config_y = {"vid_config_y", "600", CVAR_ARCHIVE};
182
183 byte globalcolormap[VID_GRADES*256];
184 float RTint[256], GTint[256], BTint[256];
185 unsigned short d_8to16table[256];
186 unsigned int d_8to24table[256];
187 unsigned int d_8to24TranslucentTable[256];
188 unsigned char *inverse_pal;
189
190 // gl stuff
191 static void GL_Init (void);
192
193 static HINSTANCE hInstGL;
194 #ifdef GL_DLSYM
195 static const char *gl_library;
196 #endif
197
198 static const char *gl_vendor;
199 static const char *gl_renderer;
200 static const char *gl_version;
201 static const char *gl_extensions;
202 qboolean is_3dfx = false;
203
204 GLint gl_max_size = 256;
205 static qboolean have_NPOT = false;
206 qboolean gl_tex_NPOT = false;
207 static cvar_t gl_texture_NPOT = {"gl_texture_NPOT", "0", CVAR_ARCHIVE};
208 GLfloat gl_max_anisotropy;
209 float gldepthmin, gldepthmax;
210
211 // palettized textures
212 static qboolean have8bit = false;
213 qboolean is8bit = false;
214 static cvar_t vid_config_gl8bit = {"vid_config_gl8bit", "0", CVAR_ARCHIVE};
215
216 // Gamma stuff
217 typedef BOOL (WINAPI *GAMMA_RAMP_FN)(HDC, LPVOID);
218 static GAMMA_RAMP_FN GetDeviceGammaRamp_f;
219 static GAMMA_RAMP_FN SetDeviceGammaRamp_f;
220 extern unsigned short ramps[3][256]; // for hw- or 3dfx-gamma
221 static unsigned short orig_ramps[3][256]; // for hw- or 3dfx-gamma
222 static qboolean gammaworks = false; // whether hw-gamma works
223
224 // multitexturing
225 qboolean gl_mtexable = false;
226 static GLint num_tmus = 1;
227 static qboolean have_mtex = false;
228 static cvar_t gl_multitexture = {"gl_multitexture", "0", CVAR_ARCHIVE};
229
230 // stencil buffer
231 qboolean have_stencil = false;
232
233 // this is useless: things aren't like those in quake
234 //static qboolean fullsbardraw = false;
235
236 // menu drawing
237 static void VID_MenuDraw (void);
238 static void VID_MenuKey (int key);
239
240 // input stuff
241 static void ClearAllStates (void);
242 static int enable_mouse;
243 cvar_t _enable_mouse = {"_enable_mouse", "0", CVAR_ARCHIVE};
244
245
246 //====================================
247
GL_ParseExtensionList(const char * list,const char * name)248 static qboolean GL_ParseExtensionList (const char *list, const char *name)
249 {
250 const char *start;
251 const char *where, *terminator;
252
253 if (!list || !name || !*name)
254 return false;
255 if (strchr(name, ' ') != NULL)
256 return false; // extension names must not have spaces
257
258 start = list;
259 while (1) {
260 where = strstr (start, name);
261 if (!where)
262 break;
263 terminator = where + strlen (name);
264 if (where == start || where[-1] == ' ')
265 if (*terminator == ' ' || *terminator == '\0')
266 return true;
267 start = terminator;
268 }
269 return false;
270 }
271
272 //====================================
273
VID_LockBuffer(void)274 void VID_LockBuffer (void)
275 {
276 // nothing to do
277 }
278
VID_UnlockBuffer(void)279 void VID_UnlockBuffer (void)
280 {
281 // nothing to do
282 }
283
VID_HandlePause(qboolean paused)284 void VID_HandlePause (qboolean paused)
285 {
286 if ((modestate == MS_WINDOWED) && _enable_mouse.integer)
287 {
288 if (paused)
289 {
290 IN_DeactivateMouse ();
291 IN_ShowMouse ();
292 }
293 else
294 {
295 IN_ActivateMouse ();
296 IN_HideMouse ();
297 }
298 }
299 }
300
301
302 //====================================
303
CenterWindow(HWND hWndCenter,int width,int height)304 static void CenterWindow (HWND hWndCenter, int width, int height)
305 {
306 int CenterX, CenterY;
307
308 CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
309 CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
310 if (CenterX > 2*CenterY)
311 CenterX >>= 1; // dual screen?
312 if (CenterX < 0)
313 CenterX = 0;
314 if (CenterY < 0)
315 CenterY = 0;
316 SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0,
317 SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
318 }
319
VID_ConWidth(int modenum)320 static void VID_ConWidth (int modenum)
321 {
322 int w, h;
323
324 if (!vid_conscale)
325 {
326 Cvar_SetValueQuick (&vid_config_consize, modelist[modenum].width);
327 return;
328 }
329
330 w = vid_config_consize.integer;
331 w &= ~7; /* make it a multiple of eight */
332 if (w < MIN_WIDTH)
333 w = MIN_WIDTH;
334 else if (w > modelist[modenum].width)
335 w = modelist[modenum].width;
336
337 h = w * modelist[modenum].height / modelist[modenum].width;
338 if (h < 200 /* MIN_HEIGHT */ ||
339 h > modelist[modenum].height || w > modelist[modenum].width)
340 {
341 vid_conscale = false;
342 Cvar_SetValueQuick (&vid_config_consize, modelist[modenum].width);
343 return;
344 }
345 vid.width = vid.conwidth = w;
346 vid.height = vid.conheight = h;
347 if (w != modelist[modenum].width)
348 vid_conscale = true;
349 else vid_conscale = false;
350 }
351
VID_ChangeConsize(int dir)352 void VID_ChangeConsize (int dir)
353 {
354 int w, h;
355
356 switch (dir)
357 {
358 case -1: /* smaller text */
359 w = ((float)vid.conwidth/(float)vid.width + 0.05f) * vid.width; /* use 0.10f increment ?? */
360 w &= ~7; /* make it a multiple of eight */
361 if (w > modelist[vid_modenum].width)
362 w = modelist[vid_modenum].width;
363 break;
364
365 case 1: /* bigger text */
366 w = ((float)vid.conwidth/(float)vid.width - 0.05f) * vid.width;
367 w &= ~7; /* make it a multiple of eight */
368 if (w < MIN_WIDTH)
369 w = MIN_WIDTH;
370 break;
371
372 default: /* bad key */
373 return;
374 }
375
376 h = w * modelist[vid_modenum].height / modelist[vid_modenum].width;
377 if (h < 200)
378 return;
379 vid.width = vid.conwidth = w;
380 vid.height = vid.conheight = h;
381 Cvar_SetValueQuick (&vid_config_consize, vid.conwidth);
382 vid.recalc_refdef = 1;
383 if (vid.conwidth != modelist[vid_modenum].width)
384 vid_conscale = true;
385 else vid_conscale = false;
386 }
387
VID_ReportConsize(void)388 float VID_ReportConsize(void)
389 {
390 return (float)modelist[vid_modenum].width/vid.conwidth;
391 }
392
393
VID_SetWindowedMode(int modenum)394 static qboolean VID_SetWindowedMode (int modenum)
395 {
396 int width, height;
397 RECT rect;
398
399 pfd.cColorBits = 24;
400 pfd.cRedBits = 0;
401 pfd.cGreenBits = 0;
402 pfd.cBlueBits = 0;
403 pfd.cAlphaBits = 0;
404 pfd.cDepthBits = 32;
405 pfd.cStencilBits = 0;
406 if (vid_deskbpp >= 32) {
407 pfd.cRedBits = 8;
408 pfd.cGreenBits = 8;
409 pfd.cBlueBits = 8;
410 pfd.cAlphaBits = 8;
411 pfd.cDepthBits = 24;
412 pfd.cStencilBits = 8;
413 }
414
415 // Pa3PyX: set the original fullscreen mode if
416 // we are switching to window from fullscreen.
417 if (modestate == MS_FULLDIB)
418 ChangeDisplaySettings(NULL, 0);
419
420 WindowRect.top = WindowRect.left = 0;
421
422 WindowRect.right = modelist[modenum].width;
423 WindowRect.bottom = modelist[modenum].height;
424
425 DIBWidth = modelist[modenum].width;
426 DIBHeight = modelist[modenum].height;
427
428 WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE;
429 ExWindowStyle = 0;
430
431 rect = WindowRect;
432 AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
433
434 width = rect.right - rect.left;
435 height = rect.bottom - rect.top;
436
437 mainwindow = CreateWindowEx (ExWindowStyle, WM_CLASSNAME, WM_WINDOWNAME, WindowStyle,
438 rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
439 if (!mainwindow)
440 Sys_Error ("Couldn't create DIB window");
441
442 // center the DIB window
443 CenterWindow(mainwindow, WindowRect.right - WindowRect.left,
444 WindowRect.bottom - WindowRect.top);
445
446 modestate = MS_WINDOWED;
447 Cvar_SetQuick (&vid_config_fscr, "0");
448
449 return true;
450 }
451
452
VID_SetFullDIBMode(int modenum)453 static qboolean VID_SetFullDIBMode (int modenum)
454 {
455 int width, height;
456 RECT rect;
457
458 pfd.cColorBits = modelist[modenum].bpp;
459 if (modelist[modenum].bpp >= 32) {
460 pfd.cRedBits = 8;
461 pfd.cGreenBits = 8;
462 pfd.cBlueBits = 8;
463 pfd.cAlphaBits = 8;
464 pfd.cDepthBits = 24;
465 pfd.cStencilBits = 8;
466 }
467 else {
468 pfd.cRedBits = 5;
469 pfd.cGreenBits = 5;
470 pfd.cBlueBits = 5;
471 pfd.cAlphaBits = 0;
472 pfd.cDepthBits = 16;
473 pfd.cStencilBits = 0;
474 }
475
476 gdevmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
477 if (!Win95old)
478 {
479 gdevmode.dmFields |= DM_BITSPERPEL;
480 gdevmode.dmBitsPerPel = modelist[modenum].bpp;
481 }
482 gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].halfscreen;
483 gdevmode.dmPelsHeight = modelist[modenum].height;
484 gdevmode.dmSize = sizeof (gdevmode);
485
486 if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
487 Sys_Error ("Couldn't set fullscreen DIB mode");
488
489 WindowRect.top = WindowRect.left = 0;
490
491 WindowRect.right = modelist[modenum].width;
492 WindowRect.bottom = modelist[modenum].height;
493
494 DIBWidth = modelist[modenum].width;
495 DIBHeight = modelist[modenum].height;
496
497 WindowStyle = WS_POPUP | WS_SYSMENU | WS_VISIBLE;
498 ExWindowStyle = WS_EX_TOPMOST;
499
500 rect = WindowRect;
501 AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
502
503 width = rect.right - rect.left;
504 height = rect.bottom - rect.top;
505
506 mainwindow = CreateWindowEx (ExWindowStyle, WM_CLASSNAME, WM_WINDOWNAME, WindowStyle,
507 rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
508 if (!mainwindow)
509 Sys_Error ("Couldn't create DIB window");
510
511 modestate = MS_FULLDIB;
512 Cvar_SetQuick (&vid_config_fscr, "1");
513
514 // needed because we're not getting WM_MOVE messages fullscreen on NT
515 window_x = 0;
516 window_y = 0;
517
518 return true;
519 }
520
521
VID_SetMode(int modenum,const unsigned char * palette)522 static qboolean VID_SetMode (int modenum, const unsigned char *palette)
523 {
524 qboolean status = false;
525 MSG msg;
526 HDC hdc;
527
528 if (modenum < 0 || modenum >= *nummodes)
529 Sys_Error ("Bad video mode\n");
530
531 CDAudio_Pause ();
532
533 // Set either the fullscreen or windowed mode
534 if (modelist[modenum].type == MS_WINDOWED)
535 {
536 if (_enable_mouse.integer)
537 {
538 status = VID_SetWindowedMode(modenum);
539 IN_ActivateMouse ();
540 IN_HideMouse ();
541 }
542 else
543 {
544 status = VID_SetWindowedMode(modenum);
545 IN_DeactivateMouse ();
546 IN_ShowMouse ();
547 }
548 }
549 else if (modelist[modenum].type == MS_FULLDIB)
550 {
551 status = VID_SetFullDIBMode(modenum);
552 IN_ActivateMouse ();
553 IN_HideMouse ();
554 }
555 else
556 {
557 Sys_Error ("%s: Bad mode type in modelist", __thisfunc__);
558 }
559
560 if (!status)
561 {
562 Sys_Error ("Couldn't set video mode");
563 }
564
565 ShowWindow (mainwindow, SW_SHOWDEFAULT);
566 UpdateWindow (mainwindow);
567 SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
568 SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
569
570 // Because we have set the background brush for the window to NULL
571 // (to avoid flickering when re-sizing the window on the desktop),
572 // we clear the window to black when created, otherwise it will be
573 // empty while Quake starts up.
574 hdc = GetDC(mainwindow);
575 PatBlt(hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS);
576 ReleaseDC(mainwindow, hdc);
577
578 vid.numpages = 2;
579 vid.width = vid.conwidth = modelist[modenum].width;
580 vid.height = vid.conheight = modelist[modenum].height;
581
582 // setup the effective console width
583 VID_ConWidth(modenum);
584
585 window_width = DIBWidth;
586 window_height = DIBHeight;
587 VID_UpdateWindowStatus ();
588
589 // now we try to make sure we get the focus on the mode switch, because
590 // sometimes in some systems we don't. We grab the foreground, then
591 // finish setting up, pump all our messages, and sleep for a little while
592 // to let messages finish bouncing around the system, then we put
593 // ourselves at the top of the z order, then grab the foreground again,
594 // Who knows if it helps, but it probably doesn't hurt
595 SetForegroundWindow (mainwindow);
596 vid_modenum = modenum;
597 Cvar_SetValueQuick (&vid_config_glx, modelist[vid_modenum].width);
598 Cvar_SetValueQuick (&vid_config_gly, modelist[vid_modenum].height);
599 if (modestate != MS_WINDOWED)
600 Cvar_SetValueQuick (&vid_config_bpp, modelist[vid_modenum].bpp);
601
602 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
603 {
604 TranslateMessage (&msg);
605 DispatchMessage (&msg);
606 }
607
608 Sleep (100);
609
610 SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
611 SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
612 SWP_NOCOPYBITS);
613
614 SetForegroundWindow (mainwindow);
615
616 // fix the leftover Alt from any Alt-Tab or the like that switched us away
617 ClearAllStates ();
618
619 CDAudio_Resume ();
620
621 return true;
622 }
623
624
625 //====================================
626
627 #if 0 /* No.. */
628 static void CheckSetGlobalPalette (void)
629 {
630 gl3DfxSetPaletteEXT_f gl3DfxSetPaletteEXT_fp;
631
632 if (GL_ParseExtensionList(gl_extensions, "3DFX_set_global_palette"))
633 {
634 gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) wglGetProcAddress_fp("gl3DfxSetPaletteEXT");
635 if (!gl3DfxSetPaletteEXT_fp)
636 gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) wglGetProcAddress_fp("3DFX_set_global_palette");
637 if (!gl3DfxSetPaletteEXT_fp)
638 return;
639 Con_SafePrintf("Found 3DFX_set_global_palette\n");
640 }
641 else if (GL_ParseExtensionList(gl_extensions, "POWERVR_set_global_palette"))
642 {
643 gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) wglGetProcAddress_fp("glSetGlobalPalettePOWERVR");
644 if (!gl3DfxSetPaletteEXT_fp)
645 gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) wglGetProcAddress_fp("POWERVR_set_global_palette");
646 if (!gl3DfxSetPaletteEXT_fp)
647 return;
648 Con_SafePrintf("Found POWERVR_set_global_palette\n");
649 }
650 else {
651 return;
652 }
653
654 have8bit = true;
655 if (!vid_config_gl8bit.integer)
656 return;
657 else
658 {
659 int i;
660 GLubyte table[256][4];
661 char *oldpal;
662
663 is8bit = true;
664 oldpal = (char *) d_8to24table;
665 for (i = 0; i < 256; i++) {
666 table[i][2] = *oldpal++;
667 table[i][1] = *oldpal++;
668 table[i][0] = *oldpal++;
669 table[i][3] = 255;
670 oldpal++;
671 }
672 glEnable_fp (GL_SHARED_TEXTURE_PALETTE_EXT);
673 gl3DfxSetPaletteEXT_fp ((GLuint *)table);
674 }
675 }
676 #endif /* #if 0 */
677
CheckSharedTexturePalette(void)678 static void CheckSharedTexturePalette (void)
679 {
680 glColorTableEXT_f glColorTableEXT_fp;
681
682 if (!GL_ParseExtensionList(gl_extensions, "GL_EXT_shared_texture_palette"))
683 return;
684
685 glColorTableEXT_fp = (glColorTableEXT_f) wglGetProcAddress_fp("glColorTableEXT");
686 if (glColorTableEXT_fp == NULL)
687 return;
688
689 have8bit = true;
690 Con_SafePrintf("Found GL_EXT_shared_texture_palette\n");
691 if (!vid_config_gl8bit.integer)
692 return;
693 else
694 {
695 int i;
696 char thePalette[256*3];
697 char *oldPalette, *newPalette;
698
699 is8bit = true;
700 oldPalette = (char *) d_8to24table;
701 newPalette = thePalette;
702 for (i = 0; i < 256; i++) {
703 *newPalette++ = *oldPalette++;
704 *newPalette++ = *oldPalette++;
705 *newPalette++ = *oldPalette++;
706 oldPalette++;
707 }
708
709 glEnable_fp (GL_SHARED_TEXTURE_PALETTE_EXT);
710 glColorTableEXT_fp (GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256,
711 GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
712 }
713 }
714
VID_Init8bitPalette(void)715 static void VID_Init8bitPalette (void)
716 {
717 have8bit = false;
718 is8bit = false;
719
720 /* Check for 8bit Extensions and initialize them */
721 CheckSharedTexturePalette();
722 #if 0 /* No.. */
723 if (!have8bit)
724 CheckSetGlobalPalette();
725 #endif
726
727 if (is8bit)
728 Con_SafePrintf("8-bit palettized textures enabled\n");
729 }
730
731
VID_Check3dfxGamma(void)732 static void VID_Check3dfxGamma (void)
733 {
734 if (!GL_ParseExtensionList(gl_extensions, "WGL_3DFX_gamma_control"))
735 {
736 GetDeviceGammaRamp_f = GetDeviceGammaRamp;
737 SetDeviceGammaRamp_f = SetDeviceGammaRamp;
738 }
739 else
740 {
741 GetDeviceGammaRamp_f = (GAMMA_RAMP_FN) wglGetProcAddress_fp("wglGetDeviceGammaRamp3DFX");
742 SetDeviceGammaRamp_f = (GAMMA_RAMP_FN) wglGetProcAddress_fp("wglSetDeviceGammaRamp3DFX");
743 if (GetDeviceGammaRamp_f && SetDeviceGammaRamp_f)
744 Con_SafePrintf("Using 3Dfx specific gamma control\n");
745 else
746 {
747 GetDeviceGammaRamp_f = GetDeviceGammaRamp;
748 SetDeviceGammaRamp_f = SetDeviceGammaRamp;
749 }
750 }
751 }
752
VID_InitGamma(void)753 static void VID_InitGamma (void)
754 {
755 GetDeviceGammaRamp_f = NULL;
756 SetDeviceGammaRamp_f = NULL;
757 gammaworks = false;
758
759 VID_Check3dfxGamma ();
760
761 if (GetDeviceGammaRamp_f)
762 gammaworks = GetDeviceGammaRamp_f(maindc, orig_ramps);
763
764 if (!gammaworks)
765 Con_SafePrintf("gamma adjustment not available\n");
766 }
767
VID_ShiftPalette(const unsigned char * palette)768 void VID_ShiftPalette (const unsigned char *palette)
769 {
770 if (gammaworks && SetDeviceGammaRamp_f)
771 SetDeviceGammaRamp_f (maindc, ramps);
772 }
773
774
CheckMultiTextureExtensions(void)775 static void CheckMultiTextureExtensions (void)
776 {
777 gl_mtexable = have_mtex = false;
778
779 if (COM_CheckParm("-nomtex"))
780 {
781 Con_SafePrintf("Multitexture extensions disabled\n");
782 }
783 else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_multitexture"))
784 {
785 Con_SafePrintf("ARB Multitexture extensions found\n");
786
787 glGetIntegerv_fp(GL_MAX_TEXTURE_UNITS_ARB, &num_tmus);
788 if (num_tmus < 2)
789 {
790 Con_SafePrintf("ignoring multitexture (%i TMUs)\n", (int) num_tmus);
791 return;
792 }
793
794 glMultiTexCoord2fARB_fp = (glMultiTexCoord2fARB_f) wglGetProcAddress_fp("glMultiTexCoord2fARB");
795 glActiveTextureARB_fp = (glActiveTextureARB_f) wglGetProcAddress_fp("glActiveTextureARB");
796 if (glMultiTexCoord2fARB_fp == NULL || glActiveTextureARB_fp == NULL)
797 {
798 Con_SafePrintf ("Couldn't link to multitexture functions\n");
799 return;
800 }
801
802 have_mtex = true;
803 if (!gl_multitexture.integer)
804 {
805 Con_SafePrintf("ignoring multitexture (cvar disabled)\n");
806 return;
807 }
808
809 Con_SafePrintf("Found %i TMUs support\n", num_tmus);
810 gl_mtexable = true;
811 glDisable_fp(GL_TEXTURE_2D);
812 glActiveTextureARB_fp(GL_TEXTURE0_ARB);
813 }
814 else
815 {
816 Con_SafePrintf("GL_ARB_multitexture not found\n");
817 }
818 }
819
CheckAnisotropyExtensions(void)820 static void CheckAnisotropyExtensions (void)
821 {
822 gl_max_anisotropy = 1;
823
824 Con_SafePrintf("Anisotropic filtering ");
825 if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_filter_anisotropic"))
826 {
827 GLfloat test1 = 0, test2 = 0;
828 GLuint tex;
829 glGetTexParameterfv_f glGetTexParameterfv_fp;
830
831 glGetTexParameterfv_fp = (glGetTexParameterfv_f) GetProcAddress(hInstGL, "glGetTexParameterfv");
832 if (glGetTexParameterfv_fp == NULL)
833 {
834 Con_SafePrintf("... can't check driver-lock status\n... ");
835 goto _skiptest;
836 }
837 // test to make sure we really have control over it
838 // 1.0 and 2.0 should always be legal values.
839 glGenTextures_fp(1, &tex);
840 glBindTexture_fp(GL_TEXTURE_2D, tex);
841 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
842 glGetTexParameterfv_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test1);
843 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
844 glGetTexParameterfv_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test2);
845 glDeleteTextures_fp(1, &tex);
846 if (test1 != 1 || test2 != 2)
847 {
848 Con_SafePrintf("driver-locked @ %.1f\n", test1);
849 }
850 else
851 {
852 _skiptest:
853 glGetFloatv_fp(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max_anisotropy);
854 if (gl_max_anisotropy < 2)
855 Con_SafePrintf("broken\n");
856 else Con_SafePrintf("found, max %.1f\n", gl_max_anisotropy);
857 }
858 }
859 else
860 {
861 Con_SafePrintf("not found\n");
862 }
863 }
864
CheckNonPowerOfTwoTextures(void)865 static void CheckNonPowerOfTwoTextures (void)
866 {
867 /* On Mac OS X, old Radeons lie about NPOT textures capability, they
868 * fallback to software with mipmap NPOT textures. see, e.g.:
869 * http://lists.apple.com/archives/mac-opengl/2006/Dec/msg00000.html
870 * http://lists.apple.com/archives/mac-opengl/2009/Oct/msg00040.html
871 * http://www.idevgames.com/forums/printthread.php?tid=3814&page=2
872 * MH says NVIDIA once did the same with their GeForce FX on Windows:
873 * http://forums.inside3d.com/viewtopic.php?f=10&t=4832
874 * Therefore, advertisement of this extension is an unreliable way of
875 * detecting the actual capability.
876 */
877 gl_tex_NPOT = have_NPOT = false;
878 if (GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_non_power_of_two"))
879 {
880 have_NPOT = true;
881 Con_SafePrintf("Found ARB_texture_non_power_of_two\n");
882 if (!gl_texture_NPOT.integer) {
883 Con_SafePrintf("ignoring texture_NPOT (cvar disabled)\n");
884 }
885 else {
886 gl_tex_NPOT = true;
887 }
888 }
889 else
890 {
891 Con_SafePrintf("GL_ARB_texture_non_power_of_two not found\n");
892 }
893 }
894
CheckStencilBuffer(void)895 static void CheckStencilBuffer (void)
896 {
897 have_stencil = !!vid_attribs.stencil;
898 }
899
900
901 #ifdef GL_DLSYM
GL_OpenLibrary(const char * name)902 static qboolean GL_OpenLibrary (const char *name)
903 {
904 int drv_standalone = q_strcasecmp(name, "opengl32.dll");
905
906 Con_SafePrintf("Loading OpenGL library %s\n", name);
907
908 // open the library
909 if (!(hInstGL = LoadLibrary(name)))
910 {
911 Con_SafePrintf("Unable to LoadLibrary %s\n", name);
912 return false;
913 }
914
915 // link to necessary wgl functions
916 #define GL_FUNCTION(ret, func, params) \
917 do { \
918 func##_fp = (func##_f) GetProcAddress(hInstGL, #func); \
919 if (func##_fp == NULL) \
920 Sys_Error("Couldn't link to %s", #func); \
921 } while (0);
922 #define GL_FUNCTION_OPT(ret,func,def,params) \
923 do { \
924 func##_fp = (drv_standalone)? \
925 (func##_f) GetProcAddress(hInstGL, #func) : def; \
926 if (func##_fp == NULL) \
927 Sys_Error("Couldn't link to %s", #func); \
928 } while (0);
929 #include "wgl_func.h"
930
931 return true;
932 }
933
GL_CloseLibrary(void)934 static void GL_CloseLibrary (void)
935 {
936 // clear the wgl function pointers
937 #define GL_FUNCTION(ret, func, params) \
938 func##_fp = NULL;
939 #define GL_FUNCTION_OPT(ret,func,def,params) \
940 func##_fp = NULL;
941 #include "wgl_func.h"
942
943 // free the library
944 if (hInstGL != NULL)
945 FreeLibrary(hInstGL);
946 hInstGL = NULL;
947 }
948
GL_Init_Functions(void)949 static void GL_Init_Functions (void)
950 {
951 #define GL_FUNCTION(ret, func, params) \
952 do { \
953 func##_fp = (func##_f) GetProcAddress(hInstGL, #func); \
954 if (func##_fp == NULL) \
955 Sys_Error("%s not found in GL library", #func); \
956 } while (0);
957 #define GL_FUNCTION_OPT(ret, func, params)
958 #include "gl_func.h"
959 }
960 #endif /* GL_DLSYM */
961
GL_ResetFunctions(void)962 static void GL_ResetFunctions (void)
963 {
964 #ifdef GL_DLSYM
965 #define GL_FUNCTION(ret, func, params) \
966 func##_fp = NULL;
967 #endif
968 #define GL_FUNCTION_OPT(ret, func, params) \
969 func##_fp = NULL;
970 #include "gl_func.h"
971
972 GetDeviceGammaRamp_f = NULL;
973 SetDeviceGammaRamp_f = NULL;
974
975 have_stencil = false;
976 gl_mtexable = false;
977 have_mtex = false;
978 have8bit = false;
979 is8bit = false;
980 have_NPOT = false;
981 gl_tex_NPOT = false;
982 }
983
984
985 /*
986 ===============
987 GL_Init
988 ===============
989 */
GL_Init(void)990 static void GL_Init (void)
991 {
992 PIXELFORMATDESCRIPTOR new_pfd;
993
994 Con_SafePrintf ("Video mode %s initialized\n", VID_GetModeDescription (vid_modenum));
995
996 #ifdef GL_DLSYM
997 // initialize gl function pointers
998 GL_Init_Functions();
999 #endif
1000
1001 // collect the visual attributes
1002 memset (&new_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
1003 memset (&vid_attribs, 0, sizeof(attributes_t));
1004 glGetIntegerv_fp(GL_RED_BITS, &vid_attribs.red);
1005 glGetIntegerv_fp(GL_GREEN_BITS, &vid_attribs.green);
1006 glGetIntegerv_fp(GL_BLUE_BITS, &vid_attribs.blue);
1007 glGetIntegerv_fp(GL_ALPHA_BITS, &vid_attribs.alpha);
1008 glGetIntegerv_fp(GL_DEPTH_BITS, &vid_attribs.depth);
1009 glGetIntegerv_fp(GL_STENCIL_BITS, &vid_attribs.stencil);
1010 Con_SafePrintf ("R:%d G:%d B:%d A:%d, Z:%d, S:%d\n",
1011 vid_attribs.red, vid_attribs.green, vid_attribs.blue, vid_attribs.alpha,
1012 vid_attribs.depth, vid_attribs.stencil);
1013 /* FIXME: DescribePixelFormat() used to fail with old 3dfx minigl drivers ??? */
1014 if (wglDescribePixelFormat_fp(maindc, wglGetPixelFormat_fp(maindc), sizeof(PIXELFORMATDESCRIPTOR), &new_pfd))
1015 {
1016 Con_SafeDPrintf ("PFD: C:%d, R:%d G:%d B:%d A:%d, Z:%d, S:%d\n",
1017 new_pfd.cColorBits, new_pfd.cRedBits, new_pfd.cGreenBits, new_pfd.cBlueBits,
1018 new_pfd.cAlphaBits, new_pfd.cDepthBits, new_pfd.cStencilBits);
1019 if ((new_pfd.dwFlags & PFD_GENERIC_FORMAT) && !(new_pfd.dwFlags & PFD_GENERIC_ACCELERATED))
1020 Con_SafePrintf ("WARNING: Hardware acceleration not present\n");
1021 else if (new_pfd.dwFlags & PFD_GENERIC_ACCELERATED)
1022 Con_SafePrintf ("OpenGL: MCD acceleration found\n");
1023 }
1024
1025 gl_vendor = (const char *)glGetString_fp (GL_VENDOR);
1026 Con_SafePrintf ("GL_VENDOR: %s\n", gl_vendor);
1027 gl_renderer = (const char *)glGetString_fp (GL_RENDERER);
1028 Con_SafePrintf ("GL_RENDERER: %s\n", gl_renderer);
1029
1030 gl_version = (const char *)glGetString_fp (GL_VERSION);
1031 Con_SafePrintf ("GL_VERSION: %s\n", gl_version);
1032 gl_extensions = (const char *)glGetString_fp (GL_EXTENSIONS);
1033 Con_SafeDPrintf ("GL_EXTENSIONS: %s\n", gl_extensions);
1034
1035 glGetIntegerv_fp(GL_MAX_TEXTURE_SIZE, &gl_max_size);
1036 if (gl_max_size < 256) // Refuse to work when less than 256
1037 Sys_Error ("hardware capable of min. 256k opengl texture size needed");
1038 Con_SafePrintf("OpenGL max.texture size: %i\n", gl_max_size);
1039
1040 is_3dfx = false;
1041 if (!q_strncasecmp(gl_renderer, "3dfx", 4) ||
1042 !q_strncasecmp(gl_renderer, "SAGE Glide", 10) ||
1043 !q_strncasecmp(gl_renderer, "Glide ", 6) || /* possible with Mesa 3.x/4.x/5.0.x */
1044 !q_strncasecmp(gl_renderer, "Mesa Glide", 10))
1045 {
1046 Con_SafePrintf("3dfx Voodoo found\n");
1047 is_3dfx = true;
1048 }
1049
1050 // if (!q_strncasecmp(gl_renderer, "PowerVR", 7))
1051 // fullsbardraw = true;
1052
1053 VID_InitGamma ();
1054
1055 CheckMultiTextureExtensions();
1056 CheckAnisotropyExtensions();
1057 CheckNonPowerOfTwoTextures();
1058 CheckStencilBuffer();
1059
1060 glClearColor_fp (1,0,0,0);
1061 glCullFace_fp(GL_FRONT);
1062 glEnable_fp(GL_TEXTURE_2D);
1063
1064 glEnable_fp(GL_ALPHA_TEST);
1065 glAlphaFunc_fp(GL_GREATER, 0.632); // 1 - e^-1 : replaced 0.666 to avoid clipping of smaller fonts/graphics
1066 #if 0 /* causes side effects at least in 16 bpp. */
1067 /* Get rid of Z-fighting for textures by offsetting the
1068 * drawing of entity models compared to normal polygons.
1069 * (See: R_DrawBrushModel.)
1070 * (Only works if gl_ztrick is turned off) */
1071 glPolygonOffset_fp(0.05f, 25.0f);
1072 #endif /* #if 0 */
1073 glPolygonMode_fp (GL_FRONT_AND_BACK, GL_FILL);
1074 glShadeModel_fp (GL_FLAT);
1075
1076 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1077 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1078
1079 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1080 glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1081
1082 glBlendFunc_fp (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1083
1084 // glTexEnvf_fp(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1085 glTexEnvf_fp(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1086 }
1087
1088
1089 /*
1090 =================
1091 GL_BeginRendering
1092
1093 =================
1094 */
GL_BeginRendering(int * x,int * y,int * width,int * height)1095 void GL_BeginRendering (int *x, int *y, int *width, int *height)
1096 {
1097 *x = *y = 0;
1098 *width = WindowRect.right - WindowRect.left;
1099 *height = WindowRect.bottom - WindowRect.top;
1100
1101 // if (!wglMakeCurrent_fp( maindc, baseRC ))
1102 // Sys_Error ("wglMakeCurrent failed");
1103
1104 // glViewport_fp (*x, *y, *width, *height);
1105 }
1106
1107
GL_EndRendering(void)1108 void GL_EndRendering (void)
1109 {
1110 if (!scr_skipupdate)
1111 wglSwapBuffers_fp(maindc);
1112
1113 // handle the mouse state when windowed if that's changed
1114 if (modestate == MS_WINDOWED)
1115 {
1116 if (_enable_mouse.integer != enable_mouse)
1117 {
1118 if (_enable_mouse.integer)
1119 {
1120 IN_ActivateMouse ();
1121 IN_HideMouse ();
1122 }
1123 else
1124 {
1125 IN_DeactivateMouse ();
1126 IN_ShowMouse ();
1127 }
1128
1129 enable_mouse = _enable_mouse.integer;
1130 }
1131 }
1132
1133 // if (fullsbardraw)
1134 // Sbar_Changed();
1135 }
1136
1137
1138 const int ColorIndex[16] = {
1139 0, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 199, 207, 223, 231
1140 };
1141
1142 const unsigned int ColorPercent[16] = {
1143 25, 51, 76, 102, 114, 127, 140, 153, 165, 178, 191, 204, 216, 229, 237, 247
1144 };
1145
1146 #define INVERSE_PALNAME "gfx/invpal.lmp"
ConvertTrueColorToPal(const unsigned char * true_color,const unsigned char * palette)1147 static int ConvertTrueColorToPal (const unsigned char *true_color, const unsigned char *palette)
1148 {
1149 int i;
1150 long min_dist;
1151 int min_index;
1152 long r, g, b;
1153
1154 min_dist = 256 * 256 + 256 * 256 + 256 * 256;
1155 min_index = -1;
1156 r = (long) true_color[0];
1157 g = (long) true_color[1];
1158 b = (long) true_color[2];
1159
1160 for (i = 0; i < 256; i++)
1161 {
1162 long palr, palg, palb, dist;
1163 long dr, dg, db;
1164
1165 palr = palette[3*i];
1166 palg = palette[3*i+1];
1167 palb = palette[3*i+2];
1168 dr = palr - r;
1169 dg = palg - g;
1170 db = palb - b;
1171 dist = dr * dr + dg * dg + db * db;
1172 if (dist < min_dist)
1173 {
1174 min_dist = dist;
1175 min_index = i;
1176 }
1177 }
1178 return min_index;
1179 }
1180
VID_CreateInversePalette(const unsigned char * palette)1181 static void VID_CreateInversePalette (const unsigned char *palette)
1182 {
1183 long r, g, b;
1184 long idx = 0;
1185 unsigned char true_color[3];
1186
1187 Con_SafePrintf ("Creating inverse palette\n");
1188
1189 for (r = 0; r < (1 << INVERSE_PAL_R_BITS); r++)
1190 {
1191 for (g = 0; g < (1 << INVERSE_PAL_G_BITS); g++)
1192 {
1193 for (b = 0; b < (1 << INVERSE_PAL_B_BITS); b++)
1194 {
1195 true_color[0] = (unsigned char)(r << (8 - INVERSE_PAL_R_BITS));
1196 true_color[1] = (unsigned char)(g << (8 - INVERSE_PAL_G_BITS));
1197 true_color[2] = (unsigned char)(b << (8 - INVERSE_PAL_B_BITS));
1198 inverse_pal[idx] = ConvertTrueColorToPal(true_color, palette);
1199 idx++;
1200 }
1201 }
1202 }
1203
1204 FS_CreatePath(FS_MakePath(FS_USERDIR, NULL, INVERSE_PALNAME));
1205 FS_WriteFile (INVERSE_PALNAME, inverse_pal, INVERSE_PAL_SIZE);
1206 }
1207
VID_InitPalette(const unsigned char * palette)1208 static void VID_InitPalette (const unsigned char *palette)
1209 {
1210 const unsigned char *pal;
1211 unsigned short r, g, b;
1212 unsigned short i, p, c;
1213 unsigned int v, *table;
1214 int mark;
1215
1216 #if ENDIAN_RUNTIME_DETECT
1217 switch (host_byteorder)
1218 {
1219 case BIG_ENDIAN: /* R G B A */
1220 MASK_r = 0xff000000;
1221 MASK_g = 0x00ff0000;
1222 MASK_b = 0x0000ff00;
1223 MASK_a = 0x000000ff;
1224 SHIFT_r = 24;
1225 SHIFT_g = 16;
1226 SHIFT_b = 8;
1227 SHIFT_a = 0;
1228 break;
1229 case LITTLE_ENDIAN: /* A B G R */
1230 MASK_r = 0x000000ff;
1231 MASK_g = 0x0000ff00;
1232 MASK_b = 0x00ff0000;
1233 MASK_a = 0xff000000;
1234 SHIFT_r = 0;
1235 SHIFT_g = 8;
1236 SHIFT_b = 16;
1237 SHIFT_a = 24;
1238 break;
1239 default:
1240 break;
1241 }
1242 MASK_rgb = (MASK_r|MASK_g|MASK_b);
1243 #endif /* ENDIAN_RUNTIME_DETECT */
1244
1245 //
1246 // 8 8 8 encoding
1247 //
1248 pal = palette;
1249 table = d_8to24table;
1250 for (i = 0; i < 256; i++)
1251 {
1252 r = pal[0];
1253 g = pal[1];
1254 b = pal[2];
1255 pal += 3;
1256
1257 v = (255 << SHIFT_a) + (r << SHIFT_r) + (g << SHIFT_g) + (b << SHIFT_b);
1258 *table++ = v;
1259 }
1260
1261 d_8to24table[255] &= MASK_rgb; // 255 is transparent
1262
1263 pal = palette;
1264 table = d_8to24TranslucentTable;
1265
1266 for (i = 0; i < 16; i++)
1267 {
1268 c = ColorIndex[i] * 3;
1269
1270 r = pal[c];
1271 g = pal[c + 1];
1272 b = pal[c + 2];
1273
1274 for (p = 0; p < 16; p++)
1275 {
1276 v = (ColorPercent[15 - p] << SHIFT_a) + (r << SHIFT_r) + (g << SHIFT_g) + (b << SHIFT_b);
1277 *table++ = v;
1278
1279 RTint[i*16 + p] = ((float)r) / ((float)ColorPercent[15-p]);
1280 GTint[i*16 + p] = ((float)g) / ((float)ColorPercent[15-p]);
1281 BTint[i*16 + p] = ((float)b) / ((float)ColorPercent[15-p]);
1282 }
1283 }
1284
1285 // Initialize the palettized textures data
1286 mark = Hunk_LowMark ();
1287 inverse_pal = (unsigned char *) FS_LoadHunkFile (INVERSE_PALNAME, NULL);
1288 if (inverse_pal != NULL && fs_filesize != INVERSE_PAL_SIZE)
1289 {
1290 Hunk_FreeToLowMark (mark);
1291 inverse_pal = NULL;
1292 }
1293 if (inverse_pal == NULL)
1294 {
1295 inverse_pal = (unsigned char *) Hunk_AllocName (INVERSE_PAL_SIZE + 1, INVERSE_PALNAME);
1296 VID_CreateInversePalette (palette);
1297 }
1298 }
1299
VID_SetPalette(const unsigned char * palette)1300 void VID_SetPalette (const unsigned char *palette)
1301 {
1302 // nothing to do
1303 }
1304
1305
1306 //==========================================================================
1307
bSetupPixelFormat(HDC hDC)1308 static BOOL bSetupPixelFormat (HDC hDC)
1309 {
1310 int pixelformat;
1311
1312 if ( (pixelformat = wglChoosePixelFormat_fp(hDC, &pfd)) == 0 )
1313 {
1314 MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
1315 return FALSE;
1316 }
1317
1318 if (wglSetPixelFormat_fp(hDC, pixelformat, &pfd) == FALSE)
1319 {
1320 MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
1321 return FALSE;
1322 }
1323
1324 return TRUE;
1325 }
1326
1327
1328 /*
1329 =======
1330 MapKey
1331
1332 Map from windows to quake keynums
1333 =======
1334 */
1335 static byte scantokey[128] =
1336 {
1337 // 0 1 2 3 4 5 6 7
1338 // 8 9 A B C D E F
1339 0 , 27, '1', '2', '3', '4', '5', '6',
1340 '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
1341 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
1342 'o', 'p', '[', ']', K_ENTER, K_CTRL, 'a', 's', // 1
1343 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
1344 '\'', '`', K_SHIFT, '\\', 'z', 'x', 'c', 'v', // 2
1345 'b', 'n', 'm', ',', '.', '/', K_SHIFT, K_KP_STAR,
1346 K_ALT, ' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
1347 K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME,
1348 K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW,K_KP_PLUS,K_END, // 4
1349 K_DOWNARROW,K_PGDN,K_INS,K_DEL, 0 , 0 , 0 , K_F11,
1350 K_F12, 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 5
1351 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1352 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 6
1353 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1354 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
1355 };
1356
1357 #if 0 /* not used */
1358 static byte shiftscantokey[128] =
1359 {
1360 // 0 1 2 3 4 5 6 7
1361 // 8 9 A B C D E F
1362 0 , 27, '!', '@', '#', '$', '%', '^',
1363 '&', '*', '(', ')', '_', '+', K_BACKSPACE, 9, // 0
1364 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
1365 'O', 'P', '{', '}', K_ENTER, K_CTRL, 'A', 'S', // 1
1366 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
1367 '"' , '~', K_SHIFT, '|', 'Z', 'X', 'C', 'V', // 2
1368 'B', 'N', 'M', '<', '>', '?', K_SHIFT, K_KP_STAR,
1369 K_ALT, ' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
1370 K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME,
1371 K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW,K_KP_PLUS,K_END, // 4
1372 K_DOWNARROW,K_PGDN,K_INS,K_DEL, 0 , 0 , 0 , K_F11,
1373 K_F12, 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 5
1374 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1375 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 6
1376 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1377 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
1378 };
1379 #endif
1380
MapKey(int key)1381 static int MapKey (int key)
1382 {
1383 int result = (key >> 16) & 255;
1384
1385 if (result > 127)
1386 return 0;
1387 result = scantokey[result];
1388
1389 if (key & (1 << 24)) /* extended */
1390 {
1391 switch (result)
1392 {
1393 case K_PAUSE:
1394 return (Key_IsGameKey()) ? K_KP_NUMLOCK : 0;
1395 case K_ENTER:
1396 return (Key_IsGameKey()) ? K_KP_ENTER : K_ENTER;
1397 case '/':
1398 return (Key_IsGameKey()) ? K_KP_SLASH : '/';
1399 }
1400 }
1401 else /* standart */
1402 {
1403 switch (result)
1404 {
1405 case K_KP_STAR:
1406 return (Key_IsGameKey()) ? K_KP_STAR : '*';
1407 case K_KP_PLUS:
1408 return (Key_IsGameKey()) ? K_KP_PLUS : '+';
1409 case K_KP_MINUS:
1410 return (Key_IsGameKey()) ? K_KP_MINUS : '-';
1411 case K_HOME:
1412 return (Key_IsGameKey()) ? K_KP_HOME :
1413 (GetKeyState(VK_NUMLOCK) & 0x01) ? '7' : K_HOME;
1414 case K_UPARROW:
1415 return (Key_IsGameKey()) ? K_KP_UPARROW :
1416 (GetKeyState(VK_NUMLOCK) & 0x01) ? '8' : K_UPARROW;
1417 case K_PGUP:
1418 return (Key_IsGameKey()) ? K_KP_PGUP :
1419 (GetKeyState(VK_NUMLOCK) & 0x01) ? '9' : K_PGUP;
1420 case K_LEFTARROW:
1421 return (Key_IsGameKey()) ? K_KP_LEFTARROW :
1422 (GetKeyState(VK_NUMLOCK) & 0x01) ? '4' : K_LEFTARROW;
1423 case K_KP_5:
1424 return (Key_IsGameKey()) ? K_KP_5 : '5';
1425 case K_RIGHTARROW:
1426 return (Key_IsGameKey()) ? K_KP_RIGHTARROW :
1427 (GetKeyState(VK_NUMLOCK) & 0x01) ? '6' : K_RIGHTARROW;
1428 case K_END:
1429 return (Key_IsGameKey()) ? K_KP_END :
1430 (GetKeyState(VK_NUMLOCK) & 0x01) ? '1' : K_END;
1431 case K_DOWNARROW:
1432 return (Key_IsGameKey()) ? K_KP_DOWNARROW :
1433 (GetKeyState(VK_NUMLOCK) & 0x01) ? '2' : K_DOWNARROW;
1434 case K_PGDN:
1435 return (Key_IsGameKey()) ? K_KP_PGDN :
1436 (GetKeyState(VK_NUMLOCK) & 0x01) ? '3' : K_PGDN;
1437 case K_INS:
1438 return (Key_IsGameKey()) ? K_KP_INS :
1439 (GetKeyState(VK_NUMLOCK) & 0x01) ? '0' : K_INS;
1440 case K_DEL:
1441 return (Key_IsGameKey()) ? K_KP_DEL :
1442 (GetKeyState(VK_NUMLOCK) & 0x01) ? '.' : K_DEL;
1443 }
1444 }
1445
1446 return result;
1447 }
1448
1449 /*
1450 ===================================================================
1451
1452 MAIN WINDOW
1453
1454 ===================================================================
1455 */
1456
1457 /*
1458 ================
1459 ClearAllStates
1460 ================
1461 */
ClearAllStates(void)1462 static void ClearAllStates (void)
1463 {
1464 Key_ClearStates ();
1465 IN_ClearStates ();
1466 }
1467
1468 /*
1469 ================
1470 VID_UpdateWindowStatus
1471 ================
1472 */
VID_UpdateWindowStatus(void)1473 static void VID_UpdateWindowStatus (void)
1474 {
1475 window_rect.left = window_x;
1476 window_rect.top = window_y;
1477 window_rect.right = window_x + window_width;
1478 window_rect.bottom = window_y + window_height;
1479 window_center_x = (window_rect.left + window_rect.right) / 2;
1480 window_center_y = (window_rect.top + window_rect.bottom) / 2;
1481
1482 IN_UpdateClipCursor ();
1483 }
1484
1485
AppActivate(BOOL fActive,BOOL minimize)1486 static void AppActivate (BOOL fActive, BOOL minimize)
1487 /****************************************************************************
1488 *
1489 * Function: AppActivate
1490 * Parameters: fActive - True if app is activating
1491 *
1492 * Description: If the application is activating, then swap the system
1493 * into SYSPAL_NOSTATIC mode so that our palettes will display
1494 * correctly.
1495 *
1496 ****************************************************************************/
1497 {
1498 static BOOL sound_active;
1499
1500 ActiveApp = fActive;
1501 Minimized = minimize;
1502
1503 // enable/disable sound on focus gain/loss
1504 if (!ActiveApp && sound_active)
1505 {
1506 S_BlockSound ();
1507 sound_active = false;
1508 }
1509 else if (ActiveApp && !sound_active)
1510 {
1511 S_UnblockSound ();
1512 sound_active = true;
1513 }
1514
1515 if (fActive)
1516 {
1517 if (modestate == MS_FULLDIB)
1518 {
1519 if (vid_canalttab && vid_wassuspended)
1520 {
1521 vid_wassuspended = false;
1522 ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
1523 ShowWindow(mainwindow, SW_SHOWNORMAL);
1524 // Fix for alt-tab bug in NVidia drivers, from quakeforge
1525 MoveWindow(mainwindow, 0, 0, gdevmode.dmPelsWidth,
1526 gdevmode.dmPelsHeight, false);
1527 }
1528 IN_ActivateMouse ();
1529 IN_HideMouse ();
1530 }
1531 else if (modestate == MS_WINDOWED && _enable_mouse.integer)
1532 {
1533 // with winmouse, we may fail having our
1534 // window back from the iconified state. yuck...
1535 if (dinput_init)
1536 {
1537 IN_ActivateMouse ();
1538 IN_HideMouse ();
1539 }
1540 }
1541
1542 if (host_initialized && !draw_reinit) // paranoia, but just in case..
1543 VID_ShiftPalette(NULL);
1544 }
1545
1546 if (!fActive)
1547 {
1548 if (maindc && gammaworks && SetDeviceGammaRamp_f)
1549 {
1550 SetDeviceGammaRamp_f(maindc, orig_ramps);
1551 }
1552 if (modestate == MS_FULLDIB)
1553 {
1554 IN_DeactivateMouse ();
1555 IN_ShowMouse ();
1556 if (vid_canalttab)
1557 {
1558 ChangeDisplaySettings (NULL, 0);
1559 vid_wassuspended = true;
1560 }
1561 }
1562 else if (modestate == MS_WINDOWED && _enable_mouse.integer)
1563 {
1564 IN_DeactivateMouse ();
1565 IN_ShowMouse ();
1566 }
1567 }
1568 }
1569
1570
1571 static int MWheelAccumulator;
1572 static UINT uMSG_MOUSEWHEEL = 0;
1573 extern cvar_t mwheelthreshold;
1574
1575 /* main window procedure */
MainWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1576 static LRESULT WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1577 {
1578 LRESULT ret = 0;
1579 int fActive, fMinimized, temp;
1580
1581 if (uMSG_MOUSEWHEEL && uMsg == uMSG_MOUSEWHEEL)
1582 {
1583 /* Win95/WinNT-3.51 code using MSH_MOUSEWHEEL, see:
1584 * http://msdn.microsoft.com/en-us/library/ms645617.aspx */
1585 if (mwheelthreshold.integer >= 1)
1586 {
1587 MWheelAccumulator += (int) wParam;
1588 while (MWheelAccumulator >= mwheelthreshold.integer)
1589 {
1590 Key_Event(K_MWHEELUP, true);
1591 Key_Event(K_MWHEELUP, false);
1592 MWheelAccumulator -= mwheelthreshold.integer;
1593 }
1594 while (MWheelAccumulator <= -mwheelthreshold.integer)
1595 {
1596 Key_Event(K_MWHEELDOWN, true);
1597 Key_Event(K_MWHEELDOWN, false);
1598 MWheelAccumulator += mwheelthreshold.integer;
1599 }
1600 }
1601 return DefWindowProc (hWnd, uMsg, wParam, lParam);
1602 }
1603
1604 switch (uMsg)
1605 {
1606 case WM_ERASEBKGND:
1607 return 1;
1608
1609 case WM_KILLFOCUS:
1610 if (modestate == MS_FULLDIB)
1611 ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
1612 break;
1613
1614 case WM_CREATE:
1615 if (Win95)
1616 {
1617 uMSG_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG");
1618 if (!uMSG_MOUSEWHEEL)
1619 Con_SafePrintf ("couldn't register mousewheel\n");
1620 }
1621 break;
1622
1623 case WM_MOVE:
1624 // ignore when fullscreen
1625 if (modestate == MS_FULLDIB)
1626 break;
1627 window_x = (short) LOWORD(lParam);
1628 window_y = (short) HIWORD(lParam);
1629 VID_UpdateWindowStatus ();
1630 break;
1631
1632 case WM_SIZE:
1633 break;
1634
1635 case WM_SYSCHAR:
1636 // keep Alt-Space from happening
1637 break;
1638
1639 case WM_ACTIVATE:
1640 fActive = LOWORD(wParam);
1641 fMinimized = (BOOL) HIWORD(wParam);
1642 AppActivate(!(fActive == WA_INACTIVE), fMinimized);
1643
1644 // fix the leftover Alt from any Alt-Tab or the like that switched us away
1645 ClearAllStates ();
1646
1647 break;
1648
1649 case WM_KEYDOWN:
1650 case WM_SYSKEYDOWN:
1651 Key_Event (MapKey(lParam), true);
1652 break;
1653
1654 case WM_KEYUP:
1655 case WM_SYSKEYUP:
1656 Key_Event (MapKey(lParam), false);
1657 break;
1658
1659 // this is complicated because Win32 seems to pack multiple mouse
1660 // events into one update sometimes, so we always check all states
1661 // and look for events
1662 case WM_LBUTTONDOWN:
1663 case WM_LBUTTONUP:
1664 case WM_RBUTTONDOWN:
1665 case WM_RBUTTONUP:
1666 case WM_MBUTTONDOWN:
1667 case WM_MBUTTONUP:
1668 case WM_XBUTTONDOWN:
1669 case WM_XBUTTONUP:
1670 case WM_MOUSEMOVE:
1671 temp = 0;
1672
1673 if (wParam & MK_LBUTTON)
1674 temp |= 1;
1675
1676 if (wParam & MK_RBUTTON)
1677 temp |= 2;
1678
1679 if (wParam & MK_MBUTTON)
1680 temp |= 4;
1681
1682 // intellimouse explorer
1683 if (wParam & MK_XBUTTON1)
1684 temp |= 8;
1685
1686 if (wParam & MK_XBUTTON2)
1687 temp |= 16;
1688
1689 IN_MouseEvent (temp);
1690
1691 break;
1692
1693 case WM_MOUSEWHEEL:
1694 if ((short) HIWORD(wParam) > 0)
1695 {
1696 Key_Event(K_MWHEELUP, true);
1697 Key_Event(K_MWHEELUP, false);
1698 }
1699 else
1700 {
1701 Key_Event(K_MWHEELDOWN, true);
1702 Key_Event(K_MWHEELDOWN, false);
1703 }
1704 return 0;
1705
1706 case WM_CLOSE:
1707 if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
1708 MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
1709 {
1710 Sys_Quit ();
1711 }
1712 break;
1713
1714 case WM_DESTROY:
1715 // PostQuitMessage (0);
1716 break;
1717
1718 case MM_MCINOTIFY:
1719 #if !defined(_NO_CDAUDIO)
1720 ret = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
1721 #endif /* ! _NO_CDAUDIO */
1722 break;
1723
1724 default:
1725 /* pass all unhandled messages to DefWindowProc */
1726 ret = DefWindowProc (hWnd, uMsg, wParam, lParam);
1727 break;
1728 }
1729
1730 /* return 1 if handled message, 0 if not */
1731 return ret;
1732 }
1733
1734
1735 /*
1736 =================
1737 VID_NumModes
1738 =================
1739 */
VID_NumModes(void)1740 static int VID_NumModes (void)
1741 {
1742 return *nummodes;
1743 }
1744
1745
1746 /*
1747 =================
1748 VID_GetModePtr
1749 =================
1750 */
VID_GetModePtr(int modenum)1751 static vmode_t *VID_GetModePtr (int modenum)
1752 {
1753 if ((modenum >= 0) && (modenum < *nummodes))
1754 return &modelist[modenum];
1755 else
1756 return &badmode;
1757 }
1758
1759
1760 /*
1761 =================
1762 VID_GetModeDescription
1763 =================
1764 */
VID_GetModeDescription(int mode)1765 static const char *VID_GetModeDescription (int mode)
1766 {
1767 const char *pinfo;
1768 vmode_t *pv;
1769
1770 if ((mode < 0) || (mode >= *nummodes))
1771 return NULL;
1772
1773 pv = VID_GetModePtr (mode);
1774 pinfo = pv->modedesc;
1775
1776 return pinfo;
1777 }
1778
1779
1780 // KJB: Added this to return the mode driver name in description for console
1781
VID_GetExtModeDescription(int mode)1782 static const char *VID_GetExtModeDescription (int mode)
1783 {
1784 static char pinfo[100];
1785 vmode_t *pv;
1786
1787 if ((mode < 0) || (mode >= *nummodes))
1788 return NULL;
1789
1790 pv = VID_GetModePtr (mode);
1791 if (modelist[mode].type == MS_FULLDIB)
1792 {
1793 q_snprintf(pinfo, sizeof(pinfo), "%s fullscreen", pv->modedesc);
1794 }
1795 else
1796 {
1797 if (modestate == MS_WINDOWED)
1798 q_snprintf(pinfo, sizeof(pinfo), "%s windowed", pv->modedesc);
1799 else
1800 q_snprintf(pinfo, sizeof(pinfo), "windowed");
1801 }
1802
1803 return pinfo;
1804 }
1805
1806
1807 /*
1808 =================
1809 VID_DescribeCurrentMode_f
1810 =================
1811 */
VID_DescribeCurrentMode_f(void)1812 static void VID_DescribeCurrentMode_f (void)
1813 {
1814 Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
1815 }
1816
1817
1818 /*
1819 =================
1820 VID_NumModes_f
1821 =================
1822 */
VID_NumModes_f(void)1823 static void VID_NumModes_f (void)
1824 {
1825 if (*nummodes == 1)
1826 Con_Printf ("1 video mode is available\n");
1827 else
1828 Con_Printf ("%d video modes are available\n", *nummodes);
1829 }
1830
1831
1832 /*
1833 =================
1834 VID_DescribeMode_f
1835 =================
1836 */
VID_DescribeMode_f(void)1837 static void VID_DescribeMode_f (void)
1838 {
1839 int modenum;
1840
1841 modenum = atoi (Cmd_Argv(1));
1842
1843 Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
1844 }
1845
1846 /*
1847 =================
1848 VID_DescribeModes_f
1849 =================
1850 */
VID_DescribeModes_f(void)1851 static void VID_DescribeModes_f (void)
1852 {
1853 int i, lnummodes;
1854 const char *pinfo;
1855 vmode_t *pv;
1856
1857 lnummodes = VID_NumModes ();
1858
1859 for (i = 0; i < lnummodes; i++)
1860 {
1861 pv = VID_GetModePtr (i);
1862 pinfo = VID_GetExtModeDescription (i);
1863 Con_Printf ("%2d: %s\n", i, pinfo);
1864 }
1865 }
1866
1867
VID_RegisterWndClass(HINSTANCE hInstance)1868 static void VID_RegisterWndClass (HINSTANCE hInstance)
1869 {
1870 WNDCLASS wc;
1871
1872 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
1873 wc.lpfnWndProc = MainWndProc;
1874 wc.cbClsExtra = 0;
1875 wc.cbWndExtra = 0;
1876 wc.hInstance = hInstance;
1877 wc.hIcon = NULL;
1878 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
1879 wc.hbrBackground = NULL;
1880 wc.lpszMenuName = NULL;
1881 wc.lpszClassName = WM_CLASSNAME;
1882
1883 if (!RegisterClass(&wc))
1884 Sys_Error ("Couldn't register main window class");
1885
1886 classregistered = true;
1887 }
1888
VID_InitDIB(HINSTANCE hInstance)1889 static void VID_InitDIB (HINSTANCE hInstance)
1890 {
1891 int i;
1892 HDC tempDC;
1893
1894 // get desktop settings, hope that the user don't do a silly
1895 // thing like going back to desktop and changing its settings
1896 //vid_deskwidth = GetSystemMetrics (SM_CXSCREEN);
1897 //vid_deskheight = GetSystemMetrics (SM_CXSCREEN);
1898 tempDC = GetDC (GetDesktopWindow());
1899 vid_deskwidth = GetDeviceCaps (tempDC, HORZRES);
1900 vid_deskheight = GetDeviceCaps(tempDC, VERTRES);
1901 vid_deskbpp = GetDeviceCaps (tempDC, BITSPIXEL);
1902 ReleaseDC (GetDesktopWindow(), tempDC);
1903
1904 // refuse to run if vid_deskbpp < 15
1905 if (vid_deskbpp < 15)
1906 Sys_Error ("Desktop color depth too low\n"
1907 "Make sure you are running at 16 bpp or better");
1908
1909 /* Register the frame class */
1910 VID_RegisterWndClass(hInstance);
1911
1912 // initialize standart windowed modes list
1913 num_wmodes = 0;
1914
1915 for (i = 0, num_wmodes = 0; i < (int)MAX_STDMODES; i++)
1916 {
1917 if (std_modes[i].width <= vid_deskwidth && std_modes[i].height <= vid_deskheight)
1918 {
1919 wmodelist[num_wmodes].type = MS_WINDOWED;
1920 wmodelist[num_wmodes].width = std_modes[i].width;
1921 wmodelist[num_wmodes].height = std_modes[i].height;
1922 q_snprintf (wmodelist[num_wmodes].modedesc, MAX_DESC, "%dx%d",
1923 wmodelist[num_wmodes].width, wmodelist[num_wmodes].height);
1924 wmodelist[num_wmodes].modenum = MODE_WINDOWED;
1925 wmodelist[num_wmodes].dib = 1;
1926 wmodelist[num_wmodes].fullscreen = 0;
1927 wmodelist[num_wmodes].halfscreen = 0;
1928 wmodelist[num_wmodes].bpp = 0;
1929 num_wmodes++;
1930 }
1931 }
1932 }
1933
1934
1935 /*
1936 =================
1937 VID_InitFullDIB
1938 =================
1939 */
VID_InitFullDIB(HINSTANCE hInstance)1940 static void VID_InitFullDIB (HINSTANCE hInstance)
1941 {
1942 DEVMODE devmode;
1943 int i, modenum, existingmode;
1944 int j, bpp, done;
1945 BOOL status;
1946
1947 num_fmodes = 0;
1948
1949 modenum = 0;
1950
1951 // enumerate >8 bpp modes
1952 do
1953 {
1954 status = EnumDisplaySettings (NULL, modenum, &devmode);
1955
1956 if ((devmode.dmBitsPerPel >= 15) &&
1957 (devmode.dmPelsWidth <= MAXWIDTH) &&
1958 (devmode.dmPelsHeight <= MAXHEIGHT) &&
1959 (num_fmodes < MAX_MODE_LIST))
1960 {
1961 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1962
1963 if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
1964 DISP_CHANGE_SUCCESSFUL)
1965 {
1966 fmodelist[num_fmodes].type = MS_FULLDIB;
1967 fmodelist[num_fmodes].width = devmode.dmPelsWidth;
1968 fmodelist[num_fmodes].height = devmode.dmPelsHeight;
1969 fmodelist[num_fmodes].modenum = 0;
1970 fmodelist[num_fmodes].halfscreen = 0;
1971 fmodelist[num_fmodes].dib = 1;
1972 fmodelist[num_fmodes].fullscreen = 1;
1973 fmodelist[num_fmodes].bpp = devmode.dmBitsPerPel;
1974 q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%dx%dx%d",
1975 (int)devmode.dmPelsWidth, (int)devmode.dmPelsHeight,
1976 (int)devmode.dmBitsPerPel);
1977
1978 // if the width is more than twice the height, reduce it by half because this
1979 // is probably a dual-screen monitor
1980 if (!COM_CheckParm("-noadjustaspect"))
1981 {
1982 if (fmodelist[num_fmodes].width > (fmodelist[num_fmodes].height << 1))
1983 {
1984 fmodelist[num_fmodes].width >>= 1;
1985 fmodelist[num_fmodes].halfscreen = 1;
1986 q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%dx%dx%d",
1987 fmodelist[num_fmodes].width,
1988 fmodelist[num_fmodes].height,
1989 fmodelist[num_fmodes].bpp);
1990 }
1991 }
1992
1993 for (i = 0, existingmode = 0; i < num_fmodes; i++)
1994 {
1995 if ((fmodelist[num_fmodes].width == fmodelist[i].width) &&
1996 (fmodelist[num_fmodes].height == fmodelist[i].height) &&
1997 (fmodelist[num_fmodes].bpp == fmodelist[i].bpp))
1998 {
1999 existingmode = 1;
2000 break;
2001 }
2002 }
2003
2004 if (!existingmode)
2005 {
2006 num_fmodes++;
2007 }
2008 }
2009 }
2010
2011 modenum++;
2012 } while (status);
2013
2014 // see if there are any low-res modes that aren't being reported
2015 bpp = 16;
2016 done = 0;
2017
2018 do
2019 {
2020 for (j = 0; (j < NUM_LOWRESMODES) && (num_fmodes < MAX_MODE_LIST); j++)
2021 {
2022 devmode.dmBitsPerPel = bpp;
2023 devmode.dmPelsWidth = std_modes[j].width;
2024 devmode.dmPelsHeight = std_modes[j].height;
2025 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2026
2027 if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
2028 DISP_CHANGE_SUCCESSFUL)
2029 {
2030 fmodelist[num_fmodes].type = MS_FULLDIB;
2031 fmodelist[num_fmodes].width = devmode.dmPelsWidth;
2032 fmodelist[num_fmodes].height = devmode.dmPelsHeight;
2033 fmodelist[num_fmodes].modenum = 0;
2034 fmodelist[num_fmodes].halfscreen = 0;
2035 fmodelist[num_fmodes].dib = 1;
2036 fmodelist[num_fmodes].fullscreen = 1;
2037 fmodelist[num_fmodes].bpp = devmode.dmBitsPerPel;
2038 q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%dx%dx%d",
2039 (int)devmode.dmPelsWidth, (int)devmode.dmPelsHeight,
2040 (int)devmode.dmBitsPerPel);
2041
2042 for (i = 0, existingmode = 0; i < num_fmodes; i++)
2043 {
2044 if ((fmodelist[num_fmodes].width == fmodelist[i].width) &&
2045 (fmodelist[num_fmodes].height == fmodelist[i].height) &&
2046 (fmodelist[num_fmodes].bpp == fmodelist[i].bpp))
2047 {
2048 existingmode = 1;
2049 break;
2050 }
2051 }
2052
2053 if (!existingmode)
2054 {
2055 num_fmodes++;
2056 }
2057 }
2058 }
2059 switch (bpp)
2060 {
2061 case 16:
2062 bpp = 32;
2063 break;
2064
2065 case 32:
2066 #if 0 /* O.S: don't mess with silly 24 bit lowres modes, they may not work correctly */
2067 bpp = 24;
2068 break;
2069
2070 case 24:
2071 #endif
2072 done = 1;
2073 break;
2074 }
2075 } while (!done);
2076
2077 if (num_fmodes == 0)
2078 Con_SafePrintf ("No fullscreen DIB modes found\n");
2079 }
2080
2081 /*
2082 =================
2083 VID_ChangeVideoMode
2084 intended only as a callback for VID_Restart_f
2085 =================
2086 */
VID_ChangeVideoMode(int newmode)2087 static void VID_ChangeVideoMode (int newmode)
2088 {
2089 int temp, temp2;
2090
2091 // Avoid window updates and alt+tab handling (which sets modes back)
2092 temp = scr_disabled_for_loading;
2093 temp2 = vid_canalttab;
2094 scr_disabled_for_loading = true;
2095 vid_canalttab = false;
2096
2097 // restore gamma
2098 if (maindc && gammaworks && SetDeviceGammaRamp_f)
2099 SetDeviceGammaRamp_f(maindc, orig_ramps);
2100 CDAudio_Pause ();
2101 BGM_Pause ();
2102 S_ClearBuffer ();
2103
2104 // Unload all textures and reset texture counts
2105 D_ClearOpenGLTextures(0);
2106 memset (lightmap_textures, 0, sizeof(lightmap_textures));
2107
2108 // reset all opengl function pointers
2109 GL_ResetFunctions();
2110
2111 // Avoid re-registering commands and re-allocating memory
2112 draw_reinit = true;
2113
2114 // temporarily disable input devices
2115 IN_DeactivateMouse();
2116
2117 // Kill device and rendering contexts
2118 wglMakeCurrent_fp(NULL, NULL);
2119 if (baseRC)
2120 wglDeleteContext_fp(baseRC);
2121 baseRC = NULL;
2122 if (maindc && mainwindow)
2123 ReleaseDC(mainwindow, maindc);
2124 maindc = NULL;
2125 // Destroy main window and unregister its class
2126 if (mainwindow)
2127 {
2128 ShowWindow(mainwindow, SW_HIDE);
2129 DestroyWindow(mainwindow);
2130 }
2131 if (classregistered)
2132 UnregisterClass(WM_CLASSNAME, global_hInstance);
2133 mainwindow = NULL;
2134 classregistered = false;
2135
2136 #if 0 /* some setups (Vista) don't like this: */
2137 /* the dll already loaded at program init
2138 is still valid, we aren't changing the
2139 opengl library, so no problems... */
2140 #ifdef GL_DLSYM
2141 // reload the opengl library
2142 GL_CloseLibrary();
2143 Sleep (100);
2144 if (!GL_OpenLibrary(gl_library))
2145 Sys_Error ("Unable to load GL library %s", gl_library);
2146 #endif
2147 #endif /* #if 0 */
2148
2149 // Register main window class and create main window
2150 VID_RegisterWndClass(global_hInstance);
2151 VID_SetMode(newmode, host_basepal);
2152
2153 // Obtain device context and set up pixel format
2154 maindc = GetDC(mainwindow);
2155 bSetupPixelFormat(maindc);
2156
2157 // Create OpenGL rendering context and make it current
2158 baseRC = wglCreateContext_fp(maindc);
2159 if (!baseRC)
2160 Sys_Error("wglCreateContext failed");
2161 if (!wglMakeCurrent_fp(maindc, baseRC ))
2162 Sys_Error("wglMakeCurrent failed");
2163
2164 // Reload graphics wad file (Draw_PicFromWad writes glpic_t data (sizes,
2165 // texnums) right on top of the original pic data, so the pic data will
2166 // be dirty after gl textures are loaded the first time; we need to load
2167 // a clean version)
2168 W_LoadWadFile ("gfx.wad");
2169 // Initialize extensions and default OpenGL parameters
2170 GL_Init();
2171 VID_Init8bitPalette();
2172
2173 // Reload pre-map pics, fonts, console, etc
2174 Draw_Init();
2175 SCR_Init();
2176 // R_Init() stuff:
2177 R_InitParticleTexture();
2178 R_InitExtraTextures ();
2179 #if defined(H2W)
2180 R_InitNetgraphTexture();
2181 #endif /* H2W */
2182 Sbar_Init();
2183 vid.recalc_refdef = 1;
2184
2185 IN_ReInit ();
2186 CDAudio_Resume ();
2187 BGM_Resume ();
2188
2189 // Reload model textures and player skins
2190 Mod_ReloadTextures();
2191 // rebuild the lightmaps
2192 GL_BuildLightmaps();
2193 // finished reloading all images
2194 draw_reinit = false;
2195 scr_disabled_for_loading = temp;
2196 // apply our gamma
2197 VID_ShiftPalette(NULL);
2198 vid_canalttab = temp2;
2199 }
2200
VID_Restart_f(void)2201 static void VID_Restart_f (void)
2202 {
2203 if (vid_mode.integer < 0 || vid_mode.integer >= *nummodes)
2204 {
2205 Con_Printf ("Bad video mode %d\n", vid_mode.integer);
2206 Cvar_SetValueQuick (&vid_mode, vid_modenum);
2207 return;
2208 }
2209
2210 Con_Printf ("Re-initializing video:\n");
2211 VID_ChangeVideoMode (vid_mode.integer);
2212 }
2213
sort_modes(const void * arg1,const void * arg2)2214 static int sort_modes (const void *arg1, const void *arg2)
2215 {
2216 const vmode_t *a1, *a2;
2217 a1 = (vmode_t *) arg1;
2218 a2 = (vmode_t *) arg2;
2219
2220 /* low to high bpp ? */
2221 if (a1->bpp != a2->bpp)
2222 return a1->bpp - a2->bpp;
2223 /* lowres to highres */
2224 if (a1->width == a2->width)
2225 return a1->height - a2->height;
2226 return a1->width - a2->width;
2227 }
2228
VID_SortModes(void)2229 static void VID_SortModes (void)
2230 {
2231 int i, j;
2232
2233 if (num_fmodes == 0)
2234 return;
2235
2236 // sort the fullscreen modes list
2237 if (num_fmodes > 1)
2238 qsort(fmodelist, num_fmodes, sizeof fmodelist[0], sort_modes);
2239 // find which bpp values are reported to us
2240 for (i = 0; i < MAX_NUMBPP; i++)
2241 {
2242 bpplist[i][0] = 0;
2243 bpplist[i][1] = 0;
2244 }
2245 bpplist[0][0] = fmodelist[0].bpp;
2246 bpplist[0][1] = 0;
2247 for (i = 1, j = 0; i < num_fmodes && j < MAX_NUMBPP; i++)
2248 {
2249 if (fmodelist[i-1].bpp != fmodelist[i].bpp)
2250 {
2251 bpplist[++j][0] = fmodelist[i].bpp;
2252 bpplist[j][1] = i;
2253 }
2254 }
2255
2256 vid_deskmode = -1;
2257
2258 // find the desktop mode number. shouldn't fail!
2259 for (i = 1; i < num_fmodes; i++)
2260 {
2261 if ((fmodelist[i].width == vid_deskwidth) &&
2262 (fmodelist[i].height == vid_deskheight) &&
2263 (fmodelist[i].bpp == vid_deskbpp))
2264 {
2265 vid_deskmode = i;
2266 break;
2267 }
2268 }
2269 if (vid_deskmode < 0)
2270 Con_SafePrintf ("WARNING: desktop resolution not found in modelist\n");
2271 }
2272
2273
2274 /*
2275 ===================
2276 VID_Init
2277 ===================
2278 */
VID_Init(const unsigned char * palette)2279 void VID_Init (const unsigned char *palette)
2280 {
2281 static char fxmesa_env_multitex[32] = "FX_DONT_FAKE_MULTITEX=1";
2282 static char fxglide_env_nosplash[32] = "FX_GLIDE_NO_SPLASH=1";
2283 int i, j, existingmode;
2284 int width, height, bpp, findbpp, done;
2285 HDC hdc;
2286 const char *read_vars[] = {
2287 "vid_config_fscr",
2288 "vid_config_gl8bit",
2289 "vid_config_bpp",
2290 "vid_config_glx",
2291 "vid_config_gly",
2292 "vid_config_consize",
2293 "gl_texture_NPOT",
2294 "gl_multitexture",
2295 "gl_lightmapfmt" };
2296 #define num_readvars ( sizeof(read_vars)/sizeof(read_vars[0]) )
2297
2298 Cvar_RegisterVariable (&vid_config_gl8bit);
2299 Cvar_RegisterVariable (&vid_config_fscr);
2300 Cvar_RegisterVariable (&vid_config_bpp);
2301 Cvar_RegisterVariable (&vid_config_gly);
2302 Cvar_RegisterVariable (&vid_config_glx);
2303 Cvar_RegisterVariable (&vid_config_consize);
2304 Cvar_RegisterVariable (&vid_mode);
2305 Cvar_RegisterVariable (&_enable_mouse);
2306 Cvar_RegisterVariable (&gl_texture_NPOT);
2307 Cvar_RegisterVariable (&gl_lightmapfmt);
2308 Cvar_RegisterVariable (&gl_multitexture);
2309 // these are for compatibility with the software version
2310 Cvar_RegisterVariable (&vid_wait);
2311 Cvar_RegisterVariable (&_vid_default_mode);
2312 Cvar_RegisterVariable (&_vid_default_mode_win);
2313 Cvar_RegisterVariable (&vid_config_x);
2314 Cvar_RegisterVariable (&vid_config_y);
2315 Cvar_RegisterVariable (&vid_stretch_by_2);
2316 Cvar_RegisterVariable (&vid_maxpages);
2317 Cvar_RegisterVariable (&vid_nopageflip);
2318
2319 Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
2320 Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
2321 Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
2322 Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
2323 Cmd_AddCommand ("vid_restart", VID_Restart_f);
2324
2325 VID_InitPalette (palette);
2326
2327 // don't let fxMesa cheat multitexturing
2328 _putenv (fxmesa_env_multitex);
2329 // disable the 3dfx splash screen.
2330 _putenv (fxglide_env_nosplash);
2331
2332 #ifdef GL_DLSYM
2333 i = COM_CheckParm ("-gllibrary");
2334 if (i == 0)
2335 i = COM_CheckParm ("-g");
2336 if (i && i < com_argc - 1)
2337 gl_library = com_argv[i+1];
2338 else
2339 gl_library = "opengl32.dll";
2340 if (!GL_OpenLibrary(gl_library))
2341 Sys_Error ("Unable to load GL library %s", gl_library);
2342 #else
2343 hInstGL = GetModuleHandle("opengl32.dll");
2344 #endif
2345
2346 hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2));
2347
2348 VID_InitDIB (global_hInstance);
2349
2350 VID_InitFullDIB (global_hInstance);
2351
2352 Con_SafePrintf ("Desktop settings: %d x %d x %d\n", vid_deskwidth, vid_deskheight, vid_deskbpp);
2353
2354 // sort the modes
2355 VID_SortModes();
2356 // make sure our vid_config_bpp default is supported by the OS
2357 // (we have a findbpp code below, but let's be on the safe side..)
2358 for (i = 0; i < MAX_NUMBPP; i++)
2359 {
2360 if (!bpplist[i][0])
2361 break;
2362 if (vid_config_bpp.integer == bpplist[i][0])
2363 break; // OK.
2364 }
2365 if (i == MAX_NUMBPP || vid_config_bpp.integer != bpplist[i][0]) // not OK
2366 Cvar_SetValueQuick(&vid_config_bpp, bpplist[0][0]);
2367
2368 // perform an early read of config.cfg
2369 CFG_ReadCvars (read_vars, num_readvars);
2370
2371 width = vid_config_glx.integer;
2372 height = vid_config_gly.integer;
2373
2374 if (COM_CheckParm("-window") || COM_CheckParm("-w"))
2375 {
2376 Cvar_SetQuick (&vid_config_fscr, "0");
2377 }
2378 else if (COM_CheckParm("-fullscreen") || COM_CheckParm("-f"))
2379 {
2380 Cvar_SetQuick (&vid_config_fscr, "1");
2381 }
2382
2383 if (vid_config_consize.integer != width)
2384 vid_conscale = true;
2385
2386 if (!vid_config_fscr.integer)
2387 {
2388 hdc = GetDC (NULL);
2389 if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
2390 {
2391 Sys_Error ("Can't run in non-RGB mode");
2392 }
2393 ReleaseDC (NULL, hdc);
2394
2395 modelist = wmodelist;
2396 nummodes = &num_wmodes;
2397 vid_default = RES_640X480;
2398
2399 // start parsing any dimension request from user
2400 i = COM_CheckParm("-width");
2401 if (i && i < com_argc-1)
2402 {
2403 j = atoi(com_argv[i+1]);
2404 // don't allow requests larger than desktop
2405 if (j <= vid_deskwidth && j >= 320)
2406 {
2407 width = j;
2408 height = width * 3 / 4;
2409 i = COM_CheckParm("-height");
2410 if (i && i < com_argc-1)
2411 {
2412 j = atoi(com_argv[i+1]);
2413 if (j <= vid_deskheight && j >= 240)
2414 {
2415 height= j;
2416 }
2417 }
2418 }
2419 }
2420 // end of parsing user commandline
2421
2422 wmodelist[num_wmodes].width = width;
2423 wmodelist[num_wmodes].height = height;
2424 wmodelist[num_wmodes].type = MS_WINDOWED;
2425 q_snprintf (wmodelist[num_wmodes].modedesc, MAX_DESC, "%dx%d",
2426 wmodelist[num_wmodes].width, wmodelist[num_wmodes].height);
2427 wmodelist[num_wmodes].modenum = MODE_WINDOWED;
2428 wmodelist[num_wmodes].dib = 1;
2429 wmodelist[num_wmodes].fullscreen = 0;
2430 wmodelist[num_wmodes].halfscreen = 0;
2431 wmodelist[num_wmodes].bpp = 0;
2432
2433 for (i = 0, existingmode = 0; i < num_wmodes; i++)
2434 {
2435 if ((wmodelist[num_wmodes].width == wmodelist[i].width) &&
2436 (wmodelist[num_wmodes].height == wmodelist[i].height))
2437 {
2438 existingmode = 1;
2439 vid_default = i;
2440 break;
2441 }
2442 }
2443
2444 if (!existingmode)
2445 {
2446 q_strlcat (wmodelist[num_wmodes].modedesc, " (user mode)", MAX_DESC);
2447 vid_default = num_wmodes;
2448 num_wmodes++;
2449 }
2450
2451 }
2452 else // fullscreen, default
2453 {
2454 if (num_fmodes == 0)
2455 {
2456 Sys_Error ("No RGB fullscreen modes available");
2457 }
2458
2459 modelist = fmodelist;
2460 nummodes = &num_fmodes;
2461 vid_default = -1;
2462
2463 findbpp = 1;
2464 bpp = vid_config_bpp.integer;
2465 if (Win95old)
2466 { // don't bother with multiple bpp values on
2467 // windows versions older than win95-osr2.
2468 // in fact, should we stop supporting it?
2469 bpp = vid_deskbpp;
2470 findbpp = 0;
2471 }
2472
2473 if (COM_CheckParm("-current"))
2474 { // user wants fullscreen and
2475 // with desktop dimensions
2476 if (vid_deskmode >= 0)
2477 {
2478 q_strlcat (modelist[vid_deskmode].modedesc, " (desktop)", MAX_DESC);
2479 vid_default = vid_deskmode;
2480 }
2481 else
2482 {
2483 Con_SafePrintf ("WARNING: desktop mode not available for the -current switch\n");
2484 }
2485 }
2486 else
2487 {
2488 // start parsing any dimension/bpp request from user
2489 i = COM_CheckParm("-width");
2490 if (i && i < com_argc-1)
2491 {
2492 width = atoi(com_argv[i+1]);
2493 if (width < 320)
2494 width = 320;
2495 height = 3 * width / 4;
2496 i = COM_CheckParm("-height");
2497 if (i && i < com_argc-1)
2498 {
2499 height = atoi(com_argv[i+1]);
2500 if (height < 240)
2501 height = 240;
2502 }
2503 }
2504
2505 i = COM_CheckParm("-bpp");
2506 if (i && i < com_argc-1 && !Win95old)
2507 {
2508 bpp = atoi(com_argv[i+1]);
2509 findbpp = 0;
2510 }
2511
2512 // if they want to force it, add the specified mode to the list
2513 if (COM_CheckParm("-force"))
2514 {
2515 fmodelist[num_fmodes].type = MS_FULLDIB;
2516 fmodelist[num_fmodes].width = width;
2517 fmodelist[num_fmodes].height = height;
2518 fmodelist[num_fmodes].modenum = 0;
2519 fmodelist[num_fmodes].halfscreen = 0;
2520 fmodelist[num_fmodes].dib = 1;
2521 fmodelist[num_fmodes].fullscreen = 1;
2522 fmodelist[num_fmodes].bpp = bpp;
2523 q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%dx%dx%d",
2524 fmodelist[num_fmodes].width, fmodelist[num_fmodes].height,
2525 fmodelist[num_fmodes].bpp);
2526
2527 for (i = 0, existingmode = 0; i < num_fmodes; i++)
2528 {
2529 if ((fmodelist[num_fmodes].width == fmodelist[i].width) &&
2530 (fmodelist[num_fmodes].height == fmodelist[i].height) &&
2531 (fmodelist[num_fmodes].bpp == modelist[i].bpp))
2532 {
2533 existingmode = 1;
2534 break;
2535 }
2536 }
2537
2538 if (!existingmode)
2539 {
2540 q_strlcat (fmodelist[num_fmodes].modedesc, " (user mode)", MAX_DESC);
2541 num_fmodes++;
2542 // re-sort the modes
2543 VID_SortModes();
2544 if (findbpp)
2545 bpp = bpplist[0][0];
2546 }
2547 }
2548
2549 if (vid_deskmode >= 0)
2550 q_strlcat (fmodelist[vid_deskmode].modedesc, " (desktop)", MAX_DESC);
2551
2552 j = done = 0;
2553
2554 do
2555 {
2556 for (i = 0; i < *nummodes; i++)
2557 {
2558 if ((modelist[i].width == width) &&
2559 (modelist[i].height == height) &&
2560 (modelist[i].bpp == bpp))
2561 {
2562 vid_default = i;
2563 done = 1;
2564 break;
2565 }
2566 }
2567
2568 if (!done)
2569 {
2570 if (findbpp)
2571 {
2572 if (bpp == bpplist[j][0])
2573 j++;
2574 if (j >= MAX_NUMBPP || !bpplist[j][0])
2575 done = 1;
2576 if (!done)
2577 bpp = bpplist[j][0];
2578 j++;
2579 }
2580 else
2581 {
2582 done = 1;
2583 }
2584 }
2585 } while (!done);
2586
2587 if (vid_default < 0)
2588 {
2589 Sys_Error ("Specified video mode not available:\n\n"
2590 "If you used -width,-height or -bpp commandline arguments,\n"
2591 "try changing their values. If your config.cfg has bad or stale\n"
2592 "video options, try changing them, or delete your config.cfg\n"
2593 "altogether and try again.");
2594 }
2595 }
2596 } // end of fullscreen parsing
2597
2598 if (!vid_conscale)
2599 Cvar_SetValueQuick (&vid_config_consize, width);
2600
2601 // This will display a bigger hud and readable fonts at high
2602 // resolutions. The fonts will be somewhat distorted, though
2603 i = COM_CheckParm("-conwidth");
2604 if (i != 0 && i < com_argc-1)
2605 i = atoi(com_argv[i + 1]);
2606 else i = vid_config_consize.integer;
2607 if (i < MIN_WIDTH) i = MIN_WIDTH;
2608 else if (i > width) i = width;
2609 Cvar_SetValueQuick(&vid_config_consize, i);
2610 if (vid_config_consize.integer != width)
2611 vid_conscale = true;
2612
2613 vid_initialized = true;
2614
2615 vid.maxwarpwidth = WARP_WIDTH;
2616 vid.maxwarpheight = WARP_HEIGHT;
2617 vid.colormap = host_colormap;
2618 vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
2619
2620 #if !defined(NO_SPLASHES)
2621 DestroyWindow (hwnd_dialog);
2622 #endif
2623
2624 if (COM_CheckParm("-paltex"))
2625 Cvar_SetQuick (&vid_config_gl8bit, "1");
2626
2627 j = scr_disabled_for_loading;
2628 scr_disabled_for_loading = true;
2629
2630 Cvar_SetValueQuick (&vid_mode, vid_default);
2631 VID_SetMode (vid_default, palette);
2632
2633 maindc = GetDC(mainwindow);
2634 bSetupPixelFormat(maindc);
2635
2636 baseRC = wglCreateContext_fp( maindc );
2637 if (!baseRC)
2638 Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
2639 if (!wglMakeCurrent_fp( maindc, baseRC ))
2640 Sys_Error ("wglMakeCurrent failed");
2641
2642 GL_SetupLightmapFmt();
2643 GL_Init ();
2644 VID_Init8bitPalette();
2645
2646 // lock the early-read cvars until Host_Init is finished
2647 for (i = 0; i < (int)num_readvars; i++)
2648 Cvar_LockVar (read_vars[i]);
2649
2650 scr_disabled_for_loading = j;
2651 vid.recalc_refdef = 1;
2652
2653 vid_menudrawfn = VID_MenuDraw;
2654 vid_menukeyfn = VID_MenuKey;
2655
2656 q_strlcpy (badmode.modedesc,"Bad mode", MAX_DESC);
2657 vid_canalttab = true;
2658
2659 // if (COM_CheckParm("-fullsbar"))
2660 // fullsbardraw = true;
2661 }
2662
2663
VID_Shutdown(void)2664 void VID_Shutdown (void)
2665 {
2666 HGLRC hRC;
2667 HDC hDC;
2668
2669 if (vid_initialized)
2670 {
2671 vid_canalttab = false;
2672 hRC = wglGetCurrentContext_fp();
2673 hDC = wglGetCurrentDC_fp();
2674
2675 if (maindc && gammaworks && SetDeviceGammaRamp_f)
2676 SetDeviceGammaRamp_f(maindc, orig_ramps);
2677
2678 wglMakeCurrent_fp(NULL, NULL);
2679
2680 if (hRC)
2681 wglDeleteContext_fp(hRC);
2682
2683 if (hDC && mainwindow)
2684 ReleaseDC(mainwindow, hDC);
2685
2686 if (modestate == MS_FULLDIB)
2687 ChangeDisplaySettings (NULL, 0);
2688
2689 if (maindc && mainwindow)
2690 ReleaseDC (mainwindow, maindc);
2691 maindc = NULL;
2692
2693 AppActivate(false, false);
2694 if (mainwindow)
2695 {
2696 ShowWindow(mainwindow, SW_HIDE);
2697 DestroyWindow(mainwindow);
2698 }
2699 if (classregistered)
2700 UnregisterClass(WM_CLASSNAME, global_hInstance);
2701 mainwindow = NULL;
2702 classregistered = false;
2703 #ifdef GL_DLSYM
2704 GL_CloseLibrary();
2705 #endif
2706 }
2707 }
2708
2709
VID_ToggleFullscreen(void)2710 void VID_ToggleFullscreen (void)
2711 {
2712 }
2713
2714
2715 #ifndef H2W /* unused in hexenworld */
D_ShowLoadingSize(void)2716 void D_ShowLoadingSize (void)
2717 {
2718 #if defined(DRAW_PROGRESSBARS)
2719 int cur_perc;
2720 static int prev_perc;
2721
2722 if (!vid_initialized)
2723 return;
2724
2725 cur_perc = loading_stage * 100;
2726 if (total_loading_size)
2727 cur_perc += current_loading_size * 100 / total_loading_size;
2728 if (cur_perc == prev_perc)
2729 return;
2730 prev_perc = cur_perc;
2731
2732 glDrawBuffer_fp (GL_FRONT);
2733
2734 SCR_DrawLoading();
2735
2736 glFlush_fp();
2737
2738 glDrawBuffer_fp (GL_BACK);
2739 #endif /* DRAW_PROGRESSBARS */
2740 }
2741 #endif
2742
2743
2744 //========================================================
2745 // Video menu stuff
2746 //========================================================
2747
2748 static int vid_menunum;
2749 static int vid_cursor;
2750 static vmode_t *vid_menulist; // this changes when vid_menu_fs changes
2751 static int vid_menubpp; // if this changes, vid_menunum already changes
2752 static qboolean vid_menu_fs;
2753 static qboolean want_fstoggle, need_apply;
2754 static qboolean vid_menu_firsttime = true;
2755
2756 enum {
2757 VID_FULLSCREEN,
2758 VID_RESOLUTION,
2759 VID_BPP,
2760 VID_MULTITEXTURE,
2761 VID_NPOT,
2762 VID_PALTEX,
2763 VID_BLANKLINE, // spacer line
2764 VID_RESET,
2765 VID_APPLY,
2766 VID_ITEMS
2767 };
2768
2769
M_DrawYesNo(int x,int y,int on,int white)2770 static void M_DrawYesNo (int x, int y, int on, int white)
2771 {
2772 if (on)
2773 {
2774 if (white)
2775 M_PrintWhite (x, y, "yes");
2776 else
2777 M_Print (x, y, "yes");
2778 }
2779 else
2780 {
2781 if (white)
2782 M_PrintWhite (x, y, "no");
2783 else
2784 M_Print (x, y, "no");
2785 }
2786 }
2787
2788 /*
2789 ================
2790 VID_MenuDraw
2791 ================
2792 */
VID_MenuDraw(void)2793 static void VID_MenuDraw (void)
2794 {
2795 ScrollTitle("gfx/menu/title7.lmp");
2796
2797 if (vid_menu_firsttime)
2798 { // settings for entering the menu first time
2799 vid_menunum = vid_modenum;
2800 vid_menubpp = modelist[vid_modenum].bpp;
2801 vid_menu_fs = (modestate != MS_WINDOWED);
2802 vid_menulist = (modestate == MS_WINDOWED) ? wmodelist : fmodelist;
2803 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2804 vid_menu_firsttime = false;
2805 }
2806
2807 want_fstoggle = ( ((modestate == MS_WINDOWED) && vid_menu_fs) || ((modestate != MS_WINDOWED) && !vid_menu_fs) );
2808
2809 need_apply = (vid_menunum != vid_modenum) || want_fstoggle ||
2810 (have_mtex && (gl_mtexable != !!gl_multitexture.integer)) ||
2811 (have_NPOT && (gl_tex_NPOT != !!gl_texture_NPOT.integer)) ||
2812 (have8bit && (is8bit != !!vid_config_gl8bit.integer));
2813
2814 M_Print (76, 92 + 8*VID_FULLSCREEN, "Fullscreen: ");
2815 M_DrawYesNo (76+12*8, 92 + 8*VID_FULLSCREEN, vid_menu_fs, !want_fstoggle);
2816
2817 M_Print (76, 92 + 8*VID_RESOLUTION, "Resolution: ");
2818 if (vid_menunum == vid_modenum)
2819 M_PrintWhite (76+12*8, 92 + 8*VID_RESOLUTION, vid_menulist[vid_menunum].modedesc);
2820 else
2821 M_Print (76+12*8, 92 + 8*VID_RESOLUTION, vid_menulist[vid_menunum].modedesc);
2822
2823 if (vid_menu_fs && num_fmodes && !Win95old)
2824 {
2825 M_Print (76, 92 + 8*VID_BPP, "Color BPP : ");
2826 if (vid_menubpp == modelist[vid_modenum].bpp)
2827 M_PrintWhite (76+12*8, 92 + 8*VID_BPP, va("%d",vid_menubpp));
2828 else
2829 M_Print (76+12*8, 92 + 8*VID_BPP, va("%d",vid_menubpp));
2830 }
2831
2832 M_Print (76, 92 + 8*VID_MULTITEXTURE, "Multitexturing:");
2833 if (have_mtex)
2834 M_DrawYesNo (76+16*8, 92 + 8*VID_MULTITEXTURE, gl_multitexture.integer, (gl_mtexable == !!gl_multitexture.integer));
2835 else
2836 M_PrintWhite (76+16*8, 92 + 8*VID_MULTITEXTURE, "Not found");
2837
2838 M_Print (76, 92 + 8*VID_NPOT, "NPOT textures :");
2839 if (have_NPOT)
2840 M_DrawYesNo (76+16*8, 92 + 8*VID_NPOT, gl_texture_NPOT.integer, (gl_tex_NPOT == !!gl_texture_NPOT.integer));
2841 else
2842 M_PrintWhite (76+16*8, 92 + 8*VID_NPOT, "Not found");
2843
2844 M_Print (76, 92 + 8*VID_PALTEX, "8 bit textures:");
2845 if (have8bit)
2846 M_DrawYesNo (76+16*8, 92 + 8*VID_PALTEX, vid_config_gl8bit.integer, (is8bit == !!vid_config_gl8bit.integer));
2847 else
2848 M_PrintWhite (76+16*8, 92 + 8*VID_PALTEX, "Not found");
2849
2850 if (need_apply)
2851 {
2852 M_Print (76, 92 + 8*VID_RESET, "RESET CHANGES");
2853 M_Print (76, 92 + 8*VID_APPLY, "APPLY CHANGES");
2854 }
2855
2856 M_DrawCharacter (64, 92 + vid_cursor*8, 12+((int)(realtime*4)&1));
2857 }
2858
find_bppnum(int incr)2859 static int find_bppnum (int incr)
2860 {
2861 int j, pos = -1;
2862
2863 if (!vid_menu_fs) // then it doesn't matter
2864 return 0;
2865
2866 for (j = 0; j < MAX_NUMBPP; j++)
2867 { // find the pos in the bpplist
2868 if (vid_menubpp == bpplist[j][0])
2869 {
2870 pos = j;
2871 j = j+incr;
2872 break;
2873 }
2874 }
2875 if (pos < 0)
2876 Sys_Error ("bpp unexpectedly not found in list");
2877 if (incr == 0)
2878 return pos;
2879 // find the next available bpp
2880 while (1)
2881 {
2882 if (j >= MAX_NUMBPP)
2883 j = 0;
2884 if (j < 0)
2885 j = MAX_NUMBPP-1;
2886 if (bpplist[j][0])
2887 break;
2888 j = j + incr;
2889 }
2890 return j;
2891 }
2892
match_mode_to_bpp(int bppnum)2893 static int match_mode_to_bpp (int bppnum)
2894 {
2895 int k, l;
2896
2897 k = bpplist[bppnum][1];
2898 l = bpplist[bppnum][1] + 1;
2899 for ( ; l < num_fmodes && fmodelist[l].bpp == vid_menubpp; l++)
2900 {
2901 if (fmodelist[vid_menunum].width == fmodelist[l].width &&
2902 fmodelist[vid_menunum].height == fmodelist[l].height)
2903 {
2904 k = l;
2905 break;
2906 }
2907 }
2908 return k;
2909 }
2910
match_windowed_fullscr_modes(void)2911 static int match_windowed_fullscr_modes (void)
2912 {
2913 int l;
2914 vmode_t *tmplist;
2915 int *tmpcount;
2916
2917 // choose the new mode
2918 tmplist = (vid_menu_fs) ? fmodelist : wmodelist;
2919 tmpcount = (vid_menu_fs) ? &num_fmodes : &num_wmodes;
2920 for (l = 0; l < *tmpcount; l++)
2921 {
2922 if (tmplist[l].width == vid_menulist[vid_menunum].width &&
2923 tmplist[l].height == vid_menulist[vid_menunum].height)
2924 {
2925 return l;
2926 }
2927 }
2928 return 0;
2929 }
2930
2931 /*
2932 ================
2933 VID_MenuKey
2934 ================
2935 */
VID_MenuKey(int key)2936 static void VID_MenuKey (int key)
2937 {
2938 int i;
2939 int *tmpnum;
2940
2941 switch (key)
2942 {
2943 case K_ESCAPE:
2944 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2945 M_Menu_Options_f ();
2946 break;
2947
2948 case K_UPARROW:
2949 S_LocalSound ("raven/menu1.wav");
2950 vid_cursor--;
2951 if (vid_cursor < 0)
2952 {
2953 vid_cursor = (need_apply) ? VID_ITEMS-1 : VID_BLANKLINE-1;
2954 }
2955 else if (vid_cursor == VID_BLANKLINE)
2956 {
2957 vid_cursor--;
2958 }
2959 if (!num_fmodes && vid_cursor == 0)
2960 {
2961 vid_cursor = VID_RESOLUTION;
2962 }
2963 if ( vid_cursor == VID_BPP && (!vid_menu_fs || !num_fmodes || Win95old ))
2964 {
2965 vid_cursor--;
2966 }
2967 break;
2968
2969 case K_DOWNARROW:
2970 S_LocalSound ("raven/menu1.wav");
2971 vid_cursor++;
2972 if (vid_cursor >= VID_ITEMS)
2973 {
2974 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2975 break;
2976 }
2977 if ( vid_cursor == VID_BPP && (!vid_menu_fs || !num_fmodes || Win95old ))
2978 vid_cursor++;
2979 if (vid_cursor >= VID_BLANKLINE)
2980 {
2981 if (need_apply)
2982 {
2983 if (vid_cursor == VID_BLANKLINE)
2984 vid_cursor++;
2985 }
2986 else
2987 {
2988 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2989 }
2990 }
2991 break;
2992
2993 case K_ENTER:
2994 switch (vid_cursor)
2995 {
2996 case VID_RESET:
2997 vid_menunum = vid_modenum;
2998 vid_menubpp = modelist[vid_modenum].bpp;
2999 vid_menu_fs = (modestate != MS_WINDOWED);
3000 vid_menulist = (modestate == MS_WINDOWED) ? wmodelist : fmodelist;
3001 Cvar_SetValueQuick (&vid_config_gl8bit, is8bit);
3002 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
3003 break;
3004 case VID_APPLY:
3005 if (need_apply)
3006 {
3007 Cvar_SetValueQuick(&vid_mode, vid_menunum);
3008 modelist = (vid_menu_fs) ? fmodelist : wmodelist;
3009 nummodes = (vid_menu_fs) ? &num_fmodes : &num_wmodes;
3010 VID_Restart_f();
3011 }
3012 vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
3013 break;
3014 }
3015 return;
3016
3017 case K_LEFTARROW:
3018 switch (vid_cursor)
3019 {
3020 case VID_FULLSCREEN:
3021 if (!num_fmodes)
3022 break;
3023 vid_menu_fs = !vid_menu_fs;
3024 vid_menunum = match_windowed_fullscr_modes();
3025 vid_menulist = (vid_menu_fs) ? fmodelist : wmodelist;
3026 vid_menubpp = vid_menulist[vid_menunum].bpp;
3027 break;
3028 case VID_RESOLUTION:
3029 S_LocalSound ("raven/menu1.wav");
3030 vid_menunum--;
3031 if (vid_menunum < 0 || vid_menubpp != vid_menulist[vid_menunum].bpp)
3032 vid_menunum++;
3033 break;
3034 case VID_BPP:
3035 i = find_bppnum (-1);
3036 if (vid_menubpp == bpplist[i][0])
3037 break;
3038 vid_menubpp = bpplist[i][0];
3039 //find a matching video mode for this bpp
3040 vid_menunum = match_mode_to_bpp(i);
3041 break;
3042 case VID_MULTITEXTURE:
3043 if (have_mtex)
3044 Cvar_SetQuick (&gl_multitexture, gl_multitexture.integer ? "0" : "1");
3045 break;
3046 case VID_NPOT:
3047 if (have_NPOT)
3048 Cvar_SetQuick (&gl_texture_NPOT, gl_texture_NPOT.integer ? "0" : "1");
3049 break;
3050 case VID_PALTEX:
3051 if (have8bit)
3052 Cvar_SetQuick (&vid_config_gl8bit, vid_config_gl8bit.integer ? "0" : "1");
3053 break;
3054 }
3055 return;
3056
3057 case K_RIGHTARROW:
3058 switch (vid_cursor)
3059 {
3060 case VID_FULLSCREEN:
3061 if (!num_fmodes)
3062 break;
3063 vid_menu_fs = !vid_menu_fs;
3064 vid_menunum = match_windowed_fullscr_modes();
3065 vid_menulist = (vid_menu_fs) ? fmodelist : wmodelist;
3066 vid_menubpp = vid_menulist[vid_menunum].bpp;
3067 break;
3068 case VID_RESOLUTION:
3069 S_LocalSound ("raven/menu1.wav");
3070 tmpnum = (vid_menu_fs) ? &num_fmodes : &num_wmodes;
3071 vid_menunum++;
3072 if (vid_menunum >= *tmpnum || vid_menubpp != vid_menulist[vid_menunum].bpp)
3073 vid_menunum--;
3074 break;
3075 case VID_BPP:
3076 i = find_bppnum (1);
3077 if (vid_menubpp == bpplist[i][0])
3078 break;
3079 vid_menubpp = bpplist[i][0];
3080 //find a matching video mode for this bpp
3081 vid_menunum = match_mode_to_bpp(i);
3082 break;
3083 case VID_MULTITEXTURE:
3084 if (have_mtex)
3085 Cvar_SetQuick (&gl_multitexture, gl_multitexture.integer ? "0" : "1");
3086 break;
3087 case VID_NPOT:
3088 if (have_NPOT)
3089 Cvar_SetQuick (&gl_texture_NPOT, gl_texture_NPOT.integer ? "0" : "1");
3090 break;
3091 case VID_PALTEX:
3092 if (have8bit)
3093 Cvar_SetQuick (&vid_config_gl8bit, vid_config_gl8bit.integer ? "0" : "1");
3094 break;
3095 }
3096 return;
3097
3098 default:
3099 break;
3100 }
3101 }
3102
3103