2 Copyright (C) 2003 T. Joseph Carter
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #undef WIN32_LEAN_AND_MEAN //hush a warning, SDL.h redefines this
25 // Tell startup code that we have a client
26 int cl_available = true;
28 qboolean vid_supportrefreshrate = false;
30 cvar_t joy_detected = {CVAR_READONLY, "joy_detected", "0", "number of joysticks detected by engine"};
31 cvar_t joy_enable = {CVAR_SAVE, "joy_enable", "0", "enables joystick support"};
32 cvar_t joy_index = {0, "joy_index", "0", "selects which joystick to use if you have multiple"};
33 cvar_t joy_axisforward = {0, "joy_axisforward", "1", "which joystick axis to query for forward/backward movement"};
34 cvar_t joy_axisside = {0, "joy_axisside", "0", "which joystick axis to query for right/left movement"};
35 cvar_t joy_axisup = {0, "joy_axisup", "-1", "which joystick axis to query for up/down movement"};
36 cvar_t joy_axispitch = {0, "joy_axispitch", "3", "which joystick axis to query for looking up/down"};
37 cvar_t joy_axisyaw = {0, "joy_axisyaw", "2", "which joystick axis to query for looking right/left"};
38 cvar_t joy_axisroll = {0, "joy_axisroll", "-1", "which joystick axis to query for tilting head right/left"};
39 cvar_t joy_deadzoneforward = {0, "joy_deadzoneforward", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
40 cvar_t joy_deadzoneside = {0, "joy_deadzoneside", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
41 cvar_t joy_deadzoneup = {0, "joy_deadzoneup", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
42 cvar_t joy_deadzonepitch = {0, "joy_deadzonepitch", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
43 cvar_t joy_deadzoneyaw = {0, "joy_deadzoneyaw", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
44 cvar_t joy_deadzoneroll = {0, "joy_deadzoneroll", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
45 cvar_t joy_sensitivityforward = {0, "joy_sensitivityforward", "-1", "movement multiplier"};
46 cvar_t joy_sensitivityside = {0, "joy_sensitivityside", "1", "movement multiplier"};
47 cvar_t joy_sensitivityup = {0, "joy_sensitivityup", "1", "movement multiplier"};
48 cvar_t joy_sensitivitypitch = {0, "joy_sensitivitypitch", "1", "movement multiplier"};
49 cvar_t joy_sensitivityyaw = {0, "joy_sensitivityyaw", "-1", "movement multiplier"};
50 cvar_t joy_sensitivityroll = {0, "joy_sensitivityroll", "1", "movement multiplier"};
52 static qboolean vid_usingmouse = false;
53 static qboolean vid_usinghidecursor = false;
54 static qboolean vid_isfullscreen;
55 static int vid_numjoysticks = 0;
56 #define MAX_JOYSTICKS 8
57 static SDL_Joystick *vid_joysticks[MAX_JOYSTICKS];
59 static int win_half_width = 50;
60 static int win_half_height = 50;
61 static int video_bpp, video_flags;
63 static SDL_Surface *screen;
65 /////////////////////////
68 //TODO: Add joystick support
69 //TODO: Add error checking
72 //keysym to quake keysym mapping
73 #define tenoh 0,0,0,0,0, 0,0,0,0,0
74 #define fiftyoh tenoh, tenoh, tenoh, tenoh, tenoh
75 #define hundredoh fiftyoh, fiftyoh
76 static unsigned int tbl_sdltoquake[] =
78 0,0,0,0, //SDLK_UNKNOWN = 0,
79 0,0,0,0, //SDLK_FIRST = 0,
80 K_BACKSPACE, //SDLK_BACKSPACE = 8,
81 K_TAB, //SDLK_TAB = 9,
84 K_ENTER, //SDLK_RETURN = 13,
86 K_PAUSE, //SDLK_PAUSE = 19,
88 K_ESCAPE, //SDLK_ESCAPE = 27,
90 K_SPACE, //SDLK_SPACE = 32,
91 '!', //SDLK_EXCLAIM = 33,
92 '"', //SDLK_QUOTEDBL = 34,
93 '#', //SDLK_HASH = 35,
94 '$', //SDLK_DOLLAR = 36,
96 '&', //SDLK_AMPERSAND = 38,
97 '\'', //SDLK_QUOTE = 39,
98 '(', //SDLK_LEFTPAREN = 40,
99 ')', //SDLK_RIGHTPAREN = 41,
100 '*', //SDLK_ASTERISK = 42,
101 '+', //SDLK_PLUS = 43,
102 ',', //SDLK_COMMA = 44,
103 '-', //SDLK_MINUS = 45,
104 '.', //SDLK_PERIOD = 46,
105 '/', //SDLK_SLASH = 47,
116 ':', //SDLK_COLON = 58,
117 ';', //SDLK_SEMICOLON = 59,
118 '<', //SDLK_LESS = 60,
119 '=', //SDLK_EQUALS = 61,
120 '>', //SDLK_GREATER = 62,
121 '?', //SDLK_QUESTION = 63,
123 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
124 '[', //SDLK_LEFTBRACKET = 91,
125 '\\', //SDLK_BACKSLASH = 92,
126 ']', //SDLK_RIGHTBRACKET = 93,
127 '^', //SDLK_CARET = 94,
128 '_', //SDLK_UNDERSCORE = 95,
129 '`', //SDLK_BACKQUOTE = 96,
157 K_DEL, //SDLK_DELETE = 127,
158 hundredoh /*227*/, tenoh, tenoh, 0,0,0,0,0,0,0,0,
159 K_KP_0, //SDLK_KP0 = 256,
160 K_KP_1, //SDLK_KP1 = 257,
161 K_KP_2, //SDLK_KP2 = 258,
162 K_KP_3, //SDLK_KP3 = 259,
163 K_KP_4, //SDLK_KP4 = 260,
164 K_KP_5, //SDLK_KP5 = 261,
165 K_KP_6, //SDLK_KP6 = 262,
166 K_KP_7, //SDLK_KP7 = 263,
167 K_KP_8, //SDLK_KP8 = 264,
168 K_KP_9, //SDLK_KP9 = 265,
169 K_KP_PERIOD,//SDLK_KP_PERIOD = 266,
170 K_KP_DIVIDE,//SDLK_KP_DIVIDE = 267,
171 K_KP_MULTIPLY,//SDLK_KP_MULTIPLY= 268,
172 K_KP_MINUS, //SDLK_KP_MINUS = 269,
173 K_KP_PLUS, //SDLK_KP_PLUS = 270,
174 K_KP_ENTER, //SDLK_KP_ENTER = 271,
175 K_KP_EQUALS,//SDLK_KP_EQUALS = 272,
176 K_UPARROW, //SDLK_UP = 273,
177 K_DOWNARROW,//SDLK_DOWN = 274,
178 K_RIGHTARROW,//SDLK_RIGHT = 275,
179 K_LEFTARROW,//SDLK_LEFT = 276,
180 K_INS, //SDLK_INSERT = 277,
181 K_HOME, //SDLK_HOME = 278,
182 K_END, //SDLK_END = 279,
183 K_PGUP, //SDLK_PAGEUP = 280,
184 K_PGDN, //SDLK_PAGEDOWN = 281,
185 K_F1, //SDLK_F1 = 282,
186 K_F2, //SDLK_F2 = 283,
187 K_F3, //SDLK_F3 = 284,
188 K_F4, //SDLK_F4 = 285,
189 K_F5, //SDLK_F5 = 286,
190 K_F6, //SDLK_F6 = 287,
191 K_F7, //SDLK_F7 = 288,
192 K_F8, //SDLK_F8 = 289,
193 K_F9, //SDLK_F9 = 290,
194 K_F10, //SDLK_F10 = 291,
195 K_F11, //SDLK_F11 = 292,
196 K_F12, //SDLK_F12 = 293,
201 K_NUMLOCK, //SDLK_NUMLOCK = 300,
202 K_CAPSLOCK, //SDLK_CAPSLOCK = 301,
203 K_SCROLLOCK,//SDLK_SCROLLOCK= 302,
204 K_SHIFT, //SDLK_RSHIFT = 303,
205 K_SHIFT, //SDLK_LSHIFT = 304,
206 K_CTRL, //SDLK_RCTRL = 305,
207 K_CTRL, //SDLK_LCTRL = 306,
208 K_ALT, //SDLK_RALT = 307,
209 K_ALT, //SDLK_LALT = 308,
210 0, //SDLK_RMETA = 309,
211 0, //SDLK_LMETA = 310,
212 0, //SDLK_LSUPER = 311, /* Left "Windows" key */
213 0, //SDLK_RSUPER = 312, /* Right "Windows" key */
214 K_ALT, //SDLK_MODE = 313, /* "Alt Gr" key */
215 0, //SDLK_COMPOSE = 314, /* Multi-key compose key */
216 0, //SDLK_HELP = 315,
217 0, //SDLK_PRINT = 316,
218 0, //SDLK_SYSREQ = 317,
219 K_PAUSE, //SDLK_BREAK = 318,
220 0, //SDLK_MENU = 319,
221 0, //SDLK_POWER = 320, /* Power Macintosh power key */
222 'e', //SDLK_EURO = 321, /* Some european keyboards */
223 0 //SDLK_UNDO = 322, /* Atari keyboard has Undo */
229 static int MapKey( unsigned int sdlkey )
231 if( sdlkey > sizeof(tbl_sdltoquake)/ sizeof(int) )
233 return tbl_sdltoquake[ sdlkey ];
236 void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor)
238 if (vid_usingmouse != relative)
240 vid_usingmouse = relative;
241 cl_ignoremousemoves = 2;
242 SDL_WM_GrabInput( relative ? SDL_GRAB_ON : SDL_GRAB_OFF );
244 if (vid_usinghidecursor != hidecursor)
246 vid_usinghidecursor = hidecursor;
247 SDL_ShowCursor( hidecursor ? SDL_DISABLE : SDL_ENABLE);
251 static double IN_JoystickGetAxis(SDL_Joystick *joy, int axis, double sensitivity, double deadzone)
254 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
255 return 0; // no such axis on this joystick
256 value = SDL_JoystickGetAxis(joy, axis) * (1.0 / 32767.0);
257 value = bound(-1, value, 1);
258 if (fabs(value) < deadzone)
259 return 0; // within deadzone around center
260 return value * sensitivity;
266 static int old_x = 0, old_y = 0;
267 static int stuck = 0;
271 if(vid_stick_mouse.integer)
273 // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
274 // window grabbing. --blub
276 // we need 2 frames to initialize the center position
279 SDL_WarpMouse(win_half_width, win_half_height);
280 SDL_GetMouseState(&x, &y);
281 SDL_GetRelativeMouseState(&x, &y);
284 SDL_GetRelativeMouseState(&x, &y);
285 in_mouse_x = x + old_x;
286 in_mouse_y = y + old_y;
287 SDL_GetMouseState(&x, &y);
288 old_x = x - win_half_width;
289 old_y = y - win_half_height;
290 SDL_WarpMouse(win_half_width, win_half_height);
293 SDL_GetRelativeMouseState( &x, &y );
299 SDL_GetMouseState(&x, &y);
300 in_windowmouse_x = x;
301 in_windowmouse_y = y;
303 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
305 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
306 int numballs = SDL_JoystickNumBalls(joy);
307 for (j = 0;j < numballs;j++)
309 SDL_JoystickGetBall(joy, j, &x, &y);
313 cl.cmd.forwardmove += IN_JoystickGetAxis(joy, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
314 cl.cmd.sidemove += IN_JoystickGetAxis(joy, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
315 cl.cmd.upmove += IN_JoystickGetAxis(joy, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
316 cl.viewangles[0] += IN_JoystickGetAxis(joy, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
317 cl.viewangles[1] += IN_JoystickGetAxis(joy, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
318 //cl.viewangles[2] += IN_JoystickGetAxis(joy, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
322 /////////////////////
326 static int Sys_EventFilter( SDL_Event *event )
328 //TODO: Add a quit query in linux, too - though linux user are more likely to know what they do
329 if (event->type == SDL_QUIT)
332 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
339 static keynum_t buttonremap[18] =
361 void Sys_SendKeyEvents( void )
363 static qboolean sound_active = true;
366 while( SDL_PollEvent( &event ) )
367 switch( event.type ) {
373 Key_Event( MapKey( event.key.keysym.sym ), (char)event.key.keysym.unicode, (event.key.state == SDL_PRESSED) );
375 case SDL_ACTIVEEVENT:
376 if( event.active.state & SDL_APPACTIVE )
378 if( event.active.gain )
384 case SDL_MOUSEBUTTONDOWN:
385 case SDL_MOUSEBUTTONUP:
386 if (event.button.button <= 18)
387 Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
389 case SDL_JOYBUTTONDOWN:
390 if (!joy_enable.integer)
391 break; // ignore down events if joystick has been disabled
392 case SDL_JOYBUTTONUP:
393 if (event.jbutton.button < 48)
394 Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
396 case SDL_VIDEORESIZE:
397 if(vid_resizable.integer < 2)
399 vid.width = event.resize.w;
400 vid.height = event.resize.h;
401 SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
406 // enable/disable sound on focus gain/loss
407 if (!vid_hidden && (vid_activewindow || !snd_mutewhenidle.integer))
420 sound_active = false;
429 void *GL_GetProcAddress(const char *name)
432 p = SDL_GL_GetProcAddress(name);
436 static int Sys_EventFilter( SDL_Event *event );
437 static qboolean vid_sdl_initjoysticksystem = false;
440 Cvar_RegisterVariable(&joy_detected);
441 Cvar_RegisterVariable(&joy_enable);
442 Cvar_RegisterVariable(&joy_index);
443 Cvar_RegisterVariable(&joy_axisforward);
444 Cvar_RegisterVariable(&joy_axisside);
445 Cvar_RegisterVariable(&joy_axisup);
446 Cvar_RegisterVariable(&joy_axispitch);
447 Cvar_RegisterVariable(&joy_axisyaw);
448 //Cvar_RegisterVariable(&joy_axisroll);
449 Cvar_RegisterVariable(&joy_deadzoneforward);
450 Cvar_RegisterVariable(&joy_deadzoneside);
451 Cvar_RegisterVariable(&joy_deadzoneup);
452 Cvar_RegisterVariable(&joy_deadzonepitch);
453 Cvar_RegisterVariable(&joy_deadzoneyaw);
454 //Cvar_RegisterVariable(&joy_deadzoneroll);
455 Cvar_RegisterVariable(&joy_sensitivityforward);
456 Cvar_RegisterVariable(&joy_sensitivityside);
457 Cvar_RegisterVariable(&joy_sensitivityup);
458 Cvar_RegisterVariable(&joy_sensitivitypitch);
459 Cvar_RegisterVariable(&joy_sensitivityyaw);
460 //Cvar_RegisterVariable(&joy_sensitivityroll);
462 if (SDL_Init(SDL_INIT_VIDEO) < 0)
463 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
464 vid_sdl_initjoysticksystem = SDL_Init(SDL_INIT_JOYSTICK) >= 0;
465 if (vid_sdl_initjoysticksystem)
466 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
467 vid_isfullscreen = false;
470 // set the icon (we dont use SDL here since it would be too much a PITA)
472 #include "resource.h"
473 #include <SDL_syswm.h>
474 static void VID_SetCaption()
480 SDL_WM_SetCaption( gamename, NULL );
482 // get the HWND handle
483 SDL_VERSION( &info.version );
484 if( !SDL_GetWMInfo( &info ) )
487 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
488 #ifndef _W64 //If Windows 64bit data types don't exist
489 #ifndef SetClassLongPtr
490 #define SetClassLongPtr SetClassLong
493 #define GCLP_HICON GCL_HICON
496 #define LONG_PTR LONG
499 SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
501 static void VID_SetIcon()
505 // Adding the OS independent XPM version --blub
506 #include "darkplaces.xpm"
507 #include "nexuiz.xpm"
508 static SDL_Surface *icon = NULL;
509 static void VID_SetIcon()
512 * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
513 * default settings with less than 91 colors and transparency.
516 int width, height, colors, isize, i, j;
518 static SDL_Color palette[256];
519 unsigned short palenc[256]; // store color id by char
521 char **idata = ENGINE_ICON;
522 char *data = idata[0];
524 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) != 4)
526 // NOTE: Only 1-char colornames are supported
527 Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
533 // NOTE: Only 1-char colornames are supported
534 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
538 for(i = 0; i < colors; ++i)
540 unsigned int r, g, b;
543 if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
546 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
548 Con_Printf("This XPM's palette looks odd. Can't continue.\n");
553 palette[i].r = 255; // color key
556 thenone = i; // weeeee
561 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
566 palenc[(unsigned char) idx] = i;
569 // allocate the image data
570 data = (char*) malloc(width*height);
572 for(j = 0; j < height; ++j)
574 for(i = 0; i < width; ++i)
576 // casting to the safest possible datatypes ^^
577 data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
583 // SDL_FreeSurface should free the data too
584 // but for completeness' sake...
585 if(icon->flags & SDL_PREALLOC)
588 icon->pixels = NULL; // safety
590 SDL_FreeSurface(icon);
593 icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
594 // 8 bit surfaces get an empty palette allocated according to the docs
595 // so it's a palette image for sure :) no endian check necessary for the mask
598 Con_Printf( "Failed to create surface for the window Icon!\n"
599 "%s\n", SDL_GetError());
604 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
605 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
607 SDL_WM_SetIcon(icon, NULL);
611 static void VID_SetCaption()
613 SDL_WM_SetCaption( gamename, NULL );
617 static void VID_OutputVersion()
619 const SDL_version *version;
620 version = SDL_Linked_Version();
621 Con_Printf( "Linked against SDL version %d.%d.%d\n"
622 "Using SDL library version %d.%d.%d\n",
623 SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
624 version->major, version->minor, version->patch );
627 int VID_InitMode(int fullscreen, int *width, int *height, int bpp, int refreshrate, int stereobuffer, int samples)
630 static int notfirstvideomode = false;
631 int flags = SDL_OPENGL;
632 const char *drivername;
634 win_half_width = *width>>1;
635 win_half_height = *height>>1;
637 if(vid_resizable.integer)
638 flags |= SDL_RESIZABLE;
644 We cant switch from one OpenGL video mode to another.
645 Thus we first switch to some stupid 2D mode and then back to OpenGL.
647 if (notfirstvideomode)
648 SDL_SetVideoMode( 0, 0, 0, 0 );
649 notfirstvideomode = true;
651 // SDL usually knows best
654 // COMMANDLINEOPTION: SDL GL: -gl_driver <drivername> selects a GL driver library, default is whatever SDL recommends, useful only for 3dfxogl.dll/3dfxvgl.dll or fxmesa or similar, if you don't know what this is for, you don't need it
655 i = COM_CheckParm("-gl_driver");
656 if (i && i < com_argc - 1)
657 drivername = com_argv[i + 1];
658 if (SDL_GL_LoadLibrary(drivername) < 0)
660 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
664 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
667 Con_Print("Required OpenGL function glGetString not found\n");
671 // Knghtbrd: should do platform-specific extension string function here
673 vid_isfullscreen = false;
675 flags |= SDL_FULLSCREEN;
676 vid_isfullscreen = true;
678 //flags |= SDL_HWSURFACE;
680 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
683 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
684 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
685 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
686 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
687 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
688 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
692 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
693 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
694 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
695 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
698 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
699 if (vid_vsync.integer)
700 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
702 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
705 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
706 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, samples);
712 screen = SDL_SetVideoMode(*width, *height, bpp, flags);
716 Con_Printf("Failed to set video mode to %ix%i: %s\n", *width, *height, SDL_GetError());
723 // set up an event filter to ask confirmation on close button in WIN32
724 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
726 SDL_EnableUNICODE( SDL_ENABLE );
727 // enable key repeat since everyone expects it
728 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
731 gl_platformextensions = "";
732 gl_videosyncavailable = true;
736 vid_numjoysticks = SDL_NumJoysticks();
737 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
738 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
739 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
740 memset(vid_joysticks, 0, sizeof(vid_joysticks));
741 for (i = 0;i < vid_numjoysticks;i++)
744 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
747 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
750 Con_Printf("joystick #%i: opened \"%s\" with %i axes, %i buttons, %i balls\n", i, SDL_JoystickName(i), (int)SDL_JoystickNumAxes(joy), (int)SDL_JoystickNumButtons(joy), (int)SDL_JoystickNumBalls(joy));
754 vid_activewindow = false;
755 vid_usingmouse = false;
756 vid_usinghidecursor = false;
758 SDL_WM_GrabInput(SDL_GRAB_OFF);
762 void VID_Shutdown (void)
764 VID_SetMouse(false, false, false);
765 VID_RestoreSystemGamma();
767 SDL_QuitSubSystem(SDL_INIT_VIDEO);
772 gl_platformextensions = "";
775 int VID_SetGamma (unsigned short *ramps, int rampsize)
777 return !SDL_SetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
780 int VID_GetGamma (unsigned short *ramps, int rampsize)
782 return !SDL_GetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
785 void VID_Finish (void)
789 //react on appstate changes
790 appstate = SDL_GetAppState();
792 vid_hidden = !(appstate & SDL_APPACTIVE);
794 if( vid_hidden || !( appstate & SDL_APPMOUSEFOCUS ) || !( appstate & SDL_APPINPUTFOCUS ) )
795 vid_activewindow = false;
797 vid_activewindow = true;
799 VID_UpdateGamma(false, 256);
801 if (r_render.integer && !vid_hidden)
804 if (r_speeds.integer == 2 || gl_finish.integer)
806 qglFinish();CHECKGLERROR
808 SDL_GL_SwapBuffers();