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>
31 // Tell startup code that we have a client
32 int cl_available = true;
34 qboolean vid_supportrefreshrate = false;
36 cvar_t joy_detected = {CVAR_READONLY, "joy_detected", "0", "number of joysticks detected by engine"};
37 cvar_t joy_enable = {CVAR_SAVE, "joy_enable", "0", "enables joystick support"};
38 cvar_t joy_index = {0, "joy_index", "0", "selects which joystick to use if you have multiple"};
39 cvar_t joy_axisforward = {0, "joy_axisforward", "1", "which joystick axis to query for forward/backward movement"};
40 cvar_t joy_axisside = {0, "joy_axisside", "0", "which joystick axis to query for right/left movement"};
41 cvar_t joy_axisup = {0, "joy_axisup", "-1", "which joystick axis to query for up/down movement"};
42 cvar_t joy_axispitch = {0, "joy_axispitch", "3", "which joystick axis to query for looking up/down"};
43 cvar_t joy_axisyaw = {0, "joy_axisyaw", "2", "which joystick axis to query for looking right/left"};
44 cvar_t joy_axisroll = {0, "joy_axisroll", "-1", "which joystick axis to query for tilting head right/left"};
45 cvar_t joy_deadzoneforward = {0, "joy_deadzoneforward", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
46 cvar_t joy_deadzoneside = {0, "joy_deadzoneside", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
47 cvar_t joy_deadzoneup = {0, "joy_deadzoneup", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
48 cvar_t joy_deadzonepitch = {0, "joy_deadzonepitch", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
49 cvar_t joy_deadzoneyaw = {0, "joy_deadzoneyaw", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
50 cvar_t joy_deadzoneroll = {0, "joy_deadzoneroll", "0", "deadzone tolerance, suggested values are in the range 0 to 0.01"};
51 cvar_t joy_sensitivityforward = {0, "joy_sensitivityforward", "-1", "movement multiplier"};
52 cvar_t joy_sensitivityside = {0, "joy_sensitivityside", "1", "movement multiplier"};
53 cvar_t joy_sensitivityup = {0, "joy_sensitivityup", "1", "movement multiplier"};
54 cvar_t joy_sensitivitypitch = {0, "joy_sensitivitypitch", "1", "movement multiplier"};
55 cvar_t joy_sensitivityyaw = {0, "joy_sensitivityyaw", "-1", "movement multiplier"};
56 cvar_t joy_sensitivityroll = {0, "joy_sensitivityroll", "1", "movement multiplier"};
58 static qboolean vid_usingmouse = false;
59 static qboolean vid_usinghidecursor = false;
60 static qboolean vid_isfullscreen;
61 static int vid_numjoysticks = 0;
62 #define MAX_JOYSTICKS 8
63 static SDL_Joystick *vid_joysticks[MAX_JOYSTICKS];
65 static int win_half_width = 50;
66 static int win_half_height = 50;
67 static int video_bpp, video_flags;
69 static SDL_Surface *screen;
71 /////////////////////////
74 //TODO: Add joystick support
75 //TODO: Add error checking
78 //keysym to quake keysym mapping
79 #define tenoh 0,0,0,0,0, 0,0,0,0,0
80 #define fiftyoh tenoh, tenoh, tenoh, tenoh, tenoh
81 #define hundredoh fiftyoh, fiftyoh
82 static unsigned int tbl_sdltoquake[] =
84 0,0,0,0, //SDLK_UNKNOWN = 0,
85 0,0,0,0, //SDLK_FIRST = 0,
86 K_BACKSPACE, //SDLK_BACKSPACE = 8,
87 K_TAB, //SDLK_TAB = 9,
90 K_ENTER, //SDLK_RETURN = 13,
92 K_PAUSE, //SDLK_PAUSE = 19,
94 K_ESCAPE, //SDLK_ESCAPE = 27,
96 K_SPACE, //SDLK_SPACE = 32,
97 '!', //SDLK_EXCLAIM = 33,
98 '"', //SDLK_QUOTEDBL = 34,
99 '#', //SDLK_HASH = 35,
100 '$', //SDLK_DOLLAR = 36,
102 '&', //SDLK_AMPERSAND = 38,
103 '\'', //SDLK_QUOTE = 39,
104 '(', //SDLK_LEFTPAREN = 40,
105 ')', //SDLK_RIGHTPAREN = 41,
106 '*', //SDLK_ASTERISK = 42,
107 '+', //SDLK_PLUS = 43,
108 ',', //SDLK_COMMA = 44,
109 '-', //SDLK_MINUS = 45,
110 '.', //SDLK_PERIOD = 46,
111 '/', //SDLK_SLASH = 47,
122 ':', //SDLK_COLON = 58,
123 ';', //SDLK_SEMICOLON = 59,
124 '<', //SDLK_LESS = 60,
125 '=', //SDLK_EQUALS = 61,
126 '>', //SDLK_GREATER = 62,
127 '?', //SDLK_QUESTION = 63,
129 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,
130 '[', //SDLK_LEFTBRACKET = 91,
131 '\\', //SDLK_BACKSLASH = 92,
132 ']', //SDLK_RIGHTBRACKET = 93,
133 '^', //SDLK_CARET = 94,
134 '_', //SDLK_UNDERSCORE = 95,
135 '`', //SDLK_BACKQUOTE = 96,
163 K_DEL, //SDLK_DELETE = 127,
164 hundredoh /*227*/, tenoh, tenoh, 0,0,0,0,0,0,0,0,
165 K_KP_0, //SDLK_KP0 = 256,
166 K_KP_1, //SDLK_KP1 = 257,
167 K_KP_2, //SDLK_KP2 = 258,
168 K_KP_3, //SDLK_KP3 = 259,
169 K_KP_4, //SDLK_KP4 = 260,
170 K_KP_5, //SDLK_KP5 = 261,
171 K_KP_6, //SDLK_KP6 = 262,
172 K_KP_7, //SDLK_KP7 = 263,
173 K_KP_8, //SDLK_KP8 = 264,
174 K_KP_9, //SDLK_KP9 = 265,
175 K_KP_PERIOD,//SDLK_KP_PERIOD = 266,
176 K_KP_DIVIDE,//SDLK_KP_DIVIDE = 267,
177 K_KP_MULTIPLY,//SDLK_KP_MULTIPLY= 268,
178 K_KP_MINUS, //SDLK_KP_MINUS = 269,
179 K_KP_PLUS, //SDLK_KP_PLUS = 270,
180 K_KP_ENTER, //SDLK_KP_ENTER = 271,
181 K_KP_EQUALS,//SDLK_KP_EQUALS = 272,
182 K_UPARROW, //SDLK_UP = 273,
183 K_DOWNARROW,//SDLK_DOWN = 274,
184 K_RIGHTARROW,//SDLK_RIGHT = 275,
185 K_LEFTARROW,//SDLK_LEFT = 276,
186 K_INS, //SDLK_INSERT = 277,
187 K_HOME, //SDLK_HOME = 278,
188 K_END, //SDLK_END = 279,
189 K_PGUP, //SDLK_PAGEUP = 280,
190 K_PGDN, //SDLK_PAGEDOWN = 281,
191 K_F1, //SDLK_F1 = 282,
192 K_F2, //SDLK_F2 = 283,
193 K_F3, //SDLK_F3 = 284,
194 K_F4, //SDLK_F4 = 285,
195 K_F5, //SDLK_F5 = 286,
196 K_F6, //SDLK_F6 = 287,
197 K_F7, //SDLK_F7 = 288,
198 K_F8, //SDLK_F8 = 289,
199 K_F9, //SDLK_F9 = 290,
200 K_F10, //SDLK_F10 = 291,
201 K_F11, //SDLK_F11 = 292,
202 K_F12, //SDLK_F12 = 293,
207 K_NUMLOCK, //SDLK_NUMLOCK = 300,
208 K_CAPSLOCK, //SDLK_CAPSLOCK = 301,
209 K_SCROLLOCK,//SDLK_SCROLLOCK= 302,
210 K_SHIFT, //SDLK_RSHIFT = 303,
211 K_SHIFT, //SDLK_LSHIFT = 304,
212 K_CTRL, //SDLK_RCTRL = 305,
213 K_CTRL, //SDLK_LCTRL = 306,
214 K_ALT, //SDLK_RALT = 307,
215 K_ALT, //SDLK_LALT = 308,
216 0, //SDLK_RMETA = 309,
217 0, //SDLK_LMETA = 310,
218 0, //SDLK_LSUPER = 311, /* Left "Windows" key */
219 0, //SDLK_RSUPER = 312, /* Right "Windows" key */
220 K_ALT, //SDLK_MODE = 313, /* "Alt Gr" key */
221 0, //SDLK_COMPOSE = 314, /* Multi-key compose key */
222 0, //SDLK_HELP = 315,
223 0, //SDLK_PRINT = 316,
224 0, //SDLK_SYSREQ = 317,
225 K_PAUSE, //SDLK_BREAK = 318,
226 0, //SDLK_MENU = 319,
227 0, //SDLK_POWER = 320, /* Power Macintosh power key */
228 'e', //SDLK_EURO = 321, /* Some european keyboards */
229 0 //SDLK_UNDO = 322, /* Atari keyboard has Undo */
235 static int MapKey( unsigned int sdlkey )
237 if( sdlkey > sizeof(tbl_sdltoquake)/ sizeof(int) )
239 return tbl_sdltoquake[ sdlkey ];
242 void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor)
244 if (vid_usingmouse != relative)
246 vid_usingmouse = relative;
247 cl_ignoremousemoves = 2;
248 SDL_WM_GrabInput( relative ? SDL_GRAB_ON : SDL_GRAB_OFF );
250 if (vid_usinghidecursor != hidecursor)
252 vid_usinghidecursor = hidecursor;
253 SDL_ShowCursor( hidecursor ? SDL_DISABLE : SDL_ENABLE);
257 static double IN_JoystickGetAxis(SDL_Joystick *joy, int axis, double sensitivity, double deadzone)
260 if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
261 return 0; // no such axis on this joystick
262 value = SDL_JoystickGetAxis(joy, axis) * (1.0 / 32767.0);
263 value = bound(-1, value, 1);
264 if (fabs(value) < deadzone)
265 return 0; // within deadzone around center
266 return value * sensitivity;
272 static int old_x = 0, old_y = 0;
273 static int stuck = 0;
277 if(vid_stick_mouse.integer)
279 // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
280 // window grabbing. --blub
282 // we need 2 frames to initialize the center position
285 SDL_WarpMouse(win_half_width, win_half_height);
286 SDL_GetMouseState(&x, &y);
287 SDL_GetRelativeMouseState(&x, &y);
290 SDL_GetRelativeMouseState(&x, &y);
291 in_mouse_x = x + old_x;
292 in_mouse_y = y + old_y;
293 SDL_GetMouseState(&x, &y);
294 old_x = x - win_half_width;
295 old_y = y - win_half_height;
296 SDL_WarpMouse(win_half_width, win_half_height);
299 SDL_GetRelativeMouseState( &x, &y );
305 SDL_GetMouseState(&x, &y);
306 in_windowmouse_x = x;
307 in_windowmouse_y = y;
309 if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
311 SDL_Joystick *joy = vid_joysticks[joy_index.integer];
312 int numballs = SDL_JoystickNumBalls(joy);
313 for (j = 0;j < numballs;j++)
315 SDL_JoystickGetBall(joy, j, &x, &y);
319 cl.cmd.forwardmove += IN_JoystickGetAxis(joy, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
320 cl.cmd.sidemove += IN_JoystickGetAxis(joy, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
321 cl.cmd.upmove += IN_JoystickGetAxis(joy, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
322 cl.viewangles[0] += IN_JoystickGetAxis(joy, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
323 cl.viewangles[1] += IN_JoystickGetAxis(joy, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
324 //cl.viewangles[2] += IN_JoystickGetAxis(joy, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
328 /////////////////////
332 static int Sys_EventFilter( SDL_Event *event )
334 //TODO: Add a quit query in linux, too - though linux user are more likely to know what they do
335 if (event->type == SDL_QUIT)
338 if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
346 static qboolean sdl_needs_restart;
347 static void sdl_start(void)
350 static void sdl_shutdown(void)
352 sdl_needs_restart = false;
354 static void sdl_newmap(void)
359 static keynum_t buttonremap[18] =
381 void Sys_SendKeyEvents( void )
383 static qboolean sound_active = true;
386 while( SDL_PollEvent( &event ) )
387 switch( event.type ) {
393 Key_Event( MapKey( event.key.keysym.sym ), event.key.keysym.unicode, (event.key.state == SDL_PRESSED) );
395 case SDL_ACTIVEEVENT:
396 if( event.active.state & SDL_APPACTIVE )
398 if( event.active.gain )
404 case SDL_MOUSEBUTTONDOWN:
405 case SDL_MOUSEBUTTONUP:
406 if (event.button.button <= 18)
407 Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
409 case SDL_JOYBUTTONDOWN:
410 if (!joy_enable.integer)
411 break; // ignore down events if joystick has been disabled
412 case SDL_JOYBUTTONUP:
413 if (event.jbutton.button < 48)
414 Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
416 case SDL_VIDEORESIZE:
417 if(vid_resizable.integer < 2)
419 vid.width = event.resize.w;
420 vid.height = event.resize.h;
421 SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
423 // better not call R_Modules_Restart from here directly, as this may wreak havoc...
424 // so, let's better queue it for next frame
425 if(!sdl_needs_restart)
427 Cbuf_AddText("\nr_restart\n");
428 sdl_needs_restart = true;
435 // enable/disable sound on focus gain/loss
436 if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
449 sound_active = false;
458 void *GL_GetProcAddress(const char *name)
461 p = SDL_GL_GetProcAddress(name);
465 static int Sys_EventFilter( SDL_Event *event );
466 static qboolean vid_sdl_initjoysticksystem = false;
470 Cvar_RegisterVariable(&joy_detected);
471 Cvar_RegisterVariable(&joy_enable);
472 Cvar_RegisterVariable(&joy_index);
473 Cvar_RegisterVariable(&joy_axisforward);
474 Cvar_RegisterVariable(&joy_axisside);
475 Cvar_RegisterVariable(&joy_axisup);
476 Cvar_RegisterVariable(&joy_axispitch);
477 Cvar_RegisterVariable(&joy_axisyaw);
478 //Cvar_RegisterVariable(&joy_axisroll);
479 Cvar_RegisterVariable(&joy_deadzoneforward);
480 Cvar_RegisterVariable(&joy_deadzoneside);
481 Cvar_RegisterVariable(&joy_deadzoneup);
482 Cvar_RegisterVariable(&joy_deadzonepitch);
483 Cvar_RegisterVariable(&joy_deadzoneyaw);
484 //Cvar_RegisterVariable(&joy_deadzoneroll);
485 Cvar_RegisterVariable(&joy_sensitivityforward);
486 Cvar_RegisterVariable(&joy_sensitivityside);
487 Cvar_RegisterVariable(&joy_sensitivityup);
488 Cvar_RegisterVariable(&joy_sensitivitypitch);
489 Cvar_RegisterVariable(&joy_sensitivityyaw);
490 //Cvar_RegisterVariable(&joy_sensitivityroll);
493 R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap, NULL, NULL);
496 if (SDL_Init(SDL_INIT_VIDEO) < 0)
497 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
498 vid_sdl_initjoysticksystem = SDL_Init(SDL_INIT_JOYSTICK) >= 0;
499 if (vid_sdl_initjoysticksystem)
500 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
501 vid_isfullscreen = false;
504 // set the icon (we dont use SDL here since it would be too much a PITA)
506 #include "resource.h"
507 #include <SDL_syswm.h>
508 static void VID_SetCaption(void)
514 SDL_WM_SetCaption( gamename, NULL );
516 // get the HWND handle
517 SDL_VERSION( &info.version );
518 if( !SDL_GetWMInfo( &info ) )
521 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
522 #ifndef _W64 //If Windows 64bit data types don't exist
523 #ifndef SetClassLongPtr
524 #define SetClassLongPtr SetClassLong
527 #define GCLP_HICON GCL_HICON
530 #define LONG_PTR LONG
533 SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
535 static void VID_SetIcon_Pre(void)
538 static void VID_SetIcon_Post(void)
542 // Adding the OS independent XPM version --blub
543 #include "darkplaces.xpm"
544 #include "nexuiz.xpm"
545 static SDL_Surface *icon = NULL;
546 static void VID_SetIcon_Pre(void)
549 * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
550 * default settings with less than 91 colors and transparency.
553 int width, height, colors, isize, i, j;
555 static SDL_Color palette[256];
556 unsigned short palenc[256]; // store color id by char
559 const SDL_version *version;
561 version = SDL_Linked_Version();
562 // only use non-XPM icon support in SDL v1.3 and higher
563 // SDL v1.2 does not support "smooth" transparency, and thus is better
565 if(version->major >= 2 || (version->major == 1 && version->minor >= 3))
567 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
570 unsigned int red = 0x00FF0000;
571 unsigned int green = 0x0000FF00;
572 unsigned int blue = 0x000000FF;
573 unsigned int alpha = 0xFF000000;
575 height = image_height;
577 // reallocate with malloc, as this is in tempmempool (do not want)
579 data = malloc(width * height * 4);
580 memcpy(data, xpm, width * height * 4);
584 icon = SDL_CreateRGBSurface(SDL_SRCALPHA, width, height, 32, LittleLong(red), LittleLong(green), LittleLong(blue), LittleLong(alpha));
587 Con_Printf( "Failed to create surface for the window Icon!\n"
588 "%s\n", SDL_GetError());
597 // we only get here if non-XPM icon was missing, or SDL version is not
598 // sufficient for transparent non-XPM icons
601 xpm = (char *) FS_LoadFile("darkplaces-icon.xpm", tempmempool, false, NULL);
604 idata = XPM_DecodeString(xpm);
612 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) != 4)
614 // NOTE: Only 1-char colornames are supported
615 Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
621 // NOTE: Only 1-char colornames are supported
622 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
626 for(i = 0; i < colors; ++i)
628 unsigned int r, g, b;
631 if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
634 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
636 Con_Printf("This XPM's palette looks odd. Can't continue.\n");
641 palette[i].r = 255; // color key
644 thenone = i; // weeeee
649 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
654 palenc[(unsigned char) idx] = i;
657 // allocate the image data
658 data = (char*) malloc(width*height);
660 for(j = 0; j < height; ++j)
662 for(i = 0; i < width; ++i)
664 // casting to the safest possible datatypes ^^
665 data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
671 // SDL_FreeSurface should free the data too
672 // but for completeness' sake...
673 if(icon->flags & SDL_PREALLOC)
676 icon->pixels = NULL; // safety
678 SDL_FreeSurface(icon);
681 icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
682 // 8 bit surfaces get an empty palette allocated according to the docs
683 // so it's a palette image for sure :) no endian check necessary for the mask
686 Con_Printf( "Failed to create surface for the window Icon!\n"
687 "%s\n", SDL_GetError());
693 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
694 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
697 SDL_WM_SetIcon(icon, NULL);
699 static void VID_SetIcon_Post(void)
701 #if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
704 const SDL_version *version;
706 version = SDL_Linked_Version();
707 // only use non-XPM icon support in SDL v1.3 and higher
708 // SDL v1.2 does not support "smooth" transparency, and thus is better
710 if(!(version->major >= 2 || (version->major == 1 && version->minor >= 3)))
712 // in this case, we did not set the good icon yet
714 SDL_VERSION(&info.version);
715 if(SDL_GetWMInfo(&info) == 1 && info.subsystem == SDL_SYSWM_X11)
717 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
720 // use _NET_WM_ICON too
721 static long netwm_icon[MAX_NETWM_ICON];
727 if(pos + 2 * image_width * image_height < MAX_NETWM_ICON)
729 netwm_icon[pos++] = image_width;
730 netwm_icon[pos++] = image_height;
731 for(i = 0; i < image_height; ++i)
732 for(j = 0; j < image_width; ++j)
733 netwm_icon[pos++] = BuffLittleLong((unsigned char *) &data[(i*image_width+j)*4]);
737 Con_Printf("Skipping NETWM icon #%d because there is no space left\n", i);
741 data = (char *) loadimagepixelsbgra(va("darkplaces-icon%d", i), false, false, false, NULL);
744 info.info.x11.lock_func();
746 Atom net_wm_icon = XInternAtom(info.info.x11.display, "_NET_WM_ICON", false);
747 XChangeProperty(info.info.x11.display, info.info.x11.wmwindow, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos);
749 info.info.x11.unlock_func();
757 static void VID_SetCaption(void)
759 SDL_WM_SetCaption( gamename, NULL );
763 static void VID_OutputVersion(void)
765 const SDL_version *version;
766 version = SDL_Linked_Version();
767 Con_Printf( "Linked against SDL version %d.%d.%d\n"
768 "Using SDL library version %d.%d.%d\n",
769 SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
770 version->major, version->minor, version->patch );
773 qboolean VID_InitMode(viddef_mode_t *mode)
776 static int notfirstvideomode = false;
777 int flags = SDL_OPENGL;
778 const char *drivername;
780 win_half_width = mode->width>>1;
781 win_half_height = mode->height>>1;
783 if(vid_resizable.integer)
784 flags |= SDL_RESIZABLE;
790 We cant switch from one OpenGL video mode to another.
791 Thus we first switch to some stupid 2D mode and then back to OpenGL.
793 if (notfirstvideomode)
794 SDL_SetVideoMode( 0, 0, 0, 0 );
795 notfirstvideomode = true;
797 // SDL usually knows best
800 // 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
801 i = COM_CheckParm("-gl_driver");
802 if (i && i < com_argc - 1)
803 drivername = com_argv[i + 1];
804 if (SDL_GL_LoadLibrary(drivername) < 0)
806 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
810 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
813 Con_Print("Required OpenGL function glGetString not found\n");
817 // Knghtbrd: should do platform-specific extension string function here
819 vid_isfullscreen = false;
820 if (mode->fullscreen) {
821 flags |= SDL_FULLSCREEN;
822 vid_isfullscreen = true;
824 //flags |= SDL_HWSURFACE;
826 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
827 if (mode->bitsperpixel >= 32)
829 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
830 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
831 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
832 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
833 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
834 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
838 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
839 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
840 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
841 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
843 if (mode->stereobuffer)
844 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
845 if (vid_vsync.integer)
846 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
848 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
849 if (mode->samples > 1)
851 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
852 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples);
855 video_bpp = mode->bitsperpixel;
858 screen = SDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
863 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
870 // set up an event filter to ask confirmation on close button in WIN32
871 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
873 SDL_EnableUNICODE( SDL_ENABLE );
874 // enable key repeat since everyone expects it
875 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
878 gl_platformextensions = "";
882 vid_numjoysticks = SDL_NumJoysticks();
883 vid_numjoysticks = bound(0, vid_numjoysticks, MAX_JOYSTICKS);
884 Cvar_SetValueQuick(&joy_detected, vid_numjoysticks);
885 Con_Printf("%d SDL joystick(s) found:\n", vid_numjoysticks);
886 memset(vid_joysticks, 0, sizeof(vid_joysticks));
887 for (i = 0;i < vid_numjoysticks;i++)
890 joy = vid_joysticks[i] = SDL_JoystickOpen(i);
893 Con_Printf("joystick #%i: open failed: %s\n", i, SDL_GetError());
896 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));
900 vid_activewindow = false;
901 vid_usingmouse = false;
902 vid_usinghidecursor = false;
904 SDL_WM_GrabInput(SDL_GRAB_OFF);
908 void VID_Shutdown (void)
910 VID_SetMouse(false, false, false);
911 VID_RestoreSystemGamma();
913 SDL_QuitSubSystem(SDL_INIT_VIDEO);
918 gl_platformextensions = "";
921 int VID_SetGamma (unsigned short *ramps, int rampsize)
923 return !SDL_SetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
926 int VID_GetGamma (unsigned short *ramps, int rampsize)
928 return !SDL_GetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
931 void VID_Finish (void)
935 //react on appstate changes
936 appstate = SDL_GetAppState();
938 vid_hidden = !(appstate & SDL_APPACTIVE);
940 if( vid_hidden || !( appstate & SDL_APPMOUSEFOCUS ) || !( appstate & SDL_APPINPUTFOCUS ) )
941 vid_activewindow = false;
943 vid_activewindow = true;
945 VID_UpdateGamma(false, 256);
950 if (r_speeds.integer == 2 || gl_finish.integer)
952 qglFinish();CHECKGLERROR
954 SDL_GL_SwapBuffers();
958 size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
962 int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
965 for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); *vidmodes; ++vidmodes)
969 modes[k].width = (*vidmodes)->w;
970 modes[k].height = (*vidmodes)->h;
972 modes[k].refreshrate = 60; // no support for refresh rate in SDL
973 modes[k].pixelheight_num = 1;
974 modes[k].pixelheight_denom = 1; // SDL does not provide this