|
|
1.1 root 1: // gl_vidnt.c -- NT GL vid component
2:
3: #include "quakedef.h"
4: #include "winquake.h"
5: #include "resource.h"
6:
7: #define MAX_MODE_LIST 30
8: #define VID_ROW_SIZE 3
9: #define WARP_WIDTH 320
10: #define WARP_HEIGHT 200
11: #define MAXWIDTH 1600
12: #define MAXHEIGHT 1200
13:
14: #define MODE_WINDOWED 0
15: #define MODE_SETTABLE_WINDOW 2
16: #define NO_MODE (MODE_WINDOWED - 1)
17: #define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3)
18:
19: typedef struct {
20: modestate_t type;
21: int width;
22: int height;
23: int modenum;
24: int dib;
25: int fullscreen;
26: int bpp;
27: int halfscreen;
28: char modedesc[13];
29: } vmode_t;
30:
31: static vmode_t modelist[MAX_MODE_LIST];
32: static int nummodes;
33: static vmode_t *pcurrentmode;
34: static vmode_t badmode;
35:
36: static DEVMODE gdevmode;
37: static qboolean startwindowed = 0;
38: static int firstupdate = 1;
39: static qboolean vid_initialized = false;
40: static int vid_fulldib_on_focus_mode;
41: static qboolean force_minimized, in_mode_set, force_mode_set;
42: static int windowed_mouse;
43: static HICON hIcon;
44:
45: int DIBWidth, DIBHeight;
46: RECT WindowRect;
47: DWORD WindowStyle, ExWindowStyle;
48:
49: HWND mainwindow, dibwindow;
50: MGLDC *dibdc = NULL,*windc = NULL;
51:
52: int vid_modenum = NO_MODE;
53: int vid_testingmode, vid_realmode;
54: double vid_testendtime;
55: int vid_default = MODE_WINDOWED;
56: static int windowed_default;
57:
58: unsigned char vid_curpal[256*3];
59:
60: HGLRC baseRC;
61: HDC maindc;
62: HWND mainwindow;
63: RECT winrect;
64:
65: glvert_t glv;
66:
67: cvar_t gl_ztrick = {"gl_ztrick","0"};
68:
69: HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
70:
71: viddef_t vid; // global video state
72:
73: unsigned short d_8to16table[256];
74: unsigned d_8to24table[256];
75:
76: float gldepthmin, gldepthmax;
77:
78: int scr_skipupdate;
79: qboolean DDActive;
80: modestate_t modestate = MS_UNINIT;
81:
82: void VID_MenuDraw (void);
83: void VID_MenuKey (int key);
84:
85: LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
86: void AppActivate(BOOL fActive, BOOL minimize);
87: void DestroyDIBWindow (void);
88: void DestroyFullDIBWindow (void);
89: char *VID_GetModeDescription (int mode);
90: void ClearAllStates (void);
91: void VID_UpdateWindowStatus (void);
92:
93: PROC glArrayElementEXT;
94: PROC glColorPointerEXT;
95: PROC glTexCoordPointerEXT;
96: PROC glVertexPointerEXT;
97:
98: //====================================
99:
100: cvar_t vid_mode = {"vid_mode","0", false};
101: // Note that 0 is MODE_WINDOWED
102: cvar_t _vid_default_mode = {"_vid_default_mode","0", true};
103: // Note that 3 is MODE_FULLSCREEN_DEFAULT
104: cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true};
105: cvar_t vid_wait = {"vid_wait","0"};
106: cvar_t vid_nopageflip = {"vid_nopageflip","0", true};
107: cvar_t _vid_wait_override = {"_vid_wait_override", "0", true};
108: cvar_t vid_config_x = {"vid_config_x","800", true};
109: cvar_t vid_config_y = {"vid_config_y","600", true};
110: cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
111: cvar_t _windowed_mouse = {"_windowed_mouse","0", true};
112:
113: int window_center_x, window_center_y, window_x, window_y, window_width, window_height;
114: RECT window_rect;
115: qboolean in_mode_set;
116: qboolean vid_fulldib_on_focus_mode;
117: qboolean force_minimized;
118:
119: // direct draw software compatability stuff
120:
121: void VID_HandlePause (qboolean pause)
122: {
123: }
124:
125: void VID_ForceLockState (int lk)
126: {
127: }
128:
129: void VID_LockBuffer (void)
130: {
131: }
132:
133: void VID_UnlockBuffer (void)
134: {
135: }
136:
137: int VID_ForceUnlockedAndReturnState (void)
138: {
139: return 0;
140: }
141:
142: void VID_Update (vrect_t *rects)
143: {
144: }
145:
146: void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
147: {
148: }
149:
150: void D_EndDirectRect (int x, int y, int width, int height)
151: {
152: }
153:
154:
155: void initFatalError(void)
156: {
157: MGL_exit();
158: MGL_fatalError(MGL_errorMsg(MGL_result()));
159: exit(EXIT_FAILURE);
160: }
161:
162:
163: void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify)
164: {
165: RECT RectCenter;
166: int CenterX, CenterY;
167:
168: if (lefttopjustify)
169: {
170: CenterX = 0;
171: CenterY = 0;
172: }
173: else
174: {
175: CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
176: CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
177: CenterX = (CenterX < 0) ? 0: CenterX;
178: CenterY = (CenterY < 0) ? 0: CenterY;
179: }
180:
181: SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0,
182: SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
183: }
184:
185: qboolean VID_SetWindowedMode (int modenum)
186: {
187: HDC hdc;
188: pixel_format_t pf;
189: int lastmodestate;
190:
191: DDActive = 0;
192: lastmodestate = modestate;
193:
194: DestroyFullDIBWindow ();
195:
196: // KJB: Signal to the MGL that we are going back to windowed mode
197: if (!MGL_changeDisplayMode(grWINDOWED))
198: initFatalError();
199:
200: WindowRect.top = WindowRect.left = 0;
201:
202: WindowRect.right = modelist[modenum].width;
203: WindowRect.bottom = modelist[modenum].height;
204:
205: DIBWidth = modelist[modenum].width;
206: DIBHeight = modelist[modenum].height;
207:
208: WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
209: WS_MINIMIZEBOX;
210: ExWindowStyle = 0;
211: AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0);
212:
213: if (lastmodestate != MS_WINDOWED)
214: {
215: // Create the DIB window
216: dibwindow = CreateWindowEx (
217: ExWindowStyle,
218: "WinQuake",
219: "GLQuake",
220: WindowStyle,
221: 0, 0,
222: WindowRect.right - WindowRect.left,
223: WindowRect.bottom - WindowRect.top,
224: NULL,
225: NULL,
226: global_hInstance,
227: NULL);
228:
229: if (!dibwindow)
230: Sys_Error ("Couldn't create DIB window");
231: }
232: else
233: {
234: if (!SetWindowPos (dibwindow,
235: NULL,
236: 0, 0,
237: WindowRect.right - WindowRect.left,
238: WindowRect.bottom - WindowRect.top,
239: SWP_NOCOPYBITS | SWP_NOZORDER |
240: SWP_HIDEWINDOW))
241: {
242: Sys_Error ("Couldn't resize DIB window");
243: }
244: }
245:
246: // Center and show the DIB window
247: CenterWindow(dibwindow, WindowRect.right - WindowRect.left,
248: WindowRect.bottom - WindowRect.top, false);
249:
250: if (force_minimized)
251: ShowWindow (dibwindow, SW_MINIMIZE);
252: else
253: ShowWindow (dibwindow, SW_SHOWDEFAULT);
254:
255: UpdateWindow (dibwindow);
256:
257: modestate = MS_WINDOWED;
258: vid_fulldib_on_focus_mode = 0;
259:
260: // because we have set the background brush for the window to NULL
261: // (to avoid flickering when re-sizing the window on the desktop),
262: // we clear the window to black when created, otherwise it will be
263: // empty while Quake starts up.
264: hdc = GetDC(dibwindow);
265: PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
266: ReleaseDC(dibwindow, hdc);
267:
268: /* Create the MGL window DC and the MGL memory DC */
269: if ((windc = MGL_createWindowedDC(dibwindow)) == NULL)
270: MGL_fatalError("Unable to create Windowed DC!");
271:
272: if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL)
273: MGL_fatalError("Unable to create Memory DC!");
274:
275: MGL_makeCurrentDC(dibdc);
276:
277: vid.buffer = vid.conbuffer = vid.direct = dibdc->surface;
278: vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine;
279: vid.numpages = 1;
280: vid.maxwarpwidth = WARP_WIDTH;
281: vid.maxwarpheight = WARP_HEIGHT;
282: vid.height = vid.conheight = DIBHeight;
283: vid.width = vid.conwidth = DIBWidth;
284: vid.aspect = ((float)vid.height / (float)vid.width) *
285: (320.0 / 240.0);
286:
287: mainwindow = dibwindow;
288:
289: SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
290: SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
291:
292: return true;
293: }
294:
295:
296: qboolean VID_SetFullDIBMode (int modenum)
297: {
298: HDC hdc;
299: pixel_format_t pf;
300: int lastmodestate;
301:
302: DDActive = 0;
303:
304: DestroyDIBWindow ();
305:
306: // KJB: Signal to the MGL that we are going back to windowed mode
307: if (!MGL_changeDisplayMode(grWINDOWED))
308: initFatalError();
309:
310: gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
311: gdevmode.dmBitsPerPel = modelist[modenum].bpp;
312: gdevmode.dmPelsWidth = modelist[modenum].width <<
313: modelist[modenum].halfscreen;
314: gdevmode.dmPelsHeight = modelist[modenum].height;
315: gdevmode.dmSize = sizeof (gdevmode);
316:
317: if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
318: Sys_Error ("Couldn't set fullscreen DIB mode");
319:
320: lastmodestate = modestate;
321: modestate = MS_FULLDIB;
322: vid_fulldib_on_focus_mode = modenum;
323:
324: WindowRect.top = WindowRect.left = 0;
325:
326: hdc = GetDC(NULL);
327:
328: WindowRect.right = modelist[modenum].width;
329: WindowRect.bottom = modelist[modenum].height;
330:
331: ReleaseDC(NULL,hdc);
332:
333: DIBWidth = modelist[modenum].width;
334: DIBHeight = modelist[modenum].height;
335:
336: WindowStyle = WS_POPUP;
337: ExWindowStyle = 0;
338: AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0);
339:
340: if (lastmodestate != MS_FULLDIB)
341: {
342: // Create the DIB window
343: dibwindow = CreateWindowEx (
344: ExWindowStyle,
345: "WinQuake",
346: "GLQuake",
347: WindowStyle,
348: 0, 0,
349: WindowRect.right - WindowRect.left,
350: WindowRect.bottom - WindowRect.top,
351: NULL,
352: NULL,
353: global_hInstance,
354: NULL);
355:
356: if (!dibwindow)
357: Sys_Error ("Couldn't create DIB window");
358: }
359: else
360: {
361: if (!SetWindowPos (dibwindow,
362: NULL,
363: 0, 0,
364: WindowRect.right - WindowRect.left,
365: WindowRect.bottom - WindowRect.top,
366: SWP_NOCOPYBITS | SWP_NOZORDER))
367: {
368: Sys_Error ("Couldn't resize DIB window");
369: }
370: }
371:
372: // Center and show the DIB window
373: CenterWindow(dibwindow,
374: WindowRect.right - WindowRect.left,
375: WindowRect.bottom - WindowRect.top,
376: modelist[modenum].halfscreen);
377: ShowWindow (dibwindow, SW_SHOWDEFAULT);
378: UpdateWindow (dibwindow);
379:
380: // Because we have set the background brush for the window to NULL
381: // (to avoid flickering when re-sizing the window on the desktop), we
382: // clear the window to black when created, otherwise it will be
383: // empty while Quake starts up.
384: hdc = GetDC(dibwindow);
385: PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
386: ReleaseDC(dibwindow, hdc);
387:
388: /* Create the MGL window DC and the MGL memory DC */
389: if ((windc = MGL_createWindowedDC(dibwindow)) == NULL)
390: MGL_fatalError("Unable to create Fullscreen DIB DC!");
391:
392: if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL)
393: MGL_fatalError("Unable to create Memory DC!");
394:
395: MGL_makeCurrentDC(dibdc);
396:
397: vid.buffer = vid.conbuffer = vid.direct = dibdc->surface;
398: vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine;
399: vid.numpages = 1;
400: vid.maxwarpwidth = WARP_WIDTH;
401: vid.maxwarpheight = WARP_HEIGHT;
402: vid.height = vid.conheight = DIBHeight;
403: vid.width = vid.conwidth = DIBWidth;
404: vid.aspect = ((float)vid.height / (float)vid.width) *
405: (320.0 / 240.0);
406:
407: // needed because we're not getting WM_MOVE messages fullscreen on NT
408: window_x = 0;
409: window_y = 0;
410:
411: mainwindow = dibwindow;
412: return true;
413: }
414:
415:
416: void VID_RestoreOldMode (int original_mode)
417: {
418: static qboolean inerror = false;
419:
420: if (inerror)
421: return;
422:
423: in_mode_set = false;
424: inerror = true;
425:
426: // make sure mode set happens (video mode changes)
427: vid_modenum = original_mode - 1;
428:
429: if (!VID_SetMode (original_mode, vid_curpal))
430: {
431: vid_modenum = MODE_WINDOWED - 1;
432:
433: if (!VID_SetMode (windowed_default, vid_curpal))
434: Sys_Error ("Can't set any video mode");
435: }
436:
437: inerror = false;
438: }
439:
440:
441: int VID_SetMode (int modenum, unsigned char *palette)
442: {
443: int original_mode, temp;
444: qboolean stat;
445: MSG msg;
446: HDC hdc;
447:
448: while ((modenum >= nummodes) || (modenum < 0))
449: {
450: if (vid_modenum == NO_MODE)
451: {
452: if (modenum == vid_default)
453: {
454: modenum = windowed_default;
455: }
456: else
457: {
458: modenum = vid_default;
459: }
460:
461: Cvar_SetValue ("vid_mode", (float)modenum);
462: }
463: else
464: {
465: Cvar_SetValue ("vid_mode", (float)vid_modenum);
466: return 0;
467: }
468: }
469:
470: if (!force_mode_set && (modenum == vid_modenum))
471: return true;
472:
473: // so Con_Printfs don't mess us up by forcing vid and snd updates
474: temp = scr_disabled_for_loading;
475: scr_disabled_for_loading = true;
476: in_mode_set = true;
477:
478: Snd_ReleaseBuffer ();
479: CDAudio_Pause ();
480:
481: if (vid_modenum == NO_MODE)
482: original_mode = windowed_default;
483: else
484: original_mode = vid_modenum;
485:
486: // Set either the fullscreen or windowed mode
487: if (modelist[modenum].type == MS_WINDOWED)
488: {
489: if (_windowed_mouse.value)
490: {
491: stat = VID_SetWindowedMode(modenum);
492: IN_ActivateMouse ();
493: IN_HideMouse ();
494: }
495: else
496: {
497: IN_DeactivateMouse ();
498: IN_ShowMouse ();
499: stat = VID_SetWindowedMode(modenum);
500: }
501: }
502: else if (modelist[modenum].type == MS_FULLDIB)
503: {
504: stat = VID_SetFullDIBMode(modenum);
505: IN_ActivateMouse ();
506: IN_HideMouse ();
507: }
508: else
509: {
510: Sys_Error ("VID_SetMode: Bad mode type in modelist");
511: }
512:
513: window_width = vid.width;
514: window_height = vid.height;
515: VID_UpdateWindowStatus ();
516:
517: CDAudio_Resume ();
518: Snd_AcquireBuffer ();
519: scr_disabled_for_loading = temp;
520:
521: if (!stat)
522: {
523: VID_RestoreOldMode (original_mode);
524: return false;
525: }
526:
527: // now we try to make sure we get the focus on the mode switch, because
528: // sometimes in some systems we don't. We grab the foreground, then
529: // finish setting up, pump all our messages, and sleep for a little while
530: // to let messages finish bouncing around the system, then we put
531: // ourselves at the top of the z order, then grab the foreground again,
532: // Who knows if it helps, but it probably doesn't hurt
533: if (!force_minimized)
534: SetForegroundWindow (mainwindow);
535:
536: VID_SetPalette (palette);
537:
538: vid_modenum = modenum;
539: Cvar_SetValue ("vid_mode", (float)vid_modenum);
540:
541: while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
542: {
543: TranslateMessage (&msg);
544: DispatchMessage (&msg);
545: }
546:
547: Sleep (100);
548:
549: if (!force_minimized)
550: {
551: SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
552: SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
553: SWP_NOCOPYBITS);
554:
555: SetForegroundWindow (mainwindow);
556: }
557:
558: // fix the leftover Alt from any Alt-Tab or the like that switched us away
559: ClearAllStates ();
560:
561: if (!msg_suppress_1)
562: Con_SafePrintf ("%s\n", VID_GetModeDescription (vid_modenum));
563:
564: VID_SetPalette (palette);
565:
566: in_mode_set = false;
567: vid.recalc_refdef = 1;
568:
569: return true;
570: }
571:
572:
573: /*
574: ================
575: VID_UpdateWindowStatus
576: ================
577: */
578: void VID_UpdateWindowStatus (void)
579: {
580:
581: window_rect.left = window_x;
582: window_rect.top = window_y;
583: window_rect.right = window_x + window_width;
584: window_rect.bottom = window_y + window_height;
585: window_center_x = (window_rect.left + window_rect.right) / 2;
586: window_center_y = (window_rect.top + window_rect.bottom) / 2;
587:
588: IN_UpdateClipCursor ();
589: }
590:
591:
592: //====================================
593:
594: BINDTEXFUNCPTR bindTexFunc;
595: DELTEXFUNCPTR delTexFunc;
596:
597: #define TEXTURE_EXT_STRING "GL_EXT_texture_object"
598:
599:
600: void CheckTextureExtensions (void)
601: {
602: char *tmp;
603: qboolean texture_ext;
604:
605:
606: texture_ext = FALSE;
607: /* check for texture extension */
608: tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
609: while (*tmp)
610: {
611: if (strncmp((const char*)tmp, TEXTURE_EXT_STRING, strlen(TEXTURE_EXT_STRING)) == 0)
612: texture_ext = TRUE;
613: tmp++;
614: }
615:
616: if (!texture_ext || COM_CheckParm ("-gl11") )
617: {
618: #if 0 //@@@
619: bindTexFunc = glBindTexture;
620: delTexFunc = glDeleteTextures;
621: #endif
622: return;
623: }
624:
625: /* load library and get procedure adresses for texture extension API */
626: if ((bindTexFunc = (BINDTEXFUNCPTR)
627: wglGetProcAddress((LPCSTR) "glBindTextureEXT")) == NULL)
628: {
629: Sys_Error ("GetProcAddress for BindTextureEXT failed");
630: return;
631: }
632: if ((delTexFunc = (DELTEXFUNCPTR)
633: wglGetProcAddress((LPCSTR) "glDeleteTexturesEXT")) == NULL)
634: {
635: Sys_Error ("GetProcAddress for DeleteTexturesEXT failed");
636: return;
637: }
638:
639: }
640:
641: void CheckArrayExtensions (void)
642: {
643: char *tmp;
644:
645: /* check for texture extension */
646: tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
647: while (*tmp)
648: {
649: if (strncmp((const char*)tmp, "GL_EXT_vertex_array", strlen("GL_EXT_vertex_array")) == 0)
650: {
651: if (
652: ((glArrayElementEXT = wglGetProcAddress("glArrayElementEXT")) == NULL) ||
653: ((glColorPointerEXT = wglGetProcAddress("glColorPointerEXT")) == NULL) ||
654: ((glTexCoordPointerEXT = wglGetProcAddress("glTexCoordPointerEXT")) == NULL) ||
655: ((glVertexPointerEXT = wglGetProcAddress("glVertexPointerEXT")) == NULL) )
656: {
657: Sys_Error ("GetProcAddress for vertex extension failed");
658: return;
659: }
660: return;
661: }
662: tmp++;
663: }
664:
665: Sys_Error ("Vertex array extension not present");
666: }
667:
668: //int texture_mode = GL_NEAREST;
669: //int texture_mode = GL_NEAREST_MIPMAP_NEAREST;
670: //int texture_mode = GL_NEAREST_MIPMAP_LINEAR;
671: int texture_mode = GL_LINEAR;
672: //int texture_mode = GL_LINEAR_MIPMAP_NEAREST;
673: //int texture_mode = GL_LINEAR_MIPMAP_LINEAR;
674:
675: int texture_extension_number = 1;
676:
677: /*
678: ===============
679: GL_Init
680: ===============
681: */
682: void GL_Init (void)
683: {
684: CheckTextureExtensions ();
685:
686: glCullFace(GL_FRONT);
687: glEnable(GL_TEXTURE_2D);
688: glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
689: glShadeModel (GL_FLAT);
690:
691: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
692: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
693: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
694: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
695:
696: glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
697:
698: // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
699: glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
700:
701: #if 0
702: CheckArrayExtensions ();
703:
704: glEnable (GL_VERTEX_ARRAY_EXT);
705: glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
706: glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
707: glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
708: glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
709: #endif
710: }
711:
712: /*
713: =================
714: GL_BeginRendering
715:
716: =================
717: */
718: void GL_BeginRendering (int *width, int *height)
719: {
720: extern cvar_t gl_clear;
721:
722: GetClientRect(mainwindow, &winrect);
723: *width = winrect.right - winrect.left;
724: *height = winrect.bottom - winrect.top;
725:
726: if (!wglMakeCurrent( maindc, baseRC ))
727: Sys_Error ("wglMakeCurrent failed");
728:
729: if (gl_ztrick.value)
730: {
731: static int trickframe;
732:
733: if (gl_clear.value)
734: glClear (GL_COLOR_BUFFER_BIT);
735:
736: trickframe++;
737: if (trickframe & 1)
738: {
739: gldepthmin = 0;
740: gldepthmax = 0.49999;
741: glDepthFunc (GL_LEQUAL);
742: }
743: else
744: {
745: gldepthmin = 1;
746: gldepthmax = 0.5;
747: glDepthFunc (GL_GEQUAL);
748: }
749: }
750: else
751: {
752: if (gl_clear.value)
753: glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
754: else
755: glClear (GL_DEPTH_BUFFER_BIT);
756: gldepthmin = 0;
757: gldepthmax = 1;
758: glDepthFunc (GL_LEQUAL);
759: }
760:
761: glDepthRange (gldepthmin, gldepthmax);
762: glViewport (0, 0, *width, *height);
763: }
764:
765: void GL_EndRendering (void)
766: {
767: SwapBuffers(maindc);
768: }
769:
770:
771:
772:
773: void VID_SetPalette (unsigned char *palette)
774: {
775: byte *pal;
776: int r,g,b,v;
777: int i;
778: unsigned *table;
779:
780:
781: //
782: // 8 8 8 encoding
783: //
784: pal = palette;
785: table = d_8to24table;
786:
787: for (i=0 ; i<256 ; i++)
788: {
789: r = pal[0];
790: g = pal[1];
791: b = pal[2];
792: pal += 3;
793:
794: // v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
795: // v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
796: v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
797: *table++ = v;
798: }
799:
800: d_8to24table[255] &= 0xffffff; // 255 is transparent
801: }
802:
803: BOOL gammaworks;
804: void VID_ShiftPalette (unsigned char *palette)
805: {
806: extern byte ramps[3][256];
807:
808: // VID_SetPalette (palette);
809: gammaworks = SetDeviceGammaRamp (maindc, ramps);
810: }
811:
812:
813: void VID_Shutdown (void)
814: {
815: HDC hdc;
816:
817: if (vid_initialized)
818: {
819: if (modestate == MS_FULLDIB)
820: ChangeDisplaySettings (NULL, 0);
821:
822: PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0);
823: PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0);
824:
825: AppActivate(false, false);
826: DestroyDIBWindow ();
827: DestroyFullDIBWindow ();
828: MGL_exit();
829: vid_testingmode = 0;
830: }
831: }
832:
833:
834: //==========================================================================
835:
836:
837: BOOL bSetupPixelFormat(HDC hDC)
838: {
839: static PIXELFORMATDESCRIPTOR pfd = {
840: sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
841: 1, // version number
842: PFD_DRAW_TO_WINDOW // support window
843: | PFD_SUPPORT_OPENGL // support OpenGL
844: | PFD_DOUBLEBUFFER , // double buffered
845: PFD_TYPE_RGBA, // RGBA type
846: 24, // 24-bit color depth
847: 0, 0, 0, 0, 0, 0, // color bits ignored
848: 0, // no alpha buffer
849: 0, // shift bit ignored
850: 0, // no accumulation buffer
851: 0, 0, 0, 0, // accum bits ignored
852: 32, // 32-bit z-buffer
853: 0, // no stencil buffer
854: 0, // no auxiliary buffer
855: PFD_MAIN_PLANE, // main layer
856: 0, // reserved
857: 0, 0, 0 // layer masks ignored
858: };
859: int pixelformat;
860:
861: if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
862: {
863: MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
864: return FALSE;
865: }
866:
867: if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE)
868: {
869: MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
870: return FALSE;
871: }
872:
873: return TRUE;
874: }
875:
876:
877:
878: byte scantokey[128] =
879: {
880: // 0 1 2 3 4 5 6 7
881: // 8 9 A B C D E F
882: 0 , 27, '1', '2', '3', '4', '5', '6',
883: '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
884: 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
885: 'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1
886: 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
887: '\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
888: 'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*',
889: K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
890: K_F6, K_F7, K_F8, K_F9, K_F10,0 , 0 , K_HOME,
891: K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4
892: K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11,
893: K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
894: 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
895: 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
896: 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
897: 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
898: };
899:
900: byte shiftscantokey[128] =
901: {
902: // 0 1 2 3 4 5 6 7
903: // 8 9 A B C D E F
904: 0 , 27, '!', '@', '#', '$', '%', '^',
905: '&', '*', '(', ')', '_', '+', K_BACKSPACE, 9, // 0
906: 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
907: 'O', 'P', '{', '}', 13 , K_CTRL,'A', 'S', // 1
908: 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
909: '"' , '~', K_SHIFT,'|', 'Z', 'X', 'C', 'V', // 2
910: 'B', 'N', 'M', '<', '>', '?', K_SHIFT,'*',
911: K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
912: K_F6, K_F7, K_F8, K_F9, K_F10,0 , 0 , K_HOME,
913: K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4
914: K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11,
915: K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
916: 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
917: 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
918: 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
919: 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
920: };
921:
922:
923: /*
924: =======
925: MapKey
926:
927: Map from windows to quake keynums
928: =======
929: */
930: int MapKey (int key)
931: {
932: key = (key>>16)&255;
933: if (key > 127)
934: return 0;
935: return scantokey[key];
936: }
937:
938: /*
939: ===================================================================
940:
941: MAIN WINDOW
942:
943: ===================================================================
944: */
945:
946: /*
947: ================
948: ClearAllStates
949: ================
950: */
951: void ClearAllStates (void)
952: {
953: int i;
954:
955: // send an up event for each key, to make sure the server clears them all
956: for (i=0 ; i<256 ; i++)
957: {
958: Key_Event (i, false);
959: }
960:
961: Key_ClearStates ();
962: IN_ClearStates ();
963: }
964:
965: void AppActivate(BOOL fActive, BOOL minimize)
966: /****************************************************************************
967: *
968: * Function: AppActivate
969: * Parameters: fActive - True if app is activating
970: *
971: * Description: If the application is activating, then swap the system
972: * into SYSPAL_NOSTATIC mode so that our palettes will display
973: * correctly.
974: *
975: ****************************************************************************/
976: {
977: HDC hdc;
978: int i, t;
979: static BOOL sound_active;
980:
981: ActiveApp = fActive;
982: Minimized = minimize;
983:
984: // enable/disable sound on focus gain/loss
985: if (!ActiveApp && sound_active)
986: {
987: S_BlockSound ();
988: Snd_ReleaseBuffer ();
989: sound_active = false;
990: }
991: else if (ActiveApp && !sound_active)
992: {
993: Snd_AcquireBuffer ();
994: S_UnblockSound ();
995: sound_active = true;
996: }
997:
998: // minimize/restore fulldib windows/mouse-capture normal windows on demand
999: if (!in_mode_set)
1000: {
1001: if (fActive)
1002: {
1003: if (vid_fulldib_on_focus_mode)
1004: {
1005: msg_suppress_1 = true; // don't want to see normal mode set message
1006: VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal);
1007: msg_suppress_1 = false;
1008:
1009: t = in_mode_set;
1010: in_mode_set = true;
1011: AppActivate (true, false);
1012: in_mode_set = t;
1013:
1014: IN_ActivateMouse ();
1015: IN_HideMouse ();
1016: }
1017: else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
1018: {
1019: IN_ActivateMouse ();
1020: IN_HideMouse ();
1021: }
1022: }
1023:
1024: if (!fActive)
1025: {
1026: if (modestate == MS_FULLDIB)
1027: {
1028: force_minimized = true;
1029: i = vid_fulldib_on_focus_mode;
1030: msg_suppress_1 = true; // don't want to see normal mode set message
1031: VID_SetMode (windowed_default, vid_curpal);
1032: msg_suppress_1 = false;
1033: vid_fulldib_on_focus_mode = i;
1034: force_minimized = false;
1035:
1036: // we never seem to get WM_ACTIVATE inactive from this mode set, so we'll
1037: // do it manually
1038: t = in_mode_set;
1039: in_mode_set = true;
1040: AppActivate (false, true);
1041: in_mode_set = t;
1042:
1043: IN_DeactivateMouse ();
1044: IN_ShowMouse ();
1045: }
1046: else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
1047: {
1048: IN_DeactivateMouse ();
1049: IN_ShowMouse ();
1050: }
1051: }
1052: }
1053: }
1054:
1055:
1056: /* main window procedure */
1057: LONG WINAPI MainWndProc (
1058: HWND hWnd,
1059: UINT uMsg,
1060: WPARAM wParam,
1061: LPARAM lParam)
1062: {
1063: LONG lRet = 1;
1064: RECT rect;
1065: int fwKeys, xPos, yPos, fActive, fMinimized, temp;
1066:
1067: GetClientRect(hWnd, &rect);
1068:
1069: switch (uMsg)
1070: {
1071: case WM_CREATE:
1072: {
1073: //@@@
1074: }
1075: break;
1076:
1077: case WM_MOVE:
1078: window_x = (int) LOWORD(lParam);
1079: window_y = (int) HIWORD(lParam);
1080: VID_UpdateWindowStatus ();
1081: break;
1082:
1083: case WM_KEYDOWN:
1084: case WM_SYSKEYDOWN:
1085: Key_Event (MapKey(lParam), true);
1086: break;
1087:
1088: case WM_KEYUP:
1089: case WM_SYSKEYUP:
1090: Key_Event (MapKey(lParam), false);
1091: break;
1092:
1093: // this is complicated because Win32 seems to pack multiple mouse events into
1094: // one update sometimes, so we always check all states and look for events
1095: case WM_LBUTTONDOWN:
1096: case WM_LBUTTONUP:
1097: case WM_RBUTTONDOWN:
1098: case WM_RBUTTONUP:
1099: case WM_MBUTTONDOWN:
1100: case WM_MBUTTONUP:
1101: case WM_MOUSEMOVE:
1102: temp = 0;
1103:
1104: if (wParam & MK_LBUTTON)
1105: temp |= 1;
1106:
1107: if (wParam & MK_RBUTTON)
1108: temp |= 2;
1109:
1110: if (wParam & MK_MBUTTON)
1111: temp |= 4;
1112:
1113: IN_MouseEvent (temp);
1114:
1115: break;
1116:
1117:
1118: case WM_SIZE:
1119: break;
1120:
1121: case WM_CLOSE:
1122: {
1123: HGLRC hRC;
1124: HDC hDC;
1125:
1126: /* release and free the device context and rendering context */
1127: hRC = wglGetCurrentContext();
1128: hDC = wglGetCurrentDC();
1129:
1130: wglMakeCurrent(NULL, NULL);
1131:
1132: if (hRC)
1133: wglDeleteContext(hRC);
1134: if (hDC)
1135: ReleaseDC(hWnd, hDC);
1136:
1137: /* call destroy window to cleanup and go away */
1138: DestroyWindow (hWnd);
1139: }
1140: break;
1141:
1142: case WM_ACTIVATE:
1143: fActive = LOWORD(wParam);
1144: fMinimized = (BOOL) HIWORD(wParam);
1145: AppActivate(!(fActive == WA_INACTIVE), fMinimized);
1146:
1147: // fix the leftover Alt from any Alt-Tab or the like that switched us away
1148: ClearAllStates ();
1149:
1150: break;
1151:
1152: case WM_DESTROY:
1153: {
1154: HGLRC hRC;
1155: HDC hDC;
1156:
1157: /* release and free the device context and rendering context */
1158: hRC = wglGetCurrentContext();
1159: hDC = wglGetCurrentDC();
1160:
1161: wglMakeCurrent(NULL, NULL);
1162:
1163: if (hRC)
1164: wglDeleteContext(hRC);
1165: if (hDC)
1166: ReleaseDC(hWnd, hDC);
1167:
1168: PostQuitMessage (0);
1169: }
1170: break;
1171:
1172: default:
1173: /* pass all unhandled messages to DefWindowProc */
1174: lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
1175: break;
1176: }
1177:
1178: /* return 1 if handled message, 0 if not */
1179: return lRet;
1180: }
1181:
1182:
1183: /*
1184: =================
1185: VID_NumModes
1186: =================
1187: */
1188: int VID_NumModes (void)
1189: {
1190: return nummodes;
1191: }
1192:
1193:
1194: /*
1195: =================
1196: VID_GetModePtr
1197: =================
1198: */
1199: vmode_t *VID_GetModePtr (int modenum)
1200: {
1201:
1202: if ((modenum >= 0) && (modenum < nummodes))
1203: return &modelist[modenum];
1204: else
1205: return &badmode;
1206: }
1207:
1208:
1209: /*
1210: =================
1211: VID_GetModeDescription
1212: =================
1213: */
1214: char *VID_GetModeDescription (int mode)
1215: {
1216: char *pinfo;
1217: vmode_t *pv;
1218:
1219: if ((mode < 0) || (mode >= nummodes))
1220: return NULL;
1221:
1222: pv = VID_GetModePtr (mode);
1223: pinfo = pv->modedesc;
1224: return pinfo;
1225: }
1226:
1227:
1228: /*
1229: =================
1230: VID_GetModeDescription2
1231:
1232: Tacks on "windowed" or "fullscreen"
1233: =================
1234: */
1235: char *VID_GetModeDescription2 (int mode)
1236: {
1237: static char pinfo[40];
1238: vmode_t *pv;
1239:
1240: if ((mode < 0) || (mode >= nummodes))
1241: return NULL;
1242:
1243: pv = VID_GetModePtr (mode);
1244:
1245: if (modelist[mode].type == MS_FULLDIB)
1246: {
1247: sprintf(pinfo,"%s fullscreen", pv->modedesc);
1248: }
1249: else
1250: {
1251: sprintf(pinfo, "%s windowed", pv->modedesc);
1252: }
1253:
1254: return pinfo;
1255: }
1256:
1257:
1258: // KJB: Added this to return the mode driver name in description for console
1259:
1260: char *VID_GetExtModeDescription (int mode)
1261: {
1262: static char pinfo[40];
1263: vmode_t *pv;
1264:
1265: if ((mode < 0) || (mode >= nummodes))
1266: return NULL;
1267:
1268: pv = VID_GetModePtr (mode);
1269: if (modelist[mode].type == MS_FULLDIB)
1270: {
1271: sprintf(pinfo,"%s fullscreen DIB", pv->modedesc);
1272: }
1273: else
1274: {
1275: sprintf(pinfo, "%s windowed", pv->modedesc);
1276: }
1277:
1278: return pinfo;
1279: }
1280:
1281:
1282: void DestroyDIBWindow (void)
1283: {
1284:
1285: if (modestate == MS_WINDOWED)
1286: {
1287: // Destroy the DIB window and associated MGL DC's
1288: DestroyWindow(dibwindow);
1289: MGL_destroyDC(windc);
1290: MGL_destroyDC(dibdc);
1291: windc = dibdc = NULL;
1292: }
1293: }
1294:
1295:
1296: void DestroyFullDIBWindow (void)
1297: {
1298: if (modestate == MS_FULLDIB)
1299: {
1300: ChangeDisplaySettings (NULL, 0);
1301:
1302: // Destroy the fullscreen DIB window and associated MGL DC's
1303: DestroyWindow(dibwindow);
1304: MGL_destroyDC(windc);
1305: MGL_destroyDC(dibdc);
1306: windc = dibdc = NULL;
1307: }
1308: }
1309:
1310:
1311: /*
1312: =================
1313: VID_DescribeCurrentMode_f
1314: =================
1315: */
1316: void VID_DescribeCurrentMode_f (void)
1317: {
1318: Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
1319: }
1320:
1321:
1322: /*
1323: =================
1324: VID_NumModes_f
1325: =================
1326: */
1327: void VID_NumModes_f (void)
1328: {
1329:
1330: if (nummodes == 1)
1331: Con_Printf ("%d video mode is available\n", nummodes);
1332: else
1333: Con_Printf ("%d video modes are available\n", nummodes);
1334: }
1335:
1336:
1337: /*
1338: =================
1339: VID_DescribeMode_f
1340: =================
1341: */
1342: void VID_DescribeMode_f (void)
1343: {
1344: int modenum;
1345:
1346: modenum = Q_atoi (Cmd_Argv(1));
1347:
1348: Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
1349: }
1350:
1351:
1352: /*
1353: =================
1354: VID_DescribeModes_f
1355: =================
1356: */
1357: void VID_DescribeModes_f (void)
1358: {
1359: int i, lnummodes;
1360: char *pinfo;
1361: vmode_t *pv;
1362:
1363: lnummodes = VID_NumModes ();
1364:
1365: for (i=0 ; i<lnummodes ; i++)
1366: {
1367: pv = VID_GetModePtr (i);
1368: pinfo = VID_GetExtModeDescription (i);
1369: Con_Printf ("%2d: %s\n", i, pinfo);
1370: }
1371: }
1372:
1373:
1374: /*
1375: =================
1376: VID_TestMode_f
1377: =================
1378: */
1379: void VID_TestMode_f (void)
1380: {
1381: int modenum;
1382: double testduration;
1383:
1384: if (!vid_testingmode)
1385: {
1386: modenum = Q_atoi (Cmd_Argv(1));
1387:
1388: if (VID_SetMode (modenum, vid_curpal))
1389: {
1390: vid_testingmode = 1;
1391: testduration = Q_atof (Cmd_Argv(2));
1392: if (testduration == 0)
1393: testduration = 5.0;
1394: vid_testendtime = realtime + testduration;
1395: }
1396: }
1397: }
1398:
1399:
1400: /*
1401: =================
1402: VID_ForceMode_f
1403: =================
1404: */
1405: void VID_ForceMode_f (void)
1406: {
1407: int modenum;
1408: double testduration;
1409:
1410: if (!vid_testingmode)
1411: {
1412: modenum = Q_atoi (Cmd_Argv(1));
1413:
1414: force_mode_set = 1;
1415: VID_SetMode (modenum, vid_curpal);
1416: force_mode_set = 0;
1417: }
1418: }
1419:
1420:
1421: void registerAllMemDrivers(void)
1422: {
1423: /* Register memory context drivers */
1424: MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver);
1425: }
1426:
1427:
1428: void VID_InitMGLDIB (HINSTANCE hInstance)
1429: {
1430: WNDCLASS wc;
1431: HDC hdc;
1432: int i;
1433:
1434: hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2));
1435:
1436: /* Register the frame class */
1437: wc.style = 0;
1438: wc.lpfnWndProc = (WNDPROC)MainWndProc;
1439: wc.cbClsExtra = 0;
1440: wc.cbWndExtra = 0;
1441: wc.hInstance = hInstance;
1442: wc.hIcon = 0;
1443: wc.hCursor = LoadCursor (NULL,IDC_ARROW);
1444: wc.hbrBackground = NULL;
1445: wc.lpszMenuName = 0;
1446: wc.lpszClassName = "WinQuake";
1447:
1448: if (!RegisterClass (&wc) )
1449: Sys_Error ("Couldn't register window class");
1450:
1451: /* Find the size for the DIB window */
1452: /* Initialise the MGL for windowed operation */
1453: MGL_setAppInstance(hInstance);
1454: MGL_registerEventProc(MainWndProc);
1455: registerAllMemDrivers();
1456: MGL_initWindowed("");
1457:
1458: modelist[0].type = MS_WINDOWED;
1459: modelist[0].width = 320;
1460: modelist[0].height = 240;
1461: strcpy (modelist[0].modedesc, "320x240");
1462: modelist[0].modenum = MODE_WINDOWED;
1463: modelist[0].dib = 1;
1464: modelist[0].fullscreen = 0;
1465: modelist[0].halfscreen = 0;
1466: modelist[0].bpp = 0;
1467:
1468: modelist[1].type = MS_WINDOWED;
1469: modelist[1].width = 640;
1470: modelist[1].height = 480;
1471: strcpy (modelist[1].modedesc, "640x480");
1472: modelist[1].modenum = MODE_WINDOWED + 1;
1473: modelist[1].dib = 1;
1474: modelist[1].fullscreen = 0;
1475: modelist[1].halfscreen = 0;
1476: modelist[1].bpp = 0;
1477:
1478: modelist[2].type = MS_WINDOWED;
1479: modelist[2].width = 800;
1480: modelist[2].height = 600;
1481: strcpy (modelist[2].modedesc, "800x600");
1482: modelist[2].modenum = MODE_WINDOWED + 2;
1483: modelist[2].dib = 1;
1484: modelist[2].fullscreen = 0;
1485: modelist[2].halfscreen = 0;
1486: modelist[2].bpp = 0;
1487:
1488: vid_default = MODE_WINDOWED;
1489: windowed_default = vid_default;
1490:
1491: ReleaseDC(NULL,hdc);
1492:
1493: nummodes = 3; // reserve space for windowed mode
1494:
1495: DDActive = 0;
1496: }
1497:
1498:
1499: /*
1500: =================
1501: VID_InitFullDIB
1502: =================
1503: */
1504: void VID_InitFullDIB (HINSTANCE hInstance)
1505: {
1506: DEVMODE devmode;
1507: int i, modenum, cmodes, originalnummodes;
1508: BOOL stat;
1509:
1510: // enumerate >8 bpp modes
1511: originalnummodes = nummodes;
1512: modenum = 0;
1513:
1514: do
1515: {
1516: stat = EnumDisplaySettings (NULL, modenum, &devmode);
1517:
1518: if ((devmode.dmBitsPerPel > 8) &&
1519: (devmode.dmPelsWidth <= MAXWIDTH) &&
1520: (devmode.dmPelsHeight <= MAXHEIGHT) &&
1521: (nummodes < MAX_MODE_LIST))
1522: {
1523: devmode.dmFields = DM_BITSPERPEL |
1524: DM_PELSWIDTH |
1525: DM_PELSHEIGHT;
1526:
1527: if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
1528: DISP_CHANGE_SUCCESSFUL)
1529: {
1530: modelist[nummodes].type = MS_FULLDIB;
1531: modelist[nummodes].width = devmode.dmPelsWidth;
1532: modelist[nummodes].height = devmode.dmPelsHeight;
1533: modelist[nummodes].modenum = 0;
1534: modelist[nummodes].halfscreen = 0;
1535: modelist[nummodes].dib = 1;
1536: modelist[nummodes].fullscreen = 1;
1537: modelist[nummodes].bpp = devmode.dmBitsPerPel;
1538: sprintf (modelist[nummodes].modedesc, "%dx%d",
1539: devmode.dmPelsWidth, devmode.dmPelsHeight);
1540:
1541: // if the width is more than twice the height, reduce it by half because this
1542: // is probably a dual-screen monitor
1543: if (!COM_CheckParm("-noadjustaspect"))
1544: {
1545: if (modelist[nummodes].width > (modelist[nummodes].height << 1))
1546: {
1547: modelist[nummodes].width >>= 1;
1548: modelist[nummodes].halfscreen = 1;
1549: sprintf (modelist[nummodes].modedesc, "%dx%d",
1550: modelist[nummodes].width,
1551: modelist[nummodes].height);
1552: }
1553: }
1554:
1555: nummodes++;
1556: }
1557: }
1558:
1559: modenum++;
1560: } while (stat);
1561:
1562: if (nummodes != originalnummodes)
1563: vid_default = MODE_FULLSCREEN_DEFAULT;
1564: else
1565: Con_SafePrintf ("No fullscreen DIB modes found\n");
1566: }
1567:
1568:
1569: /*
1570: ===================
1571: VID_Init
1572: ===================
1573: */
1574: void VID_Init (unsigned char *palette)
1575: {
1576: int i;
1577: int basenummodes;
1578: byte *ptmp;
1579: char gldir[MAX_OSPATH];
1580:
1581: Cvar_RegisterVariable (&vid_mode);
1582: Cvar_RegisterVariable (&vid_wait);
1583: Cvar_RegisterVariable (&vid_nopageflip);
1584: Cvar_RegisterVariable (&_vid_wait_override);
1585: Cvar_RegisterVariable (&_vid_default_mode);
1586: Cvar_RegisterVariable (&_vid_default_mode_win);
1587: Cvar_RegisterVariable (&vid_config_x);
1588: Cvar_RegisterVariable (&vid_config_y);
1589: Cvar_RegisterVariable (&vid_stretch_by_2);
1590: Cvar_RegisterVariable (&_windowed_mouse);
1591: Cvar_RegisterVariable (&gl_ztrick);
1592:
1593:
1594: Cmd_AddCommand ("vid_testmode", VID_TestMode_f);
1595: Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
1596: Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
1597: Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
1598: Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
1599: Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f);
1600:
1601: VID_InitMGLDIB (global_hInstance);
1602:
1603: basenummodes = nummodes;
1604:
1605: VID_InitFullDIB (global_hInstance);
1606:
1607: vid_initialized = true;
1608:
1609: vid.maxwarpwidth = WARP_WIDTH;
1610: vid.maxwarpheight = WARP_HEIGHT;
1611: vid.colormap = host_colormap;
1612: vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
1613: vid_testingmode = 0;
1614:
1615: if (COM_CheckParm("-startwindowed"))
1616: {
1617: startwindowed = 1;
1618: vid_default = windowed_default;
1619: }
1620:
1621: VID_SetMode (vid_default, palette);
1622:
1623: sprintf (gldir, "%s/glquake", com_gamedir);
1624: Sys_mkdir (gldir);
1625:
1626: maindc = GetDC(mainwindow);
1627: bSetupPixelFormat(maindc);
1628:
1629: baseRC = wglCreateContext( maindc );
1630: if (!baseRC)
1631: Sys_Error ("wglCreateContect failed");
1632: if (!wglMakeCurrent( maindc, baseRC ))
1633: Sys_Error ("wglMakeCurrent failed");
1634:
1635: GL_Init ();
1636:
1637: vid_realmode = vid_modenum;
1638:
1639: VID_SetPalette (palette);
1640:
1641: vid_menudrawfn = VID_MenuDraw;
1642: vid_menukeyfn = VID_MenuKey;
1643:
1644: strcpy (badmode.modedesc, "Bad mode");
1645: }
1646:
1647:
1648: //========================================================
1649: // Video menu stuff
1650: //========================================================
1651:
1652: extern void M_Menu_Options_f (void);
1653: extern void M_Print (int cx, int cy, char *str);
1654: extern void M_PrintWhite (int cx, int cy, char *str);
1655: extern void M_DrawCharacter (int cx, int line, int num);
1656: extern void M_DrawTransPic (int x, int y, qpic_t *pic);
1657: extern void M_DrawPic (int x, int y, qpic_t *pic);
1658:
1659: static int vid_line, vid_wmodes;
1660:
1661: typedef struct
1662: {
1663: int modenum;
1664: char *desc;
1665: int iscur;
1666: } modedesc_t;
1667:
1668: #define MAX_COLUMN_SIZE 5
1669: #define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6)
1670: #define MAX_MODEDESCS (MAX_COLUMN_SIZE*3)
1671:
1672: static modedesc_t modedescs[MAX_MODEDESCS];
1673:
1674: /*
1675: ================
1676: VID_MenuDraw
1677: ================
1678: */
1679: void VID_MenuDraw (void)
1680: {
1681: qpic_t *p;
1682: char *ptr;
1683: int lnummodes, i, j, k, column, row, dup, dupmode;
1684: char temp[100];
1685: vmode_t *pv;
1686:
1687: p = Draw_CachePic ("gfx/vidmodes.lmp");
1688: M_DrawPic ( (320-p->width)/2, 4, p);
1689:
1690: for (i=0 ; i<3 ; i++)
1691: {
1692: ptr = VID_GetModeDescription (i);
1693: modedescs[i].modenum = modelist[i].modenum;
1694: modedescs[i].desc = ptr;
1695: modedescs[i].iscur = 0;
1696:
1697: if (vid_modenum == i)
1698: modedescs[i].iscur = 1;
1699: }
1700:
1701: vid_wmodes = 3;
1702: lnummodes = VID_NumModes ();
1703:
1704: for (i=3 ; i<lnummodes ; i++)
1705: {
1706: ptr = VID_GetModeDescription (i);
1707: pv = VID_GetModePtr (i);
1708:
1709: k = vid_wmodes;
1710:
1711: modedescs[k].modenum = i;
1712: modedescs[k].desc = ptr;
1713: modedescs[k].iscur = 0;
1714:
1715: if (i == vid_modenum)
1716: modedescs[k].iscur = 1;
1717:
1718: vid_wmodes++;
1719: }
1720:
1721: M_Print (13*8, 36, "Windowed Modes");
1722:
1723: column = 16;
1724: row = 36+2*8;
1725:
1726: for (i=0 ; i<3; i++)
1727: {
1728: if (modedescs[i].iscur)
1729: M_PrintWhite (column, row, modedescs[i].desc);
1730: else
1731: M_Print (column, row, modedescs[i].desc);
1732:
1733: column += 13*8;
1734: }
1735:
1736: if (vid_wmodes > 3)
1737: {
1738: M_Print (12*8, 36+4*8, "Fullscreen Modes");
1739:
1740: column = 16;
1741: row = 36+6*8;
1742:
1743: for (i=3 ; i<vid_wmodes ; i++)
1744: {
1745: if (modedescs[i].iscur)
1746: M_PrintWhite (column, row, modedescs[i].desc);
1747: else
1748: M_Print (column, row, modedescs[i].desc);
1749:
1750: column += 13*8;
1751:
1752: if (((i - 3) % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
1753: {
1754: column = 16;
1755: row += 8;
1756: }
1757: }
1758: }
1759:
1760: // line cursor
1761: if (vid_testingmode)
1762: {
1763: sprintf (temp, "TESTING %s",
1764: modedescs[vid_line].desc);
1765: M_Print (13*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4, temp);
1766: M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
1767: "Please wait 5 seconds...");
1768: }
1769: else
1770: {
1771: M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8,
1772: "Press Enter to set mode");
1773: M_Print (6*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
1774: "T to test mode for 5 seconds");
1775: ptr = VID_GetModeDescription2 (vid_modenum);
1776:
1777: if (ptr)
1778: {
1779: sprintf (temp, "D to set default: %s", ptr);
1780: M_Print (2*8, 36 + MODE_AREA_HEIGHT * 8 + 8*5, temp);
1781: }
1782:
1783: ptr = VID_GetModeDescription2 ((int)_vid_default_mode_win.value);
1784:
1785: if (ptr)
1786: {
1787: sprintf (temp, "Current default: %s", ptr);
1788: M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, temp);
1789: }
1790:
1791: M_Print (15*8, 36 + MODE_AREA_HEIGHT * 8 + 8*8,
1792: "Esc to exit");
1793:
1794: row = 36 + 2*8 + (vid_line / VID_ROW_SIZE) * 8;
1795: column = 8 + (vid_line % VID_ROW_SIZE) * 13*8;
1796:
1797: if (vid_line >= 3)
1798: row += 3*8;
1799:
1800: M_DrawCharacter (column, row, 12+((int)(realtime*4)&1));
1801: }
1802: }
1803:
1804:
1805: /*
1806: ================
1807: VID_MenuKey
1808: ================
1809: */
1810: void VID_MenuKey (int key)
1811: {
1812: if (vid_testingmode)
1813: return;
1814:
1815: switch (key)
1816: {
1817: case K_ESCAPE:
1818: S_LocalSound ("misc/menu1.wav");
1819: M_Menu_Options_f ();
1820: break;
1821:
1822: case K_LEFTARROW:
1823: S_LocalSound ("misc/menu1.wav");
1824: vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) +
1825: ((vid_line + 2) % VID_ROW_SIZE);
1826:
1827: if (vid_line >= vid_wmodes)
1828: vid_line = vid_wmodes - 1;
1829: break;
1830:
1831: case K_RIGHTARROW:
1832: S_LocalSound ("misc/menu1.wav");
1833: vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) +
1834: ((vid_line + 4) % VID_ROW_SIZE);
1835:
1836: if (vid_line >= vid_wmodes)
1837: vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE;
1838: break;
1839:
1840: case K_UPARROW:
1841: S_LocalSound ("misc/menu1.wav");
1842: vid_line -= VID_ROW_SIZE;
1843:
1844: if (vid_line < 0)
1845: {
1846: vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) /
1847: VID_ROW_SIZE) * VID_ROW_SIZE;
1848:
1849: while (vid_line >= vid_wmodes)
1850: vid_line -= VID_ROW_SIZE;
1851: }
1852: break;
1853:
1854: case K_DOWNARROW:
1855: S_LocalSound ("misc/menu1.wav");
1856: vid_line += VID_ROW_SIZE;
1857:
1858: if (vid_line >= vid_wmodes)
1859: {
1860: vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) /
1861: VID_ROW_SIZE) * VID_ROW_SIZE;
1862:
1863: while (vid_line < 0)
1864: vid_line += VID_ROW_SIZE;
1865: }
1866: break;
1867:
1868: case K_ENTER:
1869: S_LocalSound ("misc/menu1.wav");
1870: VID_SetMode (modedescs[vid_line].modenum, vid_curpal);
1871: break;
1872:
1873: case 'T':
1874: case 't':
1875: S_LocalSound ("misc/menu1.wav");
1876: // have to set this before setting the mode because WM_PAINT
1877: // happens during the mode set and does a VID_Update, which
1878: // checks vid_testingmode
1879: vid_testingmode = 1;
1880: vid_testendtime = realtime + 5.0;
1881:
1882: if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal))
1883: {
1884: vid_testingmode = 0;
1885: }
1886: break;
1887:
1888: case 'D':
1889: case 'd':
1890: S_LocalSound ("misc/menu1.wav");
1891: firstupdate = 0;
1892: Cvar_SetValue ("_vid_default_mode_win", vid_modenum);
1893: break;
1894:
1895: default:
1896: break;
1897: }
1898: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.