2 Copyright (C) 2003 T. Joseph Carter
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #undef WIN32_LEAN_AND_MEAN //hush a warning, SDL.h redefines this
29 #include <Carbon/Carbon.h>
30 #include <IOKit/hidsystem/IOHIDLib.h>
31 #include <IOKit/hidsystem/IOHIDParameter.h>
32 #include <IOKit/hidsystem/event_status_driver.h>
33 static cvar_t apple_mouse_noaccel = {CVAR_SAVE, "apple_mouse_noaccel", "1", "disables mouse acceleration while DarkPlaces is active"};
34 static qboolean vid_usingnoaccel;
35 static double originalMouseSpeed = -1.0;
36 io_connect_t IN_GetIOHandle(void)
38 io_connect_t iohandle = MACH_PORT_NULL;
40 io_service_t iohidsystem = MACH_PORT_NULL;
41 mach_port_t masterport;
43 status = IOMasterPort(MACH_PORT_NULL, &masterport);
44 if(status != KERN_SUCCESS)
47 iohidsystem = IORegistryEntryFromPath(masterport, kIOServicePlane ":/IOResources/IOHIDSystem");
51 status = IOServiceOpen(iohidsystem, mach_task_self(), kIOHIDParamConnectType, &iohandle);
52 IOObjectRelease(iohidsystem);
63 // Tell startup code that we have a client
64 int cl_available = true;
66 qboolean vid_supportrefreshrate = false;
68 static qboolean vid_usingmouse = false;
69 static qboolean vid_usingmouse_relativeworks = false; // SDL2 workaround for unimplemented RelativeMouse mode
70 static qboolean vid_usinghidecursor = false;
71 static qboolean vid_hasfocus = false;
72 static qboolean vid_isfullscreen;
73 #if SDL_MAJOR_VERSION != 1
74 static qboolean vid_usingvsync = false;
76 static SDL_Joystick *vid_sdljoystick = NULL;
77 // GAME_STEELSTORM specific
78 static cvar_t *steelstorm_showing_map = NULL; // detect but do not create the cvar
79 static cvar_t *steelstorm_showing_mousecursor = NULL; // detect but do not create the cvar
81 static int win_half_width = 50;
82 static int win_half_height = 50;
85 #if SDL_MAJOR_VERSION == 1
86 static SDL_Surface *video_screen;
87 static int video_flags;
89 static SDL_GLContext context;
90 static SDL_Window *window;
91 static int window_flags;
93 static vid_mode_t desktop_mode;
95 /////////////////////////
98 //TODO: Add error checking
101 #define SDLK_PERCENT '%'
102 #if SDL_MAJOR_VERSION == 1
103 #define SDLK_PRINTSCREEN SDLK_PRINT
104 #define SDLK_SCROLLLOCK SDLK_SCROLLOCK
105 #define SDLK_NUMLOCKCLEAR SDLK_NUMLOCK
106 #define SDLK_KP_1 SDLK_KP1
107 #define SDLK_KP_2 SDLK_KP2
108 #define SDLK_KP_3 SDLK_KP3
109 #define SDLK_KP_4 SDLK_KP4
110 #define SDLK_KP_5 SDLK_KP5
111 #define SDLK_KP_6 SDLK_KP6
112 #define SDLK_KP_7 SDLK_KP7
113 #define SDLK_KP_8 SDLK_KP8
114 #define SDLK_KP_9 SDLK_KP9
115 #define SDLK_KP_0 SDLK_KP0
119 static int MapKey( unsigned int sdlkey )
124 // case SDLK_UNKNOWN: return K_UNKNOWN;
125 case SDLK_RETURN: return K_ENTER;
126 case SDLK_ESCAPE: return K_ESCAPE;
127 case SDLK_BACKSPACE: return K_BACKSPACE;
128 case SDLK_TAB: return K_TAB;
129 case SDLK_SPACE: return K_SPACE;
130 case SDLK_EXCLAIM: return '!';
131 case SDLK_QUOTEDBL: return '"';
132 case SDLK_HASH: return '#';
133 case SDLK_PERCENT: return '%';
134 case SDLK_DOLLAR: return '$';
135 case SDLK_AMPERSAND: return '&';
136 case SDLK_QUOTE: return '\'';
137 case SDLK_LEFTPAREN: return '(';
138 case SDLK_RIGHTPAREN: return ')';
139 case SDLK_ASTERISK: return '*';
140 case SDLK_PLUS: return '+';
141 case SDLK_COMMA: return ',';
142 case SDLK_MINUS: return '-';
143 case SDLK_PERIOD: return '.';
144 case SDLK_SLASH: return '/';
145 case SDLK_0: return '0';
146 case SDLK_1: return '1';
147 case SDLK_2: return '2';
148 case SDLK_3: return '3';
149 case SDLK_4: return '4';
150 case SDLK_5: return '5';
151 case SDLK_6: return '6';
152 case SDLK_7: return '7';
153 case SDLK_8: return '8';
154 case SDLK_9: return '9';
155 case SDLK_COLON: return ':';
156 case SDLK_SEMICOLON: return ';';
157 case SDLK_LESS: return '<';
158 case SDLK_EQUALS: return '=';
159 case SDLK_GREATER: return '>';
160 case SDLK_QUESTION: return '?';
161 case SDLK_AT: return '@';
162 case SDLK_LEFTBRACKET: return '[';
163 case SDLK_BACKSLASH: return '\\';
164 case SDLK_RIGHTBRACKET: return ']';
165 case SDLK_CARET: return '^';
166 case SDLK_UNDERSCORE: return '_';
167 case SDLK_BACKQUOTE: return '`';
168 case SDLK_a: return 'a';
169 case SDLK_b: return 'b';
170 case SDLK_c: return 'c';
171 case SDLK_d: return 'd';
172 case SDLK_e: return 'e';
173 case SDLK_f: return 'f';
174 case SDLK_g: return 'g';
175 case SDLK_h: return 'h';
176 case SDLK_i: return 'i';
177 case SDLK_j: return 'j';
178 case SDLK_k: return 'k';
179 case SDLK_l: return 'l';
180 case SDLK_m: return 'm';
181 case SDLK_n: return 'n';
182 case SDLK_o: return 'o';
183 case SDLK_p: return 'p';
184 case SDLK_q: return 'q';
185 case SDLK_r: return 'r';
186 case SDLK_s: return 's';
187 case SDLK_t: return 't';
188 case SDLK_u: return 'u';
189 case SDLK_v: return 'v';
190 case SDLK_w: return 'w';
191 case SDLK_x: return 'x';
192 case SDLK_y: return 'y';
193 case SDLK_z: return 'z';
194 case SDLK_CAPSLOCK: return K_CAPSLOCK;
195 case SDLK_F1: return K_F1;
196 case SDLK_F2: return K_F2;
197 case SDLK_F3: return K_F3;
198 case SDLK_F4: return K_F4;
199 case SDLK_F5: return K_F5;
200 case SDLK_F6: return K_F6;
201 case SDLK_F7: return K_F7;
202 case SDLK_F8: return K_F8;
203 case SDLK_F9: return K_F9;
204 case SDLK_F10: return K_F10;
205 case SDLK_F11: return K_F11;
206 case SDLK_F12: return K_F12;
207 case SDLK_PRINTSCREEN: return K_PRINTSCREEN;
208 case SDLK_SCROLLLOCK: return K_SCROLLOCK;
209 case SDLK_PAUSE: return K_PAUSE;
210 case SDLK_INSERT: return K_INS;
211 case SDLK_HOME: return K_HOME;
212 case SDLK_PAGEUP: return K_PGUP;
214 case SDLK_DELETE: return K_BACKSPACE;
216 case SDLK_DELETE: return K_DEL;
218 case SDLK_END: return K_END;
219 case SDLK_PAGEDOWN: return K_PGDN;
220 case SDLK_RIGHT: return K_RIGHTARROW;
221 case SDLK_LEFT: return K_LEFTARROW;
222 case SDLK_DOWN: return K_DOWNARROW;
223 case SDLK_UP: return K_UPARROW;
224 case SDLK_NUMLOCKCLEAR: return K_NUMLOCK;
225 case SDLK_KP_DIVIDE: return K_KP_DIVIDE;
226 case SDLK_KP_MULTIPLY: return K_KP_MULTIPLY;
227 case SDLK_KP_MINUS: return K_KP_MINUS;
228 case SDLK_KP_PLUS: return K_KP_PLUS;
229 case SDLK_KP_ENTER: return K_KP_ENTER;
230 case SDLK_KP_1: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_1 : K_END);
231 case SDLK_KP_2: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_2 : K_DOWNARROW);
232 case SDLK_KP_3: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_3 : K_PGDN);
233 case SDLK_KP_4: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_4 : K_LEFTARROW);
234 case SDLK_KP_5: return K_KP_5;
235 case SDLK_KP_6: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_6 : K_RIGHTARROW);
236 case SDLK_KP_7: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_7 : K_HOME);
237 case SDLK_KP_8: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_8 : K_UPARROW);
238 case SDLK_KP_9: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_9 : K_PGUP);
239 case SDLK_KP_0: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_0 : K_INS);
240 case SDLK_KP_PERIOD: return ((SDL_GetModState() & KMOD_NUM) ? K_KP_PERIOD : K_DEL);
241 // case SDLK_APPLICATION: return K_APPLICATION;
242 // case SDLK_POWER: return K_POWER;
243 case SDLK_KP_EQUALS: return K_KP_EQUALS;
244 // case SDLK_F13: return K_F13;
245 // case SDLK_F14: return K_F14;
246 // case SDLK_F15: return K_F15;
247 // case SDLK_F16: return K_F16;
248 // case SDLK_F17: return K_F17;
249 // case SDLK_F18: return K_F18;
250 // case SDLK_F19: return K_F19;
251 // case SDLK_F20: return K_F20;
252 // case SDLK_F21: return K_F21;
253 // case SDLK_F22: return K_F22;
254 // case SDLK_F23: return K_F23;
255 // case SDLK_F24: return K_F24;
256 // case SDLK_EXECUTE: return K_EXECUTE;
257 // case SDLK_HELP: return K_HELP;
258 // case SDLK_MENU: return K_MENU;
259 // case SDLK_SELECT: return K_SELECT;
260 // case SDLK_STOP: return K_STOP;
261 // case SDLK_AGAIN: return K_AGAIN;
262 // case SDLK_UNDO: return K_UNDO;
263 // case SDLK_CUT: return K_CUT;
264 // case SDLK_COPY: return K_COPY;
265 // case SDLK_PASTE: return K_PASTE;
266 // case SDLK_FIND: return K_FIND;
267 // case SDLK_MUTE: return K_MUTE;
268 // case SDLK_VOLUMEUP: return K_VOLUMEUP;
269 // case SDLK_VOLUMEDOWN: return K_VOLUMEDOWN;
270 // case SDLK_KP_COMMA: return K_KP_COMMA;
271 // case SDLK_KP_EQUALSAS400: return K_KP_EQUALSAS400;
272 // case SDLK_ALTERASE: return K_ALTERASE;
273 // case SDLK_SYSREQ: return K_SYSREQ;
274 // case SDLK_CANCEL: return K_CANCEL;
275 // case SDLK_CLEAR: return K_CLEAR;
276 // case SDLK_PRIOR: return K_PRIOR;
277 // case SDLK_RETURN2: return K_RETURN2;
278 // case SDLK_SEPARATOR: return K_SEPARATOR;
279 // case SDLK_OUT: return K_OUT;
280 // case SDLK_OPER: return K_OPER;
281 // case SDLK_CLEARAGAIN: return K_CLEARAGAIN;
282 // case SDLK_CRSEL: return K_CRSEL;
283 // case SDLK_EXSEL: return K_EXSEL;
284 // case SDLK_KP_00: return K_KP_00;
285 // case SDLK_KP_000: return K_KP_000;
286 // case SDLK_THOUSANDSSEPARATOR: return K_THOUSANDSSEPARATOR;
287 // case SDLK_DECIMALSEPARATOR: return K_DECIMALSEPARATOR;
288 // case SDLK_CURRENCYUNIT: return K_CURRENCYUNIT;
289 // case SDLK_CURRENCYSUBUNIT: return K_CURRENCYSUBUNIT;
290 // case SDLK_KP_LEFTPAREN: return K_KP_LEFTPAREN;
291 // case SDLK_KP_RIGHTPAREN: return K_KP_RIGHTPAREN;
292 // case SDLK_KP_LEFTBRACE: return K_KP_LEFTBRACE;
293 // case SDLK_KP_RIGHTBRACE: return K_KP_RIGHTBRACE;
294 // case SDLK_KP_TAB: return K_KP_TAB;
295 // case SDLK_KP_BACKSPACE: return K_KP_BACKSPACE;
296 // case SDLK_KP_A: return K_KP_A;
297 // case SDLK_KP_B: return K_KP_B;
298 // case SDLK_KP_C: return K_KP_C;
299 // case SDLK_KP_D: return K_KP_D;
300 // case SDLK_KP_E: return K_KP_E;
301 // case SDLK_KP_F: return K_KP_F;
302 // case SDLK_KP_XOR: return K_KP_XOR;
303 // case SDLK_KP_POWER: return K_KP_POWER;
304 // case SDLK_KP_PERCENT: return K_KP_PERCENT;
305 // case SDLK_KP_LESS: return K_KP_LESS;
306 // case SDLK_KP_GREATER: return K_KP_GREATER;
307 // case SDLK_KP_AMPERSAND: return K_KP_AMPERSAND;
308 // case SDLK_KP_DBLAMPERSAND: return K_KP_DBLAMPERSAND;
309 // case SDLK_KP_VERTICALBAR: return K_KP_VERTICALBAR;
310 // case SDLK_KP_DBLVERTICALBAR: return K_KP_DBLVERTICALBAR;
311 // case SDLK_KP_COLON: return K_KP_COLON;
312 // case SDLK_KP_HASH: return K_KP_HASH;
313 // case SDLK_KP_SPACE: return K_KP_SPACE;
314 // case SDLK_KP_AT: return K_KP_AT;
315 // case SDLK_KP_EXCLAM: return K_KP_EXCLAM;
316 // case SDLK_KP_MEMSTORE: return K_KP_MEMSTORE;
317 // case SDLK_KP_MEMRECALL: return K_KP_MEMRECALL;
318 // case SDLK_KP_MEMCLEAR: return K_KP_MEMCLEAR;
319 // case SDLK_KP_MEMADD: return K_KP_MEMADD;
320 // case SDLK_KP_MEMSUBTRACT: return K_KP_MEMSUBTRACT;
321 // case SDLK_KP_MEMMULTIPLY: return K_KP_MEMMULTIPLY;
322 // case SDLK_KP_MEMDIVIDE: return K_KP_MEMDIVIDE;
323 // case SDLK_KP_PLUSMINUS: return K_KP_PLUSMINUS;
324 // case SDLK_KP_CLEAR: return K_KP_CLEAR;
325 // case SDLK_KP_CLEARENTRY: return K_KP_CLEARENTRY;
326 // case SDLK_KP_BINARY: return K_KP_BINARY;
327 // case SDLK_KP_OCTAL: return K_KP_OCTAL;
328 // case SDLK_KP_DECIMAL: return K_KP_DECIMAL;
329 // case SDLK_KP_HEXADECIMAL: return K_KP_HEXADECIMAL;
330 case SDLK_LCTRL: return K_CTRL;
331 case SDLK_LSHIFT: return K_SHIFT;
332 case SDLK_LALT: return K_ALT;
333 // case SDLK_LGUI: return K_LGUI;
334 case SDLK_RCTRL: return K_CTRL;
335 case SDLK_RSHIFT: return K_SHIFT;
336 case SDLK_RALT: return K_ALT;
337 // case SDLK_RGUI: return K_RGUI;
338 // case SDLK_MODE: return K_MODE;
339 #if SDL_MAJOR_VERSION != 1
340 // case SDLK_AUDIONEXT: return K_AUDIONEXT;
341 // case SDLK_AUDIOPREV: return K_AUDIOPREV;
342 // case SDLK_AUDIOSTOP: return K_AUDIOSTOP;
343 // case SDLK_AUDIOPLAY: return K_AUDIOPLAY;
344 // case SDLK_AUDIOMUTE: return K_AUDIOMUTE;
345 // case SDLK_MEDIASELECT: return K_MEDIASELECT;
346 // case SDLK_WWW: return K_WWW;
347 // case SDLK_MAIL: return K_MAIL;
348 // case SDLK_CALCULATOR: return K_CALCULATOR;
349 // case SDLK_COMPUTER: return K_COMPUTER;
350 // case SDLK_AC_SEARCH: return K_AC_SEARCH; // Android button
351 // case SDLK_AC_HOME: return K_AC_HOME; // Android button
352 case SDLK_AC_BACK: return K_ESCAPE; // Android button
353 // case SDLK_AC_FORWARD: return K_AC_FORWARD; // Android button
354 // case SDLK_AC_STOP: return K_AC_STOP; // Android button
355 // case SDLK_AC_REFRESH: return K_AC_REFRESH; // Android button
356 // case SDLK_AC_BOOKMARKS: return K_AC_BOOKMARKS; // Android button
357 // case SDLK_BRIGHTNESSDOWN: return K_BRIGHTNESSDOWN;
358 // case SDLK_BRIGHTNESSUP: return K_BRIGHTNESSUP;
359 // case SDLK_DISPLAYSWITCH: return K_DISPLAYSWITCH;
360 // case SDLK_KBDILLUMTOGGLE: return K_KBDILLUMTOGGLE;
361 // case SDLK_KBDILLUMDOWN: return K_KBDILLUMDOWN;
362 // case SDLK_KBDILLUMUP: return K_KBDILLUMUP;
363 // case SDLK_EJECT: return K_EJECT;
364 // case SDLK_SLEEP: return K_SLEEP;
369 qboolean VID_HasScreenKeyboardSupport(void)
371 #if SDL_MAJOR_VERSION != 1
372 return SDL_HasScreenKeyboardSupport() != SDL_FALSE;
378 void VID_ShowKeyboard(qboolean show)
380 #if SDL_MAJOR_VERSION != 1
381 if (!SDL_HasScreenKeyboardSupport())
386 if (!SDL_IsTextInputActive())
387 SDL_StartTextInput();
391 if (SDL_IsTextInputActive())
397 qboolean VID_ShowingKeyboard(void)
399 #if SDL_MAJOR_VERSION != 1
400 return SDL_IsTextInputActive() != 0;
406 void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor)
408 #ifndef DP_MOBILETOUCH
411 if(vid_usingmouse && (vid_usingnoaccel != !!apple_mouse_noaccel.integer))
412 VID_SetMouse(false, false, false); // ungrab first!
414 if (vid_usingmouse != relative)
416 vid_usingmouse = relative;
417 cl_ignoremousemoves = 2;
418 #if SDL_MAJOR_VERSION == 1
419 SDL_WM_GrabInput( relative ? SDL_GRAB_ON : SDL_GRAB_OFF );
421 vid_usingmouse_relativeworks = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == 0;
422 // Con_Printf("VID_SetMouse(%i, %i, %i) relativeworks = %i\n", (int)fullscreengrab, (int)relative, (int)hidecursor, (int)vid_usingmouse_relativeworks);
427 // Save the status of mouse acceleration
428 originalMouseSpeed = -1.0; // in case of error
429 if(apple_mouse_noaccel.integer)
431 io_connect_t mouseDev = IN_GetIOHandle();
434 if(IOHIDGetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), &originalMouseSpeed) == kIOReturnSuccess)
436 Con_DPrintf("previous mouse acceleration: %f\n", originalMouseSpeed);
437 if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), -1.0) != kIOReturnSuccess)
439 Con_Print("Could not disable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
440 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
445 Con_Print("Could not disable mouse acceleration (failed at IOHIDGetAccelerationWithKey).\n");
446 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
448 IOServiceClose(mouseDev);
452 Con_Print("Could not disable mouse acceleration (failed at IO_GetIOHandle).\n");
453 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
457 vid_usingnoaccel = !!apple_mouse_noaccel.integer;
461 if(originalMouseSpeed != -1.0)
463 io_connect_t mouseDev = IN_GetIOHandle();
466 Con_DPrintf("restoring mouse acceleration to: %f\n", originalMouseSpeed);
467 if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), originalMouseSpeed) != kIOReturnSuccess)
468 Con_Print("Could not re-enable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
469 IOServiceClose(mouseDev);
472 Con_Print("Could not re-enable mouse acceleration (failed at IO_GetIOHandle).\n");
477 if (vid_usinghidecursor != hidecursor)
479 vid_usinghidecursor = hidecursor;
480 SDL_ShowCursor( hidecursor ? SDL_DISABLE : SDL_ENABLE);
485 // multitouch[10][] represents the mouse pointer
486 // multitouch[][0]: finger active
487 // multitouch[][1]: Y
488 // multitouch[][2]: Y
489 // X and Y coordinates are 0-1.
490 #define MAXFINGERS 11
491 float multitouch[MAXFINGERS][3];
493 // this one stores how many areas this finger has touched
494 int multitouchs[MAXFINGERS];
496 // modified heavily by ELUAN
497 static qboolean VID_TouchscreenArea(int corner, float px, float py, float pwidth, float pheight, const char *icon, float textheight, const char *text, float *resultmove, qboolean *resultbutton, keynum_t key, const char *typedtext, float deadzone, float oversizepixels_x, float oversizepixels_y, qboolean iamexclusive)
500 float fx, fy, fwidth, fheight;
501 float overfx, overfy, overfwidth, overfheight;
504 qboolean button = false;
506 if (pwidth > 0 && pheight > 0)
508 if (corner & 1) px += vid_conwidth.value;
509 if (corner & 2) py += vid_conheight.value;
510 if (corner & 4) px += vid_conwidth.value * 0.5f;
511 if (corner & 8) py += vid_conheight.value * 0.5f;
512 if (corner & 16) {px *= vid_conwidth.value * (1.0f / 640.0f);py *= vid_conheight.value * (1.0f / 480.0f);pwidth *= vid_conwidth.value * (1.0f / 640.0f);pheight *= vid_conheight.value * (1.0f / 480.0f);}
513 fx = px / vid_conwidth.value;
514 fy = py / vid_conheight.value;
515 fwidth = pwidth / vid_conwidth.value;
516 fheight = pheight / vid_conheight.value;
518 // try to prevent oversizepixels_* from interfering with the iamexclusive cvar by not letting we start controlling from too far of the actual touch area (areas without resultbuttons should NEVER have the oversizepixels_* parameters set to anything other than 0)
520 if (!(*resultbutton))
522 oversizepixels_x *= 0.2;
523 oversizepixels_y *= 0.2;
526 oversizepixels_x /= vid_conwidth.value;
527 oversizepixels_y /= vid_conheight.value;
529 overfx = fx - oversizepixels_x;
530 overfy = fy - oversizepixels_y;
531 overfwidth = fwidth + 2*oversizepixels_x;
532 overfheight = fheight + 2*oversizepixels_y;
534 for (finger = 0;finger < MAXFINGERS;finger++)
536 if (multitouchs[finger] && iamexclusive) // for this to work correctly, you must call touch areas in order of highest to lowest priority
539 if (multitouch[finger][0] && multitouch[finger][1] >= overfx && multitouch[finger][2] >= overfy && multitouch[finger][1] < overfx + overfwidth && multitouch[finger][2] < overfy + overfheight)
541 multitouchs[finger]++;
543 rel[0] = bound(-1, (multitouch[finger][1] - (fx + 0.5f * fwidth)) * (2.0f / fwidth), 1);
544 rel[1] = bound(-1, (multitouch[finger][2] - (fy + 0.5f * fheight)) * (2.0f / fheight), 1);
547 sqsum = rel[0]*rel[0] + rel[1]*rel[1];
549 if (sqsum < deadzone*deadzone)
556 // ignore the third component
557 Vector2Normalize2(rel, rel);
563 if (scr_numtouchscreenareas < 128)
565 scr_touchscreenareas[scr_numtouchscreenareas].pic = icon;
566 scr_touchscreenareas[scr_numtouchscreenareas].text = text;
567 scr_touchscreenareas[scr_numtouchscreenareas].textheight = textheight;
568 scr_touchscreenareas[scr_numtouchscreenareas].rect[0] = px;
569 scr_touchscreenareas[scr_numtouchscreenareas].rect[1] = py;
570 scr_touchscreenareas[scr_numtouchscreenareas].rect[2] = pwidth;
571 scr_touchscreenareas[scr_numtouchscreenareas].rect[3] = pheight;
572 scr_touchscreenareas[scr_numtouchscreenareas].active = button;
573 // the pics may have alpha too.
574 scr_touchscreenareas[scr_numtouchscreenareas].activealpha = 1.f;
575 scr_touchscreenareas[scr_numtouchscreenareas].inactivealpha = 0.95f;
576 scr_numtouchscreenareas++;
582 VectorCopy(rel, resultmove);
584 VectorClear(resultmove);
588 if (*resultbutton != button)
591 Key_Event(key, 0, button);
592 if (typedtext && typedtext[0] && !*resultbutton)
594 // FIXME: implement UTF8 support - nothing actually specifies a UTF8 string here yet, but should support it...
596 for (i = 0;typedtext[i];i++)
598 Key_Event(K_TEXT, typedtext[i], true);
599 Key_Event(K_TEXT, typedtext[i], false);
603 *resultbutton = button;
609 // not reentrant, but we only need one mouse cursor anyway...
610 static void VID_TouchscreenCursor(float px, float py, float pwidth, float pheight, qboolean *resultbutton, keynum_t key)
613 float fx, fy, fwidth, fheight;
614 qboolean button = false;
615 static int cursorfinger = -1;
616 static int cursorfreemovement = false;
617 static int canclick = false;
618 static int clickxy[2];
619 static int relclickxy[2];
620 static double clickrealtime = 0;
622 if (steelstorm_showing_mousecursor && steelstorm_showing_mousecursor->integer)
623 if (pwidth > 0 && pheight > 0)
625 fx = px / vid_conwidth.value;
626 fy = py / vid_conheight.value;
627 fwidth = pwidth / vid_conwidth.value;
628 fheight = pheight / vid_conheight.value;
629 for (finger = 0;finger < MAXFINGERS;finger++)
631 if (multitouch[finger][0] && multitouch[finger][1] >= fx && multitouch[finger][2] >= fy && multitouch[finger][1] < fx + fwidth && multitouch[finger][2] < fy + fheight)
633 if (cursorfinger == -1)
635 clickxy[0] = multitouch[finger][1] * vid_width.value - 0.5f * pwidth;
636 clickxy[1] = multitouch[finger][2] * vid_height.value - 0.5f * pheight;
637 relclickxy[0] = (multitouch[finger][1] - fx) * vid_width.value - 0.5f * pwidth;
638 relclickxy[1] = (multitouch[finger][2] - fy) * vid_height.value - 0.5f * pheight;
640 cursorfinger = finger;
643 cursorfreemovement = false;
647 if (scr_numtouchscreenareas < 128)
649 if (clickrealtime + 1 > realtime)
651 scr_touchscreenareas[scr_numtouchscreenareas].pic = "gfx/gui/touch_puck_cur_click.tga";
655 scr_touchscreenareas[scr_numtouchscreenareas].pic = "gfx/gui/touch_puck_cur_touch.tga";
659 switch ((int)realtime * 10 % 20)
662 scr_touchscreenareas[scr_numtouchscreenareas].pic = "gfx/gui/touch_puck_cur_touch.tga";
665 scr_touchscreenareas[scr_numtouchscreenareas].pic = "gfx/gui/touch_puck_cur_idle.tga";
668 scr_touchscreenareas[scr_numtouchscreenareas].text = "";
669 scr_touchscreenareas[scr_numtouchscreenareas].textheight = 0;
670 scr_touchscreenareas[scr_numtouchscreenareas].rect[0] = px;
671 scr_touchscreenareas[scr_numtouchscreenareas].rect[1] = py;
672 scr_touchscreenareas[scr_numtouchscreenareas].rect[2] = pwidth;
673 scr_touchscreenareas[scr_numtouchscreenareas].rect[3] = pheight;
674 scr_touchscreenareas[scr_numtouchscreenareas].active = button;
675 scr_touchscreenareas[scr_numtouchscreenareas].activealpha = 1.0f;
676 scr_touchscreenareas[scr_numtouchscreenareas].inactivealpha = 1.0f;
677 scr_numtouchscreenareas++;
681 if (cursorfinger != -1)
683 if (multitouch[cursorfinger][0])
685 if (multitouch[cursorfinger][1] * vid_width.value - 0.5f * pwidth < clickxy[0] - 1 ||
686 multitouch[cursorfinger][1] * vid_width.value - 0.5f * pwidth > clickxy[0] + 1 ||
687 multitouch[cursorfinger][2] * vid_height.value - 0.5f * pheight< clickxy[1] - 1 ||
688 multitouch[cursorfinger][2] * vid_height.value - 0.5f * pheight> clickxy[1] + 1) // finger drifted more than the allowed amount
690 cursorfreemovement = true;
692 if (cursorfreemovement)
694 // in_windowmouse_x* is in screen resolution coordinates, not console resolution
695 in_windowmouse_x = multitouch[cursorfinger][1] * vid_width.value - 0.5f * pwidth - relclickxy[0];
696 in_windowmouse_y = multitouch[cursorfinger][2] * vid_height.value - 0.5f * pheight - relclickxy[1];
707 if (/**resultbutton != button && */(int)key > 0)
709 if (!button && !cursorfreemovement && canclick)
711 Key_Event(key, 0, true);
713 clickrealtime = realtime;
716 // SS:BR can't qc can't cope with presses and releases on the same frame
717 if (clickrealtime && clickrealtime + 0.1 < realtime)
719 Key_Event(key, 0, false);
724 *resultbutton = button;
728 void VID_BuildJoyState(vid_joystate_t *joystate)
730 VID_Shared_BuildJoyState_Begin(joystate);
734 SDL_Joystick *joy = vid_sdljoystick;
738 numaxes = SDL_JoystickNumAxes(joy);
739 for (j = 0;j < numaxes;j++)
740 joystate->axis[j] = SDL_JoystickGetAxis(joy, j) * (1.0f / 32767.0f);
741 numbuttons = SDL_JoystickNumButtons(joy);
742 for (j = 0;j < numbuttons;j++)
743 joystate->button[j] = SDL_JoystickGetButton(joy, j);
746 VID_Shared_BuildJoyState_Finish(joystate);
749 // clear every touch screen area, except the one with button[skip]
750 #define Vid_ClearAllTouchscreenAreas(skip) \
752 VID_TouchscreenCursor(0, 0, 0, 0, &buttons[0], K_MOUSE1); \
754 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, move, &buttons[1], K_MOUSE4, NULL, 0, 0, 0, false); \
756 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, aim, &buttons[2], K_MOUSE5, NULL, 0, 0, 0, false); \
758 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[3], K_SHIFT, NULL, 0, 0, 0, false); \
760 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 0, 0, false); \
762 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[9], K_MOUSE3, NULL, 0, 0, 0, false); \
764 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[10], (keynum_t)'m', NULL, 0, 0, 0, false); \
766 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[11], (keynum_t)'b', NULL, 0, 0, 0, false); \
768 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[12], (keynum_t)'q', NULL, 0, 0, 0, false); \
770 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, false); \
772 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, false); \
774 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[15], K_SPACE, NULL, 0, 0, 0, false); \
776 /////////////////////
780 static void IN_Move_TouchScreen_SteelStorm(void)
784 float xscale, yscale;
785 float move[3], aim[3];
786 static qboolean oldbuttons[128];
787 static qboolean buttons[128];
788 keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest;
789 memcpy(oldbuttons, buttons, sizeof(oldbuttons));
790 memset(multitouchs, 0, sizeof(multitouchs));
792 for (i = 0, numfingers = 0; i < MAXFINGERS - 1; i++)
793 if (multitouch[i][0])
797 Enable this to use a mouse as a touch device (it may conflict with the iamexclusive parameter if a finger is also reported as a mouse at the same location
800 multitouch[MAXFINGERS-1][0] = SDL_GetMouseState(&x, &y) ? 11 : 0;
801 multitouch[MAXFINGERS-1][1] = (float)x / vid.width;
802 multitouch[MAXFINGERS-1][2] = (float)y / vid.height;
806 // disable it so it doesn't get stuck, because SDL seems to stop updating it if there are more than 1 finger on screen
807 multitouch[MAXFINGERS-1][0] = 0;
810 // TODO: make touchscreen areas controlled by a config file or the VMs. THIS IS A MESS!
811 // TODO: can't just clear buttons[] when entering a new keydest, some keys would remain pressed
812 // SS:BR menuqc has many peculiarities, including that it can't accept more than one command per frame and pressing and releasing on the same frame
814 // Tuned for the SGS3, use it's value as a base. CLEAN THIS.
815 xscale = vid_touchscreen_density.value / 2.0f;
816 yscale = vid_touchscreen_density.value / 2.0f;
820 Vid_ClearAllTouchscreenAreas(14);
821 VID_TouchscreenArea( 0, 0, 160, 64, 64, "gfx/gui/touch_menu_button.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, false);
824 if (steelstorm_showing_map && steelstorm_showing_map->integer) // FIXME: another hack to be removed when touchscreen areas go to QC
826 VID_TouchscreenArea( 0, 0, 0, vid_conwidth.value, vid_conheight.value, NULL , 0.0f, NULL, NULL, &buttons[10], (keynum_t)'m', NULL, 0, 0, 0, false);
827 Vid_ClearAllTouchscreenAreas(10);
829 else if (steelstorm_showing_mousecursor && steelstorm_showing_mousecursor->integer)
831 // in_windowmouse_x* is in screen resolution coordinates, not console resolution
832 VID_TouchscreenCursor((float)in_windowmouse_x/vid_width.value*vid_conwidth.value, (float)in_windowmouse_y/vid_height.value*vid_conheight.value, 192*xscale, 192*yscale, &buttons[0], K_MOUSE1);
833 Vid_ClearAllTouchscreenAreas(0);
837 VID_TouchscreenCursor(0, 0, 0, 0, &buttons[0], K_MOUSE1);
839 VID_TouchscreenArea( 2,16*xscale,-240*yscale, 224*xscale, 224*yscale, "gfx/gui/touch_l_thumb_dpad.tga", 0.0f, NULL, move, &buttons[1], (keynum_t)0, NULL, 0.15, 112*xscale, 112*yscale, false);
841 VID_TouchscreenArea( 3,-240*xscale,-160*yscale, 224*xscale, 128*yscale, "gfx/gui/touch_r_thumb_turn_n_shoot.tga" , 0.0f, NULL, NULL, 0, (keynum_t)0, NULL, 0, 56*xscale, 0, false);
842 VID_TouchscreenArea( 3,-240*xscale,-256*yscale, 224*xscale, 224*yscale, NULL , 0.0f, NULL, aim, &buttons[2], (keynum_t)0, NULL, 0.2, 56*xscale, 0, false);
844 VID_TouchscreenArea( 2, (vid_conwidth.value / 2) - 128,-80, 256, 80, NULL, 0.0f, NULL, NULL, &buttons[3], K_SHIFT, NULL, 0, 0, 0, true);
846 VID_TouchscreenArea( 3,-240*xscale,-256*yscale, 224*xscale, 64*yscale, "gfx/gui/touch_secondary_slide.tga", 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 56*xscale, 0, false);
847 VID_TouchscreenArea( 3,-240*xscale,-256*yscale, 224*xscale, 160*yscale, NULL , 0.0f, NULL, NULL, &buttons[9], K_MOUSE3, NULL, 0.2, 56*xscale, 0, false);
849 VID_TouchscreenArea( 1,-100, 0, 100, 100, NULL , 0.0f, NULL, NULL, &buttons[10], (keynum_t)'m', NULL, 0, 0, 0, true);
850 VID_TouchscreenArea( 1,-100, 120, 100, 100, NULL , 0.0f, NULL, NULL, &buttons[11], (keynum_t)'b', NULL, 0, 0, 0, true);
851 VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[12], (keynum_t)'q', NULL, 0, 0, 0, true);
852 if (developer.integer)
853 VID_TouchscreenArea( 0, 0, 96, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, true);
855 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, false);
856 VID_TouchscreenArea( 0, 0, 160, 64, 64, "gfx/gui/touch_menu_button.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, true);
857 switch(cl.activeweapon)
860 VID_TouchscreenArea( 2, 16*xscale,-320*yscale, 224*xscale, 64*yscale, "gfx/gui/touch_booster.tga" , 0.0f, NULL, NULL, &buttons[15], K_SPACE, NULL, 0, 0, 0, true);
863 VID_TouchscreenArea( 2, 16*xscale,-320*yscale, 224*xscale, 64*yscale, "gfx/gui/touch_shockwave.tga" , 0.0f, NULL, NULL, &buttons[15], K_SPACE, NULL, 0, 0, 0, true);
866 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[15], K_SPACE, NULL, 0, 0, 0, false);
871 if (!steelstorm_showing_mousecursor || !steelstorm_showing_mousecursor->integer)
873 Vid_ClearAllTouchscreenAreas(14);
874 // this way we can skip cutscenes
875 VID_TouchscreenArea( 0, 0, 0, vid_conwidth.value, vid_conheight.value, NULL , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, false);
879 // in_windowmouse_x* is in screen resolution coordinates, not console resolution
880 VID_TouchscreenCursor((float)in_windowmouse_x/vid_width.value*vid_conwidth.value, (float)in_windowmouse_y/vid_height.value*vid_conheight.value, 192*xscale, 192*yscale, &buttons[0], K_MOUSE1);
881 Vid_ClearAllTouchscreenAreas(0);
886 if (VID_ShowingKeyboard() && (float)in_windowmouse_y > vid_height.value / 2 - 10)
887 in_windowmouse_y = 128;
889 cl.cmd.forwardmove -= move[1] * cl_forwardspeed.value;
890 cl.cmd.sidemove += move[0] * cl_sidespeed.value;
891 cl.viewangles[0] += aim[1] * cl_pitchspeed.value * cl.realframetime;
892 cl.viewangles[1] -= aim[0] * cl_yawspeed.value * cl.realframetime;
895 static void IN_Move_TouchScreen_Quake(void)
898 float move[3], aim[3], click[3];
899 static qboolean oldbuttons[128];
900 static qboolean buttons[128];
901 keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest;
902 memcpy(oldbuttons, buttons, sizeof(oldbuttons));
903 memset(multitouchs, 0, sizeof(multitouchs));
905 // simple quake controls
906 multitouch[MAXFINGERS-1][0] = SDL_GetMouseState(&x, &y);
907 multitouch[MAXFINGERS-1][1] = x * 32768 / vid.width;
908 multitouch[MAXFINGERS-1][2] = y * 32768 / vid.height;
910 // top of screen is toggleconsole and K_ESCAPE
914 VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, true);
915 VID_TouchscreenArea( 0, 64, 0, 64, 64, "gfx/touch_menu.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, true);
916 if (!VID_ShowingKeyboard())
918 // user entered a command, close the console now
919 Con_ToggleConsole_f();
921 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[15], (keynum_t)0, NULL, 0, 0, 0, true);
922 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, move, &buttons[0], K_MOUSE4, NULL, 0, 0, 0, true);
923 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, aim, &buttons[1], K_MOUSE5, NULL, 0, 0, 0, true);
924 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, click,&buttons[2], K_MOUSE1, NULL, 0, 0, 0, true);
925 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[3], K_SPACE, NULL, 0, 0, 0, true);
926 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 0, 0, true);
929 VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, true);
930 VID_TouchscreenArea( 0, 64, 0, 64, 64, "gfx/touch_menu.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, true);
931 VID_TouchscreenArea( 2, 0,-128, 128, 128, "gfx/touch_movebutton.tga" , 0.0f, NULL, move, &buttons[0], K_MOUSE4, NULL, 0, 0, 0, true);
932 VID_TouchscreenArea( 3,-128,-128, 128, 128, "gfx/touch_aimbutton.tga" , 0.0f, NULL, aim, &buttons[1], K_MOUSE5, NULL, 0, 0, 0, true);
933 VID_TouchscreenArea( 2, 0,-160, 64, 32, "gfx/touch_jumpbutton.tga" , 0.0f, NULL, NULL, &buttons[3], K_SPACE, NULL, 0, 0, 0, true);
934 VID_TouchscreenArea( 3,-128,-160, 64, 32, "gfx/touch_attackbutton.tga" , 0.0f, NULL, NULL, &buttons[2], K_MOUSE1, NULL, 0, 0, 0, true);
935 VID_TouchscreenArea( 3, -64,-160, 64, 32, "gfx/touch_attack2button.tga", 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 0, 0, true);
939 VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, true);
940 VID_TouchscreenArea( 0, 64, 0, 64, 64, "gfx/touch_menu.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, true);
941 // in menus, an icon in the corner activates keyboard
942 VID_TouchscreenArea( 2, 0, -32, 32, 32, "gfx/touch_keyboard.tga" , 0.0f, NULL, NULL, &buttons[15], (keynum_t)0, NULL, 0, 0, 0, true);
944 VID_ShowKeyboard(true);
945 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, move, &buttons[0], K_MOUSE4, NULL, 0, 0, 0, true);
946 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, aim, &buttons[1], K_MOUSE5, NULL, 0, 0, 0, true);
947 VID_TouchscreenArea(16, -320,-480,640, 960, NULL , 0.0f, NULL, click,&buttons[2], K_MOUSE1, NULL, 0, 0, 0, true);
948 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[3], K_SPACE, NULL, 0, 0, 0, true);
949 VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 0, 0, true);
952 in_windowmouse_x = x;
953 in_windowmouse_y = y;
958 cl.cmd.forwardmove -= move[1] * cl_forwardspeed.value;
959 cl.cmd.sidemove += move[0] * cl_sidespeed.value;
960 cl.viewangles[0] += aim[1] * cl_pitchspeed.value * cl.realframetime;
961 cl.viewangles[1] -= aim[0] * cl_yawspeed.value * cl.realframetime;
966 static int old_x = 0, old_y = 0;
967 static int stuck = 0;
968 static keydest_t oldkeydest;
969 static qboolean oldshowkeyboard;
971 vid_joystate_t joystate;
972 keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest;
974 scr_numtouchscreenareas = 0;
976 // Only apply the new keyboard state if the input changes.
977 if (keydest != oldkeydest || !!vid_touchscreen_showkeyboard.integer != oldshowkeyboard)
981 case key_console: VID_ShowKeyboard(true);break;
982 case key_message: VID_ShowKeyboard(true);break;
983 default: VID_ShowKeyboard(!!vid_touchscreen_showkeyboard.integer); break;
986 oldkeydest = keydest;
987 oldshowkeyboard = !!vid_touchscreen_showkeyboard.integer;
989 if (vid_touchscreen.integer)
993 case GAME_STEELSTORM:
994 IN_Move_TouchScreen_SteelStorm();
997 IN_Move_TouchScreen_Quake();
1005 if (vid_stick_mouse.integer || !vid_usingmouse_relativeworks)
1007 // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
1008 // window grabbing. --blub
1010 // we need 2 frames to initialize the center position
1013 #if SDL_MAJOR_VERSION == 1
1014 SDL_WarpMouse(win_half_width, win_half_height);
1016 SDL_WarpMouseInWindow(window, win_half_width, win_half_height);
1018 SDL_GetMouseState(&x, &y);
1019 SDL_GetRelativeMouseState(&x, &y);
1022 SDL_GetRelativeMouseState(&x, &y);
1023 in_mouse_x = x + old_x;
1024 in_mouse_y = y + old_y;
1025 SDL_GetMouseState(&x, &y);
1026 old_x = x - win_half_width;
1027 old_y = y - win_half_height;
1028 #if SDL_MAJOR_VERSION == 1
1029 SDL_WarpMouse(win_half_width, win_half_height);
1031 SDL_WarpMouseInWindow(window, win_half_width, win_half_height);
1035 SDL_GetRelativeMouseState( &x, &y );
1041 SDL_GetMouseState(&x, &y);
1042 in_windowmouse_x = x;
1043 in_windowmouse_y = y;
1046 VID_BuildJoyState(&joystate);
1047 VID_ApplyJoyState(&joystate);
1050 /////////////////////
1054 #ifdef SDL_R_RESTART
1055 static qboolean sdl_needs_restart;
1056 static void sdl_start(void)
1059 static void sdl_shutdown(void)
1061 sdl_needs_restart = false;
1063 static void sdl_newmap(void)
1068 static keynum_t buttonremap[] =
1073 #if SDL_MAJOR_VERSION == 1
1074 // TODO Find out how SDL maps these buttons. It looks like we should
1075 // still include these for sdl2? At least the button indexes don't
1076 // differ between SDL1 and SDL2 for me, thus this array should stay the
1077 // same (in X11 button order).
1096 #if SDL_MAJOR_VERSION == 1
1098 void Sys_SendKeyEvents( void )
1100 static qboolean sound_active = true;
1104 VID_EnableJoystick(true);
1106 while( SDL_PollEvent( &event ) )
1107 switch( event.type ) {
1113 keycode = MapKey(event.key.keysym.sym);
1114 if (!VID_JoyBlockEmulatedKeys(keycode))
1116 if(keycode == K_NUMLOCK || keycode == K_CAPSLOCK)
1118 // simulate down followed by up
1119 Key_Event(keycode, event.key.keysym.unicode, true);
1120 Key_Event(keycode, event.key.keysym.unicode, false);
1123 Key_Event(keycode, event.key.keysym.unicode, (event.key.state == SDL_PRESSED));
1126 case SDL_ACTIVEEVENT:
1127 if( event.active.state & SDL_APPACTIVE )
1129 if( event.active.gain )
1135 case SDL_MOUSEBUTTONDOWN:
1136 case SDL_MOUSEBUTTONUP:
1137 if (!vid_touchscreen.integer)
1138 if (event.button.button > 0 && event.button.button <= ARRAY_SIZE(buttonremap))
1139 Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
1141 case SDL_JOYBUTTONDOWN:
1142 case SDL_JOYBUTTONUP:
1143 case SDL_JOYAXISMOTION:
1144 case SDL_JOYBALLMOTION:
1145 case SDL_JOYHATMOTION:
1147 case SDL_VIDEOEXPOSE:
1149 case SDL_VIDEORESIZE:
1150 if(vid_resizable.integer < 2 || vid_isfullscreen)
1152 vid.width = event.resize.w;
1153 vid.height = event.resize.h;
1154 if (!vid_isfullscreen)
1155 video_screen = SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
1156 #ifdef SDL_R_RESTART
1157 // better not call R_Modules_Restart from here directly, as this may wreak havoc...
1158 // so, let's better queue it for next frame
1159 if(!sdl_needs_restart)
1161 Cbuf_AddText("\nr_restart\n");
1162 sdl_needs_restart = true;
1167 #if SDL_MAJOR_VERSION != 1
1168 case SDL_TEXTEDITING:
1173 case SDL_MOUSEMOTION:
1176 Con_DPrintf("Received unrecognized SDL_Event type 0x%x\n", event.type);
1180 // enable/disable sound on focus gain/loss
1181 if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
1186 sound_active = true;
1194 sound_active = false;
1201 //#define DEBUGSDLEVENTS
1204 void Sys_SendKeyEvents( void )
1206 static qboolean sound_active = true;
1213 VID_EnableJoystick(true);
1215 while( SDL_PollEvent( &event ) )
1217 switch( event.type ) {
1219 #ifdef DEBUGSDLEVENTS
1220 Con_DPrintf("SDL_Event: SDL_QUIT\n");
1226 #ifdef DEBUGSDLEVENTS
1227 if (event.type == SDL_KEYDOWN)
1228 Con_DPrintf("SDL_Event: SDL_KEYDOWN %i\n", event.key.keysym.sym);
1230 Con_DPrintf("SDL_Event: SDL_KEYUP %i\n", event.key.keysym.sym);
1232 keycode = MapKey(event.key.keysym.sym);
1233 isdown = (event.key.state == SDL_PRESSED);
1237 if(SDL_PollEvent(&event))
1239 if(event.type == SDL_TEXTINPUT)
1241 // combine key code from SDL_KEYDOWN event and character
1242 // from SDL_TEXTINPUT event in a single Key_Event call
1243 #ifdef DEBUGSDLEVENTS
1244 Con_DPrintf("SDL_Event: SDL_TEXTINPUT - text: %s\n", event.text.text);
1246 unicode = u8_getchar_utf8_enabled(event.text.text + (int)u8_bytelen(event.text.text, 0), NULL);
1250 if (!VID_JoyBlockEmulatedKeys(keycode))
1251 Key_Event(keycode, 0, isdown);
1256 if (!VID_JoyBlockEmulatedKeys(keycode))
1257 Key_Event(keycode, unicode, isdown);
1259 case SDL_MOUSEBUTTONDOWN:
1260 case SDL_MOUSEBUTTONUP:
1261 #ifdef DEBUGSDLEVENTS
1262 if (event.type == SDL_MOUSEBUTTONDOWN)
1263 Con_DPrintf("SDL_Event: SDL_MOUSEBUTTONDOWN\n");
1265 Con_DPrintf("SDL_Event: SDL_MOUSEBUTTONUP\n");
1267 if (!vid_touchscreen.integer)
1268 if (event.button.button > 0 && event.button.button <= ARRAY_SIZE(buttonremap))
1269 Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
1271 case SDL_MOUSEWHEEL:
1272 // TODO support wheel x direction.
1276 Key_Event( K_MWHEELUP, 0, true );
1277 Key_Event( K_MWHEELUP, 0, false );
1281 Key_Event( K_MWHEELDOWN, 0, true );
1282 Key_Event( K_MWHEELDOWN, 0, false );
1285 case SDL_JOYBUTTONDOWN:
1286 case SDL_JOYBUTTONUP:
1287 case SDL_JOYAXISMOTION:
1288 case SDL_JOYBALLMOTION:
1289 case SDL_JOYHATMOTION:
1290 #ifdef DEBUGSDLEVENTS
1291 Con_DPrintf("SDL_Event: SDL_JOY*\n");
1294 case SDL_WINDOWEVENT:
1295 #ifdef DEBUGSDLEVENTS
1296 Con_DPrintf("SDL_Event: SDL_WINDOWEVENT %i\n", (int)event.window.event);
1298 //if (event.window.windowID == window) // how to compare?
1300 switch(event.window.event)
1302 case SDL_WINDOWEVENT_SHOWN:
1305 case SDL_WINDOWEVENT_HIDDEN:
1308 case SDL_WINDOWEVENT_EXPOSED:
1309 #ifdef DEBUGSDLEVENTS
1310 Con_DPrintf("SDL_Event: SDL_WINDOWEVENT_EXPOSED\n");
1313 case SDL_WINDOWEVENT_MOVED:
1315 case SDL_WINDOWEVENT_RESIZED:
1316 if(vid_resizable.integer < 2)
1318 vid.width = event.window.data1;
1319 vid.height = event.window.data2;
1320 #ifdef SDL_R_RESTART
1321 // better not call R_Modules_Restart from here directly, as this may wreak havoc...
1322 // so, let's better queue it for next frame
1323 if(!sdl_needs_restart)
1325 Cbuf_AddText("\nr_restart\n");
1326 sdl_needs_restart = true;
1331 case SDL_WINDOWEVENT_MINIMIZED:
1333 case SDL_WINDOWEVENT_MAXIMIZED:
1335 case SDL_WINDOWEVENT_RESTORED:
1337 case SDL_WINDOWEVENT_ENTER:
1339 case SDL_WINDOWEVENT_LEAVE:
1341 case SDL_WINDOWEVENT_FOCUS_GAINED:
1342 vid_hasfocus = true;
1344 case SDL_WINDOWEVENT_FOCUS_LOST:
1345 vid_hasfocus = false;
1347 case SDL_WINDOWEVENT_CLOSE:
1353 case SDL_TEXTEDITING:
1354 #ifdef DEBUGSDLEVENTS
1355 Con_DPrintf("SDL_Event: SDL_TEXTEDITING - composition = %s, cursor = %d, selection lenght = %d\n", event.edit.text, event.edit.start, event.edit.length);
1357 // FIXME! this is where composition gets supported
1360 #ifdef DEBUGSDLEVENTS
1361 Con_DPrintf("SDL_Event: SDL_TEXTINPUT - text: %s\n", event.text.text);
1363 // convert utf8 string to char
1364 // NOTE: this code is supposed to run even if utf8enable is 0
1365 unicode = u8_getchar_utf8_enabled(event.text.text + (int)u8_bytelen(event.text.text, 0), NULL);
1366 Key_Event(K_TEXT, unicode, true);
1367 Key_Event(K_TEXT, unicode, false);
1369 case SDL_MOUSEMOTION:
1371 case SDL_FINGERDOWN:
1372 #ifdef DEBUGSDLEVENTS
1373 Con_DPrintf("SDL_FINGERDOWN for finger %i\n", (int)event.tfinger.fingerId);
1375 for (i = 0;i < MAXFINGERS-1;i++)
1377 if (!multitouch[i][0])
1379 multitouch[i][0] = event.tfinger.fingerId + 1;
1380 multitouch[i][1] = event.tfinger.x;
1381 multitouch[i][2] = event.tfinger.y;
1382 // TODO: use event.tfinger.pressure?
1386 if (i == MAXFINGERS-1)
1387 Con_DPrintf("Too many fingers at once!\n");
1390 #ifdef DEBUGSDLEVENTS
1391 Con_DPrintf("SDL_FINGERUP for finger %i\n", (int)event.tfinger.fingerId);
1393 for (i = 0;i < MAXFINGERS-1;i++)
1395 if (multitouch[i][0] == event.tfinger.fingerId + 1)
1397 multitouch[i][0] = 0;
1401 if (i == MAXFINGERS-1)
1402 Con_DPrintf("No SDL_FINGERDOWN event matches this SDL_FINGERMOTION event\n");
1404 case SDL_FINGERMOTION:
1405 #ifdef DEBUGSDLEVENTS
1406 Con_DPrintf("SDL_FINGERMOTION for finger %i\n", (int)event.tfinger.fingerId);
1408 for (i = 0;i < MAXFINGERS-1;i++)
1410 if (multitouch[i][0] == event.tfinger.fingerId + 1)
1412 multitouch[i][1] = event.tfinger.x;
1413 multitouch[i][2] = event.tfinger.y;
1417 if (i == MAXFINGERS-1)
1418 Con_DPrintf("No SDL_FINGERDOWN event matches this SDL_FINGERMOTION event\n");
1421 #ifdef DEBUGSDLEVENTS
1422 Con_DPrintf("Received unrecognized SDL_Event type 0x%x\n", event.type);
1427 // enable/disable sound on focus gain/loss
1428 if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
1433 sound_active = true;
1441 sound_active = false;
1454 #include <OpenGLES/ES2/gl.h>
1456 #include <SDL_opengles.h>
1459 //#define PRECALL //Con_Printf("GLCALL %s:%i\n", __FILE__, __LINE__)
1462 GLboolean wrapglIsBuffer(GLuint buffer) {PRECALL;return glIsBuffer(buffer);POSTCALL;}
1463 GLboolean wrapglIsEnabled(GLenum cap) {PRECALL;return glIsEnabled(cap);POSTCALL;}
1464 GLboolean wrapglIsFramebuffer(GLuint framebuffer) {PRECALL;return glIsFramebuffer(framebuffer);POSTCALL;}
1465 //GLboolean wrapglIsQuery(GLuint qid) {PRECALL;return glIsQuery(qid);POSTCALL;}
1466 GLboolean wrapglIsRenderbuffer(GLuint renderbuffer) {PRECALL;return glIsRenderbuffer(renderbuffer);POSTCALL;}
1467 //GLboolean wrapglUnmapBuffer(GLenum target) {PRECALL;return glUnmapBuffer(target);POSTCALL;}
1468 GLenum wrapglCheckFramebufferStatus(GLenum target) {PRECALL;return glCheckFramebufferStatus(target);POSTCALL;}
1469 GLenum wrapglGetError(void) {PRECALL;return glGetError();POSTCALL;}
1470 GLuint wrapglCreateProgram(void) {PRECALL;return glCreateProgram();POSTCALL;}
1471 GLuint wrapglCreateShader(GLenum shaderType) {PRECALL;return glCreateShader(shaderType);POSTCALL;}
1472 //GLuint wrapglGetHandle(GLenum pname) {PRECALL;return glGetHandle(pname);POSTCALL;}
1473 GLint wrapglGetAttribLocation(GLuint programObj, const GLchar *name) {PRECALL;return glGetAttribLocation(programObj, name);POSTCALL;}
1474 GLint wrapglGetUniformLocation(GLuint programObj, const GLchar *name) {PRECALL;return glGetUniformLocation(programObj, name);POSTCALL;}
1475 //GLvoid* wrapglMapBuffer(GLenum target, GLenum access) {PRECALL;return glMapBuffer(target, access);POSTCALL;}
1476 const GLubyte* wrapglGetString(GLenum name) {PRECALL;return (const GLubyte*)glGetString(name);POSTCALL;}
1477 void wrapglActiveStencilFace(GLenum e) {PRECALL;Con_Printf("glActiveStencilFace(e)\n");POSTCALL;}
1478 void wrapglActiveTexture(GLenum e) {PRECALL;glActiveTexture(e);POSTCALL;}
1479 void wrapglArrayElement(GLint i) {PRECALL;Con_Printf("glArrayElement(i)\n");POSTCALL;}
1480 void wrapglAttachShader(GLuint containerObj, GLuint obj) {PRECALL;glAttachShader(containerObj, obj);POSTCALL;}
1481 //void wrapglBeginQuery(GLenum target, GLuint qid) {PRECALL;glBeginQuery(target, qid);POSTCALL;}
1482 void wrapglBindAttribLocation(GLuint programObj, GLuint index, const GLchar *name) {PRECALL;glBindAttribLocation(programObj, index, name);POSTCALL;}
1483 //void wrapglBindFragDataLocation(GLuint programObj, GLuint index, const GLchar *name) {PRECALL;glBindFragDataLocation(programObj, index, name);POSTCALL;}
1484 void wrapglBindBuffer(GLenum target, GLuint buffer) {PRECALL;glBindBuffer(target, buffer);POSTCALL;}
1485 void wrapglBindFramebuffer(GLenum target, GLuint framebuffer) {PRECALL;glBindFramebuffer(target, framebuffer);POSTCALL;}
1486 void wrapglBindRenderbuffer(GLenum target, GLuint renderbuffer) {PRECALL;glBindRenderbuffer(target, renderbuffer);POSTCALL;}
1487 void wrapglBindTexture(GLenum target, GLuint texture) {PRECALL;glBindTexture(target, texture);POSTCALL;}
1488 void wrapglBlendEquation(GLenum e) {PRECALL;glBlendEquation(e);POSTCALL;}
1489 void wrapglBlendFunc(GLenum sfactor, GLenum dfactor) {PRECALL;glBlendFunc(sfactor, dfactor);POSTCALL;}
1490 void wrapglBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) {PRECALL;glBufferData(target, size, data, usage);POSTCALL;}
1491 void wrapglBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) {PRECALL;glBufferSubData(target, offset, size, data);POSTCALL;}
1492 void wrapglClear(GLbitfield mask) {PRECALL;glClear(mask);POSTCALL;}
1493 void wrapglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {PRECALL;glClearColor(red, green, blue, alpha);POSTCALL;}
1494 void wrapglClearDepth(GLclampd depth) {PRECALL;/*Con_Printf("glClearDepth(%f)\n", depth);glClearDepthf((float)depth);*/POSTCALL;}
1495 void wrapglClearStencil(GLint s) {PRECALL;glClearStencil(s);POSTCALL;}
1496 void wrapglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {PRECALL;glColorMask(red, green, blue, alpha);POSTCALL;}
1497 void wrapglCompileShader(GLuint shaderObj) {PRECALL;glCompileShader(shaderObj);POSTCALL;}
1498 void wrapglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) {PRECALL;glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);POSTCALL;}
1499 void wrapglCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) {PRECALL;Con_Printf("glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data)\n");POSTCALL;}
1500 void wrapglCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) {PRECALL;glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);POSTCALL;}
1501 void wrapglCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) {PRECALL;Con_Printf("glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data)\n");POSTCALL;}
1502 void wrapglCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {PRECALL;glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);POSTCALL;}
1503 void wrapglCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {PRECALL;glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);POSTCALL;}
1504 void wrapglCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {PRECALL;Con_Printf("glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height)\n");POSTCALL;}
1505 void wrapglCullFace(GLenum mode) {PRECALL;glCullFace(mode);POSTCALL;}
1506 void wrapglDeleteBuffers(GLsizei n, const GLuint *buffers) {PRECALL;glDeleteBuffers(n, buffers);POSTCALL;}
1507 void wrapglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) {PRECALL;glDeleteFramebuffers(n, framebuffers);POSTCALL;}
1508 void wrapglDeleteShader(GLuint obj) {PRECALL;glDeleteShader(obj);POSTCALL;}
1509 void wrapglDeleteProgram(GLuint obj) {PRECALL;glDeleteProgram(obj);POSTCALL;}
1510 //void wrapglDeleteQueries(GLsizei n, const GLuint *ids) {PRECALL;glDeleteQueries(n, ids);POSTCALL;}
1511 void wrapglDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) {PRECALL;glDeleteRenderbuffers(n, renderbuffers);POSTCALL;}
1512 void wrapglDeleteTextures(GLsizei n, const GLuint *textures) {PRECALL;glDeleteTextures(n, textures);POSTCALL;}
1513 void wrapglDepthFunc(GLenum func) {PRECALL;glDepthFunc(func);POSTCALL;}
1514 void wrapglDepthMask(GLboolean flag) {PRECALL;glDepthMask(flag);POSTCALL;}
1515 //void wrapglDepthRange(GLclampd near_val, GLclampd far_val) {PRECALL;glDepthRangef((float)near_val, (float)far_val);POSTCALL;}
1516 void wrapglDepthRangef(GLclampf near_val, GLclampf far_val) {PRECALL;glDepthRangef(near_val, far_val);POSTCALL;}
1517 void wrapglDetachShader(GLuint containerObj, GLuint attachedObj) {PRECALL;glDetachShader(containerObj, attachedObj);POSTCALL;}
1518 void wrapglDisable(GLenum cap) {PRECALL;glDisable(cap);POSTCALL;}
1519 void wrapglDisableVertexAttribArray(GLuint index) {PRECALL;glDisableVertexAttribArray(index);POSTCALL;}
1520 void wrapglDrawArrays(GLenum mode, GLint first, GLsizei count) {PRECALL;glDrawArrays(mode, first, count);POSTCALL;}
1521 void wrapglDrawBuffer(GLenum mode) {PRECALL;Con_Printf("glDrawBuffer(mode)\n");POSTCALL;}
1522 void wrapglDrawBuffers(GLsizei n, const GLenum *bufs) {PRECALL;Con_Printf("glDrawBuffers(n, bufs)\n");POSTCALL;}
1523 void wrapglDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {PRECALL;glDrawElements(mode, count, type, indices);POSTCALL;}
1524 //void wrapglDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) {PRECALL;glDrawRangeElements(mode, start, end, count, type, indices);POSTCALL;}
1525 //void wrapglDrawRangeElementsEXT(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) {PRECALL;glDrawRangeElements(mode, start, end, count, type, indices);POSTCALL;}
1526 void wrapglEnable(GLenum cap) {PRECALL;glEnable(cap);POSTCALL;}
1527 void wrapglEnableVertexAttribArray(GLuint index) {PRECALL;glEnableVertexAttribArray(index);POSTCALL;}
1528 //void wrapglEndQuery(GLenum target) {PRECALL;glEndQuery(target);POSTCALL;}
1529 void wrapglFinish(void) {PRECALL;glFinish();POSTCALL;}
1530 void wrapglFlush(void) {PRECALL;glFlush();POSTCALL;}
1531 void wrapglFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {PRECALL;glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);POSTCALL;}
1532 void wrapglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {PRECALL;glFramebufferTexture2D(target, attachment, textarget, texture, level);POSTCALL;}
1533 void wrapglFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {PRECALL;Con_Printf("glFramebufferTexture3D()\n");POSTCALL;}
1534 void wrapglGenBuffers(GLsizei n, GLuint *buffers) {PRECALL;glGenBuffers(n, buffers);POSTCALL;}
1535 void wrapglGenFramebuffers(GLsizei n, GLuint *framebuffers) {PRECALL;glGenFramebuffers(n, framebuffers);POSTCALL;}
1536 //void wrapglGenQueries(GLsizei n, GLuint *ids) {PRECALL;glGenQueries(n, ids);POSTCALL;}
1537 void wrapglGenRenderbuffers(GLsizei n, GLuint *renderbuffers) {PRECALL;glGenRenderbuffers(n, renderbuffers);POSTCALL;}
1538 void wrapglGenTextures(GLsizei n, GLuint *textures) {PRECALL;glGenTextures(n, textures);POSTCALL;}
1539 void wrapglGenerateMipmap(GLenum target) {PRECALL;glGenerateMipmap(target);POSTCALL;}
1540 void wrapglGetActiveAttrib(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {PRECALL;glGetActiveAttrib(programObj, index, maxLength, length, size, type, name);POSTCALL;}
1541 void wrapglGetActiveUniform(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {PRECALL;glGetActiveUniform(programObj, index, maxLength, length, size, type, name);POSTCALL;}
1542 void wrapglGetAttachedShaders(GLuint containerObj, GLsizei maxCount, GLsizei *count, GLuint *obj) {PRECALL;glGetAttachedShaders(containerObj, maxCount, count, obj);POSTCALL;}
1543 void wrapglGetBooleanv(GLenum pname, GLboolean *params) {PRECALL;glGetBooleanv(pname, params);POSTCALL;}
1544 void wrapglGetCompressedTexImage(GLenum target, GLint lod, void *img) {PRECALL;Con_Printf("glGetCompressedTexImage(target, lod, img)\n");POSTCALL;}
1545 void wrapglGetDoublev(GLenum pname, GLdouble *params) {PRECALL;Con_Printf("glGetDoublev(pname, params)\n");POSTCALL;}
1546 void wrapglGetFloatv(GLenum pname, GLfloat *params) {PRECALL;glGetFloatv(pname, params);POSTCALL;}
1547 void wrapglGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params) {PRECALL;glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);POSTCALL;}
1548 void wrapglGetShaderInfoLog(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *infoLog) {PRECALL;glGetShaderInfoLog(obj, maxLength, length, infoLog);POSTCALL;}
1549 void wrapglGetProgramInfoLog(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *infoLog) {PRECALL;glGetProgramInfoLog(obj, maxLength, length, infoLog);POSTCALL;}
1550 void wrapglGetIntegerv(GLenum pname, GLint *params) {PRECALL;glGetIntegerv(pname, params);POSTCALL;}
1551 void wrapglGetShaderiv(GLuint obj, GLenum pname, GLint *params) {PRECALL;glGetShaderiv(obj, pname, params);POSTCALL;}
1552 void wrapglGetProgramiv(GLuint obj, GLenum pname, GLint *params) {PRECALL;glGetProgramiv(obj, pname, params);POSTCALL;}
1553 //void wrapglGetQueryObjectiv(GLuint qid, GLenum pname, GLint *params) {PRECALL;glGetQueryObjectiv(qid, pname, params);POSTCALL;}
1554 //void wrapglGetQueryObjectuiv(GLuint qid, GLenum pname, GLuint *params) {PRECALL;glGetQueryObjectuiv(qid, pname, params);POSTCALL;}
1555 //void wrapglGetQueryiv(GLenum target, GLenum pname, GLint *params) {PRECALL;glGetQueryiv(target, pname, params);POSTCALL;}
1556 void wrapglGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) {PRECALL;glGetRenderbufferParameteriv(target, pname, params);POSTCALL;}
1557 void wrapglGetShaderSource(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *source) {PRECALL;glGetShaderSource(obj, maxLength, length, source);POSTCALL;}
1558 void wrapglGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels) {PRECALL;Con_Printf("glGetTexImage(target, level, format, type, pixels)\n");POSTCALL;}
1559 void wrapglGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params) {PRECALL;Con_Printf("glGetTexLevelParameterfv(target, level, pname, params)\n");POSTCALL;}
1560 void wrapglGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) {PRECALL;Con_Printf("glGetTexLevelParameteriv(target, level, pname, params)\n");POSTCALL;}
1561 void wrapglGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) {PRECALL;glGetTexParameterfv(target, pname, params);POSTCALL;}
1562 void wrapglGetTexParameteriv(GLenum target, GLenum pname, GLint *params) {PRECALL;glGetTexParameteriv(target, pname, params);POSTCALL;}
1563 void wrapglGetUniformfv(GLuint programObj, GLint location, GLfloat *params) {PRECALL;glGetUniformfv(programObj, location, params);POSTCALL;}
1564 void wrapglGetUniformiv(GLuint programObj, GLint location, GLint *params) {PRECALL;glGetUniformiv(programObj, location, params);POSTCALL;}
1565 void wrapglHint(GLenum target, GLenum mode) {PRECALL;glHint(target, mode);POSTCALL;}
1566 void wrapglLinkProgram(GLuint programObj) {PRECALL;glLinkProgram(programObj);POSTCALL;}
1567 void wrapglPixelStorei(GLenum pname, GLint param) {PRECALL;glPixelStorei(pname, param);POSTCALL;}
1568 void wrapglPointSize(GLfloat size) {PRECALL;Con_Printf("glPointSize(size)\n");POSTCALL;}
1569 //void wrapglPolygonMode(GLenum face, GLenum mode) {PRECALL;Con_Printf("glPolygonMode(face, mode)\n");POSTCALL;}
1570 void wrapglPolygonOffset(GLfloat factor, GLfloat units) {PRECALL;glPolygonOffset(factor, units);POSTCALL;}
1571 void wrapglPolygonStipple(const GLubyte *mask) {PRECALL;Con_Printf("glPolygonStipple(mask)\n");POSTCALL;}
1572 void wrapglReadBuffer(GLenum mode) {PRECALL;Con_Printf("glReadBuffer(mode)\n");POSTCALL;}
1573 void wrapglReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {PRECALL;glReadPixels(x, y, width, height, format, type, pixels);POSTCALL;}
1574 void wrapglRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {PRECALL;glRenderbufferStorage(target, internalformat, width, height);POSTCALL;}
1575 void wrapglScissor(GLint x, GLint y, GLsizei width, GLsizei height) {PRECALL;glScissor(x, y, width, height);POSTCALL;}
1576 void wrapglShaderSource(GLuint shaderObj, GLsizei count, const GLchar **string, const GLint *length) {PRECALL;glShaderSource(shaderObj, count, string, length);POSTCALL;}
1577 void wrapglStencilFunc(GLenum func, GLint ref, GLuint mask) {PRECALL;glStencilFunc(func, ref, mask);POSTCALL;}
1578 void wrapglStencilFuncSeparate(GLenum func1, GLenum func2, GLint ref, GLuint mask) {PRECALL;Con_Printf("glStencilFuncSeparate(func1, func2, ref, mask)\n");POSTCALL;}
1579 void wrapglStencilMask(GLuint mask) {PRECALL;glStencilMask(mask);POSTCALL;}
1580 void wrapglStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {PRECALL;glStencilOp(fail, zfail, zpass);POSTCALL;}
1581 void wrapglStencilOpSeparate(GLenum e1, GLenum e2, GLenum e3, GLenum e4) {PRECALL;Con_Printf("glStencilOpSeparate(e1, e2, e3, e4)\n");POSTCALL;}
1582 void wrapglTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {PRECALL;glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels);POSTCALL;}
1583 void wrapglTexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {PRECALL;Con_Printf("glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels)\n");POSTCALL;}
1584 void wrapglTexParameterf(GLenum target, GLenum pname, GLfloat param) {PRECALL;glTexParameterf(target, pname, param);POSTCALL;}
1585 void wrapglTexParameterfv(GLenum target, GLenum pname, GLfloat *params) {PRECALL;glTexParameterfv(target, pname, params);POSTCALL;}
1586 void wrapglTexParameteri(GLenum target, GLenum pname, GLint param) {PRECALL;glTexParameteri(target, pname, param);POSTCALL;}
1587 void wrapglTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {PRECALL;glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);POSTCALL;}
1588 void wrapglTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) {PRECALL;Con_Printf("glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels)\n");POSTCALL;}
1589 void wrapglUniform1f(GLint location, GLfloat v0) {PRECALL;glUniform1f(location, v0);POSTCALL;}
1590 void wrapglUniform1fv(GLint location, GLsizei count, const GLfloat *value) {PRECALL;glUniform1fv(location, count, value);POSTCALL;}
1591 void wrapglUniform1i(GLint location, GLint v0) {PRECALL;glUniform1i(location, v0);POSTCALL;}
1592 void wrapglUniform1iv(GLint location, GLsizei count, const GLint *value) {PRECALL;glUniform1iv(location, count, value);POSTCALL;}
1593 void wrapglUniform2f(GLint location, GLfloat v0, GLfloat v1) {PRECALL;glUniform2f(location, v0, v1);POSTCALL;}
1594 void wrapglUniform2fv(GLint location, GLsizei count, const GLfloat *value) {PRECALL;glUniform2fv(location, count, value);POSTCALL;}
1595 void wrapglUniform2i(GLint location, GLint v0, GLint v1) {PRECALL;glUniform2i(location, v0, v1);POSTCALL;}
1596 void wrapglUniform2iv(GLint location, GLsizei count, const GLint *value) {PRECALL;glUniform2iv(location, count, value);POSTCALL;}
1597 void wrapglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {PRECALL;glUniform3f(location, v0, v1, v2);POSTCALL;}
1598 void wrapglUniform3fv(GLint location, GLsizei count, const GLfloat *value) {PRECALL;glUniform3fv(location, count, value);POSTCALL;}
1599 void wrapglUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {PRECALL;glUniform3i(location, v0, v1, v2);POSTCALL;}
1600 void wrapglUniform3iv(GLint location, GLsizei count, const GLint *value) {PRECALL;glUniform3iv(location, count, value);POSTCALL;}
1601 void wrapglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {PRECALL;glUniform4f(location, v0, v1, v2, v3);POSTCALL;}
1602 void wrapglUniform4fv(GLint location, GLsizei count, const GLfloat *value) {PRECALL;glUniform4fv(location, count, value);POSTCALL;}
1603 void wrapglUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {PRECALL;glUniform4i(location, v0, v1, v2, v3);POSTCALL;}
1604 void wrapglUniform4iv(GLint location, GLsizei count, const GLint *value) {PRECALL;glUniform4iv(location, count, value);POSTCALL;}
1605 void wrapglUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {PRECALL;glUniformMatrix2fv(location, count, transpose, value);POSTCALL;}
1606 void wrapglUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {PRECALL;glUniformMatrix3fv(location, count, transpose, value);POSTCALL;}
1607 void wrapglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {PRECALL;glUniformMatrix4fv(location, count, transpose, value);POSTCALL;}
1608 void wrapglUseProgram(GLuint programObj) {PRECALL;glUseProgram(programObj);POSTCALL;}
1609 void wrapglValidateProgram(GLuint programObj) {PRECALL;glValidateProgram(programObj);POSTCALL;}
1610 void wrapglVertex2f(GLfloat x, GLfloat y) {PRECALL;Con_Printf("glVertex2f(x, y)\n");POSTCALL;}
1611 void wrapglVertex3f(GLfloat x, GLfloat y, GLfloat z) {PRECALL;Con_Printf("glVertex3f(x, y, z)\n");POSTCALL;}
1612 void wrapglVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {PRECALL;Con_Printf("glVertex4f(x, y, z, w)\n");POSTCALL;}
1613 void wrapglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) {PRECALL;glVertexAttribPointer(index, size, type, normalized, stride, pointer);POSTCALL;}
1614 void wrapglVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {PRECALL;Con_Printf("glVertexPointer(size, type, stride, ptr)\n");POSTCALL;}
1615 void wrapglViewport(GLint x, GLint y, GLsizei width, GLsizei height) {PRECALL;glViewport(x, y, width, height);POSTCALL;}
1616 void wrapglVertexAttrib1f(GLuint index, GLfloat v0) {PRECALL;glVertexAttrib1f(index, v0);POSTCALL;}
1617 //void wrapglVertexAttrib1s(GLuint index, GLshort v0) {PRECALL;glVertexAttrib1s(index, v0);POSTCALL;}
1618 //void wrapglVertexAttrib1d(GLuint index, GLdouble v0) {PRECALL;glVertexAttrib1d(index, v0);POSTCALL;}
1619 void wrapglVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {PRECALL;glVertexAttrib2f(index, v0, v1);POSTCALL;}
1620 //void wrapglVertexAttrib2s(GLuint index, GLshort v0, GLshort v1) {PRECALL;glVertexAttrib2s(index, v0, v1);POSTCALL;}
1621 //void wrapglVertexAttrib2d(GLuint index, GLdouble v0, GLdouble v1) {PRECALL;glVertexAttrib2d(index, v0, v1);POSTCALL;}
1622 void wrapglVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {PRECALL;glVertexAttrib3f(index, v0, v1, v2);POSTCALL;}
1623 //void wrapglVertexAttrib3s(GLuint index, GLshort v0, GLshort v1, GLshort v2) {PRECALL;glVertexAttrib3s(index, v0, v1, v2);POSTCALL;}
1624 //void wrapglVertexAttrib3d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2) {PRECALL;glVertexAttrib3d(index, v0, v1, v2);POSTCALL;}
1625 void wrapglVertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {PRECALL;glVertexAttrib4f(index, v0, v1, v2, v3);POSTCALL;}
1626 //void wrapglVertexAttrib4s(GLuint index, GLshort v0, GLshort v1, GLshort v2, GLshort v3) {PRECALL;glVertexAttrib4s(index, v0, v1, v2, v3);POSTCALL;}
1627 //void wrapglVertexAttrib4d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) {PRECALL;glVertexAttrib4d(index, v0, v1, v2, v3);POSTCALL;}
1628 //void wrapglVertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) {PRECALL;glVertexAttrib4Nub(index, x, y, z, w);POSTCALL;}
1629 void wrapglVertexAttrib1fv(GLuint index, const GLfloat *v) {PRECALL;glVertexAttrib1fv(index, v);POSTCALL;}
1630 //void wrapglVertexAttrib1sv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib1sv(index, v);POSTCALL;}
1631 //void wrapglVertexAttrib1dv(GLuint index, const GLdouble *v) {PRECALL;glVertexAttrib1dv(index, v);POSTCALL;}
1632 void wrapglVertexAttrib2fv(GLuint index, const GLfloat *v) {PRECALL;glVertexAttrib2fv(index, v);POSTCALL;}
1633 //void wrapglVertexAttrib2sv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib2sv(index, v);POSTCALL;}
1634 //void wrapglVertexAttrib2dv(GLuint index, const GLdouble *v) {PRECALL;glVertexAttrib2dv(index, v);POSTCALL;}
1635 void wrapglVertexAttrib3fv(GLuint index, const GLfloat *v) {PRECALL;glVertexAttrib3fv(index, v);POSTCALL;}
1636 //void wrapglVertexAttrib3sv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib3sv(index, v);POSTCALL;}
1637 //void wrapglVertexAttrib3dv(GLuint index, const GLdouble *v) {PRECALL;glVertexAttrib3dv(index, v);POSTCALL;}
1638 void wrapglVertexAttrib4fv(GLuint index, const GLfloat *v) {PRECALL;glVertexAttrib4fv(index, v);POSTCALL;}
1639 //void wrapglVertexAttrib4sv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib4sv(index, v);POSTCALL;}
1640 //void wrapglVertexAttrib4dv(GLuint index, const GLdouble *v) {PRECALL;glVertexAttrib4dv(index, v);POSTCALL;}
1641 //void wrapglVertexAttrib4iv(GLuint index, const GLint *v) {PRECALL;glVertexAttrib4iv(index, v);POSTCALL;}
1642 //void wrapglVertexAttrib4bv(GLuint index, const GLbyte *v) {PRECALL;glVertexAttrib4bv(index, v);POSTCALL;}
1643 //void wrapglVertexAttrib4ubv(GLuint index, const GLubyte *v) {PRECALL;glVertexAttrib4ubv(index, v);POSTCALL;}
1644 //void wrapglVertexAttrib4usv(GLuint index, const GLushort *v) {PRECALL;glVertexAttrib4usv(index, GLushort v);POSTCALL;}
1645 //void wrapglVertexAttrib4uiv(GLuint index, const GLuint *v) {PRECALL;glVertexAttrib4uiv(index, v);POSTCALL;}
1646 //void wrapglVertexAttrib4Nbv(GLuint index, const GLbyte *v) {PRECALL;glVertexAttrib4Nbv(index, v);POSTCALL;}
1647 //void wrapglVertexAttrib4Nsv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib4Nsv(index, v);POSTCALL;}
1648 //void wrapglVertexAttrib4Niv(GLuint index, const GLint *v) {PRECALL;glVertexAttrib4Niv(index, v);POSTCALL;}
1649 //void wrapglVertexAttrib4Nubv(GLuint index, const GLubyte *v) {PRECALL;glVertexAttrib4Nubv(index, v);POSTCALL;}
1650 //void wrapglVertexAttrib4Nusv(GLuint index, const GLushort *v) {PRECALL;glVertexAttrib4Nusv(index, GLushort v);POSTCALL;}
1651 //void wrapglVertexAttrib4Nuiv(GLuint index, const GLuint *v) {PRECALL;glVertexAttrib4Nuiv(index, v);POSTCALL;}
1652 //void wrapglGetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params) {PRECALL;glGetVertexAttribdv(index, pname, params);POSTCALL;}
1653 void wrapglGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) {PRECALL;glGetVertexAttribfv(index, pname, params);POSTCALL;}
1654 void wrapglGetVertexAttribiv(GLuint index, GLenum pname, GLint *params) {PRECALL;glGetVertexAttribiv(index, pname, params);POSTCALL;}
1655 void wrapglGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) {PRECALL;glGetVertexAttribPointerv(index, pname, pointer);POSTCALL;}
1658 #if SDL_MAJOR_VERSION == 1
1659 #define SDL_GL_ExtensionSupported(x) (strstr(gl_extensions, x) || strstr(gl_platformextensions, x))
1662 void GLES_Init(void)
1665 qglIsBufferARB = wrapglIsBuffer;
1666 qglIsEnabled = wrapglIsEnabled;
1667 qglIsFramebufferEXT = wrapglIsFramebuffer;
1668 // qglIsQueryARB = wrapglIsQuery;
1669 qglIsRenderbufferEXT = wrapglIsRenderbuffer;
1670 // qglUnmapBufferARB = wrapglUnmapBuffer;
1671 qglCheckFramebufferStatus = wrapglCheckFramebufferStatus;
1672 qglGetError = wrapglGetError;
1673 qglCreateProgram = wrapglCreateProgram;
1674 qglCreateShader = wrapglCreateShader;
1675 // qglGetHandleARB = wrapglGetHandle;
1676 qglGetAttribLocation = wrapglGetAttribLocation;
1677 qglGetUniformLocation = wrapglGetUniformLocation;
1678 // qglMapBufferARB = wrapglMapBuffer;
1679 qglGetString = wrapglGetString;
1680 // qglActiveStencilFaceEXT = wrapglActiveStencilFace;
1681 qglActiveTexture = wrapglActiveTexture;
1682 qglArrayElement = wrapglArrayElement;
1683 qglAttachShader = wrapglAttachShader;
1684 // qglBeginQueryARB = wrapglBeginQuery;
1685 qglBindAttribLocation = wrapglBindAttribLocation;
1686 // qglBindFragDataLocation = wrapglBindFragDataLocation;
1687 qglBindBufferARB = wrapglBindBuffer;
1688 qglBindFramebuffer = wrapglBindFramebuffer;
1689 qglBindRenderbuffer = wrapglBindRenderbuffer;
1690 qglBindTexture = wrapglBindTexture;
1691 qglBlendEquationEXT = wrapglBlendEquation;
1692 qglBlendFunc = wrapglBlendFunc;
1693 qglBufferDataARB = wrapglBufferData;
1694 qglBufferSubDataARB = wrapglBufferSubData;
1695 qglClear = wrapglClear;
1696 qglClearColor = wrapglClearColor;
1697 qglClearDepth = wrapglClearDepth;
1698 qglClearStencil = wrapglClearStencil;
1699 qglColorMask = wrapglColorMask;
1700 qglCompileShader = wrapglCompileShader;
1701 qglCompressedTexImage2DARB = wrapglCompressedTexImage2D;
1702 qglCompressedTexImage3DARB = wrapglCompressedTexImage3D;
1703 qglCompressedTexSubImage2DARB = wrapglCompressedTexSubImage2D;
1704 qglCompressedTexSubImage3DARB = wrapglCompressedTexSubImage3D;
1705 qglCopyTexImage2D = wrapglCopyTexImage2D;
1706 qglCopyTexSubImage2D = wrapglCopyTexSubImage2D;
1707 qglCopyTexSubImage3D = wrapglCopyTexSubImage3D;
1708 qglCullFace = wrapglCullFace;
1709 qglDeleteBuffersARB = wrapglDeleteBuffers;
1710 qglDeleteFramebuffers = wrapglDeleteFramebuffers;
1711 qglDeleteProgram = wrapglDeleteProgram;
1712 qglDeleteShader = wrapglDeleteShader;
1713 // qglDeleteQueriesARB = wrapglDeleteQueries;
1714 qglDeleteRenderbuffers = wrapglDeleteRenderbuffers;
1715 qglDeleteTextures = wrapglDeleteTextures;
1716 qglDepthFunc = wrapglDepthFunc;
1717 qglDepthMask = wrapglDepthMask;
1718 qglDepthRangef = wrapglDepthRangef;
1719 qglDetachShader = wrapglDetachShader;
1720 qglDisable = wrapglDisable;
1721 qglDisableVertexAttribArray = wrapglDisableVertexAttribArray;
1722 qglDrawArrays = wrapglDrawArrays;
1723 // qglDrawBuffer = wrapglDrawBuffer;
1724 // qglDrawBuffersARB = wrapglDrawBuffers;
1725 qglDrawElements = wrapglDrawElements;
1726 // qglDrawRangeElements = wrapglDrawRangeElements;
1727 qglEnable = wrapglEnable;
1728 qglEnableVertexAttribArray = wrapglEnableVertexAttribArray;
1729 // qglEndQueryARB = wrapglEndQuery;
1730 qglFinish = wrapglFinish;
1731 qglFlush = wrapglFlush;
1732 qglFramebufferRenderbufferEXT = wrapglFramebufferRenderbuffer;
1733 qglFramebufferTexture2DEXT = wrapglFramebufferTexture2D;
1734 qglFramebufferTexture3DEXT = wrapglFramebufferTexture3D;
1735 qglGenBuffersARB = wrapglGenBuffers;
1736 qglGenFramebuffers = wrapglGenFramebuffers;
1737 // qglGenQueriesARB = wrapglGenQueries;
1738 qglGenRenderbuffers = wrapglGenRenderbuffers;
1739 qglGenTextures = wrapglGenTextures;
1740 qglGenerateMipmapEXT = wrapglGenerateMipmap;
1741 qglGetActiveAttrib = wrapglGetActiveAttrib;
1742 qglGetActiveUniform = wrapglGetActiveUniform;
1743 qglGetAttachedShaders = wrapglGetAttachedShaders;
1744 qglGetBooleanv = wrapglGetBooleanv;
1745 // qglGetCompressedTexImageARB = wrapglGetCompressedTexImage;
1746 qglGetDoublev = wrapglGetDoublev;
1747 qglGetFloatv = wrapglGetFloatv;
1748 qglGetFramebufferAttachmentParameterivEXT = wrapglGetFramebufferAttachmentParameteriv;
1749 qglGetProgramInfoLog = wrapglGetProgramInfoLog;
1750 qglGetShaderInfoLog = wrapglGetShaderInfoLog;
1751 qglGetIntegerv = wrapglGetIntegerv;
1752 qglGetShaderiv = wrapglGetShaderiv;
1753 qglGetProgramiv = wrapglGetProgramiv;
1754 // qglGetQueryObjectivARB = wrapglGetQueryObjectiv;
1755 // qglGetQueryObjectuivARB = wrapglGetQueryObjectuiv;
1756 // qglGetQueryivARB = wrapglGetQueryiv;
1757 qglGetRenderbufferParameterivEXT = wrapglGetRenderbufferParameteriv;
1758 qglGetShaderSource = wrapglGetShaderSource;
1759 qglGetTexImage = wrapglGetTexImage;
1760 qglGetTexLevelParameterfv = wrapglGetTexLevelParameterfv;
1761 qglGetTexLevelParameteriv = wrapglGetTexLevelParameteriv;
1762 qglGetTexParameterfv = wrapglGetTexParameterfv;
1763 qglGetTexParameteriv = wrapglGetTexParameteriv;
1764 qglGetUniformfv = wrapglGetUniformfv;
1765 qglGetUniformiv = wrapglGetUniformiv;
1766 qglHint = wrapglHint;
1767 qglLinkProgram = wrapglLinkProgram;
1768 qglPixelStorei = wrapglPixelStorei;
1769 qglPointSize = wrapglPointSize;
1770 // qglPolygonMode = wrapglPolygonMode;
1771 qglPolygonOffset = wrapglPolygonOffset;
1772 // qglPolygonStipple = wrapglPolygonStipple;
1773 qglReadBuffer = wrapglReadBuffer;
1774 qglReadPixels = wrapglReadPixels;
1775 qglRenderbufferStorage = wrapglRenderbufferStorage;
1776 qglScissor = wrapglScissor;
1777 qglShaderSource = wrapglShaderSource;
1778 qglStencilFunc = wrapglStencilFunc;
1779 qglStencilFuncSeparate = wrapglStencilFuncSeparate;
1780 qglStencilMask = wrapglStencilMask;
1781 qglStencilOp = wrapglStencilOp;
1782 qglStencilOpSeparate = wrapglStencilOpSeparate;
1783 qglTexImage2D = wrapglTexImage2D;
1784 qglTexImage3D = wrapglTexImage3D;
1785 qglTexParameterf = wrapglTexParameterf;
1786 qglTexParameterfv = wrapglTexParameterfv;
1787 qglTexParameteri = wrapglTexParameteri;
1788 qglTexSubImage2D = wrapglTexSubImage2D;
1789 qglTexSubImage3D = wrapglTexSubImage3D;
1790 qglUniform1f = wrapglUniform1f;
1791 qglUniform1fv = wrapglUniform1fv;
1792 qglUniform1i = wrapglUniform1i;
1793 qglUniform1iv = wrapglUniform1iv;
1794 qglUniform2f = wrapglUniform2f;
1795 qglUniform2fv = wrapglUniform2fv;
1796 qglUniform2i = wrapglUniform2i;
1797 qglUniform2iv = wrapglUniform2iv;
1798 qglUniform3f = wrapglUniform3f;
1799 qglUniform3fv = wrapglUniform3fv;
1800 qglUniform3i = wrapglUniform3i;
1801 qglUniform3iv = wrapglUniform3iv;
1802 qglUniform4f = wrapglUniform4f;
1803 qglUniform4fv = wrapglUniform4fv;
1804 qglUniform4i = wrapglUniform4i;
1805 qglUniform4iv = wrapglUniform4iv;
1806 qglUniformMatrix2fv = wrapglUniformMatrix2fv;
1807 qglUniformMatrix3fv = wrapglUniformMatrix3fv;
1808 qglUniformMatrix4fv = wrapglUniformMatrix4fv;
1809 qglUseProgram = wrapglUseProgram;
1810 qglValidateProgram = wrapglValidateProgram;
1811 qglVertex2f = wrapglVertex2f;
1812 qglVertex3f = wrapglVertex3f;
1813 qglVertex4f = wrapglVertex4f;
1814 qglVertexAttribPointer = wrapglVertexAttribPointer;
1815 qglVertexPointer = wrapglVertexPointer;
1816 qglViewport = wrapglViewport;
1817 qglVertexAttrib1f = wrapglVertexAttrib1f;
1818 // qglVertexAttrib1s = wrapglVertexAttrib1s;
1819 // qglVertexAttrib1d = wrapglVertexAttrib1d;
1820 qglVertexAttrib2f = wrapglVertexAttrib2f;
1821 // qglVertexAttrib2s = wrapglVertexAttrib2s;
1822 // qglVertexAttrib2d = wrapglVertexAttrib2d;
1823 qglVertexAttrib3f = wrapglVertexAttrib3f;
1824 // qglVertexAttrib3s = wrapglVertexAttrib3s;
1825 // qglVertexAttrib3d = wrapglVertexAttrib3d;
1826 qglVertexAttrib4f = wrapglVertexAttrib4f;
1827 // qglVertexAttrib4s = wrapglVertexAttrib4s;
1828 // qglVertexAttrib4d = wrapglVertexAttrib4d;
1829 // qglVertexAttrib4Nub = wrapglVertexAttrib4Nub;
1830 qglVertexAttrib1fv = wrapglVertexAttrib1fv;
1831 // qglVertexAttrib1sv = wrapglVertexAttrib1sv;
1832 // qglVertexAttrib1dv = wrapglVertexAttrib1dv;
1833 qglVertexAttrib2fv = wrapglVertexAttrib2fv;
1834 // qglVertexAttrib2sv = wrapglVertexAttrib2sv;
1835 // qglVertexAttrib2dv = wrapglVertexAttrib2dv;
1836 qglVertexAttrib3fv = wrapglVertexAttrib3fv;
1837 // qglVertexAttrib3sv = wrapglVertexAttrib3sv;
1838 // qglVertexAttrib3dv = wrapglVertexAttrib3dv;
1839 qglVertexAttrib4fv = wrapglVertexAttrib4fv;
1840 // qglVertexAttrib4sv = wrapglVertexAttrib4sv;
1841 // qglVertexAttrib4dv = wrapglVertexAttrib4dv;
1842 // qglVertexAttrib4iv = wrapglVertexAttrib4iv;
1843 // qglVertexAttrib4bv = wrapglVertexAttrib4bv;
1844 // qglVertexAttrib4ubv = wrapglVertexAttrib4ubv;
1845 // qglVertexAttrib4usv = wrapglVertexAttrib4usv;
1846 // qglVertexAttrib4uiv = wrapglVertexAttrib4uiv;
1847 // qglVertexAttrib4Nbv = wrapglVertexAttrib4Nbv;
1848 // qglVertexAttrib4Nsv = wrapglVertexAttrib4Nsv;
1849 // qglVertexAttrib4Niv = wrapglVertexAttrib4Niv;
1850 // qglVertexAttrib4Nubv = wrapglVertexAttrib4Nubv;
1851 // qglVertexAttrib4Nusv = wrapglVertexAttrib4Nusv;
1852 // qglVertexAttrib4Nuiv = wrapglVertexAttrib4Nuiv;
1853 // qglGetVertexAttribdv = wrapglGetVertexAttribdv;
1854 qglGetVertexAttribfv = wrapglGetVertexAttribfv;
1855 qglGetVertexAttribiv = wrapglGetVertexAttribiv;
1856 qglGetVertexAttribPointerv = wrapglGetVertexAttribPointerv;
1859 gl_renderer = (const char *)qglGetString(GL_RENDERER);
1860 gl_vendor = (const char *)qglGetString(GL_VENDOR);
1861 gl_version = (const char *)qglGetString(GL_VERSION);
1862 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
1866 if (!gl_platformextensions)
1867 gl_platformextensions = "";
1869 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
1870 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
1871 Con_Printf("GL_VERSION: %s\n", gl_version);
1872 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
1873 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
1875 // LordHavoc: report supported extensions
1876 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1878 // GLES devices in general do not like GL_BGRA, so use GL_RGBA
1879 vid.forcetextype = TEXTYPE_RGBA;
1881 vid.support.gl20shaders = true;
1882 vid.support.amd_texture_texture4 = false;
1883 vid.support.arb_depth_texture = SDL_GL_ExtensionSupported("GL_OES_depth_texture") != 0; // renderbuffer used anyway on gles2?
1884 vid.support.arb_draw_buffers = false;
1885 vid.support.arb_multitexture = false;
1886 vid.support.arb_occlusion_query = false;
1887 vid.support.arb_query_buffer_object = false;
1888 vid.support.arb_shadow = false;
1889 vid.support.arb_texture_compression = false; // different (vendor-specific) formats than on desktop OpenGL...
1890 vid.support.arb_texture_cube_map = SDL_GL_ExtensionSupported("GL_OES_texture_cube_map") != 0;
1891 vid.support.arb_texture_env_combine = false;
1892 vid.support.arb_texture_gather = false;
1893 vid.support.arb_texture_non_power_of_two = strstr(gl_extensions, "GL_OES_texture_npot") != NULL;
1894 vid.support.arb_vertex_buffer_object = true; // GLES2 core
1895 vid.support.ext_blend_minmax = false;
1896 vid.support.ext_blend_subtract = true; // GLES2 core
1897 vid.support.ext_blend_func_separate = true; // GLES2 core
1898 vid.support.ext_draw_range_elements = false;
1901 Note: "In OS 2.1, the functions in GL_OES_framebuffer_object were not usable from the Java API.
1902 Calling them just threw an exception. Android developer relations confirmed that they forgot to implement these. (yeah...)
1903 It's apparently been fixed in 2.2, though I haven't tested."
1905 // LadyHavoc: Android 2.1 is way old now, enabling this again, it's going to be required soon.
1906 vid.support.ext_framebuffer_object = true;
1908 vid.support.ext_packed_depth_stencil = false;
1909 vid.support.ext_texture_3d = SDL_GL_ExtensionSupported("GL_OES_texture_3D") != 0;
1910 vid.support.ext_texture_compression_s3tc = SDL_GL_ExtensionSupported("GL_EXT_texture_compression_s3tc") != 0;
1911 vid.support.ext_texture_edge_clamp = true; // GLES2 core
1912 vid.support.ext_texture_filter_anisotropic = false; // probably don't want to use it...
1913 vid.support.ext_texture_srgb = false;
1914 vid.support.arb_texture_float = SDL_GL_ExtensionSupported("GL_OES_texture_float") != 0;
1915 vid.support.arb_half_float_pixel = SDL_GL_ExtensionSupported("GL_OES_texture_half_float") != 0;
1916 vid.support.arb_half_float_vertex = SDL_GL_ExtensionSupported("GL_OES_vertex_half_float") != 0;
1918 // NOTE: On some devices, a value of 512 gives better FPS than the maximum.
1919 qglGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_2d);
1921 #ifdef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
1922 if (vid.support.ext_texture_filter_anisotropic)
1923 qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*)&vid.max_anisotropy);
1925 if (vid.support.arb_texture_cube_map)
1926 qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_cubemap);
1927 #ifdef GL_MAX_3D_TEXTURE_SIZE
1928 if (vid.support.ext_texture_3d)
1929 qglGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_3d);
1931 Con_Printf("GL_MAX_CUBE_MAP_TEXTURE_SIZE = %i\n", vid.maxtexturesize_cubemap);
1932 Con_Printf("GL_MAX_3D_TEXTURE_SIZE = %i\n", vid.maxtexturesize_3d);
1934 #define GL_ALPHA_BITS 0x0D55
1935 #define GL_RED_BITS 0x0D52
1936 #define GL_GREEN_BITS 0x0D53
1937 #define GL_BLUE_BITS 0x0D54
1938 #define GL_DEPTH_BITS 0x0D56
1939 #define GL_STENCIL_BITS 0x0D57
1940 int fb_r = -1, fb_g = -1, fb_b = -1, fb_a = -1, fb_d = -1, fb_s = -1;
1941 qglGetIntegerv(GL_RED_BITS , &fb_r);
1942 qglGetIntegerv(GL_GREEN_BITS , &fb_g);
1943 qglGetIntegerv(GL_BLUE_BITS , &fb_b);
1944 qglGetIntegerv(GL_ALPHA_BITS , &fb_a);
1945 qglGetIntegerv(GL_DEPTH_BITS , &fb_d);
1946 qglGetIntegerv(GL_STENCIL_BITS, &fb_s);
1947 Con_Printf("Framebuffer depth is R%iG%iB%iA%iD%iS%i\n", fb_r, fb_g, fb_b, fb_a, fb_d, fb_s);
1950 // verify that cubemap textures are really supported
1951 if (vid.support.arb_texture_cube_map && vid.maxtexturesize_cubemap < 256)
1952 vid.support.arb_texture_cube_map = false;
1954 // verify that 3d textures are really supported
1955 if (vid.support.ext_texture_3d && vid.maxtexturesize_3d < 32)
1957 vid.support.ext_texture_3d = false;
1958 Con_Printf("GL_OES_texture_3d reported bogus GL_MAX_3D_TEXTURE_SIZE, disabled\n");
1962 vid.teximageunits = 8;
1963 vid.texarrayunits = 5;
1964 //qglGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&vid.texunits);
1965 qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&vid.teximageunits);CHECKGLERROR
1966 //qglGetIntegerv(GL_MAX_TEXTURE_COORDS, (GLint*)&vid.texarrayunits);CHECKGLERROR
1967 vid.texunits = bound(1, vid.texunits, MAX_TEXTUREUNITS);
1968 vid.teximageunits = bound(1, vid.teximageunits, MAX_TEXTUREUNITS);
1969 vid.texarrayunits = bound(1, vid.texarrayunits, MAX_TEXTUREUNITS);
1970 Con_DPrintf("Using GLES2.0 rendering path - %i texture matrix, %i texture images, %i texcoords%s\n", vid.texunits, vid.teximageunits, vid.texarrayunits, vid.support.ext_framebuffer_object ? ", shadowmapping supported" : "");
1971 vid.renderpath = RENDERPATH_GLES2;
1972 vid.sRGBcapable2D = false;
1973 vid.sRGBcapable3D = false;
1975 // VorteX: set other info (maybe place them in VID_InitMode?)
1976 extern cvar_t gl_info_vendor;
1977 extern cvar_t gl_info_renderer;
1978 extern cvar_t gl_info_version;
1979 extern cvar_t gl_info_platform;
1980 extern cvar_t gl_info_driver;
1981 Cvar_SetQuick(&gl_info_vendor, gl_vendor);
1982 Cvar_SetQuick(&gl_info_renderer, gl_renderer);
1983 Cvar_SetQuick(&gl_info_version, gl_version);
1984 Cvar_SetQuick(&gl_info_platform, gl_platform ? gl_platform : "");
1985 Cvar_SetQuick(&gl_info_driver, gl_driver);
1989 void *GL_GetProcAddress(const char *name)
1992 p = SDL_GL_GetProcAddress(name);
1996 static qboolean vid_sdl_initjoysticksystem = false;
1998 void VID_Init (void)
2000 #ifndef __IPHONEOS__
2002 Cvar_RegisterVariable(&apple_mouse_noaccel);
2005 #ifdef DP_MOBILETOUCH
2006 Cvar_SetValueQuick(&vid_touchscreen, 1);
2009 #ifdef SDL_R_RESTART
2010 R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap, NULL, NULL);
2013 if (SDL_Init(SDL_INIT_VIDEO) < 0)
2014 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
2015 vid_sdl_initjoysticksystem = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0;
2016 if (vid_sdl_initjoysticksystem)
2017 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
2018 vid_isfullscreen = false;
2021 static int vid_sdljoystickindex = -1;
2022 void VID_EnableJoystick(qboolean enable)
2024 int index = joy_enable.integer > 0 ? joy_index.integer : -1;
2025 int numsdljoysticks;
2026 qboolean success = false;
2027 int sharedcount = 0;
2029 sharedcount = VID_Shared_SetJoystick(index);
2030 if (index >= 0 && index < sharedcount)
2032 sdlindex = index - sharedcount;
2034 numsdljoysticks = SDL_NumJoysticks();
2035 if (sdlindex < 0 || sdlindex >= numsdljoysticks)
2038 // update cvar containing count of XInput joysticks + SDL joysticks
2039 if (joy_detected.integer != sharedcount + numsdljoysticks)
2040 Cvar_SetValueQuick(&joy_detected, sharedcount + numsdljoysticks);
2042 if (vid_sdljoystickindex != sdlindex)
2044 vid_sdljoystickindex = sdlindex;
2045 // close SDL joystick if active
2046 if (vid_sdljoystick)
2047 SDL_JoystickClose(vid_sdljoystick);
2048 vid_sdljoystick = NULL;
2051 vid_sdljoystick = SDL_JoystickOpen(sdlindex);
2052 if (vid_sdljoystick)
2054 #if SDL_MAJOR_VERSION == 1
2055 const char *joystickname = SDL_JoystickName(sdlindex);
2057 const char *joystickname = SDL_JoystickName(vid_sdljoystick);
2059 Con_Printf("Joystick %i opened (SDL_Joystick %i is \"%s\" with %i axes, %i buttons, %i balls)\n", index, sdlindex, joystickname, (int)SDL_JoystickNumAxes(vid_sdljoystick), (int)SDL_JoystickNumButtons(vid_sdljoystick), (int)SDL_JoystickNumBalls(vid_sdljoystick));
2063 Con_Printf("Joystick %i failed (SDL_JoystickOpen(%i) returned: %s)\n", index, sdlindex, SDL_GetError());
2072 if (joy_active.integer != (success ? 1 : 0))
2073 Cvar_SetValueQuick(&joy_active, success ? 1 : 0);
2076 #if SDL_MAJOR_VERSION == 1
2077 // set the icon (we dont use SDL here since it would be too much a PITA)
2079 #include "resource.h"
2080 #include <SDL_syswm.h>
2081 static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
2083 SDL_Surface *screen = NULL;
2086 SDL_WM_SetCaption( gamename, NULL );
2087 screen = SDL_SetVideoMode(screenwidth, screenheight, screenbpp, screenflags);
2090 // get the HWND handle
2091 SDL_VERSION( &info.version );
2092 if (SDL_GetWMInfo(&info))
2094 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
2095 #ifndef _W64 //If Windows 64bit data types don't exist
2096 #ifndef SetClassLongPtr
2097 #define SetClassLongPtr SetClassLong
2100 #define GCLP_HICON GCL_HICON
2103 #define LONG_PTR LONG
2106 SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
2111 #elif defined(MACOSX)
2112 static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
2114 SDL_Surface *screen = NULL;
2115 SDL_WM_SetCaption( gamename, NULL );
2116 screen = SDL_SetVideoMode(screenwidth, screenheight, screenbpp, screenflags);
2117 // we don't use SDL_WM_SetIcon here because the icon in the .app should be used
2121 // Adding the OS independent XPM version --blub
2122 #include "darkplaces.xpm"
2123 #include "nexuiz.xpm"
2124 #if SDL_MAJOR_VERSION == 1
2125 #if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
2126 #include <SDL_syswm.h>
2129 static SDL_Surface *icon = NULL;
2130 static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
2133 * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
2134 * default settings with less than 91 colors and transparency.
2137 int width, height, colors, isize, i, j;
2139 static SDL_Color palette[256];
2140 unsigned short palenc[256]; // store color id by char
2142 char **idata, *data;
2143 const SDL_version *version;
2144 SDL_Surface *screen = NULL;
2147 SDL_FreeSurface(icon);
2149 version = SDL_Linked_Version();
2150 // only use non-XPM icon support in SDL v1.3 and higher
2151 // SDL v1.2 does not support "smooth" transparency, and thus is better
2153 if(version->major >= 2 || (version->major == 1 && version->minor >= 3))
2155 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
2158 unsigned int red = 0x00FF0000;
2159 unsigned int green = 0x0000FF00;
2160 unsigned int blue = 0x000000FF;
2161 unsigned int alpha = 0xFF000000;
2162 width = image_width;
2163 height = image_height;
2165 // reallocate with malloc, as this is in tempmempool (do not want)
2167 data = (char *) malloc(width * height * 4);
2168 memcpy(data, xpm, width * height * 4);
2172 icon = SDL_CreateRGBSurface(SDL_SRCALPHA, width, height, 32, LittleLong(red), LittleLong(green), LittleLong(blue), LittleLong(alpha));
2175 icon->pixels = data;
2178 Con_Printf( "Failed to create surface for the window Icon!\n"
2179 "%s\n", SDL_GetError());
2185 // we only get here if non-XPM icon was missing, or SDL version is not
2186 // sufficient for transparent non-XPM icons
2189 xpm = (char *) FS_LoadFile("darkplaces-icon.xpm", tempmempool, false, NULL);
2192 idata = XPM_DecodeString(xpm);
2194 idata = ENGINE_ICON;
2200 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) == 4)
2204 for(i = 0; i < colors; ++i)
2206 unsigned int r, g, b;
2209 if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
2212 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
2216 palette[i].r = 255; // color key
2219 thenone = i; // weeeee
2220 palenc[(unsigned char) idx] = i;
2225 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
2228 palenc[(unsigned char) idx] = i;
2234 // allocate the image data
2235 data = (char*) malloc(width*height);
2237 for(j = 0; j < height; ++j)
2239 for(i = 0; i < width; ++i)
2241 // casting to the safest possible datatypes ^^
2242 data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
2248 // SDL_FreeSurface should free the data too
2249 // but for completeness' sake...
2250 if(icon->flags & SDL_PREALLOC)
2253 icon->pixels = NULL; // safety
2255 SDL_FreeSurface(icon);
2258 icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
2259 // 8 bit surfaces get an empty palette allocated according to the docs
2260 // so it's a palette image for sure :) no endian check necessary for the mask
2264 icon->pixels = data;
2265 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
2266 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
2270 Con_Printf( "Failed to create surface for the window Icon!\n"
2271 "%s\n", SDL_GetError());
2277 Con_Printf("This XPM's palette looks odd. Can't continue.\n");
2282 // NOTE: Only 1-char colornames are supported
2283 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
2288 // NOTE: Only 1-char colornames are supported
2289 Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
2294 SDL_WM_SetIcon(icon, NULL);
2296 SDL_WM_SetCaption( gamename, NULL );
2297 screen = SDL_SetVideoMode(screenwidth, screenheight, screenbpp, screenflags);
2299 #if SDL_MAJOR_VERSION == 1
2300 // LordHavoc: info.info.x11.lock_func and accompanying code do not seem to compile with SDL 1.3
2301 #if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
2303 version = SDL_Linked_Version();
2304 // only use non-XPM icon support in SDL v1.3 and higher
2305 // SDL v1.2 does not support "smooth" transparency, and thus is better
2307 if(screen && (!(version->major >= 2 || (version->major == 1 && version->minor >= 3))))
2309 // in this case, we did not set the good icon yet
2311 SDL_VERSION(&info.version);
2312 if(SDL_GetWMInfo(&info) == 1 && info.subsystem == SDL_SYSWM_X11)
2314 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
2317 // use _NET_WM_ICON too
2318 static long netwm_icon[MAX_NETWM_ICON];
2325 if(pos + 2 * image_width * image_height < MAX_NETWM_ICON)
2327 netwm_icon[pos++] = image_width;
2328 netwm_icon[pos++] = image_height;
2329 for(i = 0; i < image_height; ++i)
2330 for(j = 0; j < image_width; ++j)
2331 netwm_icon[pos++] = BuffLittleLong((unsigned char *) &data[(i*image_width+j)*4]);
2335 Con_Printf("Skipping NETWM icon #%d because there is no space left\n", i);
2339 data = (char *) loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "darkplaces-icon%d", i), false, false, false, NULL);
2342 info.info.x11.lock_func();
2344 Atom net_wm_icon = XInternAtom(info.info.x11.display, "_NET_WM_ICON", false);
2345 XChangeProperty(info.info.x11.display, info.info.x11.wmwindow, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos);
2347 info.info.x11.unlock_func();
2359 static void VID_OutputVersion(void)
2361 SDL_version version;
2362 #if SDL_MAJOR_VERSION == 1
2363 version = *SDL_Linked_Version();
2365 SDL_GetVersion(&version);
2367 Con_Printf( "Linked against SDL version %d.%d.%d\n"
2368 "Using SDL library version %d.%d.%d\n",
2369 SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
2370 version.major, version.minor, version.patch );
2374 static void AdjustWindowBounds(viddef_mode_t *mode, RECT *rect)
2376 LONG width = mode->width; // vid_width
2377 LONG height = mode->height; // vid_height
2379 // adjust width and height for the space occupied by window decorators (title bar, borders)
2382 rect->right = width;
2383 rect->bottom = height;
2384 AdjustWindowRectEx(rect, WS_CAPTION|WS_THICKFRAME, false, 0);
2387 SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
2388 int workWidth = workArea.right - workArea.left;
2389 int workHeight = workArea.bottom - workArea.top;
2391 // SDL forces the window height to be <= screen height - 27px (on Win8.1 - probably intended for the title bar)
2392 // If the task bar is docked to the the left screen border and we move the window to negative y,
2393 // there would be some part of the regular desktop visible on the bottom of the screen.
2394 int titleBarPixels = 2;
2395 int screenHeight = GetSystemMetrics(SM_CYSCREEN);
2396 if (screenHeight == workHeight)
2397 titleBarPixels = -rect->top;
2399 //Con_Printf("window mode: %dx%d, workArea: %d/%d-%d/%d (%dx%d), title: %d\n", width, height, workArea.left, workArea.top, workArea.right, workArea.bottom, workArea.right - workArea.left, workArea.bottom - workArea.top, titleBarPixels);
2401 // if height and width matches the physical or previously adjusted screen height and width, adjust it to available desktop area
2402 if ((width == GetSystemMetrics(SM_CXSCREEN) || width == workWidth) && (height == screenHeight || height == workHeight - titleBarPixels))
2404 rect->left = workArea.left;
2405 mode->width = workWidth;
2406 rect->top = workArea.top + titleBarPixels;
2407 mode->height = workHeight - titleBarPixels;
2411 rect->left = workArea.left + max(0, (workWidth - width) / 2);
2412 rect->top = workArea.top + max(0, (workHeight - height) / 2);
2417 static qboolean VID_InitModeGL(viddef_mode_t *mode)
2419 #if SDL_MAJOR_VERSION == 1
2420 static int notfirstvideomode = false;
2421 int flags = SDL_OPENGL;
2423 int windowflags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL;
2424 int xPos = SDL_WINDOWPOS_UNDEFINED;
2425 int yPos = SDL_WINDOWPOS_UNDEFINED;
2429 const char *drivername;
2432 win_half_width = mode->width>>1;
2433 win_half_height = mode->height>>1;
2435 if(vid_resizable.integer)
2436 #if SDL_MAJOR_VERSION == 1
2437 flags |= SDL_RESIZABLE;
2439 windowflags |= SDL_WINDOW_RESIZABLE;
2442 VID_OutputVersion();
2444 #if SDL_MAJOR_VERSION == 1
2447 We cant switch from one OpenGL video mode to another.
2448 Thus we first switch to some stupid 2D mode and then back to OpenGL.
2450 if (notfirstvideomode)
2451 SDL_SetVideoMode( 0, 0, 0, 0 );
2452 notfirstvideomode = true;
2456 // SDL usually knows best
2459 // 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
2460 i = COM_CheckParm("-gl_driver");
2461 if (i && i < com_argc - 1)
2462 drivername = com_argv[i + 1];
2463 if (SDL_GL_LoadLibrary(drivername) < 0)
2465 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
2470 #ifdef DP_MOBILETOUCH
2471 // mobile platforms are always fullscreen, we'll get the resolution after opening the window
2472 mode->fullscreen = true;
2473 // hide the menu with SDL_WINDOW_BORDERLESS
2474 windowflags |= SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS;
2477 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
2480 Con_Print("Required OpenGL function glGetString not found\n");
2485 // Knghtbrd: should do platform-specific extension string function here
2487 vid_isfullscreen = false;
2488 #if SDL_MAJOR_VERSION == 1
2490 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2491 desktop_mode.width = vi->current_w;
2492 desktop_mode.height = vi->current_h;
2493 desktop_mode.bpp = vi->vfmt->BitsPerPixel;
2494 desktop_mode.pixelheight_num = 1;
2495 desktop_mode.pixelheight_denom = 1; // SDL does not provide this
2496 if (mode->fullscreen) {
2497 if (vid_desktopfullscreen.integer)
2499 mode->width = vi->current_w;
2500 mode->height = vi->current_h;
2501 mode->bitsperpixel = vi->vfmt->BitsPerPixel;
2503 flags |= SDL_FULLSCREEN;
2504 vid_isfullscreen = true;
2509 if (mode->fullscreen) {
2510 if (vid_desktopfullscreen.integer)
2512 vid_mode_t *m = VID_GetDesktopMode();
2513 mode->width = m->width;
2514 mode->height = m->height;
2515 windowflags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
2518 windowflags |= SDL_WINDOW_FULLSCREEN;
2519 vid_isfullscreen = true;
2524 AdjustWindowBounds(mode, &rect);
2531 //flags |= SDL_HWSURFACE;
2533 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
2534 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
2535 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
2536 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
2537 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
2538 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
2539 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
2540 if (mode->stereobuffer)
2541 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
2542 if (mode->samples > 1)
2544 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
2545 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples);
2548 #if SDL_MAJOR_VERSION == 1
2549 if (vid_vsync.integer)
2550 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
2552 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
2555 SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2);
2556 SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0);
2557 SDL_GL_SetAttribute (SDL_GL_RETAINED_BACKING, 1);
2561 video_bpp = mode->bitsperpixel;
2562 #if SDL_MAJOR_VERSION == 1
2563 video_flags = flags;
2564 video_screen = VID_WrapSDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
2565 if (video_screen == NULL)
2567 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
2571 mode->width = video_screen->w;
2572 mode->height = video_screen->h;
2574 window_flags = windowflags;
2575 window = SDL_CreateWindow(gamename, xPos, yPos, mode->width, mode->height, windowflags);
2578 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
2582 SDL_GetWindowSize(window, &mode->width, &mode->height);
2583 context = SDL_GL_CreateContext(window);
2584 if (context == NULL)
2586 Con_Printf("Failed to initialize OpenGL context: %s\n", SDL_GetError());
2592 #if SDL_MAJOR_VERSION == 1
2594 SDL_EnableUNICODE( SDL_ENABLE );
2595 // enable key repeat since everyone expects it
2596 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
2599 #if SDL_MAJOR_VERSION != 1
2600 SDL_GL_SetSwapInterval(vid_vsync.integer != 0);
2601 vid_usingvsync = (vid_vsync.integer != 0);
2604 gl_platform = "SDL";
2605 gl_platformextensions = "";
2614 vid_activewindow = false;
2615 vid_hasfocus = true;
2616 vid_usingmouse = false;
2617 vid_usinghidecursor = false;
2619 #if SDL_MAJOR_VERSION == 1
2620 SDL_WM_GrabInput(SDL_GRAB_OFF);
2625 extern cvar_t gl_info_extensions;
2626 extern cvar_t gl_info_vendor;
2627 extern cvar_t gl_info_renderer;
2628 extern cvar_t gl_info_version;
2629 extern cvar_t gl_info_platform;
2630 extern cvar_t gl_info_driver;
2632 qboolean VID_InitMode(viddef_mode_t *mode)
2634 // GAME_STEELSTORM specific
2635 steelstorm_showing_map = Cvar_FindVar("steelstorm_showing_map");
2636 steelstorm_showing_mousecursor = Cvar_FindVar("steelstorm_showing_mousecursor");
2638 if (!SDL_WasInit(SDL_INIT_VIDEO) && SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
2639 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
2641 #if SDL_MAJOR_VERSION != 1
2642 Cvar_SetValueQuick(&vid_touchscreen_supportshowkeyboard, SDL_HasScreenKeyboardSupport() ? 1 : 0);
2644 return VID_InitModeGL(mode);
2647 void VID_Shutdown (void)
2649 VID_EnableJoystick(false);
2650 VID_SetMouse(false, false, false);
2652 #if SDL_MAJOR_VERSION == 1
2656 SDL_FreeSurface(icon);
2662 #if SDL_MAJOR_VERSION != 1
2663 SDL_DestroyWindow(window);
2667 SDL_QuitSubSystem(SDL_INIT_VIDEO);
2672 gl_platformextensions = "";
2675 void VID_Finish (void)
2677 #if SDL_MAJOR_VERSION == 1
2680 //react on appstate changes
2681 appstate = SDL_GetAppState();
2683 vid_hidden = !(appstate & SDL_APPACTIVE);
2684 vid_hasfocus = (appstate & SDL_APPINPUTFOCUS) != 0;
2686 vid_activewindow = !vid_hidden && vid_hasfocus;
2692 switch(vid.renderpath)
2694 case RENDERPATH_GL20:
2695 case RENDERPATH_GLES2:
2697 if (r_speeds.integer == 2 || gl_finish.integer)
2700 #if SDL_MAJOR_VERSION != 1
2702 qboolean vid_usevsync;
2703 vid_usevsync = (vid_vsync.integer && !cls.timedemo);
2704 if (vid_usingvsync != vid_usevsync)
2706 vid_usingvsync = vid_usevsync;
2707 if (SDL_GL_SetSwapInterval(vid_usevsync != 0) >= 0)
2708 Con_DPrintf("Vsync %s\n", vid_usevsync ? "activated" : "deactivated");
2710 Con_DPrintf("ERROR: can't %s vsync\n", vid_usevsync ? "activate" : "deactivate");
2714 #if SDL_MAJOR_VERSION == 1
2715 SDL_GL_SwapBuffers();
2717 SDL_GL_SwapWindow(window);
2724 vid_mode_t *VID_GetDesktopMode(void)
2726 #if SDL_MAJOR_VERSION != 1
2727 SDL_DisplayMode mode;
2729 Uint32 rmask, gmask, bmask, amask;
2730 SDL_GetDesktopDisplayMode(0, &mode);
2731 SDL_PixelFormatEnumToMasks(mode.format, &bpp, &rmask, &gmask, &bmask, &amask);
2732 desktop_mode.width = mode.w;
2733 desktop_mode.height = mode.h;
2734 desktop_mode.bpp = bpp;
2735 desktop_mode.refreshrate = mode.refresh_rate;
2736 desktop_mode.pixelheight_num = 1;
2737 desktop_mode.pixelheight_denom = 1; // SDL does not provide this
2738 // TODO check whether this actually works, or whether we do still need
2739 // a read-window-size-after-entering-desktop-fullscreen hack for
2740 // multiscreen setups.
2742 return &desktop_mode;
2745 size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
2748 #if SDL_MAJOR_VERSION == 1
2749 SDL_Rect **vidmodes;
2750 int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
2752 SDL_Rect **ENDRECT = (SDL_Rect**)-1LL;
2754 SDL_Rect **ENDRECT = (SDL_Rect**)-1;
2757 for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); vidmodes && vidmodes != ENDRECT && *vidmodes; ++vidmodes)
2761 modes[k].width = (*vidmodes)->w;
2762 modes[k].height = (*vidmodes)->h;
2764 modes[k].refreshrate = 60; // no support for refresh rate in SDL
2765 modes[k].pixelheight_num = 1;
2766 modes[k].pixelheight_denom = 1; // SDL does not provide this
2771 int nummodes = SDL_GetNumDisplayModes(0);
2772 SDL_DisplayMode mode;
2773 for (modenum = 0;modenum < nummodes;modenum++)
2777 if (SDL_GetDisplayMode(0, modenum, &mode))
2779 modes[k].width = mode.w;
2780 modes[k].height = mode.h;
2782 modes[k].refreshrate = mode.refresh_rate;
2783 modes[k].pixelheight_num = 1;
2784 modes[k].pixelheight_denom = 1; // SDL does not provide this