1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2006 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * DOOM graphics stuff for SDL
31 *
32 *-----------------------------------------------------------------------------
33 */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #ifdef _WIN32
40 #define WIN32_LEAN_AND_MEAN
41 #include <windows.h>
42 #endif // _WIN32
43
44 #include <stdlib.h>
45
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49
50 #include "SDL.h"
51 //e6y
52 #ifdef _WIN32
53 #include <SDL_syswm.h>
54 #endif
55
56 #include "m_argv.h"
57 #include "doomstat.h"
58 #include "doomdef.h"
59 #include "doomtype.h"
60 #include "v_video.h"
61 #include "r_draw.h"
62 #include "r_things.h"
63 #include "r_plane.h"
64 #include "r_main.h"
65 #include "f_wipe.h"
66 #include "d_main.h"
67 #include "d_event.h"
68 #include "i_joy.h"
69 #include "i_video.h"
70 #include "i_smp.h"
71 #include "z_zone.h"
72 #include "s_sound.h"
73 #include "sounds.h"
74 #include "w_wad.h"
75 #include "st_stuff.h"
76 #include "am_map.h"
77 #include "g_game.h"
78 #include "lprintf.h"
79
80 #ifdef GL_DOOM
81 #include "gl_struct.h"
82 #endif
83
84 #include "i_simd.h"
85 #include "r_screenmultiply.h"
86 #include "e6y.h"//e6y
87
88 //e6y: new mouse code
89 static SDL_Cursor* cursors[2] = {NULL, NULL};
90
91 dboolean window_focused;
92
93 // Window resize state.
94 static void ApplyWindowResize(SDL_Event *resize_event);
95
96 const char *sdl_videodriver;
97 const char *sdl_video_window_pos;
98
99 static void ActivateMouse(void);
100 static void DeactivateMouse(void);
101 //static int AccelerateMouse(int val);
102 static void CenterMouse(void);
103 static void I_ReadMouse(void);
104 static dboolean MouseShouldBeGrabbed();
105 static void UpdateFocus(void);
106
107 int gl_colorbuffer_bits=16;
108 int gl_depthbuffer_bits=16;
109
110 extern void M_QuitDOOM(int choice);
111 #ifdef DISABLE_DOUBLEBUFFER
112 int use_doublebuffer = 0;
113 #else
114 int use_doublebuffer = 1; // Included not to break m_misc, but not relevant to SDL
115 #endif
116 int use_fullscreen;
117 int desired_fullscreen;
118 SDL_Surface *screen;
119 #ifdef GL_DOOM
120 vid_8ingl_t vid_8ingl;
121 int use_gl_surface;
122 #endif
123
124 ////////////////////////////////////////////////////////////////////////////
125 // Input code
126 int leds_always_off = 0; // Expected by m_misc, not relevant
127
128 // Mouse handling
129 extern int usemouse; // config file var
130 static dboolean mouse_enabled; // usemouse, but can be overriden by -nomouse
131
132 int I_GetModeFromString(const char *modestr);
133
134 /////////////////////////////////////////////////////////////////////////////////
135 // Keyboard handling
136
137 //
138 // Translates the key currently in key
139 //
140
I_TranslateKey(SDL_keysym * key)141 static int I_TranslateKey(SDL_keysym* key)
142 {
143 int rc = 0;
144
145 switch (key->sym) {
146 case SDLK_LEFT: rc = KEYD_LEFTARROW; break;
147 case SDLK_RIGHT: rc = KEYD_RIGHTARROW; break;
148 case SDLK_DOWN: rc = KEYD_DOWNARROW; break;
149 case SDLK_UP: rc = KEYD_UPARROW; break;
150 case SDLK_ESCAPE: rc = KEYD_ESCAPE; break;
151 case SDLK_RETURN: rc = KEYD_ENTER; break;
152 case SDLK_TAB: rc = KEYD_TAB; break;
153 case SDLK_F1: rc = KEYD_F1; break;
154 case SDLK_F2: rc = KEYD_F2; break;
155 case SDLK_F3: rc = KEYD_F3; break;
156 case SDLK_F4: rc = KEYD_F4; break;
157 case SDLK_F5: rc = KEYD_F5; break;
158 case SDLK_F6: rc = KEYD_F6; break;
159 case SDLK_F7: rc = KEYD_F7; break;
160 case SDLK_F8: rc = KEYD_F8; break;
161 case SDLK_F9: rc = KEYD_F9; break;
162 case SDLK_F10: rc = KEYD_F10; break;
163 case SDLK_F11: rc = KEYD_F11; break;
164 case SDLK_F12: rc = KEYD_F12; break;
165 case SDLK_BACKSPACE: rc = KEYD_BACKSPACE; break;
166 case SDLK_DELETE: rc = KEYD_DEL; break;
167 case SDLK_INSERT: rc = KEYD_INSERT; break;
168 case SDLK_PAGEUP: rc = KEYD_PAGEUP; break;
169 case SDLK_PAGEDOWN: rc = KEYD_PAGEDOWN; break;
170 case SDLK_HOME: rc = KEYD_HOME; break;
171 case SDLK_END: rc = KEYD_END; break;
172 case SDLK_PAUSE: rc = KEYD_PAUSE; break;
173 case SDLK_EQUALS: rc = KEYD_EQUALS; break;
174 case SDLK_MINUS: rc = KEYD_MINUS; break;
175 case SDLK_KP0: rc = KEYD_KEYPAD0; break;
176 case SDLK_KP1: rc = KEYD_KEYPAD1; break;
177 case SDLK_KP2: rc = KEYD_KEYPAD2; break;
178 case SDLK_KP3: rc = KEYD_KEYPAD3; break;
179 case SDLK_KP4: rc = KEYD_KEYPAD4; break;
180 case SDLK_KP5: rc = KEYD_KEYPAD5; break;
181 case SDLK_KP6: rc = KEYD_KEYPAD6; break;
182 case SDLK_KP7: rc = KEYD_KEYPAD7; break;
183 case SDLK_KP8: rc = KEYD_KEYPAD8; break;
184 case SDLK_KP9: rc = KEYD_KEYPAD9; break;
185 case SDLK_KP_PLUS: rc = KEYD_KEYPADPLUS; break;
186 case SDLK_KP_MINUS: rc = KEYD_KEYPADMINUS; break;
187 case SDLK_KP_DIVIDE: rc = KEYD_KEYPADDIVIDE; break;
188 case SDLK_KP_MULTIPLY: rc = KEYD_KEYPADMULTIPLY; break;
189 case SDLK_KP_ENTER: rc = KEYD_KEYPADENTER; break;
190 case SDLK_KP_PERIOD: rc = KEYD_KEYPADPERIOD; break;
191 case SDLK_LSHIFT:
192 case SDLK_RSHIFT: rc = KEYD_RSHIFT; break;
193 case SDLK_LCTRL:
194 case SDLK_RCTRL: rc = KEYD_RCTRL; break;
195 case SDLK_LALT:
196 case SDLK_LMETA:
197 case SDLK_RALT:
198 case SDLK_RMETA: rc = KEYD_RALT; break;
199 case SDLK_CAPSLOCK: rc = KEYD_CAPSLOCK; break;
200 default: rc = key->sym; break;
201 }
202
203 return rc;
204
205 }
206
207 /////////////////////////////////////////////////////////////////////////////////
208 // Main input code
209
210 /* cph - pulled out common button code logic */
211 //e6y static
I_SDLtoDoomMouseState(Uint8 buttonstate)212 int I_SDLtoDoomMouseState(Uint8 buttonstate)
213 {
214 return 0
215 | (buttonstate & SDL_BUTTON(1) ? 1 : 0)
216 | (buttonstate & SDL_BUTTON(2) ? 2 : 0)
217 | (buttonstate & SDL_BUTTON(3) ? 4 : 0)
218 #if SDL_VERSION_ATLEAST(1, 2, 14)
219 | (buttonstate & SDL_BUTTON(6) ? 8 : 0)
220 | (buttonstate & SDL_BUTTON(7) ? 16 : 0)
221 #endif
222 ;
223 }
224
I_GetEvent(void)225 static void I_GetEvent(void)
226 {
227 event_t event;
228
229 SDL_Event SDLEvent;
230 SDL_Event *Event = &SDLEvent;
231
232 static int mwheeluptic = 0, mwheeldowntic = 0;
233
234 while (SDL_PollEvent(Event))
235 {
236 switch (Event->type) {
237 case SDL_KEYDOWN:
238 #ifdef MACOSX
239 if (Event->key.keysym.mod & KMOD_META)
240 {
241 // Switch windowed<->fullscreen if pressed <Command-F>
242 if (Event->key.keysym.sym == SDLK_f)
243 {
244 V_ToggleFullscreen();
245 break;
246 }
247 }
248 #else
249 if (Event->key.keysym.mod & KMOD_LALT)
250 {
251 // Prevent executing action on Alt-Tab
252 if (Event->key.keysym.sym == SDLK_TAB)
253 {
254 break;
255 }
256 // Switch windowed<->fullscreen if pressed Alt-Enter
257 else if (Event->key.keysym.sym == SDLK_RETURN)
258 {
259 V_ToggleFullscreen();
260 break;
261 }
262 }
263 #endif
264 event.type = ev_keydown;
265 event.data1 = I_TranslateKey(&Event->key.keysym);
266 D_PostEvent(&event);
267 break;
268
269 case SDL_KEYUP:
270 {
271 event.type = ev_keyup;
272 event.data1 = I_TranslateKey(&Event->key.keysym);
273 D_PostEvent(&event);
274 }
275 break;
276
277 case SDL_MOUSEBUTTONDOWN:
278 case SDL_MOUSEBUTTONUP:
279 if (mouse_enabled && window_focused)
280 {
281 event.type = ev_mouse;
282 event.data1 = I_SDLtoDoomMouseState(SDL_GetMouseState(NULL, NULL));
283 event.data2 = event.data3 = 0;
284
285 if (Event->type == SDL_MOUSEBUTTONDOWN)
286 {
287 switch(Event->button.button)
288 {
289 case SDL_BUTTON_WHEELUP:
290 event.type = ev_keydown;
291 event.data1 = KEYD_MWHEELUP;
292 mwheeluptic = gametic;
293 break;
294 case SDL_BUTTON_WHEELDOWN:
295 event.type = ev_keydown;
296 event.data1 = KEYD_MWHEELDOWN;
297 mwheeldowntic = gametic;
298 break;
299 }
300 }
301
302 D_PostEvent(&event);
303 }
304 break;
305
306 //e6y: new mouse code
307 case SDL_ACTIVEEVENT:
308 UpdateFocus();
309 break;
310
311 case SDL_VIDEORESIZE:
312 ApplyWindowResize(Event);
313 break;
314
315 case SDL_QUIT:
316 S_StartSound(NULL, sfx_swtchn);
317 M_QuitDOOM(0);
318
319 default:
320 break;
321 }
322 }
323
324 if(mwheeluptic && mwheeluptic + 1 < gametic)
325 {
326 event.type = ev_keyup;
327 event.data1 = KEYD_MWHEELUP;
328 D_PostEvent(&event);
329 mwheeluptic = 0;
330 }
331
332 if(mwheeldowntic && mwheeldowntic + 1 < gametic)
333 {
334 event.type = ev_keyup;
335 event.data1 = KEYD_MWHEELDOWN;
336 D_PostEvent(&event);
337 mwheeldowntic = 0;
338 }
339 }
340
341 //
342 // I_StartTic
343 //
344
I_StartTic(void)345 void I_StartTic (void)
346 {
347 I_GetEvent();
348
349 I_ReadMouse();
350
351 I_PollJoystick();
352 }
353
354 //
355 // I_StartFrame
356 //
I_StartFrame(void)357 void I_StartFrame (void)
358 {
359 }
360
361 //
362 // I_InitInputs
363 //
364
I_InitInputs(void)365 static void I_InitInputs(void)
366 {
367 static Uint8 empty_cursor_data = 0;
368
369 int nomouse_parm = M_CheckParm("-nomouse");
370
371 // check if the user wants to use the mouse
372 mouse_enabled = usemouse && !nomouse_parm;
373
374 SDL_PumpEvents();
375
376 // Save the default cursor so it can be recalled later
377 cursors[0] = SDL_GetCursor();
378 // Create an empty cursor
379 cursors[1] = SDL_CreateCursor(&empty_cursor_data, &empty_cursor_data, 8, 1, 0, 0);
380
381 if (mouse_enabled)
382 {
383 CenterMouse();
384 MouseAccelChanging();
385 }
386
387 I_InitJoystick();
388 }
389 /////////////////////////////////////////////////////////////////////////////
390
391 // I_SkipFrame
392 //
393 // Returns true if it thinks we can afford to skip this frame
394
I_SkipFrame(void)395 inline static dboolean I_SkipFrame(void)
396 {
397 static int frameno;
398
399 frameno++;
400 switch (gamestate) {
401 case GS_LEVEL:
402 if (!paused)
403 return false;
404 default:
405 // Skip odd frames
406 return (frameno & 1) ? true : false;
407 }
408 }
409
410 ///////////////////////////////////////////////////////////
411 // Palette stuff.
412 //
I_UploadNewPalette(int pal,int force)413 static void I_UploadNewPalette(int pal, int force)
414 {
415 // This is used to replace the current 256 colour cmap with a new one
416 // Used by 256 colour PseudoColor modes
417
418 // Array of SDL_Color structs used for setting the 256-colour palette
419 static SDL_Color* colours;
420 static int cachedgamma;
421 static size_t num_pals;
422
423 if (V_GetMode() == VID_MODEGL)
424 return;
425
426 if ((colours == NULL) || (cachedgamma != usegamma) || force) {
427 int pplump = W_GetNumForName("PLAYPAL");
428 int gtlump = (W_CheckNumForName)("GAMMATBL",ns_prboom);
429 register const byte * palette = W_CacheLumpNum(pplump);
430 register const byte * const gtable = (const byte *)W_CacheLumpNum(gtlump) + 256*(cachedgamma = usegamma);
431 register int i;
432
433 num_pals = W_LumpLength(pplump) / (3*256);
434 num_pals *= 256;
435
436 if (!colours) {
437 // First call - allocate and prepare colour array
438 colours = malloc(sizeof(*colours)*num_pals);
439 #ifdef GL_DOOM
440 vid_8ingl.colours = malloc(sizeof(vid_8ingl.colours[0]) * 4 * num_pals);
441 #endif
442 }
443
444 // set the colormap entries
445 for (i=0 ; (size_t)i<num_pals ; i++) {
446 #ifdef GL_DOOM
447 if (vid_8ingl.enabled)
448 {
449 if (V_GetMode() == VID_MODE8)
450 {
451 vid_8ingl.colours[i * 4 + 0] = gtable[palette[2]];
452 vid_8ingl.colours[i * 4 + 1] = gtable[palette[1]];
453 vid_8ingl.colours[i * 4 + 2] = gtable[palette[0]];
454 vid_8ingl.colours[i * 4 + 3] = 255;
455 }
456 }
457 else
458 #endif
459 {
460 colours[i].r = gtable[palette[0]];
461 colours[i].g = gtable[palette[1]];
462 colours[i].b = gtable[palette[2]];
463 }
464
465 palette += 3;
466 }
467
468 W_UnlockLumpNum(pplump);
469 W_UnlockLumpNum(gtlump);
470 num_pals/=256;
471 }
472
473 #ifdef RANGECHECK
474 if ((size_t)pal >= num_pals)
475 I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)",
476 pal, num_pals);
477 #endif
478
479 // store the colors to the current display
480 // SDL_SetColors(SDL_GetVideoSurface(), colours+256*pal, 0, 256);
481 #ifdef GL_DOOM
482 if (vid_8ingl.enabled)
483 {
484 vid_8ingl.palette = pal;
485 }
486 else
487 #endif
488 {
489 SDL_SetPalette(SDL_GetVideoSurface(),SDL_LOGPAL|SDL_PHYSPAL,colours+256*pal, 0, 256);
490 }
491 }
492
493 //////////////////////////////////////////////////////////////////////////////
494 // Graphics API
495
I_ShutdownGraphics(void)496 void I_ShutdownGraphics(void)
497 {
498 SDL_FreeCursor(cursors[1]);
499 DeactivateMouse();
500 }
501
502 //
503 // I_UpdateNoBlit
504 //
I_UpdateNoBlit(void)505 void I_UpdateNoBlit (void)
506 {
507 }
508
509 //
510 // I_FinishUpdate
511 //
512 static int newpal = 0;
513 #define NO_PALETTE_CHANGE 1000
514
I_FinishUpdate(void)515 void I_FinishUpdate (void)
516 {
517 //e6y: new mouse code
518 UpdateGrab();
519
520 // The screen wipe following pressing the exit switch on a level
521 // is noticably jerkier with I_SkipFrame
522 // if (I_SkipFrame())return;
523
524 #ifdef MONITOR_VISIBILITY
525 if (!(SDL_GetAppState()&SDL_APPACTIVE)) {
526 return;
527 }
528 #endif
529
530 #ifdef GL_DOOM
531 if (V_GetMode() == VID_MODEGL) {
532 // proff 04/05/2000: swap OpenGL buffers
533 gld_Finish();
534 return;
535 }
536 #endif
537
538 if ((screen_multiply > 1) || SDL_MUSTLOCK(screen)) {
539 int h;
540 byte *src;
541 byte *dest;
542
543 if (SDL_LockSurface(screen) < 0) {
544 lprintf(LO_INFO,"I_FinishUpdate: %s\n", SDL_GetError());
545 return;
546 }
547
548 // e6y: processing of screen_multiply
549 if (screen_multiply > 1)
550 {
551 R_ProcessScreenMultiply(screens[0].data, screen->pixels,
552 V_GetPixelDepth(), screens[0].byte_pitch, screen->pitch);
553 }
554 else
555 {
556 dest=screen->pixels;
557 src=screens[0].data;
558 h=screen->h;
559 for (; h>0; h--)
560 {
561 memcpy_fast(dest,src,SCREENWIDTH*V_GetPixelDepth()); //e6y
562 dest+=screen->pitch;
563 src+=screens[0].byte_pitch;
564 }
565 }
566
567 SDL_UnlockSurface(screen);
568 }
569
570 /* Update the display buffer (flipping video pages if supported)
571 * If we need to change palette, that implicitely does a flip */
572 if (newpal != NO_PALETTE_CHANGE) {
573 I_UploadNewPalette(newpal, false);
574 newpal = NO_PALETTE_CHANGE;
575 }
576
577 #ifdef GL_DOOM
578 if (vid_8ingl.enabled)
579 {
580 gld_Draw8InGL();
581 }
582 else
583 #endif
584 {
585 SDL_Flip(screen);
586 }
587 }
588
589 //
590 // I_ScreenShot - moved to i_sshot.c
591 //
592
593 //
594 // I_SetPalette
595 //
I_SetPalette(int pal)596 void I_SetPalette (int pal)
597 {
598 newpal = pal;
599 }
600
601 // I_PreInitGraphics
602
I_ShutdownSDL(void)603 static void I_ShutdownSDL(void)
604 {
605 SDL_Quit();
606 return;
607 }
608
I_PreInitGraphics(void)609 void I_PreInitGraphics(void)
610 {
611 int p;
612 char *video_driver = strdup(sdl_videodriver);
613
614 // Initialize SDL
615 unsigned int flags = 0;
616 if (!(M_CheckParm("-nodraw") && M_CheckParm("-nosound")))
617 flags = SDL_INIT_VIDEO;
618 #ifdef PRBOOM_DEBUG
619 flags |= SDL_INIT_NOPARACHUTE;
620 #endif
621
622 // e6y: Forcing "directx" video driver for Win9x.
623 // The "windib" video driver is the default for SDL > 1.2.9,
624 // to prevent problems with certain laptops, 64-bit Windows, and Windows Vista.
625 // The DirectX driver is still available, and can be selected by setting
626 // the environment variable SDL_VIDEODRIVER to "directx".
627
628 if ((p = M_CheckParm("-videodriver")) && (p < myargc - 1))
629 {
630 free(video_driver);
631 video_driver = strdup(myargv[p + 1]);
632 }
633
634 if (strcasecmp(video_driver, "default"))
635 {
636 // videodriver != default
637 char buf[80];
638 strcpy(buf, "SDL_VIDEODRIVER=");
639 strncat(buf, video_driver, sizeof(buf) - sizeof(buf[0]) - strlen(buf));
640 putenv(buf);
641 }
642 else
643 {
644 // videodriver == default
645 #ifdef _WIN32
646 if ((int)GetVersion() < 0 && V_GetMode() != VID_MODEGL ) // win9x
647 {
648 free(video_driver);
649 video_driver = strdup("directx");
650 putenv("SDL_VIDEODRIVER=directx");
651 }
652 #endif
653 }
654
655 p = SDL_Init(flags);
656
657 if (p < 0 && strcasecmp(video_driver, "default"))
658 {
659 static const union {
660 const char *c;
661 char *s;
662 } u = { "SDL_VIDEODRIVER=" };
663
664 //e6y: wrong videodriver?
665 lprintf(LO_ERROR, "Could not initialize SDL with SDL_VIDEODRIVER=%s [%s]\n", video_driver, SDL_GetError());
666
667 putenv(u.s);
668
669 p = SDL_Init(flags);
670 }
671
672 free(video_driver);
673
674 if (p < 0)
675 {
676 I_Error("Could not initialize SDL [%s]", SDL_GetError());
677 }
678
679 atexit(I_ShutdownSDL);
680 }
681
682 // e6y: resolution limitation is removed
I_InitBuffersRes(void)683 void I_InitBuffersRes(void)
684 {
685 R_InitMeltRes();
686 R_InitSpritesRes();
687 R_InitBuffersRes();
688 R_InitPlanesRes();
689 R_InitVisplanesRes();
690 }
691
692 #define MAX_RESOLUTIONS_COUNT 128
693 const char *screen_resolutions_list[MAX_RESOLUTIONS_COUNT] = {NULL};
694 const char *screen_resolution_lowest;
695 const char *screen_resolution = NULL;
696
697 //
698 // I_GetScreenResolution
699 // Get current resolution from the config variable (WIDTHxHEIGHT format)
700 // 640x480 if screen_resolution variable has wrong data
701 //
I_GetScreenResolution(void)702 void I_GetScreenResolution(void)
703 {
704 int width, height;
705
706 desired_screenwidth = 640;
707 desired_screenheight = 480;
708
709 if (screen_resolution)
710 {
711 if (sscanf(screen_resolution, "%dx%d", &width, &height) == 2)
712 {
713 desired_screenwidth = width;
714 desired_screenheight = height;
715 }
716 }
717 }
718
719 //
720 // I_FillScreenResolutionsList
721 // Get all the supported screen resolutions
722 // and fill the list with them
723 //
I_FillScreenResolutionsList(void)724 static void I_FillScreenResolutionsList(void)
725 {
726 SDL_Rect **modes;
727 int i, j, list_size, current_resolution_index, count;
728 char mode[256];
729 Uint32 flags;
730
731 // do it only once
732 if (screen_resolutions_list[0])
733 {
734 return;
735 }
736
737 if (desired_screenwidth == 0 || desired_screenheight == 0)
738 {
739 I_GetScreenResolution();
740 }
741
742 flags = SDL_FULLSCREEN;
743 #ifdef GL_DOOM
744 flags |= SDL_OPENGL;
745 #endif
746
747 // Don't call SDL_ListModes if SDL has not been initialized
748 if (!nodrawers)
749 modes = SDL_ListModes(NULL, flags);
750 else
751 modes = NULL;
752
753 list_size = 0;
754 current_resolution_index = -1;
755
756 if (modes)
757 {
758 count = 0;
759 for(i = 0; modes[i]; i++)
760 {
761 count++;
762 }
763 // (-2) is for NULL at the end of list and for custom resolution
764 count = MIN(count, MAX_RESOLUTIONS_COUNT - 2);
765
766 for(i = count - 1; i >= 0; i--)
767 {
768 int in_list = false;
769
770 SNPRINTF(mode, sizeof(mode), "%dx%d", modes[i]->w, modes[i]->h);
771
772 if (i == count - 1)
773 {
774 screen_resolution_lowest = strdup(mode);
775 }
776
777 for(j = 0; j < list_size; j++)
778 {
779 if (!strcmp(mode, screen_resolutions_list[j]))
780 {
781 in_list = true;
782 break;
783 }
784 }
785
786 if (!in_list)
787 {
788 screen_resolutions_list[list_size] = strdup(mode);
789
790 if (modes[i]->w == desired_screenwidth && modes[i]->h == desired_screenheight)
791 {
792 current_resolution_index = list_size;
793 }
794
795 list_size++;
796 }
797 }
798 screen_resolutions_list[list_size] = NULL;
799 }
800
801 if (list_size == 0)
802 {
803 SNPRINTF(mode, sizeof(mode), "%dx%d", desired_screenwidth, desired_screenheight);
804 screen_resolutions_list[0] = strdup(mode);
805 current_resolution_index = 0;
806 list_size = 1;
807 }
808
809 if (current_resolution_index == -1)
810 {
811 SNPRINTF(mode, sizeof(mode), "%dx%d", desired_screenwidth, desired_screenheight);
812
813 // make it first
814 list_size++;
815 for(i = list_size - 1; i > 0; i--)
816 {
817 screen_resolutions_list[i] = screen_resolutions_list[i - 1];
818 }
819 screen_resolutions_list[0] = strdup(mode);
820 current_resolution_index = 0;
821 }
822
823 screen_resolutions_list[list_size] = NULL;
824 screen_resolution = screen_resolutions_list[current_resolution_index];
825 }
826
827 // e6y
828 // GLBoom use this function for trying to set the closest supported resolution if the requested mode can't be set correctly.
829 // For example glboom.exe -geom 1025x768 -nowindow will set 1024x768.
830 // It should be used only for fullscreen modes.
I_ClosestResolution(int * width,int * height,int flags)831 static void I_ClosestResolution (int *width, int *height, int flags)
832 {
833 SDL_Rect **modes;
834 int twidth, theight;
835 int cwidth = 0, cheight = 0;
836 int i;
837 unsigned int closest = UINT_MAX;
838 unsigned int dist;
839
840 modes = SDL_ListModes(NULL, flags);
841
842 if (modes == (SDL_Rect **)-1)
843 {
844 // any dimension is okay for the given format
845 return;
846 }
847
848 if (modes)
849 {
850 for(i=0; modes[i]; ++i)
851 {
852 twidth = modes[i]->w;
853 theight = modes[i]->h;
854
855 if (twidth == *width && theight == *height)
856 return;
857
858 //if (iteration == 0 && (twidth < *width || theight < *height))
859 // continue;
860
861 dist = (twidth - *width) * (twidth - *width) +
862 (theight - *height) * (theight - *height);
863
864 if (dist < closest)
865 {
866 closest = dist;
867 cwidth = twidth;
868 cheight = theight;
869 }
870 }
871 if (closest != 4294967295u)
872 {
873 *width = cwidth;
874 *height = cheight;
875 return;
876 }
877 }
878 }
879
880 int process_affinity_mask;
881 int process_priority;
882 int try_to_reduce_cpu_cache_misses;
883
884 // e6y
885 // It is a simple test of CPU cache misses.
I_TestCPUCacheMisses(int width,int height,unsigned int mintime)886 unsigned int I_TestCPUCacheMisses(int width, int height, unsigned int mintime)
887 {
888 int i, k;
889 char *s, *d, *ps, *pd;
890 unsigned int tickStart;
891
892 s = malloc(width * height);
893 d = malloc(width * height);
894
895 tickStart = SDL_GetTicks();
896 k = 0;
897 do
898 {
899 ps = s;
900 pd = d;
901 for(i = 0; i < height; i++)
902 {
903 pd[0] = ps[0];
904 pd += width;
905 ps += width;
906 }
907 k++;
908 }
909 while (SDL_GetTicks() - tickStart < mintime);
910
911 free(d);
912 free(s);
913
914 return k;
915 }
916
917 // CPhipps -
918 // I_CalculateRes
919 // Calculates the screen resolution, possibly using the supplied guide
I_CalculateRes(int width,int height)920 void I_CalculateRes(int width, int height)
921 {
922 // e6y
923 // GLBoom will try to set the closest supported resolution
924 // if the requested mode can't be set correctly.
925 // For example glboom.exe -geom 1025x768 -nowindow will set 1024x768.
926 // It affects only fullscreen modes.
927 if (V_GetMode() == VID_MODEGL) {
928 if ( desired_fullscreen )
929 {
930 I_ClosestResolution(&width, &height, SDL_OPENGL|SDL_FULLSCREEN);
931 }
932 SCREENWIDTH = width;
933 SCREENHEIGHT = height;
934 SCREENPITCH = SCREENWIDTH;
935 } else {
936 unsigned int count1, count2;
937 int pitch1, pitch2;
938
939 SCREENWIDTH = width;//(width+15) & ~15;
940 SCREENHEIGHT = height;
941
942 // e6y
943 // Trying to optimise screen pitch for reducing of CPU cache misses.
944 // It is extremally important for wiping in software.
945 // I have ~20x improvement in speed with using 1056 instead of 1024 on Pentium4
946 // and only ~10% for Core2Duo
947 if (try_to_reduce_cpu_cache_misses)
948 {
949 unsigned int mintime = 100;
950 int w = (width+15) & ~15;
951 pitch1 = w * V_GetPixelDepth();
952 pitch2 = w * V_GetPixelDepth() + 32;
953
954 count1 = I_TestCPUCacheMisses(pitch1, SCREENHEIGHT, mintime);
955 count2 = I_TestCPUCacheMisses(pitch2, SCREENHEIGHT, mintime);
956
957 lprintf(LO_INFO, "I_CalculateRes: trying to optimize screen pitch\n");
958 lprintf(LO_INFO, " test case for pitch=%d is processed %d times for %d msec\n", pitch1, count1, mintime);
959 lprintf(LO_INFO, " test case for pitch=%d is processed %d times for %d msec\n", pitch2, count2, mintime);
960
961 SCREENPITCH = (count2 > count1 ? pitch2 : pitch1);
962
963 lprintf(LO_INFO, " optimized screen pitch is %d\n", SCREENPITCH);
964 }
965 else
966 {
967 SCREENPITCH = SCREENWIDTH * V_GetPixelDepth();
968 }
969 }
970
971 // e6y: processing of screen_multiply
972 {
973 int factor = ((V_GetMode() == VID_MODEGL) ? 1 : render_screen_multiply);
974 REAL_SCREENWIDTH = SCREENWIDTH * factor;
975 REAL_SCREENHEIGHT = SCREENHEIGHT * factor;
976 REAL_SCREENPITCH = SCREENPITCH * factor;
977 }
978 }
979
980 // CPhipps -
981 // I_InitScreenResolution
982 // Sets the screen resolution
983 // e6y: processing of screen_multiply
I_InitScreenResolution(void)984 void I_InitScreenResolution(void)
985 {
986 int i, p, w, h;
987 char c, x;
988 video_mode_t mode;
989 int init = screen == NULL;
990
991 I_GetScreenResolution();
992
993 if (init)
994 {
995 //e6y: ability to change screen resolution from GUI
996 I_FillScreenResolutionsList();
997
998 // Video stuff
999 if ((p = M_CheckParm("-width")))
1000 if (myargv[p+1])
1001 desired_screenwidth = atoi(myargv[p+1]);
1002
1003 if ((p = M_CheckParm("-height")))
1004 if (myargv[p+1])
1005 desired_screenheight = atoi(myargv[p+1]);
1006
1007 if ((p = M_CheckParm("-fullscreen")))
1008 use_fullscreen = 1;
1009
1010 if ((p = M_CheckParm("-nofullscreen")))
1011 use_fullscreen = 0;
1012
1013 // e6y
1014 // New command-line options for setting a window (-window)
1015 // or fullscreen (-nowindow) mode temporarily which is not saved in cfg.
1016 // It works like "-geom" switch
1017 desired_fullscreen = use_fullscreen;
1018 if ((p = M_CheckParm("-window")))
1019 desired_fullscreen = 0;
1020
1021 if ((p = M_CheckParm("-nowindow")))
1022 desired_fullscreen = 1;
1023
1024 // e6y
1025 // change the screen size for the current session only
1026 // syntax: -geom WidthxHeight[w|f]
1027 // examples: -geom 320x200f, -geom 640x480w, -geom 1024x768
1028 w = desired_screenwidth;
1029 h = desired_screenheight;
1030
1031 if (!(p = M_CheckParm("-geom")))
1032 p = M_CheckParm("-geometry");
1033
1034 if (p && p + 1 < myargc)
1035 {
1036 int count = sscanf(myargv[p+1], "%d%c%d%c", &w, &x, &h, &c);
1037
1038 // at least width and height must be specified
1039 // restoring original values if not
1040 if (count < 3 || tolower(x) != 'x')
1041 {
1042 w = desired_screenwidth;
1043 h = desired_screenheight;
1044 }
1045 else
1046 {
1047 if (count >= 4)
1048 {
1049 if (tolower(c) == 'w')
1050 desired_fullscreen = 0;
1051 if (tolower(c) == 'f')
1052 desired_fullscreen = 1;
1053 }
1054 }
1055 }
1056 }
1057 else
1058 {
1059 w = desired_screenwidth;
1060 h = desired_screenheight;
1061 }
1062
1063 mode = I_GetModeFromString(default_videomode);
1064 if ((i=M_CheckParm("-vidmode")) && i<myargc-1)
1065 {
1066 mode = I_GetModeFromString(myargv[i+1]);
1067 }
1068
1069 V_InitMode(mode);
1070
1071 I_CalculateRes(w, h);
1072 V_DestroyUnusedTrueColorPalettes();
1073 V_FreeScreens();
1074
1075 // set first three to standard values
1076 for (i=0; i<3; i++) {
1077 screens[i].width = REAL_SCREENWIDTH;
1078 screens[i].height = REAL_SCREENHEIGHT;
1079 screens[i].byte_pitch = REAL_SCREENPITCH;
1080 screens[i].short_pitch = REAL_SCREENPITCH / V_GetModePixelDepth(VID_MODE16);
1081 screens[i].int_pitch = REAL_SCREENPITCH / V_GetModePixelDepth(VID_MODE32);
1082 }
1083
1084 // statusbar
1085 screens[4].width = REAL_SCREENWIDTH;
1086 screens[4].height = REAL_SCREENHEIGHT;
1087 screens[4].byte_pitch = REAL_SCREENPITCH;
1088 screens[4].short_pitch = REAL_SCREENPITCH / V_GetModePixelDepth(VID_MODE16);
1089 screens[4].int_pitch = REAL_SCREENPITCH / V_GetModePixelDepth(VID_MODE32);
1090
1091 I_InitBuffersRes();
1092
1093 lprintf(LO_INFO,"I_InitScreenResolution: Using resolution %dx%d\n", REAL_SCREENWIDTH, REAL_SCREENHEIGHT);
1094 }
1095
1096 //
1097 // Set the window caption
1098 //
1099
I_SetWindowCaption(void)1100 void I_SetWindowCaption(void)
1101 {
1102 char *buf;
1103
1104 buf = malloc(strlen(PACKAGE_NAME) + strlen(VERSION) + 10);
1105
1106 sprintf(buf, "%s %s", PACKAGE_NAME, VERSION);
1107
1108 SDL_WM_SetCaption(buf, NULL);
1109
1110 free(buf);
1111 }
1112
1113 //
1114 // Set the application icon
1115 //
1116
1117 #include "icon.c"
1118
I_SetWindowIcon(void)1119 void I_SetWindowIcon(void)
1120 {
1121 static SDL_Surface *surface = NULL;
1122 static Uint8 *mask;
1123 int i;
1124
1125 // do it only once, because of crash in SDL_InitVideoMode in SDL 1.3
1126 if (!surface)
1127 {
1128 // Generate the mask
1129
1130 mask = malloc(icon_w * icon_h / 8);
1131 memset(mask, 0, icon_w * icon_h / 8);
1132
1133 for (i=0; i<icon_w * icon_h; ++i)
1134 {
1135 if (icon_data[i * 3] != 0x00
1136 || icon_data[i * 3 + 1] != 0x00
1137 || icon_data[i * 3 + 2] != 0x00)
1138 {
1139 mask[i / 8] |= 1 << (7 - i % 8);
1140 }
1141 }
1142
1143 surface = SDL_CreateRGBSurfaceFrom(icon_data,
1144 icon_w, icon_h, 24, icon_w * 3,
1145 0xff << 0, 0xff << 8, 0xff << 16, 0);
1146 }
1147
1148 if (surface && mask)
1149 {
1150 //SDL_WM_SetIcon(surface, mask);
1151 }
1152 }
1153
I_InitGraphics(void)1154 void I_InitGraphics(void)
1155 {
1156 static int firsttime=1;
1157
1158 if (firsttime)
1159 {
1160 firsttime = 0;
1161
1162 atexit(I_ShutdownGraphics);
1163 lprintf(LO_INFO, "I_InitGraphics: %dx%d\n", SCREENWIDTH, SCREENHEIGHT);
1164
1165 /* Set the video mode */
1166 I_UpdateVideoMode();
1167
1168 //e6y: setup the window title
1169 I_SetWindowCaption();
1170
1171 //e6y: set the application icon
1172 I_SetWindowIcon();
1173
1174 /* Initialize the input system */
1175 I_InitInputs();
1176
1177 //e6y: new mouse code
1178 UpdateFocus();
1179 UpdateGrab();
1180 }
1181 }
1182
I_GetModeFromString(const char * modestr)1183 int I_GetModeFromString(const char *modestr)
1184 {
1185 video_mode_t mode;
1186
1187 if (!stricmp(modestr,"15")) {
1188 mode = VID_MODE15;
1189 } else if (!stricmp(modestr,"15bit")) {
1190 mode = VID_MODE15;
1191 } else if (!stricmp(modestr,"16")) {
1192 mode = VID_MODE16;
1193 } else if (!stricmp(modestr,"16bit")) {
1194 mode = VID_MODE16;
1195 } else if (!stricmp(modestr,"32")) {
1196 mode = VID_MODE32;
1197 } else if (!stricmp(modestr,"32bit")) {
1198 mode = VID_MODE32;
1199 } else if (!stricmp(modestr,"gl")) {
1200 mode = VID_MODEGL;
1201 } else if (!stricmp(modestr,"OpenGL")) {
1202 mode = VID_MODEGL;
1203 } else {
1204 mode = VID_MODE8;
1205 }
1206
1207 return mode;
1208 }
1209
I_UpdateVideoMode(void)1210 void I_UpdateVideoMode(void)
1211 {
1212 int init_flags;
1213
1214 if(screen)
1215 {
1216 #ifdef GL_DOOM
1217 if (V_GetMode() == VID_MODEGL)
1218 {
1219 gld_CleanMemory();
1220 // hires patches
1221 gld_CleanStaticMemory();
1222 }
1223 #endif
1224
1225 I_InitScreenResolution();
1226
1227 SDL_FreeSurface(screen);
1228 screen = NULL;
1229
1230 #ifdef GL_DOOM
1231 if (vid_8ingl.surface)
1232 {
1233 SDL_FreeSurface(vid_8ingl.surface);
1234 vid_8ingl.surface = NULL;
1235 }
1236 #endif
1237
1238 SMP_Free();
1239 }
1240
1241 // e6y: initialisation of screen_multiply
1242 screen_multiply = render_screen_multiply;
1243
1244 // Initialize SDL with this graphics mode
1245 if (V_GetMode() == VID_MODEGL) {
1246 init_flags = SDL_OPENGL;
1247 } else {
1248 if (use_doublebuffer)
1249 init_flags = SDL_DOUBLEBUF;
1250 else
1251 init_flags = SDL_SWSURFACE;
1252 #ifndef PRBOOM_DEBUG
1253 init_flags |= SDL_HWPALETTE;
1254 #endif
1255 }
1256
1257 if ( desired_fullscreen )
1258 init_flags |= SDL_FULLSCREEN;
1259
1260 // In windowed mode, the window can be resized while the game is
1261 // running. This feature is disabled on OS X, as it adds an ugly
1262 // scroll handle to the corner of the screen.
1263 #ifndef MACOSX
1264 if (!desired_fullscreen)
1265 init_flags |= SDL_RESIZABLE;
1266 #endif
1267
1268 if (sdl_video_window_pos && sdl_video_window_pos[0])
1269 {
1270 char buf[80];
1271 strcpy(buf, "SDL_VIDEO_WINDOW_POS=");
1272 strncat(buf, sdl_video_window_pos, sizeof(buf) - sizeof(buf[0]) - strlen(buf));
1273 putenv(buf);
1274 }
1275
1276 #ifdef GL_DOOM
1277 vid_8ingl.enabled = false;
1278 #endif
1279
1280 if (V_GetMode() == VID_MODEGL)
1281 {
1282 #ifdef GL_DOOM
1283 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 0 );
1284 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 0 );
1285 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 0 );
1286 SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 0 );
1287 SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 0 );
1288 SDL_GL_SetAttribute( SDL_GL_ACCUM_RED_SIZE, 0 );
1289 SDL_GL_SetAttribute( SDL_GL_ACCUM_GREEN_SIZE, 0 );
1290 SDL_GL_SetAttribute( SDL_GL_ACCUM_BLUE_SIZE, 0 );
1291 SDL_GL_SetAttribute( SDL_GL_ACCUM_ALPHA_SIZE, 0 );
1292 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
1293 SDL_GL_SetAttribute( SDL_GL_BUFFER_SIZE, gl_colorbuffer_bits );
1294 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, gl_depthbuffer_bits );
1295 SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );
1296
1297 //e6y: vertical sync
1298 #if !SDL_VERSION_ATLEAST(1, 3, 0)
1299 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (gl_vsync ? 1 : 0));
1300 #endif
1301
1302 //e6y: anti-aliasing
1303 gld_MultisamplingInit();
1304
1305 screen = SDL_SetVideoMode(REAL_SCREENWIDTH, REAL_SCREENHEIGHT, gl_colorbuffer_bits, init_flags);
1306 gld_CheckHardwareGamma();
1307 #endif
1308 }
1309 else
1310 {
1311 #ifdef GL_DOOM
1312 if (use_gl_surface)
1313 {
1314 int flags = SDL_OPENGL;
1315
1316 if ( desired_fullscreen )
1317 flags |= SDL_FULLSCREEN;
1318
1319 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
1320 SDL_GL_SetAttribute( SDL_GL_BUFFER_SIZE, gl_colorbuffer_bits );
1321 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, gl_depthbuffer_bits );
1322 //e6y: vertical sync
1323 #if !SDL_VERSION_ATLEAST(1, 3, 0)
1324 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (gl_vsync ? 1 : 0));
1325 #endif
1326
1327 vid_8ingl.surface = SDL_SetVideoMode(
1328 REAL_SCREENWIDTH, REAL_SCREENHEIGHT,
1329 gl_colorbuffer_bits, flags);
1330
1331 if(vid_8ingl.surface == NULL)
1332 I_Error("Couldn't set %dx%d video mode [%s]", REAL_SCREENWIDTH, REAL_SCREENHEIGHT, SDL_GetError());
1333
1334 screen = SDL_CreateRGBSurface(
1335 init_flags & ~SDL_FULLSCREEN,
1336 REAL_SCREENWIDTH, REAL_SCREENHEIGHT,
1337 V_GetNumPixelBits(), 0, 0, 0, 0);
1338
1339 vid_8ingl.screen = screen;
1340
1341 vid_8ingl.enabled = true;
1342 }
1343 else
1344 #endif
1345 {
1346 screen = SDL_SetVideoMode(REAL_SCREENWIDTH, REAL_SCREENHEIGHT, V_GetNumPixelBits(), init_flags);
1347 }
1348 }
1349
1350 if(screen == NULL) {
1351 I_Error("Couldn't set %dx%d video mode [%s]", REAL_SCREENWIDTH, REAL_SCREENHEIGHT, SDL_GetError());
1352 }
1353
1354 SMP_Init();
1355
1356 #if SDL_VERSION_ATLEAST(1, 3, 0)
1357 #ifdef GL_DOOM
1358 if (V_GetMode() == VID_MODEGL)
1359 {
1360 SDL_GL_SetSwapInterval((gl_vsync ? 1 : 0));
1361 }
1362 #endif
1363 #endif
1364
1365 #ifdef GL_DOOM
1366 /*if (V_GetMode() == VID_MODEGL)
1367 gld_MultisamplingCheck();*/
1368 #endif
1369
1370 lprintf(LO_INFO, "I_UpdateVideoMode: 0x%x, %s, %s\n", init_flags, screen->pixels ? "SDL buffer" : "own buffer", SDL_MUSTLOCK(screen) ? "lock-and-copy": "direct access");
1371
1372 // Get the info needed to render to the display
1373 if (screen_multiply==1 && !SDL_MUSTLOCK(screen))
1374 {
1375 screens[0].not_on_heap = true;
1376 screens[0].data = (unsigned char *) (screen->pixels);
1377 screens[0].byte_pitch = screen->pitch;
1378 screens[0].short_pitch = screen->pitch / V_GetModePixelDepth(VID_MODE16);
1379 screens[0].int_pitch = screen->pitch / V_GetModePixelDepth(VID_MODE32);
1380 }
1381 else
1382 {
1383 screens[0].not_on_heap = false;
1384 }
1385
1386 V_AllocScreens();
1387
1388 R_InitBuffer(SCREENWIDTH, SCREENHEIGHT);
1389
1390 // e6y: wide-res
1391 // Need some initialisations before level precache
1392 R_ExecuteSetViewSize();
1393
1394 V_SetPalette(0);
1395 I_UploadNewPalette(0, true);
1396
1397 ST_SetResolution();
1398 AM_SetResolution();
1399
1400 #ifdef GL_DOOM
1401 if (V_GetMode() == VID_MODEGL)
1402 {
1403 int temp;
1404 lprintf(LO_INFO,"SDL OpenGL PixelFormat:\n");
1405 SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &temp );
1406 lprintf(LO_INFO," SDL_GL_RED_SIZE: %i\n",temp);
1407 SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &temp );
1408 lprintf(LO_INFO," SDL_GL_GREEN_SIZE: %i\n",temp);
1409 SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &temp );
1410 lprintf(LO_INFO," SDL_GL_BLUE_SIZE: %i\n",temp);
1411 SDL_GL_GetAttribute( SDL_GL_STENCIL_SIZE, &temp );
1412 lprintf(LO_INFO," SDL_GL_STENCIL_SIZE: %i\n",temp);
1413 SDL_GL_GetAttribute( SDL_GL_ACCUM_RED_SIZE, &temp );
1414 lprintf(LO_INFO," SDL_GL_ACCUM_RED_SIZE: %i\n",temp);
1415 SDL_GL_GetAttribute( SDL_GL_ACCUM_GREEN_SIZE, &temp );
1416 lprintf(LO_INFO," SDL_GL_ACCUM_GREEN_SIZE: %i\n",temp);
1417 SDL_GL_GetAttribute( SDL_GL_ACCUM_BLUE_SIZE, &temp );
1418 lprintf(LO_INFO," SDL_GL_ACCUM_BLUE_SIZE: %i\n",temp);
1419 SDL_GL_GetAttribute( SDL_GL_ACCUM_ALPHA_SIZE, &temp );
1420 lprintf(LO_INFO," SDL_GL_ACCUM_ALPHA_SIZE: %i\n",temp);
1421 SDL_GL_GetAttribute( SDL_GL_DOUBLEBUFFER, &temp );
1422 lprintf(LO_INFO," SDL_GL_DOUBLEBUFFER: %i\n",temp);
1423 SDL_GL_GetAttribute( SDL_GL_BUFFER_SIZE, &temp );
1424 lprintf(LO_INFO," SDL_GL_BUFFER_SIZE: %i\n",temp);
1425 SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &temp );
1426 lprintf(LO_INFO," SDL_GL_DEPTH_SIZE: %i\n",temp);
1427 SDL_GL_GetAttribute( SDL_GL_MULTISAMPLESAMPLES, &temp );
1428 lprintf(LO_INFO," SDL_GL_MULTISAMPLESAMPLES: %i\n",temp);
1429 SDL_GL_GetAttribute( SDL_GL_MULTISAMPLEBUFFERS, &temp );
1430 lprintf(LO_INFO," SDL_GL_MULTISAMPLEBUFFERS: %i\n",temp);
1431 SDL_GL_GetAttribute( SDL_GL_STENCIL_SIZE, &temp );
1432 lprintf(LO_INFO," SDL_GL_STENCIL_SIZE: %i\n",temp);
1433
1434 gld_Init(SCREENWIDTH, SCREENHEIGHT);
1435 }
1436
1437 if (vid_8ingl.enabled)
1438 {
1439 gld_Init8InGLMode();
1440 }
1441
1442 if (V_GetMode() == VID_MODEGL)
1443 {
1444 M_ChangeFOV();
1445 M_ChangeRenderPrecise();
1446 M_ChangeCompTranslucency();
1447 }
1448 #endif
1449 }
1450
ActivateMouse(void)1451 static void ActivateMouse(void)
1452 {
1453 SDL_WM_GrabInput(SDL_GRAB_ON);
1454 #if SDL_VERSION_ATLEAST(1, 3, 0)
1455 SDL_ShowCursor(0);
1456 #else
1457 SDL_SetCursor(cursors[1]);
1458 SDL_ShowCursor(1);
1459 #endif
1460 }
1461
DeactivateMouse(void)1462 static void DeactivateMouse(void)
1463 {
1464 SDL_WM_GrabInput(SDL_GRAB_OFF);
1465 #if !SDL_VERSION_ATLEAST(1, 3, 0)
1466 SDL_SetCursor(cursors[0]);
1467 #endif
1468 SDL_ShowCursor(1);
1469 }
1470
1471 // Warp the mouse back to the middle of the screen
CenterMouse(void)1472 static void CenterMouse(void)
1473 {
1474 // Warp the the screen center
1475 SDL_WarpMouse((unsigned short)(REAL_SCREENWIDTH/2), (unsigned short)(REAL_SCREENHEIGHT/2));
1476
1477 // Clear any relative movement caused by warping
1478 SDL_PumpEvents();
1479 SDL_GetRelativeMouseState(NULL, NULL);
1480 }
1481
1482 //
1483 // Read the change in mouse state to generate mouse motion events
1484 //
1485 // This is to combine all mouse movement for a tic into one mouse
1486 // motion event.
I_ReadMouse(void)1487 static void I_ReadMouse(void)
1488 {
1489 static int mouse_currently_grabbed = true;
1490 int x, y;
1491 event_t ev;
1492
1493 if (!usemouse)
1494 return;
1495
1496 if (!MouseShouldBeGrabbed())
1497 {
1498 mouse_currently_grabbed = false;
1499 return;
1500 }
1501
1502 if (!mouse_currently_grabbed && !desired_fullscreen)
1503 {
1504 CenterMouse();
1505 mouse_currently_grabbed = true;
1506 }
1507
1508 SDL_GetRelativeMouseState(&x, &y);
1509
1510 if (x != 0 || y != 0)
1511 {
1512 ev.type = ev_mouse;
1513 ev.data1 = I_SDLtoDoomMouseState(SDL_GetMouseState(NULL, NULL));
1514 ev.data2 = x << 5;
1515 ev.data3 = (-y) << 5;
1516
1517 D_PostEvent(&ev);
1518 }
1519
1520 CenterMouse();
1521 }
1522
MouseShouldBeGrabbed()1523 static dboolean MouseShouldBeGrabbed()
1524 {
1525 // never grab the mouse when in screensaver mode
1526
1527 //if (screensaver_mode)
1528 // return false;
1529
1530 // if the window doesnt have focus, never grab it
1531 if (!window_focused)
1532 return false;
1533
1534 // always grab the mouse when full screen (dont want to
1535 // see the mouse pointer)
1536 if (desired_fullscreen)
1537 return true;
1538
1539 // if we specify not to grab the mouse, never grab
1540 if (!mouse_enabled)
1541 return false;
1542
1543 // always grab the mouse in camera mode when playing levels
1544 // and menu is not active
1545 if (walkcamera.type)
1546 return (demoplayback && gamestate == GS_LEVEL && !menuactive);
1547
1548 // when menu is active or game is paused, release the mouse
1549 if (menuactive || paused)
1550 return false;
1551
1552 // only grab mouse when playing levels (but not demos)
1553 return (gamestate == GS_LEVEL) && !demoplayback;
1554 }
1555
1556 // Update the value of window_focused when we get a focus event
1557 //
1558 // We try to make ourselves be well-behaved: the grab on the mouse
1559 // is removed if we lose focus (such as a popup window appearing),
1560 // and we dont move the mouse around if we aren't focused either.
UpdateFocus(void)1561 static void UpdateFocus(void)
1562 {
1563 Uint8 state;
1564
1565 state = SDL_GetAppState();
1566
1567 // We should have input (keyboard) focus and be visible
1568 // (not minimised)
1569 window_focused = (state & SDL_APPINPUTFOCUS) && (state & SDL_APPACTIVE);
1570
1571 // e6y
1572 // Reuse of a current palette to avoid black screen at software fullscreen modes
1573 // after switching to OS and back
1574 if (desired_fullscreen && window_focused)
1575 {
1576 // currentPaletteIndex?
1577 if (st_palette < 0)
1578 st_palette = 0;
1579
1580 V_SetPalette(st_palette);
1581 }
1582
1583 #ifdef GL_DOOM
1584 if (V_GetMode() == VID_MODEGL)
1585 {
1586 if (gl_hardware_gamma)
1587 {
1588 if (!window_focused)
1589 {
1590 // e6y: Restore of startup gamma if window loses focus
1591 gld_SetGammaRamp(-1);
1592 }
1593 else
1594 {
1595 gld_SetGammaRamp(useglgamma);
1596 }
1597 }
1598 }
1599 #endif
1600
1601 // Should the screen be grabbed?
1602 // screenvisible = (state & SDL_APPACTIVE) != 0;
1603 }
1604
UpdateGrab(void)1605 void UpdateGrab(void)
1606 {
1607 static dboolean currently_grabbed = false;
1608 dboolean grab;
1609
1610 grab = MouseShouldBeGrabbed();
1611
1612 if (grab && !currently_grabbed)
1613 {
1614 ActivateMouse();
1615 }
1616
1617 if (!grab && currently_grabbed)
1618 {
1619 DeactivateMouse();
1620 }
1621
1622 currently_grabbed = grab;
1623 }
1624
ApplyWindowResize(SDL_Event * resize_event)1625 static void ApplyWindowResize(SDL_Event *resize_event)
1626 {
1627 int i, k;
1628 char mode[80];
1629
1630 int w = MAX(320, resize_event->resize.w);
1631 int h = MAX(200, resize_event->resize.h);
1632
1633 if (screen_resolution)
1634 {
1635 if (!(SDL_GetModState() & KMOD_SHIFT))
1636 {
1637 // Find the biggest screen mode that will fall within these
1638 // dimensions, falling back to the smallest mode possible if
1639 // none is found.
1640
1641 Uint32 flags = SDL_FULLSCREEN;
1642
1643 if (V_GetMode() == VID_MODEGL)
1644 flags |= SDL_OPENGL;
1645
1646 I_ClosestResolution(&w, &h, flags);
1647 }
1648
1649 w = MAX(320, w);
1650 h = MAX(200, h);
1651
1652 sprintf(mode, "%dx%d", w, h);
1653 screen_resolution = screen_resolutions_list[0];
1654 for (i = 0; i < MAX_RESOLUTIONS_COUNT; i++)
1655 {
1656 if (screen_resolutions_list[i])
1657 {
1658 if (!strcmp(mode, screen_resolutions_list[i]))
1659 {
1660 screen_resolution = screen_resolutions_list[i];
1661 break;
1662 }
1663 }
1664 }
1665
1666 // custom resolution
1667 if (screen_resolution == screen_resolutions_list[0])
1668 {
1669 if (screen_resolution_lowest &&
1670 !strcmp(screen_resolution_lowest, screen_resolutions_list[0]))
1671 {
1672 // there is no "custom resolution" entry in the list
1673 for(k = MAX_RESOLUTIONS_COUNT - 1; k > 0; k--)
1674 {
1675 screen_resolutions_list[k] = screen_resolutions_list[k - 1];
1676 }
1677 // add it
1678 screen_resolutions_list[0] = strdup(mode);
1679 screen_resolution = screen_resolutions_list[0];
1680 }
1681 else
1682 {
1683 sprintf((char*)screen_resolution, mode);
1684 }
1685 }
1686
1687 V_ChangeScreenResolution();
1688
1689 doom_printf("%dx%d", w, h);
1690 }
1691 }
1692