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
29 // Tell startup code that we have a client
30 int cl_available = true;
32 qboolean vid_supportrefreshrate = false;
34 cvar_t joy_detected = {CVAR_READONLY, "joy_detected", "0", "number of joysticks detected by engine"};
35 cvar_t joy_enable = {CVAR_SAVE, "joy_enable", "0", "enables joystick support"};
36 cvar_t joy_index = {0, "joy_index", "0", "selects which joystick to use if you have multiple"};
37 cvar_t joy_axisforward = {0, "joy_axisforward", "1", "which joystick axis to query for forward/backward movement"};
38 cvar_t joy_axisside = {0, "joy_axisside", "0", "which joystick axis to query for right/left movement"};
39 cvar_t joy_axisup = {0, "joy_axisup", "-1", "which joystick axis to query for up/down movement"};
40 cvar_t joy_axispitch = {0, "joy_axispitch", "3", "which joystick axis to query for looking up/down"};
41 cvar_t joy_axisyaw = {0, "joy_axisyaw", "2", "which joystick axis to query for looking right/left"};
42 cvar_t joy_axisroll = {0, "joy_axisroll", "-1", "which joystick axis to query for tilting head right/left"};
43 cvar_t joy_deadzoneforward = {0, "joy_deadzoneforward", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
44 cvar_t joy_deadzoneside = {0, "joy_deadzoneside", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
45 cvar_t joy_deadzoneup = {0, "joy_deadzoneup", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
46 cvar_t joy_deadzonepitch = {0, "joy_deadzonepitch", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
47 cvar_t joy_deadzoneyaw = {0, "joy_deadzoneyaw", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
48 cvar_t joy_deadzoneroll = {0, "joy_deadzoneroll", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
49 cvar_t joy_sensitivityforward = {0, "joy_sensitivityforward", "-1", "movement multiplier"};
50 cvar_t joy_sensitivityside = {0, "joy_sensitivityside", "1", "movement multiplier"};
51 cvar_t joy_sensitivityup = {0, "joy_sensitivityup", "1", "movement multiplier"};
52 cvar_t joy_sensitivitypitch = {0, "joy_sensitivitypitch", "1", "movement multiplier"};
53 cvar_t joy_sensitivityyaw = {0, "joy_sensitivityyaw", "-1", "movement multiplier"};
54 cvar_t joy_sensitivityroll = {0, "joy_sensitivityroll", "1", "movement multiplier"};
56 static qboolean vid_usingmouse = false;
57 static qboolean vid_usinghidecursor = false;
58 static qboolean vid_isfullscreen;
59 static int vid_numjoysticks = 0;
60 #define MAX_JOYSTICKS 8
61 static SDL_Joystick *vid_joysticks[MAX_JOYSTICKS];
63 static int win_half_width = 50;
64 static int win_half_height = 50;
65 static int video_bpp, video_flags;
67 static SDL_Surface *screen;
69 /////////////////////////
72 //TODO: Add joystick support
73 //TODO: Add error checking
76 //keysym to quake keysym mapping
77 #define tenoh 0,0,0,0,0, 0,0,0,0,0
78 #define fiftyoh tenoh, tenoh, tenoh, tenoh, tenoh
79 #define hundredoh fiftyoh, fiftyoh
80 static unsigned int tbl_sdltoquake[] =
82 0,0,0,0, //SDLK_UNKNOWN = 0,
83 0,0,0,0, //SDLK_FIRST = 0,
84 K_BACKSPACE, //SDLK_BACKSPACE = 8,
85 K_TAB, //SDLK_TAB = 9,
88 K_ENTER, //SDLK_RETURN = 13,
90 K_PAUSE, //SDLK_PAUSE = 19,
92 K_ESCAPE, //SDLK_ESCAPE = 27,
94 K_SPACE, //SDLK_SPACE = 32,
95 '!', //SDLK_EXCLAIM = 33,
96 '"', //SDLK_QUOTEDBL = 34,
97 '#', //SDLK_HASH = 35,
98 '$', //SDLK_DOLLAR = 36,
100 '&', //SDLK_AMPERSAND = 38,
101 '\'', //SDLK_QUOTE = 39,
102 '(', //SDLK_LEFTPAREN = 40,
103 ')', //SDLK_RIGHTPAREN = 41,
104 '*', //SDLK_ASTERISK = 42,
105 '+', //SDLK_PLUS = 43,
106 ',', //SDLK_COMMA = 44,
107 '-', //SDLK_MINUS = 45,
108 '.', //SDLK_PERIOD = 46,
109 '/', //SDLK_SLASH = 47,
120 ':', //SDLK_COLON = 58,
121 ';', //SDLK_SEMICOLON = 59,
122 '<', //SDLK_LESS = 60,
123 '=', //SDLK_EQUALS = 61,
124 '>', //SDLK_GREATER = 62,
125 '?', //SDLK_QUESTION = 63,
127 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,
128 '[', //SDLK_LEFTBRACKET = 91,
129 '\\', //SDLK_BACKSLASH = 92,
130 ']', //SDLK_RIGHTBRACKET = 93,
131 '^', //SDLK_CARET = 94,
132 '_', //SDLK_UNDERSCORE = 95,
133 '`', //SDLK_BACKQUOTE = 96,
161 K_DEL, //SDLK_DELETE = 127,
162 hundredoh /*227*/, tenoh, tenoh, 0,0,0,0,0,0,0,0,
163 K_KP_0, //SDLK_KP0 = 256,
164 K_KP_1, //SDLK_KP1 = 257,
165 K_KP_2, //SDLK_KP2 = 258,
166 K_KP_3, //SDLK_KP3 = 259,
167 K_KP_4, //SDLK_KP4 = 260,
168 K_KP_5, //SDLK_KP5 = 261,
169 K_KP_6, //SDLK_KP6 = 262,
170 K_KP_7, //SDLK_KP7 = 263,
171 K_KP_8, //SDLK_KP8 = 264,
172 K_KP_9, //SDLK_KP9 = 265,
173 K_KP_PERIOD,//SDLK_KP_PERIOD = 266,
174 K_KP_DIVIDE,//SDLK_KP_DIVIDE = 267,
175 K_KP_MULTIPLY,//SDLK_KP_MULTIPLY= 268,
176 K_KP_MINUS, //SDLK_KP_MINUS = 269,
177 K_KP_PLUS, //SDLK_KP_PLUS = 270,
178 K_KP_ENTER, //SDLK_KP_ENTER = 271,
179 K_KP_EQUALS,//SDLK_KP_EQUALS = 272,
180 K_UPARROW, //SDLK_UP = 273,
181 K_DOWNARROW,//SDLK_DOWN = 274,
182 K_RIGHTARROW,//SDLK_RIGHT = 275,
183 K_LEFTARROW,//SDLK_LEFT = 276,
184 K_INS, //SDLK_INSERT = 277,
185 K_HOME, //SDLK_HOME = 278,
186 K_END, //SDLK_END = 279,
187 K_PGUP, //SDLK_PAGEUP = 280,
188 K_PGDN, //SDLK_PAGEDOWN = 281,
189 K_F1, //SDLK_F1 = 282,
190 K_F2, //SDLK_F2 = 283,
191 K_F3, //SDLK_F3 = 284,
192 K_F4, //SDLK_F4 = 285,
193 K_F5, //SDLK_F5 = 286,
194 K_F6, //SDLK_F6 = 287,
195 K_F7, //SDLK_F7 = 288,
196 K_F8, //SDLK_F8 = 289,
197 K_F9, //SDLK_F9 = 290,
198 K_F10, //SDLK_F10 = 291,
199 K_F11, //SDLK_F11 = 292,
200 K_F12, //SDLK_F12 = 293,
205 K_NUMLOCK, //SDLK_NUMLOCK = 300,
206 K_CAPSLOCK, //SDLK_CAPSLOCK = 301,
207 K_SCROLLOCK,//SDLK_SCROLLOCK= 302,
208 K_SHIFT, //SDLK_RSHIFT = 303,
209 K_SHIFT, //SDLK_LSHIFT = 304,
210 K_CTRL, //SDLK_RCTRL = 305,
211 K_CTRL, //SDLK_LCTRL = 306,
212 K_ALT, //SDLK_RALT = 307,
213 K_ALT, //SDLK_LALT = 308,
214 0, //SDLK_RMETA = 309,
215 0, //SDLK_LMETA = 310,
216 K_SUPER, //SDLK_LSUPER = 311, /* Left "Windows" key */
217 K_SUPER, //SDLK_RSUPER = 312, /* Right "Windows" key */
218 K_ALT, //SDLK_MODE = 313, /* "Alt Gr" key */
219 0, //SDLK_COMPOSE = 314, /* Multi-key compose key */
220 0, //SDLK_HELP = 315,
221 0, //SDLK_PRINT = 316,
222 0, //SDLK_SYSREQ = 317,
223 K_PAUSE, //SDLK_BREAK = 318,
224 0, //SDLK_MENU = 319,
225 0, //SDLK_POWER = 320, /* Power Macintosh power key */
226 'e', //SDLK_EURO = 321, /* Some european keyboards */
227 0 //SDLK_UNDO = 322, /* Atari keyboard has Undo */
233 static int MapKey( unsigned int sdlkey )
235 if( sdlkey > sizeof(tbl_sdltoquake)/ sizeof(int) )
237 return tbl_sdltoquake[ sdlkey ];
240 void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor)
242 if (vid_usingmouse != relative)
244 vid_usingmouse = relative;
245 cl_ignoremousemoves = 2;
246 SDL_WM_GrabInput( relative ? SDL_GRAB_ON : SDL_GRAB_OFF );
248 if (vid_usinghidecursor != hidecursor)
250 vid_usinghidecursor = hidecursor;
251 SDL_ShowCursor( hidecursor ? SDL_DISABLE : SDL_ENABLE);
255 static double IN_JoystickGetAxis(SDL_Joystick *joy, int axis, double sensitivity, double deadzone)
258 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
259 return 0; // no such axis on this joystick
260 value = SDL_JoystickGetAxis(joy, axis) * (1.0 / 32767.0);
261 value = bound(-1, value, 1);
262 if (fabs(value) < deadzone)
263 return 0; // within deadzone around center
264 return value * sensitivity;
270 static int old_x = 0, old_y = 0;
271 static int stuck = 0;
275 if(vid_stick_mouse.integer)
277 // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
278 // window grabbing. --blub
280 // we need 2 frames to initialize the center position
283 SDL_WarpMouse(win_half_width, win_half_height);
284 SDL_GetMouseState(&x, &y);
285 SDL_GetRelativeMouseState(&x, &y);
288 SDL_GetRelativeMouseState(&x, &y);
289 in_mouse_x = x + old_x;
290 in_mouse_y = y + old_y;
291 SDL_GetMouseState(&x, &y);
292 old_x = x - win_half_width;
293 old_y = y - win_half_height;
294 SDL_WarpMouse(win_half_width, win_half_height);
297 SDL_GetRelativeMouseState( &x, &y );
303 SDL_GetMouseState(&x, &y);
304 in_windowmouse_x = x;
305 in_windowmouse_y = y;
307 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
309 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
310 int numballs = SDL_JoystickNumBalls(joy);
311 for (j = 0;j < numballs;j++)
313 SDL_JoystickGetBall(joy, j, &x, &y);
317 cl.cmd.forwardmove += IN_JoystickGetAxis(joy, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
318 cl.cmd.sidemove += IN_JoystickGetAxis(joy, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
319 cl.cmd.upmove += IN_JoystickGetAxis(joy, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
320 cl.viewangles[0] += IN_JoystickGetAxis(joy, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
321 cl.viewangles[1] += IN_JoystickGetAxis(joy, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
322 //cl.viewangles[2] += IN_JoystickGetAxis(joy, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
326 /////////////////////
330 static int Sys_EventFilter( SDL_Event *event )
332 //TODO: Add a quit query in linux, too - though linux user are more likely to know what they do
333 if (event->type == SDL_QUIT)
336 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
344 static qboolean sdl_needs_restart;
345 static void sdl_start(void)
348 static void sdl_shutdown(void)
350 sdl_needs_restart = false;
352 static void sdl_newmap(void)
357 static keynum_t buttonremap[18] =
379 void Sys_SendKeyEvents( void )
381 static qboolean sound_active = true;
384 while( SDL_PollEvent( &event ) )
385 switch( event.type ) {
391 //Con_Printf("Key: %lu\n", (long unsigned int)event.key.keysym.unicode);
392 Key_Event( MapKey( event.key.keysym.sym ), event.key.keysym.unicode, (event.key.state == SDL_PRESSED) );
394 case SDL_ACTIVEEVENT:
395 if( event.active.state & SDL_APPACTIVE )
397 if( event.active.gain )
403 case SDL_MOUSEBUTTONDOWN:
404 case SDL_MOUSEBUTTONUP:
405 if (event.button.button <= 18)
406 Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
408 case SDL_JOYBUTTONDOWN:
409 if (!joy_enable.integer)
410 break; // ignore down events if joystick has been disabled
411 case SDL_JOYBUTTONUP:
412 if (event.jbutton.button < 48)
413 Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
415 case SDL_VIDEORESIZE:
416 if(vid_resizable.integer < 2)
418 vid.width = event.resize.w;
419 vid.height = event.resize.h;
420 SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
422 // better not call R_Modules_Restart from here directly, as this may wreak havoc...
423 // so, let's better queue it for next frame
424 if(!sdl_needs_restart)
426 Cbuf_AddText("\nr_restart\n");
427 sdl_needs_restart = true;
434 // enable/disable sound on focus gain/loss
435 if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
448 sound_active = false;
457 void *GL_GetProcAddress(const char *name)
460 p = SDL_GL_GetProcAddress(name);
464 static int Sys_EventFilter( SDL_Event *event );
465 static qboolean vid_sdl_initjoysticksystem = false;
469 Cvar_RegisterVariable(&joy_detected);
470 Cvar_RegisterVariable(&joy_enable);
471 Cvar_RegisterVariable(&joy_index);
472 Cvar_RegisterVariable(&joy_axisforward);
473 Cvar_RegisterVariable(&joy_axisside);
474 Cvar_RegisterVariable(&joy_axisup);
475 Cvar_RegisterVariable(&joy_axispitch);
476 Cvar_RegisterVariable(&joy_axisyaw);
477 //Cvar_RegisterVariable(&joy_axisroll);
478 Cvar_RegisterVariable(&joy_deadzoneforward);
479 Cvar_RegisterVariable(&joy_deadzoneside);
480 Cvar_RegisterVariable(&joy_deadzoneup);
481 Cvar_RegisterVariable(&joy_deadzonepitch);
482 Cvar_RegisterVariable(&joy_deadzoneyaw);
483 //Cvar_RegisterVariable(&joy_deadzoneroll);
484 Cvar_RegisterVariable(&joy_sensitivityforward);
485 Cvar_RegisterVariable(&joy_sensitivityside);
486 Cvar_RegisterVariable(&joy_sensitivityup);
487 Cvar_RegisterVariable(&joy_sensitivitypitch);
488 Cvar_RegisterVariable(&joy_sensitivityyaw);
489 //Cvar_RegisterVariable(&joy_sensitivityroll);
492 R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap);
495 if (SDL_Init(SDL_INIT_VIDEO) < 0)
496 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
497 vid_sdl_initjoysticksystem = SDL_Init(SDL_INIT_JOYSTICK) >= 0;
498 if (vid_sdl_initjoysticksystem)
499 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
500 vid_isfullscreen = false;
503 // set the icon (we dont use SDL here since it would be too much a PITA)
505 #include "resource.h"
506 #include <SDL_syswm.h>
507 static void VID_SetCaption(void)
513 SDL_WM_SetCaption( gamename, NULL );
515 // get the HWND handle
516 SDL_VERSION( &info.version );
517 if( !SDL_GetWMInfo( &info ) )
520 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
521 #ifndef _W64 //If Windows 64bit data types don't exist
522 #ifndef SetClassLongPtr
523 #define SetClassLongPtr SetClassLong
526 #define GCLP_HICON GCL_HICON
529 #define LONG_PTR LONG
532 SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
534 static void VID_SetIcon(void)
538 // Adding the OS independent XPM version --blub
539 #include "darkplaces.xpm"
540 #include "nexuiz.xpm"
541 static SDL_Surface *icon = NULL;
542 static void VID_SetIcon(void)
545 * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
546 * default settings with less than 91 colors and transparency.
549 int width, height, colors, isize, i, j;
551 static SDL_Color palette[256];
552 unsigned short palenc[256]; // store color id by char
554 char **idata = ENGINE_ICON;
555 char *data = idata[0];
557 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) != 4)
559 // NOTE: Only 1-char colornames are supported
560 Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
566 // NOTE: Only 1-char colornames are supported
567 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
571 for(i = 0; i < colors; ++i)
573 unsigned int r, g, b;
576 if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
579 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
581 Con_Printf("This XPM's palette looks odd. Can't continue.\n");
586 palette[i].r = 255; // color key
589 thenone = i; // weeeee
594 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
599 palenc[(unsigned char) idx] = i;
602 // allocate the image data
603 data = (char*) malloc(width*height);
605 for(j = 0; j < height; ++j)
607 for(i = 0; i < width; ++i)
609 // casting to the safest possible datatypes ^^
610 data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
616 // SDL_FreeSurface should free the data too
617 // but for completeness' sake...
618 if(icon->flags & SDL_PREALLOC)
621 icon->pixels = NULL; // safety
623 SDL_FreeSurface(icon);
626 icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
627 // 8 bit surfaces get an empty palette allocated according to the docs
628 // so it's a palette image for sure :) no endian check necessary for the mask
631 Con_Printf( "Failed to create surface for the window Icon!\n"
632 "%s\n", SDL_GetError());
637 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
638 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
640 SDL_WM_SetIcon(icon, NULL);
644 static void VID_SetCaption(void)
646 SDL_WM_SetCaption( gamename, NULL );
650 static void VID_OutputVersion(void)
652 const SDL_version *version;
653 version = SDL_Linked_Version();
654 Con_Printf( "Linked against SDL version %d.%d.%d\n"
655 "Using SDL library version %d.%d.%d\n",
656 SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
657 version->major, version->minor, version->patch );
660 qboolean VID_InitMode(viddef_mode_t *mode)
663 static int notfirstvideomode = false;
664 int flags = SDL_OPENGL;
665 const char *drivername;
667 win_half_width = mode->width>>1;
668 win_half_height = mode->height>>1;
670 if(vid_resizable.integer)
671 flags |= SDL_RESIZABLE;
677 We cant switch from one OpenGL video mode to another.
678 Thus we first switch to some stupid 2D mode and then back to OpenGL.
680 if (notfirstvideomode)
681 SDL_SetVideoMode( 0, 0, 0, 0 );
682 notfirstvideomode = true;
684 // SDL usually knows best
687 // 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
688 i = COM_CheckParm("-gl_driver");
689 if (i && i < com_argc - 1)
690 drivername = com_argv[i + 1];
691 if (SDL_GL_LoadLibrary(drivername) < 0)
693 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
697 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
700 Con_Print("Required OpenGL function glGetString not found\n");
704 // Knghtbrd: should do platform-specific extension string function here
706 vid_isfullscreen = false;
707 if (mode->fullscreen) {
708 flags |= SDL_FULLSCREEN;
709 vid_isfullscreen = true;
711 //flags |= SDL_HWSURFACE;
713 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
714 if (mode->bitsperpixel >= 32)
716 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
717 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
718 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
719 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
720 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
721 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
725 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
726 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
727 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
728 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
730 if (mode->stereobuffer)
731 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
732 if (vid_vsync.integer)
733 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
735 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
736 if (mode->samples > 1)
738 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
739 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples);
742 video_bpp = mode->bitsperpixel;
745 screen = SDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
749 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
756 // set up an event filter to ask confirmation on close button in WIN32
757 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
759 SDL_EnableUNICODE( SDL_ENABLE );
760 // enable key repeat since everyone expects it
761 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
764 gl_platformextensions = "";
768 vid_numjoysticks = SDL_NumJoysticks();
769 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
770 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
771 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
772 memset(vid_joysticks, 0, sizeof(vid_joysticks));
773 for (i = 0;i < vid_numjoysticks;i++)
776 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
779 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
782 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));
786 vid_activewindow = false;
787 vid_usingmouse = false;
788 vid_usinghidecursor = false;
790 SDL_WM_GrabInput(SDL_GRAB_OFF);
794 void VID_Shutdown (void)
796 VID_SetMouse(false, false, false);
797 VID_RestoreSystemGamma();
799 SDL_QuitSubSystem(SDL_INIT_VIDEO);
804 gl_platformextensions = "";
807 int VID_SetGamma (unsigned short *ramps, int rampsize)
809 return !SDL_SetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
812 int VID_GetGamma (unsigned short *ramps, int rampsize)
814 return !SDL_GetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
817 void VID_Finish (void)
821 //react on appstate changes
822 appstate = SDL_GetAppState();
824 vid_hidden = !(appstate & SDL_APPACTIVE);
826 if( vid_hidden || !( appstate & SDL_APPMOUSEFOCUS ) || !( appstate & SDL_APPINPUTFOCUS ) )
827 vid_activewindow = false;
829 vid_activewindow = true;
831 VID_UpdateGamma(false, 256);
836 if (r_speeds.integer == 2 || gl_finish.integer)
838 qglFinish();CHECKGLERROR
840 SDL_GL_SwapBuffers();
844 size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
848 int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
851 for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); *vidmodes; ++vidmodes)
855 modes[k].width = (*vidmodes)->w;
856 modes[k].height = (*vidmodes)->h;
858 modes[k].refreshrate = 60; // no support for refresh rate in SDL
859 modes[k].pixelheight_num = 1;
860 modes[k].pixelheight_denom = 1; // SDL does not provide this