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"
30 #include <Carbon/Carbon.h>
31 #include <IOKit/hidsystem/IOHIDLib.h>
32 #include <IOKit/hidsystem/IOHIDParameter.h>
33 #include <IOKit/hidsystem/event_status_driver.h>
34 static cvar_t apple_mouse_noaccel = {CVAR_SAVE, "apple_mouse_noaccel", "1", "disables mouse acceleration while DarkPlaces is active"};
35 static qboolean vid_usingnoaccel;
36 static double originalMouseSpeed = -1.0;
37 io_connect_t IN_GetIOHandle(void)
39 io_connect_t iohandle = MACH_PORT_NULL;
41 io_service_t iohidsystem = MACH_PORT_NULL;
42 mach_port_t masterport;
44 status = IOMasterPort(MACH_PORT_NULL, &masterport);
45 if(status != KERN_SUCCESS)
48 iohidsystem = IORegistryEntryFromPath(masterport, kIOServicePlane ":/IOResources/IOHIDSystem");
52 status = IOServiceOpen(iohidsystem, mach_task_self(), kIOHIDParamConnectType, &iohandle);
53 IOObjectRelease(iohidsystem);
64 // Tell startup code that we have a client
65 int cl_available = true;
67 qboolean vid_supportrefreshrate = false;
69 cvar_t vid_soft = {CVAR_SAVE, "vid_soft", "0", "enables use of the DarkPlaces Software Rasterizer rather than OpenGL or Direct3D"};
70 cvar_t joy_detected = {CVAR_READONLY, "joy_detected", "0", "number of joysticks detected by engine"};
71 cvar_t joy_enable = {CVAR_SAVE, "joy_enable", "0", "enables joystick support"};
72 cvar_t joy_index = {0, "joy_index", "0", "selects which joystick to use if you have multiple"};
73 cvar_t joy_axisforward = {0, "joy_axisforward", "1", "which joystick axis to query for forward/backward movement"};
74 cvar_t joy_axisside = {0, "joy_axisside", "0", "which joystick axis to query for right/left movement"};
75 cvar_t joy_axisup = {0, "joy_axisup", "-1", "which joystick axis to query for up/down movement"};
76 cvar_t joy_axispitch = {0, "joy_axispitch", "3", "which joystick axis to query for looking up/down"};
77 cvar_t joy_axisyaw = {0, "joy_axisyaw", "2", "which joystick axis to query for looking right/left"};
78 cvar_t joy_axisroll = {0, "joy_axisroll", "-1", "which joystick axis to query for tilting head right/left"};
79 cvar_t joy_deadzoneforward = {0, "joy_deadzoneforward", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
80 cvar_t joy_deadzoneside = {0, "joy_deadzoneside", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
81 cvar_t joy_deadzoneup = {0, "joy_deadzoneup", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
82 cvar_t joy_deadzonepitch = {0, "joy_deadzonepitch", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
83 cvar_t joy_deadzoneyaw = {0, "joy_deadzoneyaw", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
84 cvar_t joy_deadzoneroll = {0, "joy_deadzoneroll", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
85 cvar_t joy_sensitivityforward = {0, "joy_sensitivityforward", "-1", "movement multiplier"};
86 cvar_t joy_sensitivityside = {0, "joy_sensitivityside", "1", "movement multiplier"};
87 cvar_t joy_sensitivityup = {0, "joy_sensitivityup", "1", "movement multiplier"};
88 cvar_t joy_sensitivitypitch = {0, "joy_sensitivitypitch", "1", "movement multiplier"};
89 cvar_t joy_sensitivityyaw = {0, "joy_sensitivityyaw", "-1", "movement multiplier"};
90 cvar_t joy_sensitivityroll = {0, "joy_sensitivityroll", "1", "movement multiplier"};
91 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"};
93 static qboolean vid_usingmouse = false;
94 static qboolean vid_usinghidecursor = false;
95 static qboolean vid_isfullscreen;
96 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
97 static qboolean vid_usingvsync = false;
99 static int vid_numjoysticks = 0;
100 #define MAX_JOYSTICKS 8
101 static SDL_Joystick *vid_joysticks[MAX_JOYSTICKS];
103 static int win_half_width = 50;
104 static int win_half_height = 50;
105 static int video_bpp, video_flags;
107 static SDL_Surface *screen;
108 static SDL_Surface *vid_softsurface;
110 // joystick axes state
111 #define MAX_JOYSTICK_AXES 16
118 static joy_axiscache_t joy_axescache[MAX_JOYSTICK_AXES];
120 /////////////////////////
123 //TODO: Add joystick support
124 //TODO: Add error checking
127 //keysym to quake keysym mapping
128 #define tenoh 0,0,0,0,0, 0,0,0,0,0
129 #define fiftyoh tenoh, tenoh, tenoh, tenoh, tenoh
130 #define hundredoh fiftyoh, fiftyoh
131 static unsigned int tbl_sdltoquake[] =
133 0,0,0,0, //SDLK_UNKNOWN = 0,
134 0,0,0,0, //SDLK_FIRST = 0,
135 K_BACKSPACE, //SDLK_BACKSPACE = 8,
136 K_TAB, //SDLK_TAB = 9,
138 0, //SDLK_CLEAR = 12,
139 K_ENTER, //SDLK_RETURN = 13,
141 K_PAUSE, //SDLK_PAUSE = 19,
143 K_ESCAPE, //SDLK_ESCAPE = 27,
145 K_SPACE, //SDLK_SPACE = 32,
146 '!', //SDLK_EXCLAIM = 33,
147 '"', //SDLK_QUOTEDBL = 34,
148 '#', //SDLK_HASH = 35,
149 '$', //SDLK_DOLLAR = 36,
151 '&', //SDLK_AMPERSAND = 38,
152 '\'', //SDLK_QUOTE = 39,
153 '(', //SDLK_LEFTPAREN = 40,
154 ')', //SDLK_RIGHTPAREN = 41,
155 '*', //SDLK_ASTERISK = 42,
156 '+', //SDLK_PLUS = 43,
157 ',', //SDLK_COMMA = 44,
158 '-', //SDLK_MINUS = 45,
159 '.', //SDLK_PERIOD = 46,
160 '/', //SDLK_SLASH = 47,
171 ':', //SDLK_COLON = 58,
172 ';', //SDLK_SEMICOLON = 59,
173 '<', //SDLK_LESS = 60,
174 '=', //SDLK_EQUALS = 61,
175 '>', //SDLK_GREATER = 62,
176 '?', //SDLK_QUESTION = 63,
178 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,
179 '[', //SDLK_LEFTBRACKET = 91,
180 '\\', //SDLK_BACKSLASH = 92,
181 ']', //SDLK_RIGHTBRACKET = 93,
182 '^', //SDLK_CARET = 94,
183 '_', //SDLK_UNDERSCORE = 95,
184 '`', //SDLK_BACKQUOTE = 96,
212 K_DEL, //SDLK_DELETE = 127,
213 hundredoh /*227*/, tenoh, tenoh, 0,0,0,0,0,0,0,0,
214 K_KP_0, //SDLK_KP0 = 256,
215 K_KP_1, //SDLK_KP1 = 257,
216 K_KP_2, //SDLK_KP2 = 258,
217 K_KP_3, //SDLK_KP3 = 259,
218 K_KP_4, //SDLK_KP4 = 260,
219 K_KP_5, //SDLK_KP5 = 261,
220 K_KP_6, //SDLK_KP6 = 262,
221 K_KP_7, //SDLK_KP7 = 263,
222 K_KP_8, //SDLK_KP8 = 264,
223 K_KP_9, //SDLK_KP9 = 265,
224 K_KP_PERIOD,//SDLK_KP_PERIOD = 266,
225 K_KP_DIVIDE,//SDLK_KP_DIVIDE = 267,
226 K_KP_MULTIPLY,//SDLK_KP_MULTIPLY= 268,
227 K_KP_MINUS, //SDLK_KP_MINUS = 269,
228 K_KP_PLUS, //SDLK_KP_PLUS = 270,
229 K_KP_ENTER, //SDLK_KP_ENTER = 271,
230 K_KP_EQUALS,//SDLK_KP_EQUALS = 272,
231 K_UPARROW, //SDLK_UP = 273,
232 K_DOWNARROW,//SDLK_DOWN = 274,
233 K_RIGHTARROW,//SDLK_RIGHT = 275,
234 K_LEFTARROW,//SDLK_LEFT = 276,
235 K_INS, //SDLK_INSERT = 277,
236 K_HOME, //SDLK_HOME = 278,
237 K_END, //SDLK_END = 279,
238 K_PGUP, //SDLK_PAGEUP = 280,
239 K_PGDN, //SDLK_PAGEDOWN = 281,
240 K_F1, //SDLK_F1 = 282,
241 K_F2, //SDLK_F2 = 283,
242 K_F3, //SDLK_F3 = 284,
243 K_F4, //SDLK_F4 = 285,
244 K_F5, //SDLK_F5 = 286,
245 K_F6, //SDLK_F6 = 287,
246 K_F7, //SDLK_F7 = 288,
247 K_F8, //SDLK_F8 = 289,
248 K_F9, //SDLK_F9 = 290,
249 K_F10, //SDLK_F10 = 291,
250 K_F11, //SDLK_F11 = 292,
251 K_F12, //SDLK_F12 = 293,
256 K_NUMLOCK, //SDLK_NUMLOCK = 300,
257 K_CAPSLOCK, //SDLK_CAPSLOCK = 301,
258 K_SCROLLOCK,//SDLK_SCROLLOCK= 302,
259 K_SHIFT, //SDLK_RSHIFT = 303,
260 K_SHIFT, //SDLK_LSHIFT = 304,
261 K_CTRL, //SDLK_RCTRL = 305,
262 K_CTRL, //SDLK_LCTRL = 306,
263 K_ALT, //SDLK_RALT = 307,
264 K_ALT, //SDLK_LALT = 308,
265 0, //SDLK_RMETA = 309,
266 0, //SDLK_LMETA = 310,
267 0, //SDLK_LSUPER = 311, /* Left "Windows" key */
268 0, //SDLK_RSUPER = 312, /* Right "Windows" key */
269 K_ALT, //SDLK_MODE = 313, /* "Alt Gr" key */
270 0, //SDLK_COMPOSE = 314, /* Multi-key compose key */
271 0, //SDLK_HELP = 315,
272 0, //SDLK_PRINT = 316,
273 0, //SDLK_SYSREQ = 317,
274 K_PAUSE, //SDLK_BREAK = 318,
275 0, //SDLK_MENU = 319,
276 0, //SDLK_POWER = 320, /* Power Macintosh power key */
277 'e', //SDLK_EURO = 321, /* Some european keyboards */
278 0 //SDLK_UNDO = 322, /* Atari keyboard has Undo */
284 static int MapKey( unsigned int sdlkey )
286 if( sdlkey > sizeof(tbl_sdltoquake)/ sizeof(int) )
288 return tbl_sdltoquake[ sdlkey ];
291 void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor)
296 if(vid_usingmouse && (vid_usingnoaccel != !!apple_mouse_noaccel.integer))
297 VID_SetMouse(false, false, false); // ungrab first!
300 if (vid_usingmouse != relative)
302 vid_usingmouse = relative;
303 cl_ignoremousemoves = 2;
304 SDL_WM_GrabInput( relative ? SDL_GRAB_ON : SDL_GRAB_OFF );
309 // Save the status of mouse acceleration
310 originalMouseSpeed = -1.0; // in case of error
311 if(apple_mouse_noaccel.integer)
313 io_connect_t mouseDev = IN_GetIOHandle();
316 if(IOHIDGetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), &originalMouseSpeed) == kIOReturnSuccess)
318 Con_DPrintf("previous mouse acceleration: %f\n", originalMouseSpeed);
319 if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), -1.0) != kIOReturnSuccess)
321 Con_Print("Could not disable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
322 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
327 Con_Print("Could not disable mouse acceleration (failed at IOHIDGetAccelerationWithKey).\n");
328 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
330 IOServiceClose(mouseDev);
334 Con_Print("Could not disable mouse acceleration (failed at IO_GetIOHandle).\n");
335 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
339 vid_usingnoaccel = !!apple_mouse_noaccel.integer;
343 if(originalMouseSpeed != -1.0)
345 io_connect_t mouseDev = IN_GetIOHandle();
348 Con_DPrintf("restoring mouse acceleration to: %f\n", originalMouseSpeed);
349 if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), originalMouseSpeed) != kIOReturnSuccess)
350 Con_Print("Could not re-enable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
351 IOServiceClose(mouseDev);
354 Con_Print("Could not re-enable mouse acceleration (failed at IO_GetIOHandle).\n");
360 if (vid_usinghidecursor != hidecursor)
362 vid_usinghidecursor = hidecursor;
363 SDL_ShowCursor( hidecursor ? SDL_DISABLE : SDL_ENABLE);
367 static double IN_JoystickGetAxis(SDL_Joystick *joy, int axis, double sensitivity, double deadzone)
370 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
371 return 0; // no such axis on this joystick
372 value = SDL_JoystickGetAxis(joy, axis) * (1.0 / 32767.0);
373 value = bound(-1, value, 1);
374 if (fabs(value) < deadzone)
375 return 0; // within deadzone around center
376 return value * sensitivity;
379 /////////////////////
380 // Joystick axis keyevents
381 // a sort of hack emulating Arrow keys for joystick axises
382 // as some drives dont send such keyevents for them
383 // additionally we should block drivers that do send arrow keyevents to prevent double events
386 static void IN_JoystickKeyeventForAxis(SDL_Joystick *joy, int axis, int key_pos, int key_neg)
390 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
391 return; // no such axis on this joystick
393 joytime = Sys_DoubleTime();
394 // no key event, continuous keydown event
395 if (joy_axescache[axis].move == joy_axescache[axis].oldmove)
397 if (joy_axescache[axis].move != 0 && joytime > joy_axescache[axis].keytime)
399 //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
400 Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
401 joy_axescache[axis].keytime = joytime + 0.5 / 20;
405 // generate key up event
406 if (joy_axescache[axis].oldmove)
408 //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg), 1, cl.time);
409 Key_Event((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg, 0, 0);
411 // generate key down event
412 if (joy_axescache[axis].move)
414 //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
415 Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
416 joy_axescache[axis].keytime = joytime + 0.5;
420 static qboolean IN_JoystickBlockDoubledKeyEvents(int keycode)
422 if (!joy_axiskeyevents.integer)
425 // block keyevent if it's going to be provided by joystick keyevent system
426 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
428 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
430 if (keycode == K_UPARROW || keycode == K_DOWNARROW)
431 if (IN_JoystickGetAxis(joy, joy_axisforward.integer, 1, 0.01) || joy_axescache[joy_axisforward.integer].move || joy_axescache[joy_axisforward.integer].oldmove)
433 if (keycode == K_RIGHTARROW || keycode == K_LEFTARROW)
434 if (IN_JoystickGetAxis(joy, joy_axisside.integer, 1, 0.01) || joy_axescache[joy_axisside.integer].move || joy_axescache[joy_axisside.integer].oldmove)
441 /////////////////////
448 static int old_x = 0, old_y = 0;
449 static int stuck = 0;
450 int x, y, numaxes, numballs;
454 if(vid_stick_mouse.integer)
456 // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
457 // window grabbing. --blub
459 // we need 2 frames to initialize the center position
462 SDL_WarpMouse(win_half_width, win_half_height);
463 SDL_GetMouseState(&x, &y);
464 SDL_GetRelativeMouseState(&x, &y);
467 SDL_GetRelativeMouseState(&x, &y);
468 in_mouse_x = x + old_x;
469 in_mouse_y = y + old_y;
470 SDL_GetMouseState(&x, &y);
471 old_x = x - win_half_width;
472 old_y = y - win_half_height;
473 SDL_WarpMouse(win_half_width, win_half_height);
476 SDL_GetRelativeMouseState( &x, &y );
482 SDL_GetMouseState(&x, &y);
483 in_windowmouse_x = x;
484 in_windowmouse_y = y;
486 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
488 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
490 // balls convert to mousemove
491 numballs = SDL_JoystickNumBalls(joy);
492 for (j = 0;j < numballs;j++)
494 SDL_JoystickGetBall(joy, j, &x, &y);
500 cl.cmd.forwardmove += IN_JoystickGetAxis(joy, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
501 cl.cmd.sidemove += IN_JoystickGetAxis(joy, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
502 cl.cmd.upmove += IN_JoystickGetAxis(joy, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
503 cl.viewangles[0] += IN_JoystickGetAxis(joy, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
504 cl.viewangles[1] += IN_JoystickGetAxis(joy, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
505 //cl.viewangles[2] += IN_JoystickGetAxis(joy, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
507 // cache state of axes to emulate button events for them
508 numaxes = min(MAX_JOYSTICK_AXES, SDL_JoystickNumAxes(joy));
509 for (j = 0; j < numaxes; j++)
511 joy_axescache[j].oldmove = joy_axescache[j].move;
512 joy_axescache[j].move = IN_JoystickGetAxis(joy, j, 1, 0.01);
516 if (joy_axiskeyevents.integer)
518 IN_JoystickKeyeventForAxis(joy, joy_axisforward.integer, K_DOWNARROW, K_UPARROW);
519 IN_JoystickKeyeventForAxis(joy, joy_axisside.integer, K_RIGHTARROW, K_LEFTARROW);
524 /////////////////////
528 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
529 static int Sys_EventFilter( SDL_Event *event )
531 //TODO: Add a quit query in linux, too - though linux user are more likely to know what they do
532 if (event->type == SDL_QUIT)
535 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
544 static qboolean sdl_needs_restart;
545 static void sdl_start(void)
548 static void sdl_shutdown(void)
550 sdl_needs_restart = false;
552 static void sdl_newmap(void)
557 static keynum_t buttonremap[18] =
579 void Sys_SendKeyEvents( void )
581 static qboolean sound_active = true;
585 while( SDL_PollEvent( &event ) )
586 switch( event.type ) {
588 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
590 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
598 keycode = MapKey(event.key.keysym.sym);
599 if (!IN_JoystickBlockDoubledKeyEvents(keycode))
600 Key_Event(keycode, event.key.keysym.unicode, (event.key.state == SDL_PRESSED));
602 case SDL_ACTIVEEVENT:
603 if( event.active.state & SDL_APPACTIVE )
605 if( event.active.gain )
611 case SDL_MOUSEBUTTONDOWN:
612 case SDL_MOUSEBUTTONUP:
613 if (event.button.button <= 18)
614 Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
616 case SDL_JOYBUTTONDOWN:
617 if (!joy_enable.integer)
618 break; // ignore down events if joystick has been disabled
619 case SDL_JOYBUTTONUP:
620 if (event.jbutton.button < 48)
621 Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
623 case SDL_VIDEORESIZE:
624 if(vid_resizable.integer < 2)
626 vid.width = event.resize.w;
627 vid.height = event.resize.h;
628 SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
631 SDL_FreeSurface(vid_softsurface);
632 vid_softsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, vid.width, vid.height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
633 vid.softpixels = (unsigned int *)vid_softsurface->pixels;
634 SDL_SetAlpha(vid_softsurface, 0, 255);
635 if (vid.softdepthpixels)
636 free(vid.softdepthpixels);
637 vid.softdepthpixels = (unsigned int*)calloc(1, vid.width * vid.height * 4);
640 // better not call R_Modules_Restart from here directly, as this may wreak havoc...
641 // so, let's better queue it for next frame
642 if(!sdl_needs_restart)
644 Cbuf_AddText("\nr_restart\n");
645 sdl_needs_restart = true;
652 // enable/disable sound on focus gain/loss
653 if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
666 sound_active = false;
675 void *GL_GetProcAddress(const char *name)
678 p = SDL_GL_GetProcAddress(name);
682 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
683 static int Sys_EventFilter( SDL_Event *event );
685 static qboolean vid_sdl_initjoysticksystem = false;
691 Cvar_RegisterVariable(&apple_mouse_noaccel);
694 Cvar_RegisterVariable(&vid_soft);
695 Cvar_RegisterVariable(&joy_detected);
696 Cvar_RegisterVariable(&joy_enable);
697 Cvar_RegisterVariable(&joy_index);
698 Cvar_RegisterVariable(&joy_axisforward);
699 Cvar_RegisterVariable(&joy_axisside);
700 Cvar_RegisterVariable(&joy_axisup);
701 Cvar_RegisterVariable(&joy_axispitch);
702 Cvar_RegisterVariable(&joy_axisyaw);
703 //Cvar_RegisterVariable(&joy_axisroll);
704 Cvar_RegisterVariable(&joy_deadzoneforward);
705 Cvar_RegisterVariable(&joy_deadzoneside);
706 Cvar_RegisterVariable(&joy_deadzoneup);
707 Cvar_RegisterVariable(&joy_deadzonepitch);
708 Cvar_RegisterVariable(&joy_deadzoneyaw);
709 //Cvar_RegisterVariable(&joy_deadzoneroll);
710 Cvar_RegisterVariable(&joy_sensitivityforward);
711 Cvar_RegisterVariable(&joy_sensitivityside);
712 Cvar_RegisterVariable(&joy_sensitivityup);
713 Cvar_RegisterVariable(&joy_sensitivitypitch);
714 Cvar_RegisterVariable(&joy_sensitivityyaw);
715 //Cvar_RegisterVariable(&joy_sensitivityroll);
716 Cvar_RegisterVariable(&joy_axiskeyevents);
719 R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap, NULL, NULL);
722 if (SDL_Init(SDL_INIT_VIDEO) < 0)
723 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
724 vid_sdl_initjoysticksystem = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0;
725 if (vid_sdl_initjoysticksystem)
726 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
727 vid_isfullscreen = false;
730 // set the icon (we dont use SDL here since it would be too much a PITA)
732 #include "resource.h"
733 #include <SDL_syswm.h>
734 static void VID_SetCaption(void)
740 SDL_WM_SetCaption( gamename, NULL );
742 // get the HWND handle
743 SDL_VERSION( &info.version );
744 if( !SDL_GetWMInfo( &info ) )
747 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
748 #ifndef _W64 //If Windows 64bit data types don't exist
749 #ifndef SetClassLongPtr
750 #define SetClassLongPtr SetClassLong
753 #define GCLP_HICON GCL_HICON
756 #define LONG_PTR LONG
759 SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
761 static void VID_SetIcon_Pre(void)
764 static void VID_SetIcon_Post(void)
768 // Adding the OS independent XPM version --blub
769 #include "darkplaces.xpm"
770 #include "nexuiz.xpm"
771 static SDL_Surface *icon = NULL;
772 static void VID_SetIcon_Pre(void)
775 * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
776 * default settings with less than 91 colors and transparency.
779 int width, height, colors, isize, i, j;
781 static SDL_Color palette[256];
782 unsigned short palenc[256]; // store color id by char
785 const SDL_version *version;
787 version = SDL_Linked_Version();
788 // only use non-XPM icon support in SDL v1.3 and higher
789 // SDL v1.2 does not support "smooth" transparency, and thus is better
791 if(version->major >= 2 || (version->major == 1 && version->minor >= 3))
793 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
796 unsigned int red = 0x00FF0000;
797 unsigned int green = 0x0000FF00;
798 unsigned int blue = 0x000000FF;
799 unsigned int alpha = 0xFF000000;
801 height = image_height;
803 // reallocate with malloc, as this is in tempmempool (do not want)
805 data = malloc(width * height * 4);
806 memcpy(data, xpm, width * height * 4);
810 icon = SDL_CreateRGBSurface(SDL_SRCALPHA, width, height, 32, LittleLong(red), LittleLong(green), LittleLong(blue), LittleLong(alpha));
813 Con_Printf( "Failed to create surface for the window Icon!\n"
814 "%s\n", SDL_GetError());
823 // we only get here if non-XPM icon was missing, or SDL version is not
824 // sufficient for transparent non-XPM icons
827 xpm = (char *) FS_LoadFile("darkplaces-icon.xpm", tempmempool, false, NULL);
830 idata = XPM_DecodeString(xpm);
838 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) != 4)
840 // NOTE: Only 1-char colornames are supported
841 Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
847 // NOTE: Only 1-char colornames are supported
848 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
852 for(i = 0; i < colors; ++i)
854 unsigned int r, g, b;
857 if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
860 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
862 Con_Printf("This XPM's palette looks odd. Can't continue.\n");
867 palette[i].r = 255; // color key
870 thenone = i; // weeeee
875 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
880 palenc[(unsigned char) idx] = i;
883 // allocate the image data
884 data = (char*) malloc(width*height);
886 for(j = 0; j < height; ++j)
888 for(i = 0; i < width; ++i)
890 // casting to the safest possible datatypes ^^
891 data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
897 // SDL_FreeSurface should free the data too
898 // but for completeness' sake...
899 if(icon->flags & SDL_PREALLOC)
902 icon->pixels = NULL; // safety
904 SDL_FreeSurface(icon);
907 icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
908 // 8 bit surfaces get an empty palette allocated according to the docs
909 // so it's a palette image for sure :) no endian check necessary for the mask
912 Con_Printf( "Failed to create surface for the window Icon!\n"
913 "%s\n", SDL_GetError());
919 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
920 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
923 SDL_WM_SetIcon(icon, NULL);
925 static void VID_SetIcon_Post(void)
927 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
928 // LordHavoc: info.info.x11.lock_func and accompanying code do not seem to compile with SDL 1.3
929 #if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
932 const SDL_version *version;
934 version = SDL_Linked_Version();
935 // only use non-XPM icon support in SDL v1.3 and higher
936 // SDL v1.2 does not support "smooth" transparency, and thus is better
938 if(!(version->major >= 2 || (version->major == 1 && version->minor >= 3)))
940 // in this case, we did not set the good icon yet
942 SDL_VERSION(&info.version);
943 if(SDL_GetWMInfo(&info) == 1 && info.subsystem == SDL_SYSWM_X11)
945 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
948 // use _NET_WM_ICON too
949 static long netwm_icon[MAX_NETWM_ICON];
955 if(pos + 2 * image_width * image_height < MAX_NETWM_ICON)
957 netwm_icon[pos++] = image_width;
958 netwm_icon[pos++] = image_height;
959 for(i = 0; i < image_height; ++i)
960 for(j = 0; j < image_width; ++j)
961 netwm_icon[pos++] = BuffLittleLong((unsigned char *) &data[(i*image_width+j)*4]);
965 Con_Printf("Skipping NETWM icon #%d because there is no space left\n", i);
969 data = (char *) loadimagepixelsbgra(va("darkplaces-icon%d", i), false, false, false, NULL);
972 info.info.x11.lock_func();
974 Atom net_wm_icon = XInternAtom(info.info.x11.display, "_NET_WM_ICON", false);
975 XChangeProperty(info.info.x11.display, info.info.x11.wmwindow, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos);
977 info.info.x11.unlock_func();
986 static void VID_SetCaption(void)
988 SDL_WM_SetCaption( gamename, NULL );
992 static void VID_OutputVersion(void)
994 const SDL_version *version;
995 version = SDL_Linked_Version();
996 Con_Printf( "Linked against SDL version %d.%d.%d\n"
997 "Using SDL library version %d.%d.%d\n",
998 SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
999 version->major, version->minor, version->patch );
1002 qboolean VID_InitModeGL(viddef_mode_t *mode)
1005 // FIXME SDL_SetVideoMode
1006 static int notfirstvideomode = false;
1007 int flags = SDL_OPENGL;
1008 const char *drivername;
1010 win_half_width = mode->width>>1;
1011 win_half_height = mode->height>>1;
1013 if(vid_resizable.integer)
1014 flags |= SDL_RESIZABLE;
1016 VID_OutputVersion();
1020 We cant switch from one OpenGL video mode to another.
1021 Thus we first switch to some stupid 2D mode and then back to OpenGL.
1023 if (notfirstvideomode)
1024 SDL_SetVideoMode( 0, 0, 0, 0 );
1025 notfirstvideomode = true;
1027 // SDL usually knows best
1030 // 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
1031 i = COM_CheckParm("-gl_driver");
1032 if (i && i < com_argc - 1)
1033 drivername = com_argv[i + 1];
1034 if (SDL_GL_LoadLibrary(drivername) < 0)
1036 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
1040 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
1043 Con_Print("Required OpenGL function glGetString not found\n");
1047 // Knghtbrd: should do platform-specific extension string function here
1049 vid_isfullscreen = false;
1050 if (mode->fullscreen) {
1051 flags |= SDL_FULLSCREEN;
1052 vid_isfullscreen = true;
1054 //flags |= SDL_HWSURFACE;
1056 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
1057 if (mode->bitsperpixel >= 32)
1059 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
1060 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
1061 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
1062 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
1063 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
1064 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
1068 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
1069 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
1070 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
1071 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
1073 if (mode->stereobuffer)
1074 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
1075 if (mode->samples > 1)
1077 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
1078 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples);
1080 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1081 if (vid_vsync.integer)
1082 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
1084 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
1086 // TODO: SDL_GL_CONTEXT_MAJOR_VERSION, SDL_GL_CONTEXT_MINOR_VERSION
1089 video_bpp = mode->bitsperpixel;
1090 video_flags = flags;
1092 screen = SDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
1097 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
1102 vid_softsurface = NULL;
1103 vid.softpixels = NULL;
1107 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1108 // set up an event filter to ask confirmation on close button in WIN32
1109 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
1112 SDL_EnableUNICODE( SDL_ENABLE );
1113 // enable key repeat since everyone expects it
1114 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1116 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
1117 SDL_GL_SetSwapInterval(vid_vsync.integer != 0);
1118 vid_usingvsync = (vid_vsync.integer != 0);
1121 gl_platform = "SDL";
1122 gl_platformextensions = "";
1126 vid_numjoysticks = SDL_NumJoysticks();
1127 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
1128 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
1129 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
1130 memset(vid_joysticks, 0, sizeof(vid_joysticks));
1131 for (i = 0;i < vid_numjoysticks;i++)
1134 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
1137 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
1140 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));
1144 vid_activewindow = false;
1145 vid_usingmouse = false;
1146 vid_usinghidecursor = false;
1148 SDL_WM_GrabInput(SDL_GRAB_OFF);
1152 extern cvar_t gl_info_extensions;
1153 extern cvar_t gl_info_vendor;
1154 extern cvar_t gl_info_renderer;
1155 extern cvar_t gl_info_version;
1156 extern cvar_t gl_info_platform;
1157 extern cvar_t gl_info_driver;
1159 qboolean VID_InitModeSoft(viddef_mode_t *mode)
1161 // FIXME SDL_SetVideoMode
1163 int flags = SDL_HWSURFACE;
1165 win_half_width = mode->width>>1;
1166 win_half_height = mode->height>>1;
1168 if(vid_resizable.integer)
1169 flags |= SDL_RESIZABLE;
1171 VID_OutputVersion();
1173 vid_isfullscreen = false;
1174 if (mode->fullscreen) {
1175 flags |= SDL_FULLSCREEN;
1176 vid_isfullscreen = true;
1179 video_bpp = mode->bitsperpixel;
1180 video_flags = flags;
1182 screen = SDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
1187 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
1192 // create a framebuffer using our specific color format, we let the SDL blit function convert it in VID_Finish
1193 vid_softsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, mode->width, mode->height, 32, 0x00FF0000, 0x0000FF00, 0x00000000FF, 0xFF000000);
1194 if (vid_softsurface == NULL)
1196 Con_Printf("Failed to setup software rasterizer framebuffer %ix%ix32bpp: %s\n", mode->width, mode->height, SDL_GetError());
1200 SDL_SetAlpha(vid_softsurface, 0, 255);
1202 vid.softpixels = (unsigned int *)vid_softsurface->pixels;
1203 vid.softdepthpixels = (unsigned int *)calloc(1, mode->width * mode->height * 4);
1204 DPSOFTRAST_Init(mode->width, mode->height, (unsigned int *)vid_softsurface->pixels, (unsigned int *)vid.softdepthpixels);
1208 // set up an event filter to ask confirmation on close button in WIN32
1209 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1210 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
1213 SDL_EnableUNICODE( SDL_ENABLE );
1214 // enable key repeat since everyone expects it
1215 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1217 gl_platform = "SDLSoft";
1218 gl_platformextensions = "";
1220 gl_renderer = "DarkPlaces-Soft";
1221 gl_vendor = "Forest Hale";
1225 // clear the extension flags
1226 memset(&vid.support, 0, sizeof(vid.support));
1227 Cvar_SetQuick(&gl_info_extensions, "");
1229 vid.forcevbo = false;
1230 vid.support.arb_depth_texture = true;
1231 vid.support.arb_draw_buffers = true;
1232 vid.support.arb_occlusion_query = true;
1233 vid.support.arb_shadow = true;
1234 //vid.support.arb_texture_compression = true;
1235 vid.support.arb_texture_cube_map = true;
1236 vid.support.arb_texture_non_power_of_two = false;
1237 vid.support.arb_vertex_buffer_object = true;
1238 vid.support.ext_blend_subtract = true;
1239 vid.support.ext_draw_range_elements = true;
1240 vid.support.ext_framebuffer_object = true;
1241 vid.support.ext_texture_3d = true;
1242 //vid.support.ext_texture_compression_s3tc = true;
1243 vid.support.ext_texture_filter_anisotropic = true;
1244 vid.support.ati_separate_stencil = true;
1246 vid.maxtexturesize_2d = 16384;
1247 vid.maxtexturesize_3d = 512;
1248 vid.maxtexturesize_cubemap = 16384;
1250 vid.teximageunits = 32;
1251 vid.texarrayunits = 8;
1252 vid.max_anisotropy = 1;
1253 vid.maxdrawbuffers = 4;
1255 vid.texunits = bound(4, vid.texunits, MAX_TEXTUREUNITS);
1256 vid.teximageunits = bound(16, vid.teximageunits, MAX_TEXTUREUNITS);
1257 vid.texarrayunits = bound(8, vid.texarrayunits, MAX_TEXTUREUNITS);
1258 Con_DPrintf("Using DarkPlaces Software Rasterizer rendering path\n");
1259 vid.renderpath = RENDERPATH_SOFT;
1260 vid.useinterleavedarrays = false;
1262 Cvar_SetQuick(&gl_info_vendor, gl_vendor);
1263 Cvar_SetQuick(&gl_info_renderer, gl_renderer);
1264 Cvar_SetQuick(&gl_info_version, gl_version);
1265 Cvar_SetQuick(&gl_info_platform, gl_platform ? gl_platform : "");
1266 Cvar_SetQuick(&gl_info_driver, gl_driver);
1268 // LordHavoc: report supported extensions
1269 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1271 // clear to black (loading plaque will be seen over this)
1272 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
1274 vid_numjoysticks = SDL_NumJoysticks();
1275 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
1276 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
1277 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
1278 memset(vid_joysticks, 0, sizeof(vid_joysticks));
1279 for (i = 0;i < vid_numjoysticks;i++)
1282 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
1285 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
1288 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));
1292 vid_activewindow = false;
1293 vid_usingmouse = false;
1294 vid_usinghidecursor = false;
1296 SDL_WM_GrabInput(SDL_GRAB_OFF);
1300 qboolean VID_InitMode(viddef_mode_t *mode)
1302 if (!SDL_WasInit(SDL_INIT_VIDEO) && SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
1303 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
1305 if (vid_soft.integer)
1306 return VID_InitModeSoft(mode);
1309 return VID_InitModeGL(mode);
1312 void VID_Shutdown (void)
1314 VID_SetMouse(false, false, false);
1315 VID_RestoreSystemGamma();
1319 SDL_FreeSurface(icon);
1323 if (vid_softsurface)
1324 SDL_FreeSurface(vid_softsurface);
1325 vid_softsurface = NULL;
1326 vid.softpixels = NULL;
1327 if (vid.softdepthpixels)
1328 free(vid.softdepthpixels);
1329 vid.softdepthpixels = NULL;
1331 SDL_QuitSubSystem(SDL_INIT_VIDEO);
1336 gl_platformextensions = "";
1339 int VID_SetGamma (unsigned short *ramps, int rampsize)
1341 return !SDL_SetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
1344 int VID_GetGamma (unsigned short *ramps, int rampsize)
1346 return !SDL_GetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
1349 void VID_Finish (void)
1353 //react on appstate changes
1354 appstate = SDL_GetAppState();
1356 vid_hidden = !(appstate & SDL_APPACTIVE);
1358 if( vid_hidden || !( appstate & SDL_APPMOUSEFOCUS ) || !( appstate & SDL_APPINPUTFOCUS ) )
1359 vid_activewindow = false;
1361 vid_activewindow = true;
1363 VID_UpdateGamma(false, 256);
1367 switch(vid.renderpath)
1369 case RENDERPATH_GL11:
1370 case RENDERPATH_GL13:
1371 case RENDERPATH_GL20:
1372 case RENDERPATH_CGGL:
1374 if (r_speeds.integer == 2 || gl_finish.integer)
1376 qglFinish();CHECKGLERROR
1378 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
1380 qboolean vid_usevsync;
1381 vid_usevsync = (vid_vsync.integer && !cls.timedemo);
1382 if (vid_usingvsync != vid_usevsync)
1384 if (SDL_GL_SetSwapInterval(vid_usevsync != 0) >= 0)
1385 Con_DPrintf("Vsync %s\n", vid_usevsync ? "activated" : "deactivated");
1387 Con_DPrintf("ERROR: can't %s vsync\n", vid_usevsync ? "activate" : "deactivate");
1391 SDL_GL_SwapBuffers();
1393 case RENDERPATH_SOFT:
1394 SDL_BlitSurface(vid_softsurface, NULL, screen, NULL);
1397 case RENDERPATH_D3D9:
1398 case RENDERPATH_D3D10:
1399 case RENDERPATH_D3D11:
1405 size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
1408 SDL_Rect **vidmodes;
1409 int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
1412 for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); *vidmodes; ++vidmodes)
1416 modes[k].width = (*vidmodes)->w;
1417 modes[k].height = (*vidmodes)->h;
1419 modes[k].refreshrate = 60; // no support for refresh rate in SDL
1420 modes[k].pixelheight_num = 1;
1421 modes[k].pixelheight_denom = 1; // SDL does not provide this