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 vid_soft_threads = {CVAR_SAVE, "vid_soft_threads", "1", "the number of threads the DarkPlaces Software Rasterizer should use"};
71 cvar_t joy_detected = {CVAR_READONLY, "joy_detected", "0", "number of joysticks detected by engine"};
72 cvar_t joy_enable = {CVAR_SAVE, "joy_enable", "0", "enables joystick support"};
73 cvar_t joy_index = {0, "joy_index", "0", "selects which joystick to use if you have multiple"};
74 cvar_t joy_axisforward = {0, "joy_axisforward", "1", "which joystick axis to query for forward/backward movement"};
75 cvar_t joy_axisside = {0, "joy_axisside", "0", "which joystick axis to query for right/left movement"};
76 cvar_t joy_axisup = {0, "joy_axisup", "-1", "which joystick axis to query for up/down movement"};
77 cvar_t joy_axispitch = {0, "joy_axispitch", "3", "which joystick axis to query for looking up/down"};
78 cvar_t joy_axisyaw = {0, "joy_axisyaw", "2", "which joystick axis to query for looking right/left"};
79 cvar_t joy_axisroll = {0, "joy_axisroll", "-1", "which joystick axis to query for tilting head right/left"};
80 cvar_t joy_deadzoneforward = {0, "joy_deadzoneforward", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
81 cvar_t joy_deadzoneside = {0, "joy_deadzoneside", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
82 cvar_t joy_deadzoneup = {0, "joy_deadzoneup", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
83 cvar_t joy_deadzonepitch = {0, "joy_deadzonepitch", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
84 cvar_t joy_deadzoneyaw = {0, "joy_deadzoneyaw", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
85 cvar_t joy_deadzoneroll = {0, "joy_deadzoneroll", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
86 cvar_t joy_sensitivityforward = {0, "joy_sensitivityforward", "-1", "movement multiplier"};
87 cvar_t joy_sensitivityside = {0, "joy_sensitivityside", "1", "movement multiplier"};
88 cvar_t joy_sensitivityup = {0, "joy_sensitivityup", "1", "movement multiplier"};
89 cvar_t joy_sensitivitypitch = {0, "joy_sensitivitypitch", "1", "movement multiplier"};
90 cvar_t joy_sensitivityyaw = {0, "joy_sensitivityyaw", "-1", "movement multiplier"};
91 cvar_t joy_sensitivityroll = {0, "joy_sensitivityroll", "1", "movement multiplier"};
92 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"};
94 static qboolean vid_usingmouse = false;
95 static qboolean vid_usinghidecursor = false;
96 static qboolean vid_isfullscreen;
97 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
98 static qboolean vid_usingvsync = false;
100 static int vid_numjoysticks = 0;
101 #define MAX_JOYSTICKS 8
102 static SDL_Joystick *vid_joysticks[MAX_JOYSTICKS];
104 static int win_half_width = 50;
105 static int win_half_height = 50;
106 static int video_bpp, video_flags;
108 static SDL_Surface *screen;
109 static SDL_Surface *vid_softsurface;
111 // joystick axes state
112 #define MAX_JOYSTICK_AXES 16
119 static joy_axiscache_t joy_axescache[MAX_JOYSTICK_AXES];
121 /////////////////////////
124 //TODO: Add joystick support
125 //TODO: Add error checking
128 //keysym to quake keysym mapping
129 #define tenoh 0,0,0,0,0, 0,0,0,0,0
130 #define fiftyoh tenoh, tenoh, tenoh, tenoh, tenoh
131 #define hundredoh fiftyoh, fiftyoh
132 static unsigned int tbl_sdltoquake[] =
134 0,0,0,0, //SDLK_UNKNOWN = 0,
135 0,0,0,0, //SDLK_FIRST = 0,
136 K_BACKSPACE, //SDLK_BACKSPACE = 8,
137 K_TAB, //SDLK_TAB = 9,
139 0, //SDLK_CLEAR = 12,
140 K_ENTER, //SDLK_RETURN = 13,
142 K_PAUSE, //SDLK_PAUSE = 19,
144 K_ESCAPE, //SDLK_ESCAPE = 27,
146 K_SPACE, //SDLK_SPACE = 32,
147 '!', //SDLK_EXCLAIM = 33,
148 '"', //SDLK_QUOTEDBL = 34,
149 '#', //SDLK_HASH = 35,
150 '$', //SDLK_DOLLAR = 36,
152 '&', //SDLK_AMPERSAND = 38,
153 '\'', //SDLK_QUOTE = 39,
154 '(', //SDLK_LEFTPAREN = 40,
155 ')', //SDLK_RIGHTPAREN = 41,
156 '*', //SDLK_ASTERISK = 42,
157 '+', //SDLK_PLUS = 43,
158 ',', //SDLK_COMMA = 44,
159 '-', //SDLK_MINUS = 45,
160 '.', //SDLK_PERIOD = 46,
161 '/', //SDLK_SLASH = 47,
172 ':', //SDLK_COLON = 58,
173 ';', //SDLK_SEMICOLON = 59,
174 '<', //SDLK_LESS = 60,
175 '=', //SDLK_EQUALS = 61,
176 '>', //SDLK_GREATER = 62,
177 '?', //SDLK_QUESTION = 63,
179 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,
180 '[', //SDLK_LEFTBRACKET = 91,
181 '\\', //SDLK_BACKSLASH = 92,
182 ']', //SDLK_RIGHTBRACKET = 93,
183 '^', //SDLK_CARET = 94,
184 '_', //SDLK_UNDERSCORE = 95,
185 '`', //SDLK_BACKQUOTE = 96,
213 K_DEL, //SDLK_DELETE = 127,
214 hundredoh /*227*/, tenoh, tenoh, 0,0,0,0,0,0,0,0,
215 K_KP_0, //SDLK_KP0 = 256,
216 K_KP_1, //SDLK_KP1 = 257,
217 K_KP_2, //SDLK_KP2 = 258,
218 K_KP_3, //SDLK_KP3 = 259,
219 K_KP_4, //SDLK_KP4 = 260,
220 K_KP_5, //SDLK_KP5 = 261,
221 K_KP_6, //SDLK_KP6 = 262,
222 K_KP_7, //SDLK_KP7 = 263,
223 K_KP_8, //SDLK_KP8 = 264,
224 K_KP_9, //SDLK_KP9 = 265,
225 K_KP_PERIOD,//SDLK_KP_PERIOD = 266,
226 K_KP_DIVIDE,//SDLK_KP_DIVIDE = 267,
227 K_KP_MULTIPLY,//SDLK_KP_MULTIPLY= 268,
228 K_KP_MINUS, //SDLK_KP_MINUS = 269,
229 K_KP_PLUS, //SDLK_KP_PLUS = 270,
230 K_KP_ENTER, //SDLK_KP_ENTER = 271,
231 K_KP_EQUALS,//SDLK_KP_EQUALS = 272,
232 K_UPARROW, //SDLK_UP = 273,
233 K_DOWNARROW,//SDLK_DOWN = 274,
234 K_RIGHTARROW,//SDLK_RIGHT = 275,
235 K_LEFTARROW,//SDLK_LEFT = 276,
236 K_INS, //SDLK_INSERT = 277,
237 K_HOME, //SDLK_HOME = 278,
238 K_END, //SDLK_END = 279,
239 K_PGUP, //SDLK_PAGEUP = 280,
240 K_PGDN, //SDLK_PAGEDOWN = 281,
241 K_F1, //SDLK_F1 = 282,
242 K_F2, //SDLK_F2 = 283,
243 K_F3, //SDLK_F3 = 284,
244 K_F4, //SDLK_F4 = 285,
245 K_F5, //SDLK_F5 = 286,
246 K_F6, //SDLK_F6 = 287,
247 K_F7, //SDLK_F7 = 288,
248 K_F8, //SDLK_F8 = 289,
249 K_F9, //SDLK_F9 = 290,
250 K_F10, //SDLK_F10 = 291,
251 K_F11, //SDLK_F11 = 292,
252 K_F12, //SDLK_F12 = 293,
257 K_NUMLOCK, //SDLK_NUMLOCK = 300,
258 K_CAPSLOCK, //SDLK_CAPSLOCK = 301,
259 K_SCROLLOCK,//SDLK_SCROLLOCK= 302,
260 K_SHIFT, //SDLK_RSHIFT = 303,
261 K_SHIFT, //SDLK_LSHIFT = 304,
262 K_CTRL, //SDLK_RCTRL = 305,
263 K_CTRL, //SDLK_LCTRL = 306,
264 K_ALT, //SDLK_RALT = 307,
265 K_ALT, //SDLK_LALT = 308,
266 0, //SDLK_RMETA = 309,
267 0, //SDLK_LMETA = 310,
268 0, //SDLK_LSUPER = 311, /* Left "Windows" key */
269 0, //SDLK_RSUPER = 312, /* Right "Windows" key */
270 K_ALT, //SDLK_MODE = 313, /* "Alt Gr" key */
271 0, //SDLK_COMPOSE = 314, /* Multi-key compose key */
272 0, //SDLK_HELP = 315,
273 0, //SDLK_PRINT = 316,
274 0, //SDLK_SYSREQ = 317,
275 K_PAUSE, //SDLK_BREAK = 318,
276 0, //SDLK_MENU = 319,
277 0, //SDLK_POWER = 320, /* Power Macintosh power key */
278 'e', //SDLK_EURO = 321, /* Some european keyboards */
279 0 //SDLK_UNDO = 322, /* Atari keyboard has Undo */
285 static int MapKey( unsigned int sdlkey )
287 if( sdlkey > sizeof(tbl_sdltoquake)/ sizeof(int) )
289 return tbl_sdltoquake[ sdlkey ];
292 void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor)
297 if(vid_usingmouse && (vid_usingnoaccel != !!apple_mouse_noaccel.integer))
298 VID_SetMouse(false, false, false); // ungrab first!
301 if (vid_usingmouse != relative)
303 vid_usingmouse = relative;
304 cl_ignoremousemoves = 2;
305 SDL_WM_GrabInput( relative ? SDL_GRAB_ON : SDL_GRAB_OFF );
310 // Save the status of mouse acceleration
311 originalMouseSpeed = -1.0; // in case of error
312 if(apple_mouse_noaccel.integer)
314 io_connect_t mouseDev = IN_GetIOHandle();
317 if(IOHIDGetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), &originalMouseSpeed) == kIOReturnSuccess)
319 Con_DPrintf("previous mouse acceleration: %f\n", originalMouseSpeed);
320 if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), -1.0) != kIOReturnSuccess)
322 Con_Print("Could not disable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
323 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
328 Con_Print("Could not disable mouse acceleration (failed at IOHIDGetAccelerationWithKey).\n");
329 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
331 IOServiceClose(mouseDev);
335 Con_Print("Could not disable mouse acceleration (failed at IO_GetIOHandle).\n");
336 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
340 vid_usingnoaccel = !!apple_mouse_noaccel.integer;
344 if(originalMouseSpeed != -1.0)
346 io_connect_t mouseDev = IN_GetIOHandle();
349 Con_DPrintf("restoring mouse acceleration to: %f\n", originalMouseSpeed);
350 if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), originalMouseSpeed) != kIOReturnSuccess)
351 Con_Print("Could not re-enable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
352 IOServiceClose(mouseDev);
355 Con_Print("Could not re-enable mouse acceleration (failed at IO_GetIOHandle).\n");
361 if (vid_usinghidecursor != hidecursor)
363 vid_usinghidecursor = hidecursor;
364 SDL_ShowCursor( hidecursor ? SDL_DISABLE : SDL_ENABLE);
368 static double IN_JoystickGetAxis(SDL_Joystick *joy, int axis, double sensitivity, double deadzone)
371 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
372 return 0; // no such axis on this joystick
373 value = SDL_JoystickGetAxis(joy, axis) * (1.0 / 32767.0);
374 value = bound(-1, value, 1);
375 if (fabs(value) < deadzone)
376 return 0; // within deadzone around center
377 return value * sensitivity;
380 /////////////////////
381 // Joystick axis keyevents
382 // a sort of hack emulating Arrow keys for joystick axises
383 // as some drives dont send such keyevents for them
384 // additionally we should block drivers that do send arrow keyevents to prevent double events
387 static void IN_JoystickKeyeventForAxis(SDL_Joystick *joy, int axis, int key_pos, int key_neg)
391 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
392 return; // no such axis on this joystick
394 joytime = Sys_DoubleTime();
395 // no key event, continuous keydown event
396 if (joy_axescache[axis].move == joy_axescache[axis].oldmove)
398 if (joy_axescache[axis].move != 0 && joytime > joy_axescache[axis].keytime)
400 //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
401 Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
402 joy_axescache[axis].keytime = joytime + 0.5 / 20;
406 // generate key up event
407 if (joy_axescache[axis].oldmove)
409 //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg), 1, cl.time);
410 Key_Event((joy_axescache[axis].oldmove > 0) ? key_pos : key_neg, 0, 0);
412 // generate key down event
413 if (joy_axescache[axis].move)
415 //Con_Printf("joy %s %i %f\n", Key_KeynumToString((joy_axescache[axis].move > 0) ? key_pos : key_neg), 1, cl.time);
416 Key_Event((joy_axescache[axis].move > 0) ? key_pos : key_neg, 0, 1);
417 joy_axescache[axis].keytime = joytime + 0.5;
421 static qboolean IN_JoystickBlockDoubledKeyEvents(int keycode)
423 if (!joy_axiskeyevents.integer)
426 // block keyevent if it's going to be provided by joystick keyevent system
427 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
429 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
431 if (keycode == K_UPARROW || keycode == K_DOWNARROW)
432 if (IN_JoystickGetAxis(joy, joy_axisforward.integer, 1, 0.01) || joy_axescache[joy_axisforward.integer].move || joy_axescache[joy_axisforward.integer].oldmove)
434 if (keycode == K_RIGHTARROW || keycode == K_LEFTARROW)
435 if (IN_JoystickGetAxis(joy, joy_axisside.integer, 1, 0.01) || joy_axescache[joy_axisside.integer].move || joy_axescache[joy_axisside.integer].oldmove)
442 /////////////////////
449 static int old_x = 0, old_y = 0;
450 static int stuck = 0;
451 int x, y, numaxes, numballs;
455 if(vid_stick_mouse.integer)
457 // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
458 // window grabbing. --blub
460 // we need 2 frames to initialize the center position
463 SDL_WarpMouse(win_half_width, win_half_height);
464 SDL_GetMouseState(&x, &y);
465 SDL_GetRelativeMouseState(&x, &y);
468 SDL_GetRelativeMouseState(&x, &y);
469 in_mouse_x = x + old_x;
470 in_mouse_y = y + old_y;
471 SDL_GetMouseState(&x, &y);
472 old_x = x - win_half_width;
473 old_y = y - win_half_height;
474 SDL_WarpMouse(win_half_width, win_half_height);
477 SDL_GetRelativeMouseState( &x, &y );
483 SDL_GetMouseState(&x, &y);
484 in_windowmouse_x = x;
485 in_windowmouse_y = y;
487 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
489 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
491 // balls convert to mousemove
492 numballs = SDL_JoystickNumBalls(joy);
493 for (j = 0;j < numballs;j++)
495 SDL_JoystickGetBall(joy, j, &x, &y);
501 cl.cmd.forwardmove += IN_JoystickGetAxis(joy, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
502 cl.cmd.sidemove += IN_JoystickGetAxis(joy, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
503 cl.cmd.upmove += IN_JoystickGetAxis(joy, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
504 cl.viewangles[0] += IN_JoystickGetAxis(joy, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
505 cl.viewangles[1] += IN_JoystickGetAxis(joy, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
506 //cl.viewangles[2] += IN_JoystickGetAxis(joy, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
508 // cache state of axes to emulate button events for them
509 numaxes = min(MAX_JOYSTICK_AXES, SDL_JoystickNumAxes(joy));
510 for (j = 0; j < numaxes; j++)
512 joy_axescache[j].oldmove = joy_axescache[j].move;
513 joy_axescache[j].move = IN_JoystickGetAxis(joy, j, 1, 0.01);
517 if (joy_axiskeyevents.integer)
519 IN_JoystickKeyeventForAxis(joy, joy_axisforward.integer, K_DOWNARROW, K_UPARROW);
520 IN_JoystickKeyeventForAxis(joy, joy_axisside.integer, K_RIGHTARROW, K_LEFTARROW);
525 /////////////////////
529 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
530 static int Sys_EventFilter( SDL_Event *event )
532 //TODO: Add a quit query in linux, too - though linux user are more likely to know what they do
533 if (event->type == SDL_QUIT)
536 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
545 static qboolean sdl_needs_restart;
546 static void sdl_start(void)
549 static void sdl_shutdown(void)
551 sdl_needs_restart = false;
553 static void sdl_newmap(void)
558 static keynum_t buttonremap[18] =
580 void Sys_SendKeyEvents( void )
582 static qboolean sound_active = true;
586 while( SDL_PollEvent( &event ) )
587 switch( event.type ) {
589 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
591 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
599 keycode = MapKey(event.key.keysym.sym);
600 if (!IN_JoystickBlockDoubledKeyEvents(keycode))
601 Key_Event(keycode, event.key.keysym.unicode, (event.key.state == SDL_PRESSED));
603 case SDL_ACTIVEEVENT:
604 if( event.active.state & SDL_APPACTIVE )
606 if( event.active.gain )
612 case SDL_MOUSEBUTTONDOWN:
613 case SDL_MOUSEBUTTONUP:
614 if (event.button.button <= 18)
615 Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
617 case SDL_JOYBUTTONDOWN:
618 if (!joy_enable.integer)
619 break; // ignore down events if joystick has been disabled
620 case SDL_JOYBUTTONUP:
621 if (event.jbutton.button < 48)
622 Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
624 case SDL_VIDEORESIZE:
625 if(vid_resizable.integer < 2)
627 vid.width = event.resize.w;
628 vid.height = event.resize.h;
629 SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
632 SDL_FreeSurface(vid_softsurface);
633 vid_softsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, vid.width, vid.height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
634 vid.softpixels = (unsigned int *)vid_softsurface->pixels;
635 SDL_SetAlpha(vid_softsurface, 0, 255);
636 if (vid.softdepthpixels)
637 free(vid.softdepthpixels);
638 vid.softdepthpixels = (unsigned int*)calloc(1, vid.width * vid.height * 4);
641 // better not call R_Modules_Restart from here directly, as this may wreak havoc...
642 // so, let's better queue it for next frame
643 if(!sdl_needs_restart)
645 Cbuf_AddText("\nr_restart\n");
646 sdl_needs_restart = true;
653 // enable/disable sound on focus gain/loss
654 if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
667 sound_active = false;
676 void *GL_GetProcAddress(const char *name)
679 p = SDL_GL_GetProcAddress(name);
683 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
684 static int Sys_EventFilter( SDL_Event *event );
686 static qboolean vid_sdl_initjoysticksystem = false;
692 Cvar_RegisterVariable(&apple_mouse_noaccel);
695 Cvar_RegisterVariable(&vid_soft);
696 Cvar_RegisterVariable(&vid_soft_threads);
697 Cvar_RegisterVariable(&joy_detected);
698 Cvar_RegisterVariable(&joy_enable);
699 Cvar_RegisterVariable(&joy_index);
700 Cvar_RegisterVariable(&joy_axisforward);
701 Cvar_RegisterVariable(&joy_axisside);
702 Cvar_RegisterVariable(&joy_axisup);
703 Cvar_RegisterVariable(&joy_axispitch);
704 Cvar_RegisterVariable(&joy_axisyaw);
705 //Cvar_RegisterVariable(&joy_axisroll);
706 Cvar_RegisterVariable(&joy_deadzoneforward);
707 Cvar_RegisterVariable(&joy_deadzoneside);
708 Cvar_RegisterVariable(&joy_deadzoneup);
709 Cvar_RegisterVariable(&joy_deadzonepitch);
710 Cvar_RegisterVariable(&joy_deadzoneyaw);
711 //Cvar_RegisterVariable(&joy_deadzoneroll);
712 Cvar_RegisterVariable(&joy_sensitivityforward);
713 Cvar_RegisterVariable(&joy_sensitivityside);
714 Cvar_RegisterVariable(&joy_sensitivityup);
715 Cvar_RegisterVariable(&joy_sensitivitypitch);
716 Cvar_RegisterVariable(&joy_sensitivityyaw);
717 //Cvar_RegisterVariable(&joy_sensitivityroll);
718 Cvar_RegisterVariable(&joy_axiskeyevents);
721 R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap, NULL, NULL);
724 if (SDL_Init(SDL_INIT_VIDEO) < 0)
725 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
726 vid_sdl_initjoysticksystem = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0;
727 if (vid_sdl_initjoysticksystem)
728 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
729 vid_isfullscreen = false;
732 // set the icon (we dont use SDL here since it would be too much a PITA)
734 #include "resource.h"
735 #include <SDL_syswm.h>
736 static void VID_SetCaption(void)
742 SDL_WM_SetCaption( gamename, NULL );
744 // get the HWND handle
745 SDL_VERSION( &info.version );
746 if( !SDL_GetWMInfo( &info ) )
749 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
750 #ifndef _W64 //If Windows 64bit data types don't exist
751 #ifndef SetClassLongPtr
752 #define SetClassLongPtr SetClassLong
755 #define GCLP_HICON GCL_HICON
758 #define LONG_PTR LONG
761 SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
763 static void VID_SetIcon_Pre(void)
766 static void VID_SetIcon_Post(void)
770 // Adding the OS independent XPM version --blub
771 #include "darkplaces.xpm"
772 #include "nexuiz.xpm"
773 static SDL_Surface *icon = NULL;
774 static void VID_SetIcon_Pre(void)
777 * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
778 * default settings with less than 91 colors and transparency.
781 int width, height, colors, isize, i, j;
783 static SDL_Color palette[256];
784 unsigned short palenc[256]; // store color id by char
787 const SDL_version *version;
789 version = SDL_Linked_Version();
790 // only use non-XPM icon support in SDL v1.3 and higher
791 // SDL v1.2 does not support "smooth" transparency, and thus is better
793 if(version->major >= 2 || (version->major == 1 && version->minor >= 3))
795 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
798 unsigned int red = 0x00FF0000;
799 unsigned int green = 0x0000FF00;
800 unsigned int blue = 0x000000FF;
801 unsigned int alpha = 0xFF000000;
803 height = image_height;
805 // reallocate with malloc, as this is in tempmempool (do not want)
807 data = malloc(width * height * 4);
808 memcpy(data, xpm, width * height * 4);
812 icon = SDL_CreateRGBSurface(SDL_SRCALPHA, width, height, 32, LittleLong(red), LittleLong(green), LittleLong(blue), LittleLong(alpha));
815 Con_Printf( "Failed to create surface for the window Icon!\n"
816 "%s\n", SDL_GetError());
825 // we only get here if non-XPM icon was missing, or SDL version is not
826 // sufficient for transparent non-XPM icons
829 xpm = (char *) FS_LoadFile("darkplaces-icon.xpm", tempmempool, false, NULL);
832 idata = XPM_DecodeString(xpm);
840 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) != 4)
842 // NOTE: Only 1-char colornames are supported
843 Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
849 // NOTE: Only 1-char colornames are supported
850 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
854 for(i = 0; i < colors; ++i)
856 unsigned int r, g, b;
859 if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
862 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
864 Con_Printf("This XPM's palette looks odd. Can't continue.\n");
869 palette[i].r = 255; // color key
872 thenone = i; // weeeee
877 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
882 palenc[(unsigned char) idx] = i;
885 // allocate the image data
886 data = (char*) malloc(width*height);
888 for(j = 0; j < height; ++j)
890 for(i = 0; i < width; ++i)
892 // casting to the safest possible datatypes ^^
893 data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
899 // SDL_FreeSurface should free the data too
900 // but for completeness' sake...
901 if(icon->flags & SDL_PREALLOC)
904 icon->pixels = NULL; // safety
906 SDL_FreeSurface(icon);
909 icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
910 // 8 bit surfaces get an empty palette allocated according to the docs
911 // so it's a palette image for sure :) no endian check necessary for the mask
914 Con_Printf( "Failed to create surface for the window Icon!\n"
915 "%s\n", SDL_GetError());
921 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
922 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
925 SDL_WM_SetIcon(icon, NULL);
927 static void VID_SetIcon_Post(void)
929 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
930 // LordHavoc: info.info.x11.lock_func and accompanying code do not seem to compile with SDL 1.3
931 #if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
934 const SDL_version *version;
936 version = SDL_Linked_Version();
937 // only use non-XPM icon support in SDL v1.3 and higher
938 // SDL v1.2 does not support "smooth" transparency, and thus is better
940 if(!(version->major >= 2 || (version->major == 1 && version->minor >= 3)))
942 // in this case, we did not set the good icon yet
944 SDL_VERSION(&info.version);
945 if(SDL_GetWMInfo(&info) == 1 && info.subsystem == SDL_SYSWM_X11)
947 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
950 // use _NET_WM_ICON too
951 static long netwm_icon[MAX_NETWM_ICON];
957 if(pos + 2 * image_width * image_height < MAX_NETWM_ICON)
959 netwm_icon[pos++] = image_width;
960 netwm_icon[pos++] = image_height;
961 for(i = 0; i < image_height; ++i)
962 for(j = 0; j < image_width; ++j)
963 netwm_icon[pos++] = BuffLittleLong((unsigned char *) &data[(i*image_width+j)*4]);
967 Con_Printf("Skipping NETWM icon #%d because there is no space left\n", i);
971 data = (char *) loadimagepixelsbgra(va("darkplaces-icon%d", i), false, false, false, NULL);
974 info.info.x11.lock_func();
976 Atom net_wm_icon = XInternAtom(info.info.x11.display, "_NET_WM_ICON", false);
977 XChangeProperty(info.info.x11.display, info.info.x11.wmwindow, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos);
979 info.info.x11.unlock_func();
988 static void VID_SetCaption(void)
990 SDL_WM_SetCaption( gamename, NULL );
994 static void VID_OutputVersion(void)
996 const SDL_version *version;
997 version = SDL_Linked_Version();
998 Con_Printf( "Linked against SDL version %d.%d.%d\n"
999 "Using SDL library version %d.%d.%d\n",
1000 SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
1001 version->major, version->minor, version->patch );
1004 qboolean VID_InitModeGL(viddef_mode_t *mode)
1007 // FIXME SDL_SetVideoMode
1008 static int notfirstvideomode = false;
1009 int flags = SDL_OPENGL;
1010 const char *drivername;
1012 win_half_width = mode->width>>1;
1013 win_half_height = mode->height>>1;
1015 if(vid_resizable.integer)
1016 flags |= SDL_RESIZABLE;
1018 VID_OutputVersion();
1022 We cant switch from one OpenGL video mode to another.
1023 Thus we first switch to some stupid 2D mode and then back to OpenGL.
1025 if (notfirstvideomode)
1026 SDL_SetVideoMode( 0, 0, 0, 0 );
1027 notfirstvideomode = true;
1029 // SDL usually knows best
1032 // 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
1033 i = COM_CheckParm("-gl_driver");
1034 if (i && i < com_argc - 1)
1035 drivername = com_argv[i + 1];
1036 if (SDL_GL_LoadLibrary(drivername) < 0)
1038 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
1042 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
1045 Con_Print("Required OpenGL function glGetString not found\n");
1049 // Knghtbrd: should do platform-specific extension string function here
1051 vid_isfullscreen = false;
1052 if (mode->fullscreen) {
1053 flags |= SDL_FULLSCREEN;
1054 vid_isfullscreen = true;
1056 //flags |= SDL_HWSURFACE;
1058 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
1059 if (mode->bitsperpixel >= 32)
1061 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
1062 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
1063 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
1064 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
1065 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
1066 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
1070 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
1071 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
1072 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
1073 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
1075 if (mode->stereobuffer)
1076 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
1077 if (mode->samples > 1)
1079 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
1080 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples);
1082 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1083 if (vid_vsync.integer)
1084 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
1086 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
1088 // TODO: SDL_GL_CONTEXT_MAJOR_VERSION, SDL_GL_CONTEXT_MINOR_VERSION
1091 video_bpp = mode->bitsperpixel;
1092 video_flags = flags;
1094 screen = SDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
1099 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
1104 vid_softsurface = NULL;
1105 vid.softpixels = NULL;
1109 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1110 // set up an event filter to ask confirmation on close button in WIN32
1111 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
1114 SDL_EnableUNICODE( SDL_ENABLE );
1115 // enable key repeat since everyone expects it
1116 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1118 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
1119 SDL_GL_SetSwapInterval(vid_vsync.integer != 0);
1120 vid_usingvsync = (vid_vsync.integer != 0);
1123 gl_platform = "SDL";
1124 gl_platformextensions = "";
1128 vid_numjoysticks = SDL_NumJoysticks();
1129 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
1130 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
1131 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
1132 memset(vid_joysticks, 0, sizeof(vid_joysticks));
1133 for (i = 0;i < vid_numjoysticks;i++)
1136 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
1139 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
1142 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));
1146 vid_activewindow = false;
1147 vid_usingmouse = false;
1148 vid_usinghidecursor = false;
1150 SDL_WM_GrabInput(SDL_GRAB_OFF);
1154 extern cvar_t gl_info_extensions;
1155 extern cvar_t gl_info_vendor;
1156 extern cvar_t gl_info_renderer;
1157 extern cvar_t gl_info_version;
1158 extern cvar_t gl_info_platform;
1159 extern cvar_t gl_info_driver;
1161 qboolean VID_InitModeSoft(viddef_mode_t *mode)
1163 // FIXME SDL_SetVideoMode
1165 int flags = SDL_HWSURFACE;
1167 win_half_width = mode->width>>1;
1168 win_half_height = mode->height>>1;
1170 if(vid_resizable.integer)
1171 flags |= SDL_RESIZABLE;
1173 VID_OutputVersion();
1175 vid_isfullscreen = false;
1176 if (mode->fullscreen) {
1177 flags |= SDL_FULLSCREEN;
1178 vid_isfullscreen = true;
1181 video_bpp = mode->bitsperpixel;
1182 video_flags = flags;
1184 screen = SDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
1189 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
1194 // create a framebuffer using our specific color format, we let the SDL blit function convert it in VID_Finish
1195 vid_softsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, mode->width, mode->height, 32, 0x00FF0000, 0x0000FF00, 0x00000000FF, 0xFF000000);
1196 if (vid_softsurface == NULL)
1198 Con_Printf("Failed to setup software rasterizer framebuffer %ix%ix32bpp: %s\n", mode->width, mode->height, SDL_GetError());
1202 SDL_SetAlpha(vid_softsurface, 0, 255);
1204 vid.softpixels = (unsigned int *)vid_softsurface->pixels;
1205 vid.softdepthpixels = (unsigned int *)calloc(1, mode->width * mode->height * 4);
1206 DPSOFTRAST_Init(mode->width, mode->height, vid_soft_threads.integer, (unsigned int *)vid_softsurface->pixels, (unsigned int *)vid.softdepthpixels);
1210 // set up an event filter to ask confirmation on close button in WIN32
1211 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1212 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
1215 SDL_EnableUNICODE( SDL_ENABLE );
1216 // enable key repeat since everyone expects it
1217 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1219 gl_platform = "SDLSoft";
1220 gl_platformextensions = "";
1222 gl_renderer = "DarkPlaces-Soft";
1223 gl_vendor = "Forest Hale";
1227 // clear the extension flags
1228 memset(&vid.support, 0, sizeof(vid.support));
1229 Cvar_SetQuick(&gl_info_extensions, "");
1231 vid.forcevbo = false;
1232 vid.support.arb_depth_texture = true;
1233 vid.support.arb_draw_buffers = true;
1234 vid.support.arb_occlusion_query = true;
1235 vid.support.arb_shadow = true;
1236 //vid.support.arb_texture_compression = true;
1237 vid.support.arb_texture_cube_map = true;
1238 vid.support.arb_texture_non_power_of_two = false;
1239 vid.support.arb_vertex_buffer_object = true;
1240 vid.support.ext_blend_subtract = true;
1241 vid.support.ext_draw_range_elements = true;
1242 vid.support.ext_framebuffer_object = true;
1243 vid.support.ext_texture_3d = true;
1244 //vid.support.ext_texture_compression_s3tc = true;
1245 vid.support.ext_texture_filter_anisotropic = true;
1246 vid.support.ati_separate_stencil = true;
1248 vid.maxtexturesize_2d = 16384;
1249 vid.maxtexturesize_3d = 512;
1250 vid.maxtexturesize_cubemap = 16384;
1252 vid.teximageunits = 32;
1253 vid.texarrayunits = 8;
1254 vid.max_anisotropy = 1;
1255 vid.maxdrawbuffers = 4;
1257 vid.texunits = bound(4, vid.texunits, MAX_TEXTUREUNITS);
1258 vid.teximageunits = bound(16, vid.teximageunits, MAX_TEXTUREUNITS);
1259 vid.texarrayunits = bound(8, vid.texarrayunits, MAX_TEXTUREUNITS);
1260 Con_DPrintf("Using DarkPlaces Software Rasterizer rendering path\n");
1261 vid.renderpath = RENDERPATH_SOFT;
1262 vid.useinterleavedarrays = false;
1264 Cvar_SetQuick(&gl_info_vendor, gl_vendor);
1265 Cvar_SetQuick(&gl_info_renderer, gl_renderer);
1266 Cvar_SetQuick(&gl_info_version, gl_version);
1267 Cvar_SetQuick(&gl_info_platform, gl_platform ? gl_platform : "");
1268 Cvar_SetQuick(&gl_info_driver, gl_driver);
1270 // LordHavoc: report supported extensions
1271 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1273 // clear to black (loading plaque will be seen over this)
1274 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
1276 vid_numjoysticks = SDL_NumJoysticks();
1277 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
1278 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
1279 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
1280 memset(vid_joysticks, 0, sizeof(vid_joysticks));
1281 for (i = 0;i < vid_numjoysticks;i++)
1284 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
1287 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
1290 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));
1294 vid_activewindow = false;
1295 vid_usingmouse = false;
1296 vid_usinghidecursor = false;
1298 SDL_WM_GrabInput(SDL_GRAB_OFF);
1302 qboolean VID_InitMode(viddef_mode_t *mode)
1304 if (!SDL_WasInit(SDL_INIT_VIDEO) && SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
1305 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
1307 if (vid_soft.integer)
1308 return VID_InitModeSoft(mode);
1311 return VID_InitModeGL(mode);
1314 void VID_Shutdown (void)
1316 VID_SetMouse(false, false, false);
1317 VID_RestoreSystemGamma();
1321 SDL_FreeSurface(icon);
1325 if (vid_softsurface)
1326 SDL_FreeSurface(vid_softsurface);
1327 vid_softsurface = NULL;
1328 vid.softpixels = NULL;
1329 if (vid.softdepthpixels)
1330 free(vid.softdepthpixels);
1331 vid.softdepthpixels = NULL;
1333 SDL_QuitSubSystem(SDL_INIT_VIDEO);
1338 gl_platformextensions = "";
1341 int VID_SetGamma (unsigned short *ramps, int rampsize)
1343 return !SDL_SetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
1346 int VID_GetGamma (unsigned short *ramps, int rampsize)
1348 return !SDL_GetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
1351 void VID_Finish (void)
1355 //react on appstate changes
1356 appstate = SDL_GetAppState();
1358 vid_hidden = !(appstate & SDL_APPACTIVE);
1360 if( vid_hidden || !( appstate & SDL_APPMOUSEFOCUS ) || !( appstate & SDL_APPINPUTFOCUS ) )
1361 vid_activewindow = false;
1363 vid_activewindow = true;
1365 VID_UpdateGamma(false, 256);
1369 switch(vid.renderpath)
1371 case RENDERPATH_GL11:
1372 case RENDERPATH_GL13:
1373 case RENDERPATH_GL20:
1374 case RENDERPATH_CGGL:
1376 if (r_speeds.integer == 2 || gl_finish.integer)
1378 qglFinish();CHECKGLERROR
1380 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
1382 qboolean vid_usevsync;
1383 vid_usevsync = (vid_vsync.integer && !cls.timedemo);
1384 if (vid_usingvsync != vid_usevsync)
1386 if (SDL_GL_SetSwapInterval(vid_usevsync != 0) >= 0)
1387 Con_DPrintf("Vsync %s\n", vid_usevsync ? "activated" : "deactivated");
1389 Con_DPrintf("ERROR: can't %s vsync\n", vid_usevsync ? "activate" : "deactivate");
1393 SDL_GL_SwapBuffers();
1395 case RENDERPATH_SOFT:
1397 SDL_BlitSurface(vid_softsurface, NULL, screen, NULL);
1400 case RENDERPATH_D3D9:
1401 case RENDERPATH_D3D10:
1402 case RENDERPATH_D3D11:
1408 size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
1411 SDL_Rect **vidmodes;
1412 int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
1415 for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); *vidmodes; ++vidmodes)
1419 modes[k].width = (*vidmodes)->w;
1420 modes[k].height = (*vidmodes)->h;
1422 modes[k].refreshrate = 60; // no support for refresh rate in SDL
1423 modes[k].pixelheight_num = 1;
1424 modes[k].pixelheight_denom = 1; // SDL does not provide this