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;
53 static qboolean vid_isfullscreen;
54 static int vid_numjoysticks = 0;
55 #define MAX_JOYSTICKS 8
56 static SDL_Joystick *vid_joysticks[MAX_JOYSTICKS];
58 static int win_half_width = 50;
59 static int win_half_height = 50;
60 static int video_bpp, video_flags;
62 static SDL_Surface *screen;
64 /////////////////////////
67 //TODO: Add joystick support
68 //TODO: Add error checking
71 //keysym to quake keysym mapping
72 #define tenoh 0,0,0,0,0, 0,0,0,0,0
73 #define fiftyoh tenoh, tenoh, tenoh, tenoh, tenoh
74 #define hundredoh fiftyoh, fiftyoh
75 static unsigned int tbl_sdltoquake[] =
77 0,0,0,0, //SDLK_UNKNOWN = 0,
78 0,0,0,0, //SDLK_FIRST = 0,
79 K_BACKSPACE, //SDLK_BACKSPACE = 8,
80 K_TAB, //SDLK_TAB = 9,
83 K_ENTER, //SDLK_RETURN = 13,
85 K_PAUSE, //SDLK_PAUSE = 19,
87 K_ESCAPE, //SDLK_ESCAPE = 27,
89 K_SPACE, //SDLK_SPACE = 32,
90 '!', //SDLK_EXCLAIM = 33,
91 '"', //SDLK_QUOTEDBL = 34,
92 '#', //SDLK_HASH = 35,
93 '$', //SDLK_DOLLAR = 36,
95 '&', //SDLK_AMPERSAND = 38,
96 '\'', //SDLK_QUOTE = 39,
97 '(', //SDLK_LEFTPAREN = 40,
98 ')', //SDLK_RIGHTPAREN = 41,
99 '*', //SDLK_ASTERISK = 42,
100 '+', //SDLK_PLUS = 43,
101 ',', //SDLK_COMMA = 44,
102 '-', //SDLK_MINUS = 45,
103 '.', //SDLK_PERIOD = 46,
104 '/', //SDLK_SLASH = 47,
115 ':', //SDLK_COLON = 58,
116 ';', //SDLK_SEMICOLON = 59,
117 '<', //SDLK_LESS = 60,
118 '=', //SDLK_EQUALS = 61,
119 '>', //SDLK_GREATER = 62,
120 '?', //SDLK_QUESTION = 63,
122 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,
123 '[', //SDLK_LEFTBRACKET = 91,
124 '\\', //SDLK_BACKSLASH = 92,
125 ']', //SDLK_RIGHTBRACKET = 93,
126 '^', //SDLK_CARET = 94,
127 '_', //SDLK_UNDERSCORE = 95,
128 '`', //SDLK_BACKQUOTE = 96,
156 K_DEL, //SDLK_DELETE = 127,
157 hundredoh /*227*/, tenoh, tenoh, 0,0,0,0,0,0,0,0,
158 K_KP_0, //SDLK_KP0 = 256,
159 K_KP_1, //SDLK_KP1 = 257,
160 K_KP_2, //SDLK_KP2 = 258,
161 K_KP_3, //SDLK_KP3 = 259,
162 K_KP_4, //SDLK_KP4 = 260,
163 K_KP_5, //SDLK_KP5 = 261,
164 K_KP_6, //SDLK_KP6 = 262,
165 K_KP_7, //SDLK_KP7 = 263,
166 K_KP_8, //SDLK_KP8 = 264,
167 K_KP_9, //SDLK_KP9 = 265,
168 K_KP_PERIOD,//SDLK_KP_PERIOD = 266,
169 K_KP_DIVIDE,//SDLK_KP_DIVIDE = 267,
170 K_KP_MULTIPLY,//SDLK_KP_MULTIPLY= 268,
171 K_KP_MINUS, //SDLK_KP_MINUS = 269,
172 K_KP_PLUS, //SDLK_KP_PLUS = 270,
173 K_KP_ENTER, //SDLK_KP_ENTER = 271,
174 K_KP_EQUALS,//SDLK_KP_EQUALS = 272,
175 K_UPARROW, //SDLK_UP = 273,
176 K_DOWNARROW,//SDLK_DOWN = 274,
177 K_RIGHTARROW,//SDLK_RIGHT = 275,
178 K_LEFTARROW,//SDLK_LEFT = 276,
179 K_INS, //SDLK_INSERT = 277,
180 K_HOME, //SDLK_HOME = 278,
181 K_END, //SDLK_END = 279,
182 K_PGUP, //SDLK_PAGEUP = 280,
183 K_PGDN, //SDLK_PAGEDOWN = 281,
184 K_F1, //SDLK_F1 = 282,
185 K_F2, //SDLK_F2 = 283,
186 K_F3, //SDLK_F3 = 284,
187 K_F4, //SDLK_F4 = 285,
188 K_F5, //SDLK_F5 = 286,
189 K_F6, //SDLK_F6 = 287,
190 K_F7, //SDLK_F7 = 288,
191 K_F8, //SDLK_F8 = 289,
192 K_F9, //SDLK_F9 = 290,
193 K_F10, //SDLK_F10 = 291,
194 K_F11, //SDLK_F11 = 292,
195 K_F12, //SDLK_F12 = 293,
200 K_NUMLOCK, //SDLK_NUMLOCK = 300,
201 K_CAPSLOCK, //SDLK_CAPSLOCK = 301,
202 K_SCROLLOCK,//SDLK_SCROLLOCK= 302,
203 K_SHIFT, //SDLK_RSHIFT = 303,
204 K_SHIFT, //SDLK_LSHIFT = 304,
205 K_CTRL, //SDLK_RCTRL = 305,
206 K_CTRL, //SDLK_LCTRL = 306,
207 K_ALT, //SDLK_RALT = 307,
208 K_ALT, //SDLK_LALT = 308,
209 0, //SDLK_RMETA = 309,
210 0, //SDLK_LMETA = 310,
211 0, //SDLK_LSUPER = 311, /* Left "Windows" key */
212 0, //SDLK_RSUPER = 312, /* Right "Windows" key */
213 K_ALT, //SDLK_MODE = 313, /* "Alt Gr" key */
214 0, //SDLK_COMPOSE = 314, /* Multi-key compose key */
215 0, //SDLK_HELP = 315,
216 0, //SDLK_PRINT = 316,
217 0, //SDLK_SYSREQ = 317,
218 K_PAUSE, //SDLK_BREAK = 318,
219 0, //SDLK_MENU = 319,
220 0, //SDLK_POWER = 320, /* Power Macintosh power key */
221 'e', //SDLK_EURO = 321, /* Some european keyboards */
222 0 //SDLK_UNDO = 322, /* Atari keyboard has Undo */
228 static int MapKey( unsigned int sdlkey )
230 if( sdlkey > sizeof(tbl_sdltoquake)/ sizeof(int) )
232 return tbl_sdltoquake[ sdlkey ];
235 static void IN_Activate( qboolean grab )
237 //SDL_WM_GrabInput( SDL_GRAB_OFF );
238 //Con_Printf("< Turning off input-grabbing. --blub\n");
243 vid_usingmouse = true;
244 cl_ignoremousemoves = 2;
245 SDL_WM_GrabInput( SDL_GRAB_ON );
246 SDL_ShowCursor( SDL_DISABLE );
253 vid_usingmouse = false;
254 cl_ignoremousemoves = 2;
255 SDL_WM_GrabInput( SDL_GRAB_OFF );
256 SDL_ShowCursor( SDL_ENABLE );
261 static double IN_JoystickGetAxis(SDL_Joystick *joy, int axis, double sensitivity, double deadzone)
264 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
265 return 0; // no such axis on this joystick
266 value = SDL_JoystickGetAxis(joy, axis) * (1.0 / 32767.0);
267 value = bound(-1, value, 1);
268 if (fabs(value) < deadzone)
269 return 0; // within deadzone around center
270 return value * sensitivity;
276 static int old_x = 0, old_y = 0;
277 static int stuck = 0;
281 if(vid_stick_mouse.integer)
283 // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
284 // window grabbing. --blub
286 // we need 2 frames to initialize the center position
289 SDL_WarpMouse(win_half_width, win_half_height);
290 SDL_GetMouseState(&x, &y);
291 SDL_GetRelativeMouseState(&x, &y);
294 SDL_GetRelativeMouseState(&x, &y);
295 in_mouse_x = x + old_x;
296 in_mouse_y = y + old_y;
297 SDL_GetMouseState(&x, &y);
298 old_x = x - win_half_width;
299 old_y = y - win_half_height;
300 SDL_WarpMouse(win_half_width, win_half_height);
303 SDL_GetRelativeMouseState( &x, &y );
308 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
310 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
311 int numballs = SDL_JoystickNumBalls(joy);
312 for (j = 0;j < numballs;j++)
314 SDL_JoystickGetBall(joy, j, &x, &y);
318 cl.cmd.forwardmove += IN_JoystickGetAxis(joy, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
319 cl.cmd.sidemove += IN_JoystickGetAxis(joy, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
320 cl.cmd.upmove += IN_JoystickGetAxis(joy, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
321 cl.viewangles[0] += IN_JoystickGetAxis(joy, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
322 cl.viewangles[1] += IN_JoystickGetAxis(joy, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
323 //cl.viewangles[2] += IN_JoystickGetAxis(joy, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
327 /////////////////////
331 static int Sys_EventFilter( SDL_Event *event )
333 //TODO: Add a quit query in linux, too - though linux user are more likely to know what they do
334 if (event->type == SDL_QUIT)
337 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
344 static keynum_t buttonremap[18] =
366 void Sys_SendKeyEvents( void )
368 static qboolean sound_active = true;
371 while( SDL_PollEvent( &event ) )
372 switch( event.type ) {
378 Key_Event( MapKey( event.key.keysym.sym ), (char)event.key.keysym.unicode, (event.key.state == SDL_PRESSED) );
380 case SDL_ACTIVEEVENT:
381 if( event.active.state == SDL_APPACTIVE )
383 if( event.active.gain )
389 case SDL_MOUSEBUTTONDOWN:
390 case SDL_MOUSEBUTTONUP:
391 if (event.button.button <= 18)
392 Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
394 case SDL_JOYBUTTONDOWN:
395 if (!joy_enable.integer)
396 break; // ignore down events if joystick has been disabled
397 case SDL_JOYBUTTONUP:
398 if (event.jbutton.button < 48)
399 Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
401 case SDL_VIDEORESIZE:
402 if(vid_resizable.integer < 2)
404 vid.width = event.resize.w;
405 vid.height = event.resize.h;
406 SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
411 // enable/disable sound on focus gain/loss
412 if (!vid_hidden && (vid_activewindow || !snd_mutewhenidle.integer))
425 sound_active = false;
434 void *GL_GetProcAddress(const char *name)
437 p = SDL_GL_GetProcAddress(name);
441 static int Sys_EventFilter( SDL_Event *event );
442 static qboolean vid_sdl_initjoysticksystem = false;
445 Cvar_RegisterVariable(&joy_detected);
446 Cvar_RegisterVariable(&joy_enable);
447 Cvar_RegisterVariable(&joy_index);
448 Cvar_RegisterVariable(&joy_axisforward);
449 Cvar_RegisterVariable(&joy_axisside);
450 Cvar_RegisterVariable(&joy_axisup);
451 Cvar_RegisterVariable(&joy_axispitch);
452 Cvar_RegisterVariable(&joy_axisyaw);
453 //Cvar_RegisterVariable(&joy_axisroll);
454 Cvar_RegisterVariable(&joy_deadzoneforward);
455 Cvar_RegisterVariable(&joy_deadzoneside);
456 Cvar_RegisterVariable(&joy_deadzoneup);
457 Cvar_RegisterVariable(&joy_deadzonepitch);
458 Cvar_RegisterVariable(&joy_deadzoneyaw);
459 //Cvar_RegisterVariable(&joy_deadzoneroll);
460 Cvar_RegisterVariable(&joy_sensitivityforward);
461 Cvar_RegisterVariable(&joy_sensitivityside);
462 Cvar_RegisterVariable(&joy_sensitivityup);
463 Cvar_RegisterVariable(&joy_sensitivitypitch);
464 Cvar_RegisterVariable(&joy_sensitivityyaw);
465 //Cvar_RegisterVariable(&joy_sensitivityroll);
467 if (SDL_Init(SDL_INIT_VIDEO) < 0)
468 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
469 vid_sdl_initjoysticksystem = SDL_Init(SDL_INIT_JOYSTICK) >= 0;
470 if (vid_sdl_initjoysticksystem)
471 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
472 vid_isfullscreen = false;
475 // set the icon (we dont use SDL here since it would be too much a PITA)
477 #include "resource.h"
478 #include <SDL_syswm.h>
479 static void VID_SetCaption()
485 SDL_WM_SetCaption( gamename, NULL );
487 // get the HWND handle
488 SDL_VERSION( &info.version );
489 if( !SDL_GetWMInfo( &info ) )
492 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
493 #ifndef _W64 //If Windows 64bit data types don't exist
494 #ifndef SetClassLongPtr
495 #define SetClassLongPtr SetClassLong
498 #define GCLP_HICON GCL_HICON
501 #define LONG_PTR LONG
504 SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
506 static void VID_SetIcon()
510 // Adding the OS independent XPM version --blub
511 #include "darkplaces.xpm"
512 #include "nexuiz.xpm"
513 static SDL_Surface *icon = NULL;
514 static void VID_SetIcon()
517 * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
518 * default settings with less than 91 colors and transparency.
521 int width, height, colors, isize, i, j;
523 static SDL_Color palette[256];
524 unsigned short palenc[256]; // store color id by char
526 char **idata = ENGINE_ICON;
527 char *data = idata[0];
529 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) != 4)
531 // NOTE: Only 1-char colornames are supported
532 Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
538 // NOTE: Only 1-char colornames are supported
539 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
543 for(i = 0; i < colors; ++i)
548 if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
551 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
553 Con_Printf("This XPM's palette looks odd. Can't continue.\n");
558 palette[i].r = 255; // color key
561 thenone = i; // weeeee
566 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
571 palenc[(unsigned char) idx] = i;
574 // allocate the image data
575 data = (char*) malloc(width*height);
577 for(j = 0; j < height; ++j)
579 for(i = 0; i < width; ++i)
581 // casting to the safest possible datatypes ^^
582 data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
588 // SDL_FreeSurface should free the data too
589 // but for completeness' sake...
590 if(icon->flags & SDL_PREALLOC)
593 icon->pixels = NULL; // safety
595 SDL_FreeSurface(icon);
598 icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
599 // 8 bit surfaces get an empty palette allocated according to the docs
600 // so it's a palette image for sure :) no endian check necessary for the mask
603 Con_Printf( "Failed to create surface for the window Icon!\n"
604 "%s\n", SDL_GetError());
609 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
610 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
612 SDL_WM_SetIcon(icon, NULL);
616 static void VID_SetCaption()
618 SDL_WM_SetCaption( gamename, NULL );
622 static void VID_OutputVersion()
624 const SDL_version *version;
625 version = SDL_Linked_Version();
626 Con_Printf( "Linked against SDL version %d.%d.%d\n"
627 "Using SDL library version %d.%d.%d\n",
628 SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
629 version->major, version->minor, version->patch );
632 int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples)
635 static int notfirstvideomode = false;
636 int flags = SDL_OPENGL;
637 const char *drivername;
639 win_half_width = width>>1;
640 win_half_height = height>>1;
642 if(vid_resizable.integer)
643 flags |= SDL_RESIZABLE;
649 We cant switch from one OpenGL video mode to another.
650 Thus we first switch to some stupid 2D mode and then back to OpenGL.
652 if (notfirstvideomode)
653 SDL_SetVideoMode( 0, 0, 0, 0 );
654 notfirstvideomode = true;
656 // SDL usually knows best
659 // 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
660 i = COM_CheckParm("-gl_driver");
661 if (i && i < com_argc - 1)
662 drivername = com_argv[i + 1];
663 if (SDL_GL_LoadLibrary(drivername) < 0)
665 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
669 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
672 Con_Print("Required OpenGL function glGetString not found\n");
676 // Knghtbrd: should do platform-specific extension string function here
678 vid_isfullscreen = false;
680 flags |= SDL_FULLSCREEN;
681 vid_isfullscreen = true;
683 //flags |= SDL_HWSURFACE;
685 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
688 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
689 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
690 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
691 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
692 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
693 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
697 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
698 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
699 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
700 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
703 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
704 if (vid_vsync.integer)
705 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
707 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
710 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
711 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, samples);
717 screen = SDL_SetVideoMode(width, height, bpp, flags);
721 Con_Printf("Failed to set video mode to %ix%i: %s\n", width, height, SDL_GetError());
728 // set up an event filter to ask confirmation on close button in WIN32
729 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
731 SDL_EnableUNICODE( SDL_ENABLE );
732 // enable key repeat since everyone expects it
733 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
736 gl_platformextensions = "";
737 gl_videosyncavailable = true;
741 vid_numjoysticks = SDL_NumJoysticks();
742 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
743 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
744 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
745 memset(vid_joysticks, 0, sizeof(vid_joysticks));
746 for (i = 0;i < vid_numjoysticks;i++)
749 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
752 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
755 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));
759 vid_activewindow = false;
760 vid_usingmouse = false;
762 SDL_WM_GrabInput(SDL_GRAB_OFF);
766 void VID_Shutdown (void)
768 // this is needed to retry gamma after a vid_restart
769 VID_RestoreSystemGamma();
772 SDL_QuitSubSystem(SDL_INIT_VIDEO);
777 gl_platformextensions = "";
780 int VID_SetGamma (unsigned short *ramps, int rampsize)
782 return !SDL_SetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
785 int VID_GetGamma (unsigned short *ramps, int rampsize)
787 return !SDL_GetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
790 void VID_Finish (qboolean allowmousegrab)
793 qboolean vid_usemouse;
795 //react on appstate changes
796 appstate = SDL_GetAppState();
798 vid_hidden = !(appstate & SDL_APPACTIVE);
800 if( vid_hidden || !( appstate & SDL_APPMOUSEFOCUS ) || !( appstate & SDL_APPINPUTFOCUS ) )
801 vid_activewindow = false;
803 vid_activewindow = true;
805 vid_usemouse = false;
806 if( allowmousegrab && vid_mouse.integer && !key_consoleactive && (key_dest != key_game || !cls.demoplayback) )
808 if( vid_isfullscreen )
810 if( !vid_activewindow )
811 vid_usemouse = false;
813 IN_Activate(vid_usemouse);
815 VID_UpdateGamma(false, 256);
817 if (r_render.integer && !vid_hidden)
820 if (r_speeds.integer || gl_finish.integer)
822 qglFinish();CHECKGLERROR
824 SDL_GL_SwapBuffers();