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
21 #include <SDL_syswm.h>
26 #include "dpsoftrast.h"
29 #include <Carbon/Carbon.h>
30 #include <IOKit/hidsystem/IOHIDLib.h>
31 #include <IOKit/hidsystem/IOHIDParameter.h>
32 #include <IOKit/hidsystem/event_status_driver.h>
33 static cvar_t apple_mouse_noaccel = {CVAR_SAVE, "apple_mouse_noaccel", "1", "disables mouse acceleration while DarkPlaces is active"};
34 static qboolean vid_usingnoaccel;
35 static double originalMouseSpeed = -1.0;
36 io_connect_t IN_GetIOHandle(void)
38 io_connect_t iohandle = MACH_PORT_NULL;
40 io_service_t iohidsystem = MACH_PORT_NULL;
41 mach_port_t masterport;
43 status = IOMasterPort(MACH_PORT_NULL, &masterport);
44 if(status != KERN_SUCCESS)
47 iohidsystem = IORegistryEntryFromPath(masterport, kIOServicePlane ":/IOResources/IOHIDSystem");
51 status = IOServiceOpen(iohidsystem, mach_task_self(), kIOHIDParamConnectType, &iohandle);
52 IOObjectRelease(iohidsystem);
62 // Tell startup code that we have a client
63 int cl_available = true;
65 qboolean vid_supportrefreshrate = false;
67 cvar_t vid_soft = {CVAR_SAVE, "vid_soft", "0", "enables use of the DarkPlaces Software Rasterizer rather than OpenGL or Direct3D"};
68 cvar_t joy_detected = {CVAR_READONLY, "joy_detected", "0", "number of joysticks detected by engine"};
69 cvar_t joy_enable = {CVAR_SAVE, "joy_enable", "0", "enables joystick support"};
70 cvar_t joy_index = {0, "joy_index", "0", "selects which joystick to use if you have multiple"};
71 cvar_t joy_axisforward = {0, "joy_axisforward", "1", "which joystick axis to query for forward/backward movement"};
72 cvar_t joy_axisside = {0, "joy_axisside", "0", "which joystick axis to query for right/left movement"};
73 cvar_t joy_axisup = {0, "joy_axisup", "-1", "which joystick axis to query for up/down movement"};
74 cvar_t joy_axispitch = {0, "joy_axispitch", "3", "which joystick axis to query for looking up/down"};
75 cvar_t joy_axisyaw = {0, "joy_axisyaw", "2", "which joystick axis to query for looking right/left"};
76 cvar_t joy_axisroll = {0, "joy_axisroll", "-1", "which joystick axis to query for tilting head right/left"};
77 cvar_t joy_deadzoneforward = {0, "joy_deadzoneforward", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
78 cvar_t joy_deadzoneside = {0, "joy_deadzoneside", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
79 cvar_t joy_deadzoneup = {0, "joy_deadzoneup", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
80 cvar_t joy_deadzonepitch = {0, "joy_deadzonepitch", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
81 cvar_t joy_deadzoneyaw = {0, "joy_deadzoneyaw", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
82 cvar_t joy_deadzoneroll = {0, "joy_deadzoneroll", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
83 cvar_t joy_sensitivityforward = {0, "joy_sensitivityforward", "-1", "movement multiplier"};
84 cvar_t joy_sensitivityside = {0, "joy_sensitivityside", "1", "movement multiplier"};
85 cvar_t joy_sensitivityup = {0, "joy_sensitivityup", "1", "movement multiplier"};
86 cvar_t joy_sensitivitypitch = {0, "joy_sensitivitypitch", "1", "movement multiplier"};
87 cvar_t joy_sensitivityyaw = {0, "joy_sensitivityyaw", "-1", "movement multiplier"};
88 cvar_t joy_sensitivityroll = {0, "joy_sensitivityroll", "1", "movement multiplier"};
89 cvar_t joy_axiskeyevents = {CVAR_SAVE, "joy_axiskeyevents", "0", "generate uparrow/leftarrow etc. keyevents for joystick axes, use if your joystick driver is not generating them"};
91 static qboolean vid_usingmouse = false;
92 static qboolean vid_usinghidecursor = false;
93 static qboolean vid_isfullscreen;
94 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
95 static qboolean vid_usingvsync = false;
97 static int vid_numjoysticks = 0;
98 #define MAX_JOYSTICKS 8
99 static SDL_Joystick *vid_joysticks[MAX_JOYSTICKS];
101 static int win_half_width = 50;
102 static int win_half_height = 50;
103 static int video_bpp, video_flags;
105 static SDL_Surface *screen;
106 static SDL_Surface *vid_softsurface;
108 // joystick axes state
109 #define MAX_JOYSTICK_AXES 16
116 static joy_axiscache_t joy_axescache[MAX_JOYSTICK_AXES];
118 /////////////////////////
121 //TODO: Add joystick support
122 //TODO: Add error checking
125 //keysym to quake keysym mapping
126 #define tenoh 0,0,0,0,0, 0,0,0,0,0
127 #define fiftyoh tenoh, tenoh, tenoh, tenoh, tenoh
128 #define hundredoh fiftyoh, fiftyoh
129 static unsigned int tbl_sdltoquake[] =
131 0,0,0,0, //SDLK_UNKNOWN = 0,
132 0,0,0,0, //SDLK_FIRST = 0,
133 K_BACKSPACE, //SDLK_BACKSPACE = 8,
134 K_TAB, //SDLK_TAB = 9,
136 0, //SDLK_CLEAR = 12,
137 K_ENTER, //SDLK_RETURN = 13,
139 K_PAUSE, //SDLK_PAUSE = 19,
141 K_ESCAPE, //SDLK_ESCAPE = 27,
143 K_SPACE, //SDLK_SPACE = 32,
144 '!', //SDLK_EXCLAIM = 33,
145 '"', //SDLK_QUOTEDBL = 34,
146 '#', //SDLK_HASH = 35,
147 '$', //SDLK_DOLLAR = 36,
149 '&', //SDLK_AMPERSAND = 38,
150 '\'', //SDLK_QUOTE = 39,
151 '(', //SDLK_LEFTPAREN = 40,
152 ')', //SDLK_RIGHTPAREN = 41,
153 '*', //SDLK_ASTERISK = 42,
154 '+', //SDLK_PLUS = 43,
155 ',', //SDLK_COMMA = 44,
156 '-', //SDLK_MINUS = 45,
157 '.', //SDLK_PERIOD = 46,
158 '/', //SDLK_SLASH = 47,
169 ':', //SDLK_COLON = 58,
170 ';', //SDLK_SEMICOLON = 59,
171 '<', //SDLK_LESS = 60,
172 '=', //SDLK_EQUALS = 61,
173 '>', //SDLK_GREATER = 62,
174 '?', //SDLK_QUESTION = 63,
176 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,
177 '[', //SDLK_LEFTBRACKET = 91,
178 '\\', //SDLK_BACKSLASH = 92,
179 ']', //SDLK_RIGHTBRACKET = 93,
180 '^', //SDLK_CARET = 94,
181 '_', //SDLK_UNDERSCORE = 95,
182 '`', //SDLK_BACKQUOTE = 96,
210 K_DEL, //SDLK_DELETE = 127,
211 hundredoh /*227*/, tenoh, tenoh, 0,0,0,0,0,0,0,0,
212 K_KP_0, //SDLK_KP0 = 256,
213 K_KP_1, //SDLK_KP1 = 257,
214 K_KP_2, //SDLK_KP2 = 258,
215 K_KP_3, //SDLK_KP3 = 259,
216 K_KP_4, //SDLK_KP4 = 260,
217 K_KP_5, //SDLK_KP5 = 261,
218 K_KP_6, //SDLK_KP6 = 262,
219 K_KP_7, //SDLK_KP7 = 263,
220 K_KP_8, //SDLK_KP8 = 264,
221 K_KP_9, //SDLK_KP9 = 265,
222 K_KP_PERIOD,//SDLK_KP_PERIOD = 266,
223 K_KP_DIVIDE,//SDLK_KP_DIVIDE = 267,
224 K_KP_MULTIPLY,//SDLK_KP_MULTIPLY= 268,
225 K_KP_MINUS, //SDLK_KP_MINUS = 269,
226 K_KP_PLUS, //SDLK_KP_PLUS = 270,
227 K_KP_ENTER, //SDLK_KP_ENTER = 271,
228 K_KP_EQUALS,//SDLK_KP_EQUALS = 272,
229 K_UPARROW, //SDLK_UP = 273,
230 K_DOWNARROW,//SDLK_DOWN = 274,
231 K_RIGHTARROW,//SDLK_RIGHT = 275,
232 K_LEFTARROW,//SDLK_LEFT = 276,
233 K_INS, //SDLK_INSERT = 277,
234 K_HOME, //SDLK_HOME = 278,
235 K_END, //SDLK_END = 279,
236 K_PGUP, //SDLK_PAGEUP = 280,
237 K_PGDN, //SDLK_PAGEDOWN = 281,
238 K_F1, //SDLK_F1 = 282,
239 K_F2, //SDLK_F2 = 283,
240 K_F3, //SDLK_F3 = 284,
241 K_F4, //SDLK_F4 = 285,
242 K_F5, //SDLK_F5 = 286,
243 K_F6, //SDLK_F6 = 287,
244 K_F7, //SDLK_F7 = 288,
245 K_F8, //SDLK_F8 = 289,
246 K_F9, //SDLK_F9 = 290,
247 K_F10, //SDLK_F10 = 291,
248 K_F11, //SDLK_F11 = 292,
249 K_F12, //SDLK_F12 = 293,
254 K_NUMLOCK, //SDLK_NUMLOCK = 300,
255 K_CAPSLOCK, //SDLK_CAPSLOCK = 301,
256 K_SCROLLOCK,//SDLK_SCROLLOCK= 302,
257 K_SHIFT, //SDLK_RSHIFT = 303,
258 K_SHIFT, //SDLK_LSHIFT = 304,
259 K_CTRL, //SDLK_RCTRL = 305,
260 K_CTRL, //SDLK_LCTRL = 306,
261 K_ALT, //SDLK_RALT = 307,
262 K_ALT, //SDLK_LALT = 308,
263 0, //SDLK_RMETA = 309,
264 0, //SDLK_LMETA = 310,
265 0, //SDLK_LSUPER = 311, /* Left "Windows" key */
266 0, //SDLK_RSUPER = 312, /* Right "Windows" key */
267 K_ALT, //SDLK_MODE = 313, /* "Alt Gr" key */
268 0, //SDLK_COMPOSE = 314, /* Multi-key compose key */
269 0, //SDLK_HELP = 315,
270 0, //SDLK_PRINT = 316,
271 0, //SDLK_SYSREQ = 317,
272 K_PAUSE, //SDLK_BREAK = 318,
273 0, //SDLK_MENU = 319,
274 0, //SDLK_POWER = 320, /* Power Macintosh power key */
275 'e', //SDLK_EURO = 321, /* Some european keyboards */
276 0 //SDLK_UNDO = 322, /* Atari keyboard has Undo */
282 static int MapKey( unsigned int sdlkey )
284 if( sdlkey > sizeof(tbl_sdltoquake)/ sizeof(int) )
286 return tbl_sdltoquake[ sdlkey ];
289 void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor)
293 if(vid_usingmouse && (vid_usingnoaccel != !!apple_mouse_noaccel.integer))
294 VID_SetMouse(false, false, false); // ungrab first!
296 if (vid_usingmouse != relative)
298 vid_usingmouse = relative;
299 cl_ignoremousemoves = 2;
300 SDL_WM_GrabInput( relative ? SDL_GRAB_ON : SDL_GRAB_OFF );
304 // Save the status of mouse acceleration
305 originalMouseSpeed = -1.0; // in case of error
306 if(apple_mouse_noaccel.integer)
308 io_connect_t mouseDev = IN_GetIOHandle();
311 if(IOHIDGetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), &originalMouseSpeed) == kIOReturnSuccess)
313 Con_DPrintf("previous mouse acceleration: %f\n", originalMouseSpeed);
314 if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), -1.0) != kIOReturnSuccess)
316 Con_Print("Could not disable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
317 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
322 Con_Print("Could not disable mouse acceleration (failed at IOHIDGetAccelerationWithKey).\n");
323 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
325 IOServiceClose(mouseDev);
329 Con_Print("Could not disable mouse acceleration (failed at IO_GetIOHandle).\n");
330 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
334 vid_usingnoaccel = !!apple_mouse_noaccel.integer;
338 if(originalMouseSpeed != -1.0)
340 io_connect_t mouseDev = IN_GetIOHandle();
343 Con_DPrintf("restoring mouse acceleration to: %f\n", originalMouseSpeed);
344 if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), originalMouseSpeed) != kIOReturnSuccess)
345 Con_Print("Could not re-enable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
346 IOServiceClose(mouseDev);
349 Con_Print("Could not re-enable mouse acceleration (failed at IO_GetIOHandle).\n");
354 if (vid_usinghidecursor != hidecursor)
356 vid_usinghidecursor = hidecursor;
357 SDL_ShowCursor( hidecursor ? SDL_DISABLE : SDL_ENABLE);
361 static double IN_JoystickGetAxis(SDL_Joystick *joy, int axis, double sensitivity, double deadzone)
364 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
365 return 0; // no such axis on this joystick
366 value = SDL_JoystickGetAxis(joy, axis) * (1.0 / 32767.0);
367 value = bound(-1, value, 1);
368 if (fabs(value) < deadzone)
369 return 0; // within deadzone around center
370 return value * sensitivity;
373 /////////////////////
374 // Joystick axis keyevents
375 // a sort of hack emulating Arrow keys for joystick axises
376 // as some drives dont send such keyevents for them
377 // additionally we should block drivers that do send arrow keyevents to prevent double events
380 static void IN_JoystickKeyeventForAxis(SDL_Joystick *joy, int axis, int key_pos, int key_neg)
384 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
385 return; // no such axis on this joystick
387 joytime = Sys_DoubleTime();
388 // no key event, continuous keydown event
389 if (joy_axescache[axis].move == joy_axescache[axis].oldmove)
391 if (joy_axescache[axis].move != 0 && joytime > joy_axescache[axis].keytime)
393 //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
394 Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
395 joy_axescache[axis].keytime = joytime + 0.5 / 20;
399 // generate key up event
400 if (joy_axescache[axis].oldmove)
402 //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg), 1, cl.time);
403 Key_Event((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg, 0, 0);
405 // generate key down event
406 if (joy_axescache[axis].move)
408 //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
409 Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
410 joy_axescache[axis].keytime = joytime + 0.5;
414 static qboolean IN_JoystickBlockDoubledKeyEvents(int keycode)
416 if (!joy_axiskeyevents.integer)
419 // block keyevent if it's going to be provided by joystick keyevent system
420 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
422 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
424 if (keycode == K_UPARROW || keycode == K_DOWNARROW)
425 if (IN_JoystickGetAxis(joy, joy_axisforward.integer, 1, 0.01) || joy_axescache[joy_axisforward.integer].move || joy_axescache[joy_axisforward.integer].oldmove)
427 if (keycode == K_RIGHTARROW || keycode == K_LEFTARROW)
428 if (IN_JoystickGetAxis(joy, joy_axisside.integer, 1, 0.01) || joy_axescache[joy_axisside.integer].move || joy_axescache[joy_axisside.integer].oldmove)
435 /////////////////////
442 static int old_x = 0, old_y = 0;
443 static int stuck = 0;
444 int x, y, numaxes, numballs;
448 if(vid_stick_mouse.integer)
450 // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
451 // window grabbing. --blub
453 // we need 2 frames to initialize the center position
456 SDL_WarpMouse(win_half_width, win_half_height);
457 SDL_GetMouseState(&x, &y);
458 SDL_GetRelativeMouseState(&x, &y);
461 SDL_GetRelativeMouseState(&x, &y);
462 in_mouse_x = x + old_x;
463 in_mouse_y = y + old_y;
464 SDL_GetMouseState(&x, &y);
465 old_x = x - win_half_width;
466 old_y = y - win_half_height;
467 SDL_WarpMouse(win_half_width, win_half_height);
470 SDL_GetRelativeMouseState( &x, &y );
476 SDL_GetMouseState(&x, &y);
477 in_windowmouse_x = x;
478 in_windowmouse_y = y;
480 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
482 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
484 // balls convert to mousemove
485 numballs = SDL_JoystickNumBalls(joy);
486 for (j = 0;j < numballs;j++)
488 SDL_JoystickGetBall(joy, j, &x, &y);
494 cl.cmd.forwardmove += IN_JoystickGetAxis(joy, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
495 cl.cmd.sidemove += IN_JoystickGetAxis(joy, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
496 cl.cmd.upmove += IN_JoystickGetAxis(joy, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
497 cl.viewangles[0] += IN_JoystickGetAxis(joy, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
498 cl.viewangles[1] += IN_JoystickGetAxis(joy, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
499 //cl.viewangles[2] += IN_JoystickGetAxis(joy, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
501 // cache state of axes to emulate button events for them
502 numaxes = min(MAX_JOYSTICK_AXES, SDL_JoystickNumAxes(joy));
503 for (j = 0; j < numaxes; j++)
505 joy_axescache[j].oldmove = joy_axescache[j].move;
506 joy_axescache[j].move = IN_JoystickGetAxis(joy, j, 1, 0.01);
510 if (joy_axiskeyevents.integer)
512 IN_JoystickKeyeventForAxis(joy, joy_axisforward.integer, K_DOWNARROW, K_UPARROW);
513 IN_JoystickKeyeventForAxis(joy, joy_axisside.integer, K_RIGHTARROW, K_LEFTARROW);
518 /////////////////////
522 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
523 static int Sys_EventFilter( SDL_Event *event )
525 //TODO: Add a quit query in linux, too - though linux user are more likely to know what they do
526 if (event->type == SDL_QUIT)
529 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
538 static qboolean sdl_needs_restart;
539 static void sdl_start(void)
542 static void sdl_shutdown(void)
544 sdl_needs_restart = false;
546 static void sdl_newmap(void)
551 static keynum_t buttonremap[18] =
573 void Sys_SendKeyEvents( void )
575 static qboolean sound_active = true;
579 while( SDL_PollEvent( &event ) )
580 switch( event.type ) {
582 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
584 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
592 keycode = MapKey(event.key.keysym.sym);
593 if (!IN_JoystickBlockDoubledKeyEvents(keycode))
594 Key_Event(keycode, event.key.keysym.unicode, (event.key.state == SDL_PRESSED));
596 case SDL_ACTIVEEVENT:
597 if( event.active.state & SDL_APPACTIVE )
599 if( event.active.gain )
605 case SDL_MOUSEBUTTONDOWN:
606 case SDL_MOUSEBUTTONUP:
607 if (event.button.button <= 18)
608 Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
610 case SDL_JOYBUTTONDOWN:
611 if (!joy_enable.integer)
612 break; // ignore down events if joystick has been disabled
613 case SDL_JOYBUTTONUP:
614 if (event.jbutton.button < 48)
615 Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
617 case SDL_VIDEORESIZE:
618 if(vid_resizable.integer < 2)
620 vid.width = event.resize.w;
621 vid.height = event.resize.h;
622 SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
625 SDL_FreeSurface(vid_softsurface);
626 vid_softsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, vid.width, vid.height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
627 vid.softpixels = (unsigned int *)vid_softsurface->pixels;
628 SDL_SetAlpha(vid_softsurface, 0, 255);
629 if (vid.softdepthpixels)
630 free(vid.softdepthpixels);
631 vid.softdepthpixels = (unsigned int*)calloc(1, vid.width * vid.height * 4);
634 // better not call R_Modules_Restart from here directly, as this may wreak havoc...
635 // so, let's better queue it for next frame
636 if(!sdl_needs_restart)
638 Cbuf_AddText("\nr_restart\n");
639 sdl_needs_restart = true;
646 // enable/disable sound on focus gain/loss
647 if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
660 sound_active = false;
669 void *GL_GetProcAddress(const char *name)
672 p = SDL_GL_GetProcAddress(name);
676 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
677 static int Sys_EventFilter( SDL_Event *event );
679 static qboolean vid_sdl_initjoysticksystem = false;
684 Cvar_RegisterVariable(&apple_mouse_noaccel);
686 Cvar_RegisterVariable(&vid_soft);
687 Cvar_RegisterVariable(&joy_detected);
688 Cvar_RegisterVariable(&joy_enable);
689 Cvar_RegisterVariable(&joy_index);
690 Cvar_RegisterVariable(&joy_axisforward);
691 Cvar_RegisterVariable(&joy_axisside);
692 Cvar_RegisterVariable(&joy_axisup);
693 Cvar_RegisterVariable(&joy_axispitch);
694 Cvar_RegisterVariable(&joy_axisyaw);
695 //Cvar_RegisterVariable(&joy_axisroll);
696 Cvar_RegisterVariable(&joy_deadzoneforward);
697 Cvar_RegisterVariable(&joy_deadzoneside);
698 Cvar_RegisterVariable(&joy_deadzoneup);
699 Cvar_RegisterVariable(&joy_deadzonepitch);
700 Cvar_RegisterVariable(&joy_deadzoneyaw);
701 //Cvar_RegisterVariable(&joy_deadzoneroll);
702 Cvar_RegisterVariable(&joy_sensitivityforward);
703 Cvar_RegisterVariable(&joy_sensitivityside);
704 Cvar_RegisterVariable(&joy_sensitivityup);
705 Cvar_RegisterVariable(&joy_sensitivitypitch);
706 Cvar_RegisterVariable(&joy_sensitivityyaw);
707 //Cvar_RegisterVariable(&joy_sensitivityroll);
708 Cvar_RegisterVariable(&joy_axiskeyevents);
711 R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap, NULL, NULL);
714 if (SDL_Init(SDL_INIT_VIDEO) < 0)
715 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
716 vid_sdl_initjoysticksystem = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0;
717 if (vid_sdl_initjoysticksystem)
718 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
719 vid_isfullscreen = false;
722 // set the icon (we dont use SDL here since it would be too much a PITA)
724 #include "resource.h"
725 #include <SDL_syswm.h>
726 static void VID_SetCaption(void)
732 SDL_WM_SetCaption( gamename, NULL );
734 // get the HWND handle
735 SDL_VERSION( &info.version );
736 if( !SDL_GetWMInfo( &info ) )
739 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
740 #ifndef _W64 //If Windows 64bit data types don't exist
741 #ifndef SetClassLongPtr
742 #define SetClassLongPtr SetClassLong
745 #define GCLP_HICON GCL_HICON
748 #define LONG_PTR LONG
751 SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
753 static void VID_SetIcon_Pre(void)
756 static void VID_SetIcon_Post(void)
760 // Adding the OS independent XPM version --blub
761 #include "darkplaces.xpm"
762 #include "nexuiz.xpm"
763 static SDL_Surface *icon = NULL;
764 static void VID_SetIcon_Pre(void)
767 * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
768 * default settings with less than 91 colors and transparency.
771 int width, height, colors, isize, i, j;
773 static SDL_Color palette[256];
774 unsigned short palenc[256]; // store color id by char
777 const SDL_version *version;
779 version = SDL_Linked_Version();
780 // only use non-XPM icon support in SDL v1.3 and higher
781 // SDL v1.2 does not support "smooth" transparency, and thus is better
783 if(version->major >= 2 || (version->major == 1 && version->minor >= 3))
785 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
788 unsigned int red = 0x00FF0000;
789 unsigned int green = 0x0000FF00;
790 unsigned int blue = 0x000000FF;
791 unsigned int alpha = 0xFF000000;
793 height = image_height;
795 // reallocate with malloc, as this is in tempmempool (do not want)
797 data = malloc(width * height * 4);
798 memcpy(data, xpm, width * height * 4);
802 icon = SDL_CreateRGBSurface(SDL_SRCALPHA, width, height, 32, LittleLong(red), LittleLong(green), LittleLong(blue), LittleLong(alpha));
805 Con_Printf( "Failed to create surface for the window Icon!\n"
806 "%s\n", SDL_GetError());
815 // we only get here if non-XPM icon was missing, or SDL version is not
816 // sufficient for transparent non-XPM icons
819 xpm = (char *) FS_LoadFile("darkplaces-icon.xpm", tempmempool, false, NULL);
822 idata = XPM_DecodeString(xpm);
830 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) != 4)
832 // NOTE: Only 1-char colornames are supported
833 Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
839 // NOTE: Only 1-char colornames are supported
840 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
844 for(i = 0; i < colors; ++i)
846 unsigned int r, g, b;
849 if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
852 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
854 Con_Printf("This XPM's palette looks odd. Can't continue.\n");
859 palette[i].r = 255; // color key
862 thenone = i; // weeeee
867 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
872 palenc[(unsigned char) idx] = i;
875 // allocate the image data
876 data = (char*) malloc(width*height);
878 for(j = 0; j < height; ++j)
880 for(i = 0; i < width; ++i)
882 // casting to the safest possible datatypes ^^
883 data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
889 // SDL_FreeSurface should free the data too
890 // but for completeness' sake...
891 if(icon->flags & SDL_PREALLOC)
894 icon->pixels = NULL; // safety
896 SDL_FreeSurface(icon);
899 icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
900 // 8 bit surfaces get an empty palette allocated according to the docs
901 // so it's a palette image for sure :) no endian check necessary for the mask
904 Con_Printf( "Failed to create surface for the window Icon!\n"
905 "%s\n", SDL_GetError());
911 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
912 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
915 SDL_WM_SetIcon(icon, NULL);
917 static void VID_SetIcon_Post(void)
919 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
920 // LordHavoc: info.info.x11.lock_func and accompanying code do not seem to compile with SDL 1.3
921 #if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
924 const SDL_version *version;
926 version = SDL_Linked_Version();
927 // only use non-XPM icon support in SDL v1.3 and higher
928 // SDL v1.2 does not support "smooth" transparency, and thus is better
930 if(!(version->major >= 2 || (version->major == 1 && version->minor >= 3)))
932 // in this case, we did not set the good icon yet
934 SDL_VERSION(&info.version);
935 if(SDL_GetWMInfo(&info) == 1 && info.subsystem == SDL_SYSWM_X11)
937 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
940 // use _NET_WM_ICON too
941 static long netwm_icon[MAX_NETWM_ICON];
947 if(pos + 2 * image_width * image_height < MAX_NETWM_ICON)
949 netwm_icon[pos++] = image_width;
950 netwm_icon[pos++] = image_height;
951 for(i = 0; i < image_height; ++i)
952 for(j = 0; j < image_width; ++j)
953 netwm_icon[pos++] = BuffLittleLong((unsigned char *) &data[(i*image_width+j)*4]);
957 Con_Printf("Skipping NETWM icon #%d because there is no space left\n", i);
961 data = (char *) loadimagepixelsbgra(va("darkplaces-icon%d", i), false, false, false, NULL);
964 info.info.x11.lock_func();
966 Atom net_wm_icon = XInternAtom(info.info.x11.display, "_NET_WM_ICON", false);
967 XChangeProperty(info.info.x11.display, info.info.x11.wmwindow, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos);
969 info.info.x11.unlock_func();
978 static void VID_SetCaption(void)
980 SDL_WM_SetCaption( gamename, NULL );
984 static void VID_OutputVersion(void)
986 const SDL_version *version;
987 version = SDL_Linked_Version();
988 Con_Printf( "Linked against SDL version %d.%d.%d\n"
989 "Using SDL library version %d.%d.%d\n",
990 SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
991 version->major, version->minor, version->patch );
994 qboolean VID_InitModeGL(viddef_mode_t *mode)
997 // FIXME SDL_SetVideoMode
998 static int notfirstvideomode = false;
999 int flags = SDL_OPENGL;
1000 const char *drivername;
1002 win_half_width = mode->width>>1;
1003 win_half_height = mode->height>>1;
1005 if(vid_resizable.integer)
1006 flags |= SDL_RESIZABLE;
1008 VID_OutputVersion();
1012 We cant switch from one OpenGL video mode to another.
1013 Thus we first switch to some stupid 2D mode and then back to OpenGL.
1015 if (notfirstvideomode)
1016 SDL_SetVideoMode( 0, 0, 0, 0 );
1017 notfirstvideomode = true;
1019 // SDL usually knows best
1022 // 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
1023 i = COM_CheckParm("-gl_driver");
1024 if (i && i < com_argc - 1)
1025 drivername = com_argv[i + 1];
1026 if (SDL_GL_LoadLibrary(drivername) < 0)
1028 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
1032 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
1035 Con_Print("Required OpenGL function glGetString not found\n");
1039 // Knghtbrd: should do platform-specific extension string function here
1041 vid_isfullscreen = false;
1042 if (mode->fullscreen) {
1043 flags |= SDL_FULLSCREEN;
1044 vid_isfullscreen = true;
1046 //flags |= SDL_HWSURFACE;
1048 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
1049 if (mode->bitsperpixel >= 32)
1051 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
1052 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
1053 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
1054 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
1055 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
1056 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
1060 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
1061 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
1062 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
1063 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
1065 if (mode->stereobuffer)
1066 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
1067 if (mode->samples > 1)
1069 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
1070 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples);
1072 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1073 if (vid_vsync.integer)
1074 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
1076 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
1078 // TODO: SDL_GL_CONTEXT_MAJOR_VERSION, SDL_GL_CONTEXT_MINOR_VERSION
1081 video_bpp = mode->bitsperpixel;
1082 video_flags = flags;
1084 screen = SDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
1089 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
1094 vid_softsurface = NULL;
1095 vid.softpixels = NULL;
1099 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1100 // set up an event filter to ask confirmation on close button in WIN32
1101 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
1104 SDL_EnableUNICODE( SDL_ENABLE );
1105 // enable key repeat since everyone expects it
1106 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1108 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
1109 SDL_GL_SetSwapInterval(vid_vsync.integer != 0);
1110 vid_usingvsync = (vid_vsync.integer != 0);
1113 gl_platform = "SDL";
1114 gl_platformextensions = "";
1118 vid_numjoysticks = SDL_NumJoysticks();
1119 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
1120 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
1121 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
1122 memset(vid_joysticks, 0, sizeof(vid_joysticks));
1123 for (i = 0;i < vid_numjoysticks;i++)
1126 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
1129 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
1132 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));
1136 vid_activewindow = false;
1137 vid_usingmouse = false;
1138 vid_usinghidecursor = false;
1140 SDL_WM_GrabInput(SDL_GRAB_OFF);
1144 extern cvar_t gl_info_extensions;
1145 extern cvar_t gl_info_vendor;
1146 extern cvar_t gl_info_renderer;
1147 extern cvar_t gl_info_version;
1148 extern cvar_t gl_info_platform;
1149 extern cvar_t gl_info_driver;
1151 qboolean VID_InitModeSoft(viddef_mode_t *mode)
1153 // FIXME SDL_SetVideoMode
1155 int flags = SDL_HWSURFACE;
1157 win_half_width = mode->width>>1;
1158 win_half_height = mode->height>>1;
1160 if(vid_resizable.integer)
1161 flags |= SDL_RESIZABLE;
1163 VID_OutputVersion();
1165 vid_isfullscreen = false;
1166 if (mode->fullscreen) {
1167 flags |= SDL_FULLSCREEN;
1168 vid_isfullscreen = true;
1171 video_bpp = mode->bitsperpixel;
1172 video_flags = flags;
1174 screen = SDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
1179 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
1184 // create a framebuffer using our specific color format, we let the SDL blit function convert it in VID_Finish
1185 vid_softsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, mode->width, mode->height, 32, 0x00FF0000, 0x0000FF00, 0x00000000FF, 0xFF000000);
1186 if (vid_softsurface == NULL)
1188 Con_Printf("Failed to setup software rasterizer framebuffer %ix%ix32bpp: %s\n", mode->width, mode->height, SDL_GetError());
1192 SDL_SetAlpha(vid_softsurface, 0, 255);
1194 vid.softpixels = (unsigned int *)vid_softsurface->pixels;
1195 vid.softdepthpixels = (unsigned int *)calloc(1, mode->width * mode->height * 4);
1196 DPSOFTRAST_Init(mode->width, mode->height, (unsigned int *)vid_softsurface->pixels, (unsigned int *)vid.softdepthpixels);
1200 // set up an event filter to ask confirmation on close button in WIN32
1201 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1202 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
1205 SDL_EnableUNICODE( SDL_ENABLE );
1206 // enable key repeat since everyone expects it
1207 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1209 gl_platform = "SDLSoft";
1210 gl_platformextensions = "";
1212 gl_renderer = "DarkPlaces-Soft";
1213 gl_vendor = "Forest Hale";
1217 // clear the extension flags
1218 memset(&vid.support, 0, sizeof(vid.support));
1219 Cvar_SetQuick(&gl_info_extensions, "");
1221 vid.forcevbo = false;
1222 vid.support.arb_depth_texture = true;
1223 vid.support.arb_draw_buffers = true;
1224 vid.support.arb_occlusion_query = true;
1225 vid.support.arb_shadow = true;
1226 //vid.support.arb_texture_compression = true;
1227 vid.support.arb_texture_cube_map = true;
1228 vid.support.arb_texture_non_power_of_two = false;
1229 vid.support.arb_vertex_buffer_object = true;
1230 vid.support.ext_blend_subtract = true;
1231 vid.support.ext_draw_range_elements = true;
1232 vid.support.ext_framebuffer_object = true;
1233 vid.support.ext_texture_3d = true;
1234 //vid.support.ext_texture_compression_s3tc = true;
1235 vid.support.ext_texture_filter_anisotropic = true;
1236 vid.support.ati_separate_stencil = true;
1238 vid.maxtexturesize_2d = 16384;
1239 vid.maxtexturesize_3d = 512;
1240 vid.maxtexturesize_cubemap = 16384;
1242 vid.teximageunits = 32;
1243 vid.texarrayunits = 8;
1244 vid.max_anisotropy = 1;
1245 vid.maxdrawbuffers = 4;
1247 vid.texunits = bound(4, vid.texunits, MAX_TEXTUREUNITS);
1248 vid.teximageunits = bound(16, vid.teximageunits, MAX_TEXTUREUNITS);
1249 vid.texarrayunits = bound(8, vid.texarrayunits, MAX_TEXTUREUNITS);
1250 Con_DPrintf("Using DarkPlaces Software Rasterizer rendering path\n");
1251 vid.renderpath = RENDERPATH_SOFT;
1252 vid.useinterleavedarrays = false;
1254 Cvar_SetQuick(&gl_info_vendor, gl_vendor);
1255 Cvar_SetQuick(&gl_info_renderer, gl_renderer);
1256 Cvar_SetQuick(&gl_info_version, gl_version);
1257 Cvar_SetQuick(&gl_info_platform, gl_platform ? gl_platform : "");
1258 Cvar_SetQuick(&gl_info_driver, gl_driver);
1260 // LordHavoc: report supported extensions
1261 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1263 // clear to black (loading plaque will be seen over this)
1264 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
1266 vid_numjoysticks = SDL_NumJoysticks();
1267 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
1268 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
1269 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
1270 memset(vid_joysticks, 0, sizeof(vid_joysticks));
1271 for (i = 0;i < vid_numjoysticks;i++)
1274 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
1277 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
1280 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));
1284 vid_activewindow = false;
1285 vid_usingmouse = false;
1286 vid_usinghidecursor = false;
1288 SDL_WM_GrabInput(SDL_GRAB_OFF);
1292 qboolean VID_InitMode(viddef_mode_t *mode)
1294 if (!SDL_WasInit(SDL_INIT_VIDEO) && SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
1295 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
1297 if (vid_soft.integer)
1298 return VID_InitModeSoft(mode);
1301 return VID_InitModeGL(mode);
1304 void VID_Shutdown (void)
1306 VID_SetMouse(false, false, false);
1307 VID_RestoreSystemGamma();
1311 SDL_FreeSurface(icon);
1315 if (vid_softsurface)
1316 SDL_FreeSurface(vid_softsurface);
1317 vid_softsurface = NULL;
1318 vid.softpixels = NULL;
1319 if (vid.softdepthpixels)
1320 free(vid.softdepthpixels);
1321 vid.softdepthpixels = NULL;
1323 SDL_QuitSubSystem(SDL_INIT_VIDEO);
1328 gl_platformextensions = "";
1331 int VID_SetGamma (unsigned short *ramps, int rampsize)
1333 return !SDL_SetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
1336 int VID_GetGamma (unsigned short *ramps, int rampsize)
1338 return !SDL_GetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
1341 void VID_Finish (void)
1345 //react on appstate changes
1346 appstate = SDL_GetAppState();
1348 vid_hidden = !(appstate & SDL_APPACTIVE);
1350 if( vid_hidden || !( appstate & SDL_APPMOUSEFOCUS ) || !( appstate & SDL_APPINPUTFOCUS ) )
1351 vid_activewindow = false;
1353 vid_activewindow = true;
1355 VID_UpdateGamma(false, 256);
1359 switch(vid.renderpath)
1361 case RENDERPATH_GL11:
1362 case RENDERPATH_GL13:
1363 case RENDERPATH_GL20:
1364 case RENDERPATH_CGGL:
1366 if (r_speeds.integer == 2 || gl_finish.integer)
1368 qglFinish();CHECKGLERROR
1370 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
1372 qboolean vid_usevsync;
1373 vid_usevsync = (vid_vsync.integer && !cls.timedemo);
1374 if (vid_usingvsync != vid_usevsync)
1376 if (SDL_GL_SetSwapInterval(vid_usevsync != 0) >= 0)
1377 Con_DPrintf("Vsync %s\n", vid_usevsync ? "activated" : "deactivated");
1379 Con_DPrintf("ERROR: can't %s vsync\n", vid_usevsync ? "activate" : "deactivate");
1383 SDL_GL_SwapBuffers();
1385 case RENDERPATH_SOFT:
1386 SDL_BlitSurface(vid_softsurface, NULL, screen, NULL);
1389 case RENDERPATH_D3D9:
1390 case RENDERPATH_D3D10:
1391 case RENDERPATH_D3D11:
1397 size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
1400 SDL_Rect **vidmodes;
1401 int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
1404 for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); *vidmodes; ++vidmodes)
1408 modes[k].width = (*vidmodes)->w;
1409 modes[k].height = (*vidmodes)->h;
1411 modes[k].refreshrate = 60; // no support for refresh rate in SDL
1412 modes[k].pixelheight_num = 1;
1413 modes[k].pixelheight_denom = 1; // SDL does not provide this