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.ati_separate_stencil = false;
1896 vid.support.ext_blend_minmax = false;
1897 vid.support.ext_blend_subtract = true; // GLES2 core
1898 vid.support.ext_blend_func_separate = true; // GLES2 core
1899 vid.support.ext_draw_range_elements = false;
1902 Note: "In OS 2.1, the functions in GL_OES_framebuffer_object were not usable from the Java API.
1903 Calling them just threw an exception. Android developer relations confirmed that they forgot to implement these. (yeah...)
1904 It's apparently been fixed in 2.2, though I haven't tested."
1906 // LadyHavoc: Android 2.1 is way old now, enabling this again, it's going to be required soon.
1907 vid.support.ext_framebuffer_object = true;
1909 vid.support.ext_packed_depth_stencil = false;
1910 vid.support.ext_stencil_two_side = false;
1911 vid.support.ext_texture_3d = SDL_GL_ExtensionSupported("GL_OES_texture_3D") != 0;
1912 vid.support.ext_texture_compression_s3tc = SDL_GL_ExtensionSupported("GL_EXT_texture_compression_s3tc") != 0;
1913 vid.support.ext_texture_edge_clamp = true; // GLES2 core
1914 vid.support.ext_texture_filter_anisotropic = false; // probably don't want to use it...
1915 vid.support.ext_texture_srgb = false;
1916 vid.support.arb_texture_float = SDL_GL_ExtensionSupported("GL_OES_texture_float") != 0;
1917 vid.support.arb_half_float_pixel = SDL_GL_ExtensionSupported("GL_OES_texture_half_float") != 0;
1918 vid.support.arb_half_float_vertex = SDL_GL_ExtensionSupported("GL_OES_vertex_half_float") != 0;
1920 // NOTE: On some devices, a value of 512 gives better FPS than the maximum.
1921 qglGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_2d);
1923 #ifdef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
1924 if (vid.support.ext_texture_filter_anisotropic)
1925 qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*)&vid.max_anisotropy);
1927 if (vid.support.arb_texture_cube_map)
1928 qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_cubemap);
1929 #ifdef GL_MAX_3D_TEXTURE_SIZE
1930 if (vid.support.ext_texture_3d)
1931 qglGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_3d);
1933 Con_Printf("GL_MAX_CUBE_MAP_TEXTURE_SIZE = %i\n", vid.maxtexturesize_cubemap);
1934 Con_Printf("GL_MAX_3D_TEXTURE_SIZE = %i\n", vid.maxtexturesize_3d);
1936 #define GL_ALPHA_BITS 0x0D55
1937 #define GL_RED_BITS 0x0D52
1938 #define GL_GREEN_BITS 0x0D53
1939 #define GL_BLUE_BITS 0x0D54
1940 #define GL_DEPTH_BITS 0x0D56
1941 #define GL_STENCIL_BITS 0x0D57
1942 int fb_r = -1, fb_g = -1, fb_b = -1, fb_a = -1, fb_d = -1, fb_s = -1;
1943 qglGetIntegerv(GL_RED_BITS , &fb_r);
1944 qglGetIntegerv(GL_GREEN_BITS , &fb_g);
1945 qglGetIntegerv(GL_BLUE_BITS , &fb_b);
1946 qglGetIntegerv(GL_ALPHA_BITS , &fb_a);
1947 qglGetIntegerv(GL_DEPTH_BITS , &fb_d);
1948 qglGetIntegerv(GL_STENCIL_BITS, &fb_s);
1949 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);
1952 // verify that cubemap textures are really supported
1953 if (vid.support.arb_texture_cube_map && vid.maxtexturesize_cubemap < 256)
1954 vid.support.arb_texture_cube_map = false;
1956 // verify that 3d textures are really supported
1957 if (vid.support.ext_texture_3d && vid.maxtexturesize_3d < 32)
1959 vid.support.ext_texture_3d = false;
1960 Con_Printf("GL_OES_texture_3d reported bogus GL_MAX_3D_TEXTURE_SIZE, disabled\n");
1964 vid.teximageunits = 8;
1965 vid.texarrayunits = 5;
1966 //qglGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&vid.texunits);
1967 qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&vid.teximageunits);CHECKGLERROR
1968 //qglGetIntegerv(GL_MAX_TEXTURE_COORDS, (GLint*)&vid.texarrayunits);CHECKGLERROR
1969 vid.texunits = bound(1, vid.texunits, MAX_TEXTUREUNITS);
1970 vid.teximageunits = bound(1, vid.teximageunits, MAX_TEXTUREUNITS);
1971 vid.texarrayunits = bound(1, vid.texarrayunits, MAX_TEXTUREUNITS);
1972 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" : "");
1973 vid.renderpath = RENDERPATH_GLES2;
1974 vid.useinterleavedarrays = false;
1975 vid.sRGBcapable2D = false;
1976 vid.sRGBcapable3D = false;
1978 // VorteX: set other info (maybe place them in VID_InitMode?)
1979 extern cvar_t gl_info_vendor;
1980 extern cvar_t gl_info_renderer;
1981 extern cvar_t gl_info_version;
1982 extern cvar_t gl_info_platform;
1983 extern cvar_t gl_info_driver;
1984 Cvar_SetQuick(&gl_info_vendor, gl_vendor);
1985 Cvar_SetQuick(&gl_info_renderer, gl_renderer);
1986 Cvar_SetQuick(&gl_info_version, gl_version);
1987 Cvar_SetQuick(&gl_info_platform, gl_platform ? gl_platform : "");
1988 Cvar_SetQuick(&gl_info_driver, gl_driver);
1992 void *GL_GetProcAddress(const char *name)
1995 p = SDL_GL_GetProcAddress(name);
1999 static qboolean vid_sdl_initjoysticksystem = false;
2001 void VID_Init (void)
2003 #ifndef __IPHONEOS__
2005 Cvar_RegisterVariable(&apple_mouse_noaccel);
2008 #ifdef DP_MOBILETOUCH
2009 Cvar_SetValueQuick(&vid_touchscreen, 1);
2012 #ifdef SDL_R_RESTART
2013 R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap, NULL, NULL);
2016 if (SDL_Init(SDL_INIT_VIDEO) < 0)
2017 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
2018 vid_sdl_initjoysticksystem = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0;
2019 if (vid_sdl_initjoysticksystem)
2020 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
2021 vid_isfullscreen = false;
2024 static int vid_sdljoystickindex = -1;
2025 void VID_EnableJoystick(qboolean enable)
2027 int index = joy_enable.integer > 0 ? joy_index.integer : -1;
2028 int numsdljoysticks;
2029 qboolean success = false;
2030 int sharedcount = 0;
2032 sharedcount = VID_Shared_SetJoystick(index);
2033 if (index >= 0 && index < sharedcount)
2035 sdlindex = index - sharedcount;
2037 numsdljoysticks = SDL_NumJoysticks();
2038 if (sdlindex < 0 || sdlindex >= numsdljoysticks)
2041 // update cvar containing count of XInput joysticks + SDL joysticks
2042 if (joy_detected.integer != sharedcount + numsdljoysticks)
2043 Cvar_SetValueQuick(&joy_detected, sharedcount + numsdljoysticks);
2045 if (vid_sdljoystickindex != sdlindex)
2047 vid_sdljoystickindex = sdlindex;
2048 // close SDL joystick if active
2049 if (vid_sdljoystick)
2050 SDL_JoystickClose(vid_sdljoystick);
2051 vid_sdljoystick = NULL;
2054 vid_sdljoystick = SDL_JoystickOpen(sdlindex);
2055 if (vid_sdljoystick)
2057 #if SDL_MAJOR_VERSION == 1
2058 const char *joystickname = SDL_JoystickName(sdlindex);
2060 const char *joystickname = SDL_JoystickName(vid_sdljoystick);
2062 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));
2066 Con_Printf("Joystick %i failed (SDL_JoystickOpen(%i) returned: %s)\n", index, sdlindex, SDL_GetError());
2075 if (joy_active.integer != (success ? 1 : 0))
2076 Cvar_SetValueQuick(&joy_active, success ? 1 : 0);
2079 #if SDL_MAJOR_VERSION == 1
2080 // set the icon (we dont use SDL here since it would be too much a PITA)
2082 #include "resource.h"
2083 #include <SDL_syswm.h>
2084 static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
2086 SDL_Surface *screen = NULL;
2089 SDL_WM_SetCaption( gamename, NULL );
2090 screen = SDL_SetVideoMode(screenwidth, screenheight, screenbpp, screenflags);
2093 // get the HWND handle
2094 SDL_VERSION( &info.version );
2095 if (SDL_GetWMInfo(&info))
2097 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
2098 #ifndef _W64 //If Windows 64bit data types don't exist
2099 #ifndef SetClassLongPtr
2100 #define SetClassLongPtr SetClassLong
2103 #define GCLP_HICON GCL_HICON
2106 #define LONG_PTR LONG
2109 SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
2114 #elif defined(MACOSX)
2115 static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
2117 SDL_Surface *screen = NULL;
2118 SDL_WM_SetCaption( gamename, NULL );
2119 screen = SDL_SetVideoMode(screenwidth, screenheight, screenbpp, screenflags);
2120 // we don't use SDL_WM_SetIcon here because the icon in the .app should be used
2124 // Adding the OS independent XPM version --blub
2125 #include "darkplaces.xpm"
2126 #include "nexuiz.xpm"
2127 #if SDL_MAJOR_VERSION == 1
2128 #if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
2129 #include <SDL_syswm.h>
2132 static SDL_Surface *icon = NULL;
2133 static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
2136 * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
2137 * default settings with less than 91 colors and transparency.
2140 int width, height, colors, isize, i, j;
2142 static SDL_Color palette[256];
2143 unsigned short palenc[256]; // store color id by char
2145 char **idata, *data;
2146 const SDL_version *version;
2147 SDL_Surface *screen = NULL;
2150 SDL_FreeSurface(icon);
2152 version = SDL_Linked_Version();
2153 // only use non-XPM icon support in SDL v1.3 and higher
2154 // SDL v1.2 does not support "smooth" transparency, and thus is better
2156 if(version->major >= 2 || (version->major == 1 && version->minor >= 3))
2158 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
2161 unsigned int red = 0x00FF0000;
2162 unsigned int green = 0x0000FF00;
2163 unsigned int blue = 0x000000FF;
2164 unsigned int alpha = 0xFF000000;
2165 width = image_width;
2166 height = image_height;
2168 // reallocate with malloc, as this is in tempmempool (do not want)
2170 data = (char *) malloc(width * height * 4);
2171 memcpy(data, xpm, width * height * 4);
2175 icon = SDL_CreateRGBSurface(SDL_SRCALPHA, width, height, 32, LittleLong(red), LittleLong(green), LittleLong(blue), LittleLong(alpha));
2178 icon->pixels = data;
2181 Con_Printf( "Failed to create surface for the window Icon!\n"
2182 "%s\n", SDL_GetError());
2188 // we only get here if non-XPM icon was missing, or SDL version is not
2189 // sufficient for transparent non-XPM icons
2192 xpm = (char *) FS_LoadFile("darkplaces-icon.xpm", tempmempool, false, NULL);
2195 idata = XPM_DecodeString(xpm);
2197 idata = ENGINE_ICON;
2203 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) == 4)
2207 for(i = 0; i < colors; ++i)
2209 unsigned int r, g, b;
2212 if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
2215 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
2219 palette[i].r = 255; // color key
2222 thenone = i; // weeeee
2223 palenc[(unsigned char) idx] = i;
2228 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
2231 palenc[(unsigned char) idx] = i;
2237 // allocate the image data
2238 data = (char*) malloc(width*height);
2240 for(j = 0; j < height; ++j)
2242 for(i = 0; i < width; ++i)
2244 // casting to the safest possible datatypes ^^
2245 data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
2251 // SDL_FreeSurface should free the data too
2252 // but for completeness' sake...
2253 if(icon->flags & SDL_PREALLOC)
2256 icon->pixels = NULL; // safety
2258 SDL_FreeSurface(icon);
2261 icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
2262 // 8 bit surfaces get an empty palette allocated according to the docs
2263 // so it's a palette image for sure :) no endian check necessary for the mask
2267 icon->pixels = data;
2268 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
2269 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
2273 Con_Printf( "Failed to create surface for the window Icon!\n"
2274 "%s\n", SDL_GetError());
2280 Con_Printf("This XPM's palette looks odd. Can't continue.\n");
2285 // NOTE: Only 1-char colornames are supported
2286 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
2291 // NOTE: Only 1-char colornames are supported
2292 Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
2297 SDL_WM_SetIcon(icon, NULL);
2299 SDL_WM_SetCaption( gamename, NULL );
2300 screen = SDL_SetVideoMode(screenwidth, screenheight, screenbpp, screenflags);
2302 #if SDL_MAJOR_VERSION == 1
2303 // LordHavoc: info.info.x11.lock_func and accompanying code do not seem to compile with SDL 1.3
2304 #if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
2306 version = SDL_Linked_Version();
2307 // only use non-XPM icon support in SDL v1.3 and higher
2308 // SDL v1.2 does not support "smooth" transparency, and thus is better
2310 if(screen && (!(version->major >= 2 || (version->major == 1 && version->minor >= 3))))
2312 // in this case, we did not set the good icon yet
2314 SDL_VERSION(&info.version);
2315 if(SDL_GetWMInfo(&info) == 1 && info.subsystem == SDL_SYSWM_X11)
2317 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
2320 // use _NET_WM_ICON too
2321 static long netwm_icon[MAX_NETWM_ICON];
2328 if(pos + 2 * image_width * image_height < MAX_NETWM_ICON)
2330 netwm_icon[pos++] = image_width;
2331 netwm_icon[pos++] = image_height;
2332 for(i = 0; i < image_height; ++i)
2333 for(j = 0; j < image_width; ++j)
2334 netwm_icon[pos++] = BuffLittleLong((unsigned char *) &data[(i*image_width+j)*4]);
2338 Con_Printf("Skipping NETWM icon #%d because there is no space left\n", i);
2342 data = (char *) loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "darkplaces-icon%d", i), false, false, false, NULL);
2345 info.info.x11.lock_func();
2347 Atom net_wm_icon = XInternAtom(info.info.x11.display, "_NET_WM_ICON", false);
2348 XChangeProperty(info.info.x11.display, info.info.x11.wmwindow, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos);
2350 info.info.x11.unlock_func();
2362 static void VID_OutputVersion(void)
2364 SDL_version version;
2365 #if SDL_MAJOR_VERSION == 1
2366 version = *SDL_Linked_Version();
2368 SDL_GetVersion(&version);
2370 Con_Printf( "Linked against SDL version %d.%d.%d\n"
2371 "Using SDL library version %d.%d.%d\n",
2372 SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
2373 version.major, version.minor, version.patch );
2377 static void AdjustWindowBounds(viddef_mode_t *mode, RECT *rect)
2379 LONG width = mode->width; // vid_width
2380 LONG height = mode->height; // vid_height
2382 // adjust width and height for the space occupied by window decorators (title bar, borders)
2385 rect->right = width;
2386 rect->bottom = height;
2387 AdjustWindowRectEx(rect, WS_CAPTION|WS_THICKFRAME, false, 0);
2390 SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
2391 int workWidth = workArea.right - workArea.left;
2392 int workHeight = workArea.bottom - workArea.top;
2394 // SDL forces the window height to be <= screen height - 27px (on Win8.1 - probably intended for the title bar)
2395 // If the task bar is docked to the the left screen border and we move the window to negative y,
2396 // there would be some part of the regular desktop visible on the bottom of the screen.
2397 int titleBarPixels = 2;
2398 int screenHeight = GetSystemMetrics(SM_CYSCREEN);
2399 if (screenHeight == workHeight)
2400 titleBarPixels = -rect->top;
2402 //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);
2404 // if height and width matches the physical or previously adjusted screen height and width, adjust it to available desktop area
2405 if ((width == GetSystemMetrics(SM_CXSCREEN) || width == workWidth) && (height == screenHeight || height == workHeight - titleBarPixels))
2407 rect->left = workArea.left;
2408 mode->width = workWidth;
2409 rect->top = workArea.top + titleBarPixels;
2410 mode->height = workHeight - titleBarPixels;
2414 rect->left = workArea.left + max(0, (workWidth - width) / 2);
2415 rect->top = workArea.top + max(0, (workHeight - height) / 2);
2420 static qboolean VID_InitModeGL(viddef_mode_t *mode)
2422 #if SDL_MAJOR_VERSION == 1
2423 static int notfirstvideomode = false;
2424 int flags = SDL_OPENGL;
2426 int windowflags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL;
2427 int xPos = SDL_WINDOWPOS_UNDEFINED;
2428 int yPos = SDL_WINDOWPOS_UNDEFINED;
2432 const char *drivername;
2435 win_half_width = mode->width>>1;
2436 win_half_height = mode->height>>1;
2438 if(vid_resizable.integer)
2439 #if SDL_MAJOR_VERSION == 1
2440 flags |= SDL_RESIZABLE;
2442 windowflags |= SDL_WINDOW_RESIZABLE;
2445 VID_OutputVersion();
2447 #if SDL_MAJOR_VERSION == 1
2450 We cant switch from one OpenGL video mode to another.
2451 Thus we first switch to some stupid 2D mode and then back to OpenGL.
2453 if (notfirstvideomode)
2454 SDL_SetVideoMode( 0, 0, 0, 0 );
2455 notfirstvideomode = true;
2459 // SDL usually knows best
2462 // 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
2463 i = COM_CheckParm("-gl_driver");
2464 if (i && i < com_argc - 1)
2465 drivername = com_argv[i + 1];
2466 if (SDL_GL_LoadLibrary(drivername) < 0)
2468 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
2473 #ifdef DP_MOBILETOUCH
2474 // mobile platforms are always fullscreen, we'll get the resolution after opening the window
2475 mode->fullscreen = true;
2476 // hide the menu with SDL_WINDOW_BORDERLESS
2477 windowflags |= SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS;
2480 if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
2483 Con_Print("Required OpenGL function glGetString not found\n");
2488 // Knghtbrd: should do platform-specific extension string function here
2490 vid_isfullscreen = false;
2491 #if SDL_MAJOR_VERSION == 1
2493 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2494 desktop_mode.width = vi->current_w;
2495 desktop_mode.height = vi->current_h;
2496 desktop_mode.bpp = vi->vfmt->BitsPerPixel;
2497 desktop_mode.pixelheight_num = 1;
2498 desktop_mode.pixelheight_denom = 1; // SDL does not provide this
2499 if (mode->fullscreen) {
2500 if (vid_desktopfullscreen.integer)
2502 mode->width = vi->current_w;
2503 mode->height = vi->current_h;
2504 mode->bitsperpixel = vi->vfmt->BitsPerPixel;
2506 flags |= SDL_FULLSCREEN;
2507 vid_isfullscreen = true;
2512 if (mode->fullscreen) {
2513 if (vid_desktopfullscreen.integer)
2515 vid_mode_t *m = VID_GetDesktopMode();
2516 mode->width = m->width;
2517 mode->height = m->height;
2518 windowflags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
2521 windowflags |= SDL_WINDOW_FULLSCREEN;
2522 vid_isfullscreen = true;
2527 AdjustWindowBounds(mode, &rect);
2534 //flags |= SDL_HWSURFACE;
2536 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
2537 if (mode->bitsperpixel >= 32)
2539 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
2540 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
2541 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
2542 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
2543 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
2544 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
2548 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
2549 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
2550 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
2551 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
2553 if (mode->stereobuffer)
2554 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
2555 if (mode->samples > 1)
2557 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
2558 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples);
2561 #if SDL_MAJOR_VERSION == 1
2562 if (vid_vsync.integer)
2563 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
2565 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
2568 SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2);
2569 SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0);
2570 SDL_GL_SetAttribute (SDL_GL_RETAINED_BACKING, 1);
2574 video_bpp = mode->bitsperpixel;
2575 #if SDL_MAJOR_VERSION == 1
2576 video_flags = flags;
2577 video_screen = VID_WrapSDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
2578 if (video_screen == NULL)
2580 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
2584 mode->width = video_screen->w;
2585 mode->height = video_screen->h;
2587 window_flags = windowflags;
2588 window = SDL_CreateWindow(gamename, xPos, yPos, mode->width, mode->height, windowflags);
2591 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
2595 SDL_GetWindowSize(window, &mode->width, &mode->height);
2596 context = SDL_GL_CreateContext(window);
2597 if (context == NULL)
2599 Con_Printf("Failed to initialize OpenGL context: %s\n", SDL_GetError());
2605 #if SDL_MAJOR_VERSION == 1
2607 SDL_EnableUNICODE( SDL_ENABLE );
2608 // enable key repeat since everyone expects it
2609 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
2612 #if SDL_MAJOR_VERSION != 1
2613 SDL_GL_SetSwapInterval(vid_vsync.integer != 0);
2614 vid_usingvsync = (vid_vsync.integer != 0);
2617 gl_platform = "SDL";
2618 gl_platformextensions = "";
2627 vid_activewindow = false;
2628 vid_hasfocus = true;
2629 vid_usingmouse = false;
2630 vid_usinghidecursor = false;
2632 #if SDL_MAJOR_VERSION == 1
2633 SDL_WM_GrabInput(SDL_GRAB_OFF);
2638 extern cvar_t gl_info_extensions;
2639 extern cvar_t gl_info_vendor;
2640 extern cvar_t gl_info_renderer;
2641 extern cvar_t gl_info_version;
2642 extern cvar_t gl_info_platform;
2643 extern cvar_t gl_info_driver;
2645 qboolean VID_InitMode(viddef_mode_t *mode)
2647 // GAME_STEELSTORM specific
2648 steelstorm_showing_map = Cvar_FindVar("steelstorm_showing_map");
2649 steelstorm_showing_mousecursor = Cvar_FindVar("steelstorm_showing_mousecursor");
2651 if (!SDL_WasInit(SDL_INIT_VIDEO) && SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
2652 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
2654 #if SDL_MAJOR_VERSION != 1
2655 Cvar_SetValueQuick(&vid_touchscreen_supportshowkeyboard, SDL_HasScreenKeyboardSupport() ? 1 : 0);
2657 return VID_InitModeGL(mode);
2660 void VID_Shutdown (void)
2662 VID_EnableJoystick(false);
2663 VID_SetMouse(false, false, false);
2665 #if SDL_MAJOR_VERSION == 1
2669 SDL_FreeSurface(icon);
2675 #if SDL_MAJOR_VERSION != 1
2676 SDL_DestroyWindow(window);
2680 SDL_QuitSubSystem(SDL_INIT_VIDEO);
2685 gl_platformextensions = "";
2688 void VID_Finish (void)
2690 #if SDL_MAJOR_VERSION == 1
2693 //react on appstate changes
2694 appstate = SDL_GetAppState();
2696 vid_hidden = !(appstate & SDL_APPACTIVE);
2697 vid_hasfocus = (appstate & SDL_APPINPUTFOCUS) != 0;
2699 vid_activewindow = !vid_hidden && vid_hasfocus;
2705 switch(vid.renderpath)
2707 case RENDERPATH_GL20:
2708 case RENDERPATH_GLES2:
2710 if (r_speeds.integer == 2 || gl_finish.integer)
2713 #if SDL_MAJOR_VERSION != 1
2715 qboolean vid_usevsync;
2716 vid_usevsync = (vid_vsync.integer && !cls.timedemo);
2717 if (vid_usingvsync != vid_usevsync)
2719 vid_usingvsync = vid_usevsync;
2720 if (SDL_GL_SetSwapInterval(vid_usevsync != 0) >= 0)
2721 Con_DPrintf("Vsync %s\n", vid_usevsync ? "activated" : "deactivated");
2723 Con_DPrintf("ERROR: can't %s vsync\n", vid_usevsync ? "activate" : "deactivate");
2727 #if SDL_MAJOR_VERSION == 1
2728 SDL_GL_SwapBuffers();
2730 SDL_GL_SwapWindow(window);
2737 vid_mode_t *VID_GetDesktopMode(void)
2739 #if SDL_MAJOR_VERSION != 1
2740 SDL_DisplayMode mode;
2742 Uint32 rmask, gmask, bmask, amask;
2743 SDL_GetDesktopDisplayMode(0, &mode);
2744 SDL_PixelFormatEnumToMasks(mode.format, &bpp, &rmask, &gmask, &bmask, &amask);
2745 desktop_mode.width = mode.w;
2746 desktop_mode.height = mode.h;
2747 desktop_mode.bpp = bpp;
2748 desktop_mode.refreshrate = mode.refresh_rate;
2749 desktop_mode.pixelheight_num = 1;
2750 desktop_mode.pixelheight_denom = 1; // SDL does not provide this
2751 // TODO check whether this actually works, or whether we do still need
2752 // a read-window-size-after-entering-desktop-fullscreen hack for
2753 // multiscreen setups.
2755 return &desktop_mode;
2758 size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
2761 #if SDL_MAJOR_VERSION == 1
2762 SDL_Rect **vidmodes;
2763 int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
2765 SDL_Rect **ENDRECT = (SDL_Rect**)-1LL;
2767 SDL_Rect **ENDRECT = (SDL_Rect**)-1;
2770 for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); vidmodes && vidmodes != ENDRECT && *vidmodes; ++vidmodes)
2774 modes[k].width = (*vidmodes)->w;
2775 modes[k].height = (*vidmodes)->h;
2777 modes[k].refreshrate = 60; // no support for refresh rate in SDL
2778 modes[k].pixelheight_num = 1;
2779 modes[k].pixelheight_denom = 1; // SDL does not provide this
2784 int nummodes = SDL_GetNumDisplayModes(0);
2785 SDL_DisplayMode mode;
2786 for (modenum = 0;modenum < nummodes;modenum++)
2790 if (SDL_GetDisplayMode(0, modenum, &mode))
2792 modes[k].width = mode.w;
2793 modes[k].height = mode.h;
2795 modes[k].refreshrate = mode.refresh_rate;
2796 modes[k].pixelheight_num = 1;
2797 modes[k].pixelheight_denom = 1; // SDL does not provide this