don't spam joy_active notices with developer_extra
[xonotic/darkplaces.git] / vid_sdl.c
1 /*
2 Copyright (C) 2003  T. Joseph Carter
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18 */
19 #undef WIN32_LEAN_AND_MEAN  //hush a warning, SDL.h redefines this
20 #include <SDL.h>
21 #include <SDL_syswm.h>
22 #include <stdio.h>
23
24 #include "quakedef.h"
25 #include "image.h"
26 #include "dpsoftrast.h"
27
28 #ifndef __IPHONEOS__
29 #ifdef MACOSX
30 #include <Carbon/Carbon.h>
31 #include <IOKit/hidsystem/IOHIDLib.h>
32 #include <IOKit/hidsystem/IOHIDParameter.h>
33 #include <IOKit/hidsystem/event_status_driver.h>
34 static cvar_t apple_mouse_noaccel = {CVAR_SAVE, "apple_mouse_noaccel", "1", "disables mouse acceleration while DarkPlaces is active"};
35 static qboolean vid_usingnoaccel;
36 static double originalMouseSpeed = -1.0;
37 io_connect_t IN_GetIOHandle(void)
38 {
39         io_connect_t iohandle = MACH_PORT_NULL;
40         kern_return_t status;
41         io_service_t iohidsystem = MACH_PORT_NULL;
42         mach_port_t masterport;
43
44         status = IOMasterPort(MACH_PORT_NULL, &masterport);
45         if(status != KERN_SUCCESS)
46                 return 0;
47
48         iohidsystem = IORegistryEntryFromPath(masterport, kIOServicePlane ":/IOResources/IOHIDSystem");
49         if(!iohidsystem)
50                 return 0;
51
52         status = IOServiceOpen(iohidsystem, mach_task_self(), kIOHIDParamConnectType, &iohandle);
53         IOObjectRelease(iohidsystem);
54
55         return iohandle;
56 }
57 #endif
58 #endif
59
60 #ifdef WIN32
61 #define SDL_R_RESTART
62 #endif
63
64 // Tell startup code that we have a client
65 int cl_available = true;
66
67 qboolean vid_supportrefreshrate = false;
68
69 #ifdef USE_GLES2
70 # define SETVIDEOMODE 0
71 #else
72 # if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
73 #  define SETVIDEOMODE 1
74 # else
75 // LordHavoc: SDL 1.3's SDL_CreateWindow API is not finished enough to use yet, but you can set this to 0 if you want to try it...
76 #  ifndef SETVIDEOMODE
77 #   define SETVIDEOMODE 1
78 #  endif
79 # endif
80 #endif
81
82 static qboolean vid_usingmouse = false;
83 static qboolean vid_usinghidecursor = false;
84 static qboolean vid_hasfocus = false;
85 static qboolean vid_isfullscreen;
86 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
87 #else
88 static qboolean vid_usingvsync = false;
89 #endif
90 static SDL_Joystick *vid_sdljoystick = NULL;
91
92 static int win_half_width = 50;
93 static int win_half_height = 50;
94 static int video_bpp;
95
96 #if SETVIDEOMODE
97 static SDL_Surface *screen;
98 static int video_flags;
99 #else
100 static SDL_GLContext *context;
101 static SDL_Window *window;
102 static int window_flags;
103 #endif
104 static SDL_Surface *vid_softsurface;
105
106 /////////////////////////
107 // Input handling
108 ////
109 //TODO: Add error checking
110
111 #ifndef SDLK_PERCENT
112 #define SDLK_PERCENT '%'
113 #define SDLK_PRINTSCREEN SDLK_PRINT
114 #define SDLK_SCROLLLOCK SDLK_SCROLLOCK
115 #define SDLK_NUMLOCKCLEAR SDLK_NUMLOCK
116 #define SDLK_KP_1 SDLK_KP1
117 #define SDLK_KP_2 SDLK_KP2
118 #define SDLK_KP_3 SDLK_KP3
119 #define SDLK_KP_4 SDLK_KP4
120 #define SDLK_KP_5 SDLK_KP5
121 #define SDLK_KP_6 SDLK_KP6
122 #define SDLK_KP_7 SDLK_KP7
123 #define SDLK_KP_8 SDLK_KP8
124 #define SDLK_KP_9 SDLK_KP9
125 #define SDLK_KP_0 SDLK_KP0
126 #endif
127
128 static int MapKey( unsigned int sdlkey )
129 {
130         switch(sdlkey)
131         {
132         default: return 0;
133 //      case SDLK_UNKNOWN:            return K_UNKNOWN;
134         case SDLK_RETURN:             return K_ENTER;
135         case SDLK_ESCAPE:             return K_ESCAPE;
136         case SDLK_BACKSPACE:          return K_BACKSPACE;
137         case SDLK_TAB:                return K_TAB;
138         case SDLK_SPACE:              return K_SPACE;
139         case SDLK_EXCLAIM:            return '!';
140         case SDLK_QUOTEDBL:           return '"';
141         case SDLK_HASH:               return '#';
142         case SDLK_PERCENT:            return '%';
143         case SDLK_DOLLAR:             return '$';
144         case SDLK_AMPERSAND:          return '&';
145         case SDLK_QUOTE:              return '\'';
146         case SDLK_LEFTPAREN:          return '(';
147         case SDLK_RIGHTPAREN:         return ')';
148         case SDLK_ASTERISK:           return '*';
149         case SDLK_PLUS:               return '+';
150         case SDLK_COMMA:              return ',';
151         case SDLK_MINUS:              return '-';
152         case SDLK_PERIOD:             return '.';
153         case SDLK_SLASH:              return '/';
154         case SDLK_0:                  return '0';
155         case SDLK_1:                  return '1';
156         case SDLK_2:                  return '2';
157         case SDLK_3:                  return '3';
158         case SDLK_4:                  return '4';
159         case SDLK_5:                  return '5';
160         case SDLK_6:                  return '6';
161         case SDLK_7:                  return '7';
162         case SDLK_8:                  return '8';
163         case SDLK_9:                  return '9';
164         case SDLK_COLON:              return ':';
165         case SDLK_SEMICOLON:          return ';';
166         case SDLK_LESS:               return '<';
167         case SDLK_EQUALS:             return '=';
168         case SDLK_GREATER:            return '>';
169         case SDLK_QUESTION:           return '?';
170         case SDLK_AT:                 return '@';
171         case SDLK_LEFTBRACKET:        return '[';
172         case SDLK_BACKSLASH:          return '\\';
173         case SDLK_RIGHTBRACKET:       return ']';
174         case SDLK_CARET:              return '^';
175         case SDLK_UNDERSCORE:         return '_';
176         case SDLK_BACKQUOTE:          return '`';
177         case SDLK_a:                  return 'a';
178         case SDLK_b:                  return 'b';
179         case SDLK_c:                  return 'c';
180         case SDLK_d:                  return 'd';
181         case SDLK_e:                  return 'e';
182         case SDLK_f:                  return 'f';
183         case SDLK_g:                  return 'g';
184         case SDLK_h:                  return 'h';
185         case SDLK_i:                  return 'i';
186         case SDLK_j:                  return 'j';
187         case SDLK_k:                  return 'k';
188         case SDLK_l:                  return 'l';
189         case SDLK_m:                  return 'm';
190         case SDLK_n:                  return 'n';
191         case SDLK_o:                  return 'o';
192         case SDLK_p:                  return 'p';
193         case SDLK_q:                  return 'q';
194         case SDLK_r:                  return 'r';
195         case SDLK_s:                  return 's';
196         case SDLK_t:                  return 't';
197         case SDLK_u:                  return 'u';
198         case SDLK_v:                  return 'v';
199         case SDLK_w:                  return 'w';
200         case SDLK_x:                  return 'x';
201         case SDLK_y:                  return 'y';
202         case SDLK_z:                  return 'z';
203         case SDLK_CAPSLOCK:           return K_CAPSLOCK;
204         case SDLK_F1:                 return K_F1;
205         case SDLK_F2:                 return K_F2;
206         case SDLK_F3:                 return K_F3;
207         case SDLK_F4:                 return K_F4;
208         case SDLK_F5:                 return K_F5;
209         case SDLK_F6:                 return K_F6;
210         case SDLK_F7:                 return K_F7;
211         case SDLK_F8:                 return K_F8;
212         case SDLK_F9:                 return K_F9;
213         case SDLK_F10:                return K_F10;
214         case SDLK_F11:                return K_F11;
215         case SDLK_F12:                return K_F12;
216         case SDLK_PRINTSCREEN:        return K_PRINTSCREEN;
217         case SDLK_SCROLLLOCK:         return K_SCROLLOCK;
218         case SDLK_PAUSE:              return K_PAUSE;
219         case SDLK_INSERT:             return K_INS;
220         case SDLK_HOME:               return K_HOME;
221         case SDLK_PAGEUP:             return K_PGUP;
222 #ifdef __IPHONEOS__
223         case SDLK_DELETE:             return K_BACKSPACE;
224 #else
225         case SDLK_DELETE:             return K_DEL;
226 #endif
227         case SDLK_END:                return K_END;
228         case SDLK_PAGEDOWN:           return K_PGDN;
229         case SDLK_RIGHT:              return K_RIGHTARROW;
230         case SDLK_LEFT:               return K_LEFTARROW;
231         case SDLK_DOWN:               return K_DOWNARROW;
232         case SDLK_UP:                 return K_UPARROW;
233         case SDLK_NUMLOCKCLEAR:       return K_NUMLOCK;
234         case SDLK_KP_DIVIDE:          return K_KP_DIVIDE;
235         case SDLK_KP_MULTIPLY:        return K_KP_MULTIPLY;
236         case SDLK_KP_MINUS:           return K_KP_MINUS;
237         case SDLK_KP_PLUS:            return K_KP_PLUS;
238         case SDLK_KP_ENTER:           return K_KP_ENTER;
239         case SDLK_KP_1:               return K_KP_1;
240         case SDLK_KP_2:               return K_KP_2;
241         case SDLK_KP_3:               return K_KP_3;
242         case SDLK_KP_4:               return K_KP_4;
243         case SDLK_KP_5:               return K_KP_5;
244         case SDLK_KP_6:               return K_KP_6;
245         case SDLK_KP_7:               return K_KP_7;
246         case SDLK_KP_8:               return K_KP_8;
247         case SDLK_KP_9:               return K_KP_9;
248         case SDLK_KP_0:               return K_KP_0;
249         case SDLK_KP_PERIOD:          return K_KP_PERIOD;
250 //      case SDLK_APPLICATION:        return K_APPLICATION;
251 //      case SDLK_POWER:              return K_POWER;
252         case SDLK_KP_EQUALS:          return K_KP_EQUALS;
253 //      case SDLK_F13:                return K_F13;
254 //      case SDLK_F14:                return K_F14;
255 //      case SDLK_F15:                return K_F15;
256 //      case SDLK_F16:                return K_F16;
257 //      case SDLK_F17:                return K_F17;
258 //      case SDLK_F18:                return K_F18;
259 //      case SDLK_F19:                return K_F19;
260 //      case SDLK_F20:                return K_F20;
261 //      case SDLK_F21:                return K_F21;
262 //      case SDLK_F22:                return K_F22;
263 //      case SDLK_F23:                return K_F23;
264 //      case SDLK_F24:                return K_F24;
265 //      case SDLK_EXECUTE:            return K_EXECUTE;
266 //      case SDLK_HELP:               return K_HELP;
267 //      case SDLK_MENU:               return K_MENU;
268 //      case SDLK_SELECT:             return K_SELECT;
269 //      case SDLK_STOP:               return K_STOP;
270 //      case SDLK_AGAIN:              return K_AGAIN;
271 //      case SDLK_UNDO:               return K_UNDO;
272 //      case SDLK_CUT:                return K_CUT;
273 //      case SDLK_COPY:               return K_COPY;
274 //      case SDLK_PASTE:              return K_PASTE;
275 //      case SDLK_FIND:               return K_FIND;
276 //      case SDLK_MUTE:               return K_MUTE;
277 //      case SDLK_VOLUMEUP:           return K_VOLUMEUP;
278 //      case SDLK_VOLUMEDOWN:         return K_VOLUMEDOWN;
279 //      case SDLK_KP_COMMA:           return K_KP_COMMA;
280 //      case SDLK_KP_EQUALSAS400:     return K_KP_EQUALSAS400;
281 //      case SDLK_ALTERASE:           return K_ALTERASE;
282 //      case SDLK_SYSREQ:             return K_SYSREQ;
283 //      case SDLK_CANCEL:             return K_CANCEL;
284 //      case SDLK_CLEAR:              return K_CLEAR;
285 //      case SDLK_PRIOR:              return K_PRIOR;
286 //      case SDLK_RETURN2:            return K_RETURN2;
287 //      case SDLK_SEPARATOR:          return K_SEPARATOR;
288 //      case SDLK_OUT:                return K_OUT;
289 //      case SDLK_OPER:               return K_OPER;
290 //      case SDLK_CLEARAGAIN:         return K_CLEARAGAIN;
291 //      case SDLK_CRSEL:              return K_CRSEL;
292 //      case SDLK_EXSEL:              return K_EXSEL;
293 //      case SDLK_KP_00:              return K_KP_00;
294 //      case SDLK_KP_000:             return K_KP_000;
295 //      case SDLK_THOUSANDSSEPARATOR: return K_THOUSANDSSEPARATOR;
296 //      case SDLK_DECIMALSEPARATOR:   return K_DECIMALSEPARATOR;
297 //      case SDLK_CURRENCYUNIT:       return K_CURRENCYUNIT;
298 //      case SDLK_CURRENCYSUBUNIT:    return K_CURRENCYSUBUNIT;
299 //      case SDLK_KP_LEFTPAREN:       return K_KP_LEFTPAREN;
300 //      case SDLK_KP_RIGHTPAREN:      return K_KP_RIGHTPAREN;
301 //      case SDLK_KP_LEFTBRACE:       return K_KP_LEFTBRACE;
302 //      case SDLK_KP_RIGHTBRACE:      return K_KP_RIGHTBRACE;
303 //      case SDLK_KP_TAB:             return K_KP_TAB;
304 //      case SDLK_KP_BACKSPACE:       return K_KP_BACKSPACE;
305 //      case SDLK_KP_A:               return K_KP_A;
306 //      case SDLK_KP_B:               return K_KP_B;
307 //      case SDLK_KP_C:               return K_KP_C;
308 //      case SDLK_KP_D:               return K_KP_D;
309 //      case SDLK_KP_E:               return K_KP_E;
310 //      case SDLK_KP_F:               return K_KP_F;
311 //      case SDLK_KP_XOR:             return K_KP_XOR;
312 //      case SDLK_KP_POWER:           return K_KP_POWER;
313 //      case SDLK_KP_PERCENT:         return K_KP_PERCENT;
314 //      case SDLK_KP_LESS:            return K_KP_LESS;
315 //      case SDLK_KP_GREATER:         return K_KP_GREATER;
316 //      case SDLK_KP_AMPERSAND:       return K_KP_AMPERSAND;
317 //      case SDLK_KP_DBLAMPERSAND:    return K_KP_DBLAMPERSAND;
318 //      case SDLK_KP_VERTICALBAR:     return K_KP_VERTICALBAR;
319 //      case SDLK_KP_DBLVERTICALBAR:  return K_KP_DBLVERTICALBAR;
320 //      case SDLK_KP_COLON:           return K_KP_COLON;
321 //      case SDLK_KP_HASH:            return K_KP_HASH;
322 //      case SDLK_KP_SPACE:           return K_KP_SPACE;
323 //      case SDLK_KP_AT:              return K_KP_AT;
324 //      case SDLK_KP_EXCLAM:          return K_KP_EXCLAM;
325 //      case SDLK_KP_MEMSTORE:        return K_KP_MEMSTORE;
326 //      case SDLK_KP_MEMRECALL:       return K_KP_MEMRECALL;
327 //      case SDLK_KP_MEMCLEAR:        return K_KP_MEMCLEAR;
328 //      case SDLK_KP_MEMADD:          return K_KP_MEMADD;
329 //      case SDLK_KP_MEMSUBTRACT:     return K_KP_MEMSUBTRACT;
330 //      case SDLK_KP_MEMMULTIPLY:     return K_KP_MEMMULTIPLY;
331 //      case SDLK_KP_MEMDIVIDE:       return K_KP_MEMDIVIDE;
332 //      case SDLK_KP_PLUSMINUS:       return K_KP_PLUSMINUS;
333 //      case SDLK_KP_CLEAR:           return K_KP_CLEAR;
334 //      case SDLK_KP_CLEARENTRY:      return K_KP_CLEARENTRY;
335 //      case SDLK_KP_BINARY:          return K_KP_BINARY;
336 //      case SDLK_KP_OCTAL:           return K_KP_OCTAL;
337 //      case SDLK_KP_DECIMAL:         return K_KP_DECIMAL;
338 //      case SDLK_KP_HEXADECIMAL:     return K_KP_HEXADECIMAL;
339         case SDLK_LCTRL:              return K_CTRL;
340         case SDLK_LSHIFT:             return K_SHIFT;
341         case SDLK_LALT:               return K_ALT;
342 //      case SDLK_LGUI:               return K_LGUI;
343         case SDLK_RCTRL:              return K_CTRL;
344         case SDLK_RSHIFT:             return K_SHIFT;
345         case SDLK_RALT:               return K_ALT;
346 //      case SDLK_RGUI:               return K_RGUI;
347 //      case SDLK_MODE:               return K_MODE;
348 //      case SDLK_AUDIONEXT:          return K_AUDIONEXT;
349 //      case SDLK_AUDIOPREV:          return K_AUDIOPREV;
350 //      case SDLK_AUDIOSTOP:          return K_AUDIOSTOP;
351 //      case SDLK_AUDIOPLAY:          return K_AUDIOPLAY;
352 //      case SDLK_AUDIOMUTE:          return K_AUDIOMUTE;
353 //      case SDLK_MEDIASELECT:        return K_MEDIASELECT;
354 //      case SDLK_WWW:                return K_WWW;
355 //      case SDLK_MAIL:               return K_MAIL;
356 //      case SDLK_CALCULATOR:         return K_CALCULATOR;
357 //      case SDLK_COMPUTER:           return K_COMPUTER;
358 //      case SDLK_AC_SEARCH:          return K_AC_SEARCH;
359 //      case SDLK_AC_HOME:            return K_AC_HOME;
360 //      case SDLK_AC_BACK:            return K_AC_BACK;
361 //      case SDLK_AC_FORWARD:         return K_AC_FORWARD;
362 //      case SDLK_AC_STOP:            return K_AC_STOP;
363 //      case SDLK_AC_REFRESH:         return K_AC_REFRESH;
364 //      case SDLK_AC_BOOKMARKS:       return K_AC_BOOKMARKS;
365 //      case SDLK_BRIGHTNESSDOWN:     return K_BRIGHTNESSDOWN;
366 //      case SDLK_BRIGHTNESSUP:       return K_BRIGHTNESSUP;
367 //      case SDLK_DISPLAYSWITCH:      return K_DISPLAYSWITCH;
368 //      case SDLK_KBDILLUMTOGGLE:     return K_KBDILLUMTOGGLE;
369 //      case SDLK_KBDILLUMDOWN:       return K_KBDILLUMDOWN;
370 //      case SDLK_KBDILLUMUP:         return K_KBDILLUMUP;
371 //      case SDLK_EJECT:              return K_EJECT;
372 //      case SDLK_SLEEP:              return K_SLEEP;
373         }
374 }
375
376 #ifdef __IPHONEOS__
377 int SDL_iPhoneKeyboardShow(SDL_Window * window);  // reveals the onscreen keyboard.  Returns 0 on success and -1 on error.
378 int SDL_iPhoneKeyboardHide(SDL_Window * window);  // hides the onscreen keyboard.  Returns 0 on success and -1 on error.
379 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window);  // returns whether or not the onscreen keyboard is currently visible.
380 int SDL_iPhoneKeyboardToggle(SDL_Window * window); // toggles the visibility of the onscreen keyboard.  Returns 0 on success and -1 on error.
381 #endif
382
383 void VID_ShowKeyboard(qboolean show)
384 {
385 #ifdef __IPHONEOS__
386         if (show)
387         {
388                 if (!SDL_iPhoneKeyboardIsShown(window))
389                         SDL_iPhoneKeyboardShow(window);
390         }
391         else
392         {
393                 if (SDL_iPhoneKeyboardIsShown(window))
394                         SDL_iPhoneKeyboardHide(window);
395         }
396 #endif
397 }
398
399 #ifdef __IPHONEOS__
400 qboolean VID_ShowingKeyboard(void)
401 {
402         return SDL_iPhoneKeyboardIsShown(window);
403 }
404 #endif
405
406 void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor)
407 {
408 #ifndef __IPHONEOS__
409 #ifdef MACOSX
410         if(relative)
411                 if(vid_usingmouse && (vid_usingnoaccel != !!apple_mouse_noaccel.integer))
412                         VID_SetMouse(false, false, false); // ungrab first!
413 #endif
414         if (vid_usingmouse != relative)
415         {
416                 vid_usingmouse = relative;
417                 cl_ignoremousemoves = 2;
418 #if SETVIDEOMODE
419                 SDL_WM_GrabInput( relative ? SDL_GRAB_ON : SDL_GRAB_OFF );
420 #else
421                 SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE);
422 #endif
423 #ifdef MACOSX
424                 if(relative)
425                 {
426                         // Save the status of mouse acceleration
427                         originalMouseSpeed = -1.0; // in case of error
428                         if(apple_mouse_noaccel.integer)
429                         {
430                                 io_connect_t mouseDev = IN_GetIOHandle();
431                                 if(mouseDev != 0)
432                                 {
433                                         if(IOHIDGetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), &originalMouseSpeed) == kIOReturnSuccess)
434                                         {
435                                                 Con_DPrintf("previous mouse acceleration: %f\n", originalMouseSpeed);
436                                                 if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), -1.0) != kIOReturnSuccess)
437                                                 {
438                                                         Con_Print("Could not disable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
439                                                         Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
440                                                 }
441                                         }
442                                         else
443                                         {
444                                                 Con_Print("Could not disable mouse acceleration (failed at IOHIDGetAccelerationWithKey).\n");
445                                                 Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
446                                         }
447                                         IOServiceClose(mouseDev);
448                                 }
449                                 else
450                                 {
451                                         Con_Print("Could not disable mouse acceleration (failed at IO_GetIOHandle).\n");
452                                         Cvar_SetValueQuick(&apple_mouse_noaccel, 0);
453                                 }
454                         }
455
456                         vid_usingnoaccel = !!apple_mouse_noaccel.integer;
457                 }
458                 else
459                 {
460                         if(originalMouseSpeed != -1.0)
461                         {
462                                 io_connect_t mouseDev = IN_GetIOHandle();
463                                 if(mouseDev != 0)
464                                 {
465                                         Con_DPrintf("restoring mouse acceleration to: %f\n", originalMouseSpeed);
466                                         if(IOHIDSetAccelerationWithKey(mouseDev, CFSTR(kIOHIDMouseAccelerationType), originalMouseSpeed) != kIOReturnSuccess)
467                                                 Con_Print("Could not re-enable mouse acceleration (failed at IOHIDSetAccelerationWithKey).\n");
468                                         IOServiceClose(mouseDev);
469                                 }
470                                 else
471                                         Con_Print("Could not re-enable mouse acceleration (failed at IO_GetIOHandle).\n");
472                         }
473                 }
474 #endif
475         }
476         if (vid_usinghidecursor != hidecursor)
477         {
478                 vid_usinghidecursor = hidecursor;
479                 SDL_ShowCursor( hidecursor ? SDL_DISABLE : SDL_ENABLE);
480         }
481 #endif
482 }
483
484 // multitouch[10][] represents the mouse pointer
485 // X and Y coordinates are 0-32767 as per SDL spec
486 #define MAXFINGERS 11
487 int multitouch[MAXFINGERS][3];
488
489 qboolean VID_TouchscreenArea(int corner, float px, float py, float pwidth, float pheight, const char *icon, float *resultmove, qboolean *resultbutton, keynum_t key)
490 {
491         int finger;
492         float fx, fy, fwidth, fheight;
493         float rel[3];
494         qboolean button = false;
495         VectorClear(rel);
496         if (pwidth > 0 && pheight > 0)
497 #ifdef __IPHONEOS__
498         if (!VID_ShowingKeyboard())
499 #endif
500         {
501                 if (corner & 1) px += vid_conwidth.value;
502                 if (corner & 2) py += vid_conheight.value;
503                 if (corner & 4) px += vid_conwidth.value * 0.5f;
504                 if (corner & 8) py += vid_conheight.value * 0.5f;
505                 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);}
506                 fx = px * 32768.0f / vid_conwidth.value;
507                 fy = py * 32768.0f / vid_conheight.value;
508                 fwidth = pwidth * 32768.0f / vid_conwidth.value;
509                 fheight = pheight * 32768.0f / vid_conheight.value;
510                 for (finger = 0;finger < MAXFINGERS;finger++)
511                 {
512                         if (multitouch[finger][0] && multitouch[finger][1] >= fx && multitouch[finger][2] >= fy && multitouch[finger][1] < fx + fwidth && multitouch[finger][2] < fy + fheight)
513                         {
514                                 rel[0] = (multitouch[finger][1] - (fx + 0.5f * fwidth)) * (2.0f / fwidth);
515                                 rel[1] = (multitouch[finger][2] - (fy + 0.5f * fheight)) * (2.0f / fheight);
516                                 rel[2] = 0;
517                                 button = true;
518                                 break;
519                         }
520                 }
521                 if (scr_numtouchscreenareas < 16)
522                 {
523                         scr_touchscreenareas[scr_numtouchscreenareas].pic = icon;
524                         scr_touchscreenareas[scr_numtouchscreenareas].rect[0] = px;
525                         scr_touchscreenareas[scr_numtouchscreenareas].rect[1] = py;
526                         scr_touchscreenareas[scr_numtouchscreenareas].rect[2] = pwidth;
527                         scr_touchscreenareas[scr_numtouchscreenareas].rect[3] = pheight;
528                         scr_touchscreenareas[scr_numtouchscreenareas].active = button;
529                         scr_numtouchscreenareas++;
530                 }
531         }
532         if (resultmove)
533         {
534                 if (button)
535                         VectorCopy(rel, resultmove);
536                 else
537                         VectorClear(resultmove);
538         }
539         if (resultbutton)
540         {
541                 if (*resultbutton != button && (int)key > 0)
542                         Key_Event(key, 0, button);
543                 *resultbutton = button;
544         }
545         return button;
546 }
547
548 void VID_BuildJoyState(vid_joystate_t *joystate)
549 {
550         VID_Shared_BuildJoyState_Begin(joystate);
551
552         if (vid_sdljoystick)
553         {
554                 SDL_Joystick *joy = vid_sdljoystick;
555                 int j;
556                 int numaxes;
557                 int numbuttons;
558                 numaxes = SDL_JoystickNumAxes(joy);
559                 for (j = 0;j < numaxes;j++)
560                         joystate->axis[j] = SDL_JoystickGetAxis(joy, j) * (1.0f / 32767.0f);
561                 numbuttons = SDL_JoystickNumButtons(joy);
562                 for (j = 0;j < numbuttons;j++)
563                         joystate->button[j] = SDL_JoystickGetButton(joy, j);
564         }
565
566         VID_Shared_BuildJoyState_Finish(joystate);
567 }
568
569 /////////////////////
570 // Movement handling
571 ////
572
573 void IN_Move( void )
574 {
575         static int old_x = 0, old_y = 0;
576         static int stuck = 0;
577         int x, y;
578         vid_joystate_t joystate;
579
580         scr_numtouchscreenareas = 0;
581         if (vid_touchscreen.integer)
582         {
583                 vec3_t move, aim, click;
584                 static qboolean buttons[16];
585                 static keydest_t oldkeydest;
586                 keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest;
587                 multitouch[MAXFINGERS-1][0] = SDL_GetMouseState(&x, &y);
588                 multitouch[MAXFINGERS-1][1] = x * 32768 / vid.width;
589                 multitouch[MAXFINGERS-1][2] = y * 32768 / vid.height;
590                 if (oldkeydest != keydest)
591                 {
592                         switch(keydest)
593                         {
594                         case key_game: VID_ShowKeyboard(false);break;
595                         case key_console: VID_ShowKeyboard(true);break;
596                         case key_message: VID_ShowKeyboard(true);break;
597                         default: break;
598                         }
599                 }
600                 oldkeydest = keydest;
601                 // top of screen is toggleconsole and K_ESCAPE
602                 switch(keydest)
603                 {
604                 case key_console:
605 #ifdef __IPHONEOS__
606                         VID_TouchscreenArea( 0,   0,   0,  64,  64, NULL                         , NULL, &buttons[13], (keynum_t)'`');
607                         VID_TouchscreenArea( 0,  64,   0,  64,  64, "gfx/touch_menu.tga"         , NULL, &buttons[14], K_ESCAPE);
608                         if (!VID_ShowingKeyboard())
609                         {
610                                 // user entered a command, close the console now
611                                 Con_ToggleConsole_f();
612                         }
613 #endif
614                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , NULL, &buttons[15], (keynum_t)0);
615                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , move, &buttons[0], K_MOUSE4);
616                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , aim,  &buttons[1], K_MOUSE5);
617                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , click,&buttons[2], K_MOUSE1);
618                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , NULL, &buttons[3], K_SPACE);
619                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , NULL, &buttons[4], K_MOUSE2);
620                         break;
621                 case key_game:
622 #ifdef __IPHONEOS__
623                         VID_TouchscreenArea( 0,   0,   0,  64,  64, NULL                         , NULL, &buttons[13], (keynum_t)'`');
624                         VID_TouchscreenArea( 0,  64,   0,  64,  64, "gfx/touch_menu.tga"         , NULL, &buttons[14], K_ESCAPE);
625 #endif
626                         VID_TouchscreenArea( 2,   0,-128, 128, 128, "gfx/touch_movebutton.tga"   , move, &buttons[0], K_MOUSE4);
627                         VID_TouchscreenArea( 3,-128,-128, 128, 128, "gfx/touch_aimbutton.tga"    , aim,  &buttons[1], K_MOUSE5);
628                         VID_TouchscreenArea( 2,   0,-160,  64,  32, "gfx/touch_jumpbutton.tga"   , NULL, &buttons[3], K_SPACE);
629                         VID_TouchscreenArea( 3,-128,-160,  64,  32, "gfx/touch_attackbutton.tga" , NULL, &buttons[2], K_MOUSE1);
630                         VID_TouchscreenArea( 3, -64,-160,  64,  32, "gfx/touch_attack2button.tga", NULL, &buttons[4], K_MOUSE2);
631                         buttons[15] = false;
632                         break;
633                 default:
634 #ifdef __IPHONEOS__
635                         VID_TouchscreenArea( 0,   0,   0,  64,  64, NULL                         , NULL, &buttons[13], (keynum_t)'`');
636                         VID_TouchscreenArea( 0,  64,   0,  64,  64, "gfx/touch_menu.tga"         , NULL, &buttons[14], K_ESCAPE);
637                         // in menus, an icon in the corner activates keyboard
638                         VID_TouchscreenArea( 2,   0, -32,  32,  32, "gfx/touch_keyboard.tga"     , NULL, &buttons[15], (keynum_t)0);
639                         if (buttons[15])
640                                 VID_ShowKeyboard(true);
641                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , move, &buttons[0], K_MOUSE4);
642                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , aim,  &buttons[1], K_MOUSE5);
643                         VID_TouchscreenArea(16, -320,-480,640, 960, NULL                         , click,&buttons[2], K_MOUSE1);
644                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , NULL, &buttons[3], K_SPACE);
645                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , NULL, &buttons[4], K_MOUSE2);
646                         if (buttons[2])
647                         {
648                                 in_windowmouse_x = x;
649                                 in_windowmouse_y = y;
650                         }
651 #else
652                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , NULL, &buttons[15], (keynum_t)0);
653                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , move, &buttons[0], K_MOUSE4);
654                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , aim,  &buttons[1], K_MOUSE5);
655                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , click,&buttons[2], K_MOUSE1);
656                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , NULL, &buttons[3], K_SPACE);
657                         VID_TouchscreenArea( 0,   0,   0,   0,   0, NULL                         , NULL, &buttons[4], K_MOUSE2);
658 #endif
659                         break;
660                 }
661                 cl.cmd.forwardmove -= move[1] * cl_forwardspeed.value;
662                 cl.cmd.sidemove += move[0] * cl_sidespeed.value;
663                 cl.viewangles[0] += aim[1] * cl_pitchspeed.value * cl.realframetime;
664                 cl.viewangles[1] -= aim[0] * cl_yawspeed.value * cl.realframetime;
665         }
666         else
667         {
668                 if (vid_usingmouse)
669                 {
670                         if (vid_stick_mouse.integer)
671                         {
672                                 // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
673                                 // window grabbing. --blub
674         
675                                 // we need 2 frames to initialize the center position
676                                 if(!stuck)
677                                 {
678 #if SETVIDEOMODE
679                                         SDL_WarpMouse(win_half_width, win_half_height);
680 #else
681                                         SDL_WarpMouseInWindow(window, win_half_width, win_half_height);
682 #endif
683                                         SDL_GetMouseState(&x, &y);
684                                         SDL_GetRelativeMouseState(&x, &y);
685                                         ++stuck;
686                                 } else {
687                                         SDL_GetRelativeMouseState(&x, &y);
688                                         in_mouse_x = x + old_x;
689                                         in_mouse_y = y + old_y;
690                                         SDL_GetMouseState(&x, &y);
691                                         old_x = x - win_half_width;
692                                         old_y = y - win_half_height;
693 #if SETVIDEOMODE
694                                         SDL_WarpMouse(win_half_width, win_half_height);
695 #else
696                                         SDL_WarpMouseInWindow(window, win_half_width, win_half_height);
697 #endif
698                                 }
699                         } else {
700                                 SDL_GetRelativeMouseState( &x, &y );
701                                 in_mouse_x = x;
702                                 in_mouse_y = y;
703                         }
704                 }
705
706                 SDL_GetMouseState(&x, &y);
707                 in_windowmouse_x = x;
708                 in_windowmouse_y = y;
709         }
710
711         VID_BuildJoyState(&joystate);
712         VID_ApplyJoyState(&joystate);
713 }
714
715 /////////////////////
716 // Message Handling
717 ////
718
719 #ifdef SDL_R_RESTART
720 static qboolean sdl_needs_restart;
721 static void sdl_start(void)
722 {
723 }
724 static void sdl_shutdown(void)
725 {
726         sdl_needs_restart = false;
727 }
728 static void sdl_newmap(void)
729 {
730 }
731 #endif
732
733 #ifndef __IPHONEOS__
734 static keynum_t buttonremap[18] =
735 {
736         K_MOUSE1,
737         K_MOUSE3,
738         K_MOUSE2,
739         K_MWHEELUP,
740         K_MWHEELDOWN,
741         K_MOUSE4,
742         K_MOUSE5,
743         K_MOUSE6,
744         K_MOUSE7,
745         K_MOUSE8,
746         K_MOUSE9,
747         K_MOUSE10,
748         K_MOUSE11,
749         K_MOUSE12,
750         K_MOUSE13,
751         K_MOUSE14,
752         K_MOUSE15,
753         K_MOUSE16,
754 };
755 #endif
756
757 #if SETVIDEOMODE
758 // SDL 1.2
759 void Sys_SendKeyEvents( void )
760 {
761         static qboolean sound_active = true;
762         int keycode;
763         SDL_Event event;
764
765         VID_EnableJoystick(true);
766
767         while( SDL_PollEvent( &event ) )
768                 switch( event.type ) {
769                         case SDL_QUIT:
770                                 Sys_Quit(0);
771                                 break;
772                         case SDL_KEYDOWN:
773                         case SDL_KEYUP:
774                                 keycode = MapKey(event.key.keysym.sym);
775                                 if (!VID_JoyBlockEmulatedKeys(keycode))
776                                         Key_Event(keycode, event.key.keysym.unicode, (event.key.state == SDL_PRESSED));
777                                 break;
778                         case SDL_ACTIVEEVENT:
779                                 if( event.active.state & SDL_APPACTIVE )
780                                 {
781                                         if( event.active.gain )
782                                                 vid_hidden = false;
783                                         else
784                                                 vid_hidden = true;
785                                 }
786                                 break;
787                         case SDL_MOUSEBUTTONDOWN:
788                         case SDL_MOUSEBUTTONUP:
789                                 if (!vid_touchscreen.integer)
790                                 if (event.button.button <= 18)
791                                         Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
792                                 break;
793                         case SDL_JOYBUTTONDOWN:
794                         case SDL_JOYBUTTONUP:
795                         case SDL_JOYAXISMOTION:
796                         case SDL_JOYBALLMOTION:
797                         case SDL_JOYHATMOTION:
798                                 break;
799                         case SDL_VIDEOEXPOSE:
800                                 break;
801                         case SDL_VIDEORESIZE:
802                                 if(vid_resizable.integer < 2)
803                                 {
804                                         vid.width = event.resize.w;
805                                         vid.height = event.resize.h;
806                                         screen = SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
807                                         if (vid_softsurface)
808                                         {
809                                                 SDL_FreeSurface(vid_softsurface);
810                                                 vid_softsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, vid.width, vid.height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
811                                                 vid.softpixels = (unsigned int *)vid_softsurface->pixels;
812                                                 SDL_SetAlpha(vid_softsurface, 0, 255);
813                                                 if (vid.softdepthpixels)
814                                                         free(vid.softdepthpixels);
815                                                 vid.softdepthpixels = (unsigned int*)calloc(1, vid.width * vid.height * 4);
816                                         }
817 #ifdef SDL_R_RESTART
818                                         // better not call R_Modules_Restart from here directly, as this may wreak havoc...
819                                         // so, let's better queue it for next frame
820                                         if(!sdl_needs_restart)
821                                         {
822                                                 Cbuf_AddText("\nr_restart\n");
823                                                 sdl_needs_restart = true;
824                                         }
825 #endif
826                                 }
827                                 break;
828 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
829 #else
830                         case SDL_TEXTEDITING:
831                                 // unused when SETVIDEOMODE API is used
832                                 break;
833                         case SDL_TEXTINPUT:
834                                 // this occurs with SETVIDEOMODE but we are not using it
835                                 break;
836 #endif
837                         case SDL_MOUSEMOTION:
838                                 break;
839                         default:
840                                 Con_DPrintf("Received unrecognized SDL_Event type 0x%x\n", event.type);
841                                 break;
842                 }
843
844         // enable/disable sound on focus gain/loss
845         if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
846         {
847                 if (!sound_active)
848                 {
849                         S_UnblockSound ();
850                         sound_active = true;
851                 }
852         }
853         else
854         {
855                 if (sound_active)
856                 {
857                         S_BlockSound ();
858                         sound_active = false;
859                 }
860         }
861 }
862
863 #else
864
865 // SDL 1.3
866 void Sys_SendKeyEvents( void )
867 {
868         static qboolean sound_active = true;
869         static qboolean missingunicodehack = true;
870         int keycode;
871         int i;
872         int j;
873         int unicode;
874         SDL_Event event;
875
876         VID_EnableJoystick(true);
877
878         while( SDL_PollEvent( &event ) )
879                 switch( event.type ) {
880                         case SDL_QUIT:
881                                 Sys_Quit(0);
882                                 break;
883                         case SDL_KEYDOWN:
884                         case SDL_KEYUP:
885                                 keycode = MapKey(event.key.keysym.sym);
886                                 if (!VID_JoyBlockEmulatedKeys(keycode))
887                                         Key_Event(keycode, 0, (event.key.state == SDL_PRESSED));
888                                 break;
889                         case SDL_MOUSEBUTTONDOWN:
890                         case SDL_MOUSEBUTTONUP:
891                                 if (!vid_touchscreen.integer)
892                                 if (event.button.button <= 18)
893                                         Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
894                                 break;
895                         case SDL_JOYBUTTONDOWN:
896                         case SDL_JOYBUTTONUP:
897                         case SDL_JOYAXISMOTION:
898                         case SDL_JOYBALLMOTION:
899                         case SDL_JOYHATMOTION:
900                                 break;
901                         case SDL_VIDEOEXPOSE:
902                                 break;
903                         case SDL_WINDOWEVENT:
904                                 //if (event.window.windowID == window) // how to compare?
905                                 {
906                                         switch(event.window.event)
907                                         {
908                                         case SDL_WINDOWEVENT_SHOWN:
909                                                 vid_hidden = false;
910                                                 break;
911                                         case  SDL_WINDOWEVENT_HIDDEN:
912                                                 vid_hidden = true;
913                                                 break;
914                                         case SDL_WINDOWEVENT_EXPOSED:
915                                                 break;
916                                         case SDL_WINDOWEVENT_MOVED:
917                                                 break;
918                                         case SDL_WINDOWEVENT_RESIZED:
919                                                 if(vid_resizable.integer < 2)
920                                                 {
921                                                         vid.width = event.window.data1;
922                                                         vid.height = event.window.data2;
923                                                         if (vid_softsurface)
924                                                         {
925                                                                 SDL_FreeSurface(vid_softsurface);
926                                                                 vid_softsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, vid.width, vid.height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
927                                                                 vid.softpixels = (unsigned int *)vid_softsurface->pixels;
928                                                                 SDL_SetAlpha(vid_softsurface, 0, 255);
929                                                                 if (vid.softdepthpixels)
930                                                                         free(vid.softdepthpixels);
931                                                                 vid.softdepthpixels = (unsigned int*)calloc(1, vid.width * vid.height * 4);
932                                                         }
933 #ifdef SDL_R_RESTART
934                                                         // better not call R_Modules_Restart from here directly, as this may wreak havoc...
935                                                         // so, let's better queue it for next frame
936                                                         if(!sdl_needs_restart)
937                                                         {
938                                                                 Cbuf_AddText("\nr_restart\n");
939                                                                 sdl_needs_restart = true;
940                                                         }
941 #endif
942                                                 }
943                                                 break;
944                                         case SDL_WINDOWEVENT_MINIMIZED:
945                                                 break;
946                                         case SDL_WINDOWEVENT_MAXIMIZED:
947                                                 break;
948                                         case SDL_WINDOWEVENT_RESTORED:
949                                                 break;
950                                         case SDL_WINDOWEVENT_ENTER:
951                                                 break;
952                                         case SDL_WINDOWEVENT_LEAVE:
953                                                 break;
954                                         case SDL_WINDOWEVENT_FOCUS_GAINED:
955                                                 vid_hasfocus = true;
956                                                 break;
957                                         case SDL_WINDOWEVENT_FOCUS_LOST:
958                                                 vid_hasfocus = false;
959                                                 break;
960                                         case SDL_WINDOWEVENT_CLOSE:
961                                                 Sys_Quit(0);
962                                                 break;
963                                         }
964                                 }
965                                 break;
966                         case SDL_TEXTEDITING:
967                                 // FIXME!  this is where composition gets supported
968                                 break;
969                         case SDL_TEXTINPUT:
970                                 // we have some characters to parse
971                                 missingunicodehack = false;
972                                 {
973                                         unicode = 0;
974                                         for (i = 0;event.text.text[i];)
975                                         {
976                                                 unicode = event.text.text[i++];
977                                                 if (unicode & 0x80)
978                                                 {
979                                                         // UTF-8 character
980                                                         // strip high bits (we could count these to validate character length but we don't)
981                                                         for (j = 0x80;unicode & j;j >>= 1)
982                                                                 unicode ^= j;
983                                                         for (;(event.text.text[i] & 0xC0) == 0x80;i++)
984                                                                 unicode = (unicode << 6) | (event.text.text[i] & 0x3F);
985                                                         // low characters are invalid and could be bad, so replace them
986                                                         if (unicode < 0x80)
987                                                                 unicode = '?'; // we could use 0xFFFD instead, the unicode substitute character
988                                                 }
989                                                 //Con_DPrintf("SDL_TEXTINPUT: K_TEXT %i \n", unicode);
990                                                 Key_Event(K_TEXT, unicode, true);
991                                                 Key_Event(K_TEXT, unicode, false);
992                                         }
993                                 }
994                                 break;
995                         case SDL_MOUSEMOTION:
996                                 break;
997                         case SDL_FINGERDOWN:
998                                 Con_DPrintf("SDL_FINGERDOWN for finger %i\n", (int)event.tfinger.fingerId);
999                                 for (i = 0;i < MAXFINGERS-1;i++)
1000                                 {
1001                                         if (!multitouch[i][0])
1002                                         {
1003                                                 multitouch[i][0] = event.tfinger.fingerId;
1004                                                 multitouch[i][1] = event.tfinger.x;
1005                                                 multitouch[i][2] = event.tfinger.y;
1006                                                 // TODO: use event.tfinger.pressure?
1007                                                 break;
1008                                         }
1009                                 }
1010                                 if (i == MAXFINGERS-1)
1011                                         Con_DPrintf("Too many fingers at once!\n");
1012                                 break;
1013                         case SDL_FINGERUP:
1014                                 Con_DPrintf("SDL_FINGERUP for finger %i\n", (int)event.tfinger.fingerId);
1015                                 for (i = 0;i < MAXFINGERS-1;i++)
1016                                 {
1017                                         if (multitouch[i][0] == event.tfinger.fingerId)
1018                                         {
1019                                                 multitouch[i][0] = 0;
1020                                                 break;
1021                                         }
1022                                 }
1023                                 if (i == MAXFINGERS-1)
1024                                         Con_DPrintf("No SDL_FINGERDOWN event matches this SDL_FINGERMOTION event\n");
1025                                 break;
1026                         case SDL_FINGERMOTION:
1027                                 Con_DPrintf("SDL_FINGERMOTION for finger %i\n", (int)event.tfinger.fingerId);
1028                                 for (i = 0;i < MAXFINGERS-1;i++)
1029                                 {
1030                                         if (multitouch[i][0] == event.tfinger.fingerId)
1031                                         {
1032                                                 multitouch[i][1] = event.tfinger.x;
1033                                                 multitouch[i][2] = event.tfinger.y;
1034                                                 break;
1035                                         }
1036                                 }
1037                                 if (i == MAXFINGERS-1)
1038                                         Con_DPrintf("No SDL_FINGERDOWN event matches this SDL_FINGERMOTION event\n");
1039                                 break;
1040                         case SDL_TOUCHBUTTONDOWN:
1041                                 // not sure what to do with this...
1042                                 break;
1043                         case SDL_TOUCHBUTTONUP:
1044                                 // not sure what to do with this...
1045                                 break;
1046                         default:
1047                                 Con_DPrintf("Received unrecognized SDL_Event type 0x%x\n", event.type);
1048                                 break;
1049                 }
1050
1051         // enable/disable sound on focus gain/loss
1052         if ((!vid_hidden && vid_activewindow) || !snd_mutewhenidle.integer)
1053         {
1054                 if (!sound_active)
1055                 {
1056                         S_UnblockSound ();
1057                         sound_active = true;
1058                 }
1059         }
1060         else
1061         {
1062                 if (sound_active)
1063                 {
1064                         S_BlockSound ();
1065                         sound_active = false;
1066                 }
1067         }
1068 }
1069 #endif
1070
1071 /////////////////
1072 // Video system
1073 ////
1074
1075 #ifdef USE_GLES2
1076 #ifdef __IPHONEOS__
1077 #include <OpenGLES/ES2/gl.h>
1078 #else
1079 #include <SDL_opengles.h>
1080 #endif
1081
1082 GLboolean wrapglIsBuffer(GLuint buffer) {return glIsBuffer(buffer);}
1083 GLboolean wrapglIsEnabled(GLenum cap) {return glIsEnabled(cap);}
1084 GLboolean wrapglIsFramebuffer(GLuint framebuffer) {return glIsFramebuffer(framebuffer);}
1085 //GLboolean wrapglIsQuery(GLuint qid) {return glIsQuery(qid);}
1086 GLboolean wrapglIsRenderbuffer(GLuint renderbuffer) {return glIsRenderbuffer(renderbuffer);}
1087 //GLboolean wrapglUnmapBuffer(GLenum target) {return glUnmapBuffer(target);}
1088 GLenum wrapglCheckFramebufferStatus(GLenum target) {return glCheckFramebufferStatus(target);}
1089 GLenum wrapglGetError(void) {return glGetError();}
1090 GLuint wrapglCreateProgram(void) {return glCreateProgram();}
1091 GLuint wrapglCreateShader(GLenum shaderType) {return glCreateShader(shaderType);}
1092 //GLuint wrapglGetHandle(GLenum pname) {return glGetHandle(pname);}
1093 GLint wrapglGetAttribLocation(GLuint programObj, const GLchar *name) {return glGetAttribLocation(programObj, name);}
1094 GLint wrapglGetUniformLocation(GLuint programObj, const GLchar *name) {return glGetUniformLocation(programObj, name);}
1095 //GLvoid* wrapglMapBuffer(GLenum target, GLenum access) {return glMapBuffer(target, access);}
1096 const GLubyte* wrapglGetString(GLenum name) {return glGetString(name);}
1097 void wrapglActiveStencilFace(GLenum e) {Con_Printf("glActiveStencilFace(e)\n");}
1098 void wrapglActiveTexture(GLenum e) {glActiveTexture(e);}
1099 void wrapglAlphaFunc(GLenum func, GLclampf ref) {Con_Printf("glAlphaFunc(func, ref)\n");}
1100 void wrapglArrayElement(GLint i) {Con_Printf("glArrayElement(i)\n");}
1101 void wrapglAttachShader(GLuint containerObj, GLuint obj) {glAttachShader(containerObj, obj);}
1102 //void wrapglBegin(GLenum mode) {Con_Printf("glBegin(mode)\n");}
1103 //void wrapglBeginQuery(GLenum target, GLuint qid) {glBeginQuery(target, qid);}
1104 void wrapglBindAttribLocation(GLuint programObj, GLuint index, const GLchar *name) {glBindAttribLocation(programObj, index, name);}
1105 void wrapglBindFragDataLocation(GLuint programObj, GLuint index, const GLchar *name) {glBindFragDataLocation(programObj, index, name);}
1106 void wrapglBindBuffer(GLenum target, GLuint buffer) {glBindBuffer(target, buffer);}
1107 void wrapglBindFramebuffer(GLenum target, GLuint framebuffer) {glBindFramebuffer(target, framebuffer);}
1108 void wrapglBindRenderbuffer(GLenum target, GLuint renderbuffer) {glBindRenderbuffer(target, renderbuffer);}
1109 void wrapglBindTexture(GLenum target, GLuint texture) {glBindTexture(target, texture);}
1110 void wrapglBlendEquation(GLenum e) {glBlendEquation(e);}
1111 void wrapglBlendFunc(GLenum sfactor, GLenum dfactor) {glBlendFunc(sfactor, dfactor);}
1112 void wrapglBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) {glBufferData(target, size, data, usage);}
1113 void wrapglBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) {glBufferSubData(target, offset, size, data);}
1114 void wrapglClear(GLbitfield mask) {glClear(mask);}
1115 void wrapglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {glClearColor(red, green, blue, alpha);}
1116 void wrapglClearDepth(GLclampd depth) {glClearDepthf((float)depth);}
1117 void wrapglClearStencil(GLint s) {glClearStencil(s);}
1118 void wrapglClientActiveTexture(GLenum target) {Con_Printf("glClientActiveTexture(target)\n");}
1119 void wrapglColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {Con_Printf("glColor4f(red, green, blue, alpha)\n");}
1120 void wrapglColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {Con_Printf("glColor4ub(red, green, blue, alpha)\n");}
1121 void wrapglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {glColorMask(red, green, blue, alpha);}
1122 void wrapglColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {Con_Printf("glColorPointer(size, type, stride, ptr)\n");}
1123 void wrapglCompileShader(GLuint shaderObj) {glCompileShader(shaderObj);}
1124 void wrapglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border,  GLsizei imageSize, const void *data) {glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);}
1125 void wrapglCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) {Con_Printf("glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data)\n");}
1126 void wrapglCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) {glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);}
1127 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) {Con_Printf("glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data)\n");}
1128 void wrapglCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);}
1129 void wrapglCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);}
1130 void wrapglCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {Con_Printf("glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height)\n");}
1131 void wrapglCullFace(GLenum mode) {glCullFace(mode);}
1132 void wrapglDeleteBuffers(GLsizei n, const GLuint *buffers) {glDeleteBuffers(n, buffers);}
1133 void wrapglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) {glDeleteFramebuffers(n, framebuffers);}
1134 void wrapglDeleteShader(GLuint obj) {glDeleteShader(obj);}
1135 void wrapglDeleteProgram(GLuint obj) {glDeleteProgram(obj);}
1136 //void wrapglDeleteQueries(GLsizei n, const GLuint *ids) {glDeleteQueries(n, ids);}
1137 void wrapglDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) {glDeleteRenderbuffers(n, renderbuffers);}
1138 void wrapglDeleteTextures(GLsizei n, const GLuint *textures) {glDeleteTextures(n, textures);}
1139 void wrapglDepthFunc(GLenum func) {glDepthFunc(func);}
1140 void wrapglDepthMask(GLboolean flag) {glDepthMask(flag);}
1141 void wrapglDepthRange(GLclampd near_val, GLclampd far_val) {glDepthRangef((float)near_val, (float)far_val);}
1142 void wrapglDetachShader(GLuint containerObj, GLuint attachedObj) {glDetachShader(containerObj, attachedObj);}
1143 void wrapglDisable(GLenum cap) {glDisable(cap);}
1144 void wrapglDisableClientState(GLenum cap) {Con_Printf("glDisableClientState(cap)\n");}
1145 void wrapglDisableVertexAttribArray(GLuint index) {glDisableVertexAttribArray(index);}
1146 void wrapglDrawArrays(GLenum mode, GLint first, GLsizei count) {glDrawArrays(mode, first, count);}
1147 void wrapglDrawBuffer(GLenum mode) {Con_Printf("glDrawBuffer(mode)\n");}
1148 void wrapglDrawBuffers(GLsizei n, const GLenum *bufs) {Con_Printf("glDrawBuffers(n, bufs)\n");}
1149 void wrapglDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {glDrawElements(mode, count, type, indices);}
1150 //void wrapglDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) {glDrawRangeElements(mode, start, end, count, type, indices);}
1151 //void wrapglDrawRangeElementsEXT(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) {glDrawRangeElements(mode, start, end, count, type, indices);}
1152 void wrapglEnable(GLenum cap) {glEnable(cap);}
1153 void wrapglEnableClientState(GLenum cap) {Con_Printf("glEnableClientState(cap)\n");}
1154 void wrapglEnableVertexAttribArray(GLuint index) {glEnableVertexAttribArray(index);}
1155 //void wrapglEnd(void) {Con_Printf("glEnd()\n");}
1156 //void wrapglEndQuery(GLenum target) {glEndQuery(target);}
1157 void wrapglFinish(void) {glFinish();}
1158 void wrapglFlush(void) {glFlush();}
1159 void wrapglFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);}
1160 void wrapglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {glFramebufferTexture2D(target, attachment, textarget, texture, level);}
1161 void wrapglFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {Con_Printf("glFramebufferTexture3D()\n");}
1162 void wrapglGenBuffers(GLsizei n, GLuint *buffers) {glGenBuffers(n, buffers);}
1163 void wrapglGenFramebuffers(GLsizei n, GLuint *framebuffers) {glGenFramebuffers(n, framebuffers);}
1164 //void wrapglGenQueries(GLsizei n, GLuint *ids) {glGenQueries(n, ids);}
1165 void wrapglGenRenderbuffers(GLsizei n, GLuint *renderbuffers) {glGenRenderbuffers(n, renderbuffers);}
1166 void wrapglGenTextures(GLsizei n, GLuint *textures) {glGenTextures(n, textures);}
1167 void wrapglGenerateMipmap(GLenum target) {glGenerateMipmap(target);}
1168 void wrapglGetActiveAttrib(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {glGetActiveAttrib(programObj, index, maxLength, length, size, type, name);}
1169 void wrapglGetActiveUniform(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {glGetActiveUniform(programObj, index, maxLength, length, size, type, name);}
1170 void wrapglGetAttachedShaders(GLuint containerObj, GLsizei maxCount, GLsizei *count, GLuint *obj) {glGetAttachedShaders(containerObj, maxCount, count, obj);}
1171 void wrapglGetBooleanv(GLenum pname, GLboolean *params) {glGetBooleanv(pname, params);}
1172 void wrapglGetCompressedTexImage(GLenum target, GLint lod, void *img) {Con_Printf("glGetCompressedTexImage(target, lod, img)\n");}
1173 void wrapglGetDoublev(GLenum pname, GLdouble *params) {Con_Printf("glGetDoublev(pname, params)\n");}
1174 void wrapglGetFloatv(GLenum pname, GLfloat *params) {glGetFloatv(pname, params);}
1175 void wrapglGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params) {glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);}
1176 void wrapglGetShaderInfoLog(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *infoLog) {glGetShaderInfoLog(obj, maxLength, length, infoLog);}
1177 void wrapglGetProgramInfoLog(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *infoLog) {glGetProgramInfoLog(obj, maxLength, length, infoLog);}
1178 void wrapglGetIntegerv(GLenum pname, GLint *params) {glGetIntegerv(pname, params);}
1179 void wrapglGetShaderiv(GLuint obj, GLenum pname, GLint *params) {glGetShaderiv(obj, pname, params);}
1180 void wrapglGetProgramiv(GLuint obj, GLenum pname, GLint *params) {glGetProgramiv(obj, pname, params);}
1181 //void wrapglGetQueryObjectiv(GLuint qid, GLenum pname, GLint *params) {glGetQueryObjectiv(qid, pname, params);}
1182 //void wrapglGetQueryObjectuiv(GLuint qid, GLenum pname, GLuint *params) {glGetQueryObjectuiv(qid, pname, params);}
1183 //void wrapglGetQueryiv(GLenum target, GLenum pname, GLint *params) {glGetQueryiv(target, pname, params);}
1184 void wrapglGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) {glGetRenderbufferParameteriv(target, pname, params);}
1185 void wrapglGetShaderSource(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *source) {glGetShaderSource(obj, maxLength, length, source);}
1186 void wrapglGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels) {Con_Printf("glGetTexImage(target, level, format, type, pixels)\n");}
1187 void wrapglGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params) {Con_Printf("glGetTexLevelParameterfv(target, level, pname, params)\n");}
1188 void wrapglGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) {Con_Printf("glGetTexLevelParameteriv(target, level, pname, params)\n");}
1189 void wrapglGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) {glGetTexParameterfv(target, pname, params);}
1190 void wrapglGetTexParameteriv(GLenum target, GLenum pname, GLint *params) {glGetTexParameteriv(target, pname, params);}
1191 void wrapglGetUniformfv(GLuint programObj, GLint location, GLfloat *params) {glGetUniformfv(programObj, location, params);}
1192 void wrapglGetUniformiv(GLuint programObj, GLint location, GLint *params) {glGetUniformiv(programObj, location, params);}
1193 void wrapglHint(GLenum target, GLenum mode) {glHint(target, mode);}
1194 void wrapglLineWidth(GLfloat width) {glLineWidth(width);}
1195 void wrapglLinkProgram(GLuint programObj) {glLinkProgram(programObj);}
1196 void wrapglLoadIdentity(void) {Con_Printf("glLoadIdentity()\n");}
1197 void wrapglLoadMatrixf(const GLfloat *m) {Con_Printf("glLoadMatrixf(m)\n");}
1198 void wrapglMatrixMode(GLenum mode) {Con_Printf("glMatrixMode(mode)\n");}
1199 void wrapglMultiTexCoord1f(GLenum target, GLfloat s) {Con_Printf("glMultiTexCoord1f(target, s)\n");}
1200 void wrapglMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t) {Con_Printf("glMultiTexCoord2f(target, s, t)\n");}
1201 void wrapglMultiTexCoord3f(GLenum target, GLfloat s, GLfloat t, GLfloat r) {Con_Printf("glMultiTexCoord3f(target, s, t, r)\n");}
1202 void wrapglMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {Con_Printf("glMultiTexCoord4f(target, s, t, r, q)\n");}
1203 void wrapglNormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr) {Con_Printf("glNormalPointer(type, stride, ptr)\n");}
1204 void wrapglPixelStorei(GLenum pname, GLint param) {glPixelStorei(pname, param);}
1205 void wrapglPointSize(GLfloat size) {Con_Printf("glPointSize(size)\n");}
1206 //void wrapglPolygonMode(GLenum face, GLenum mode) {Con_Printf("glPolygonMode(face, mode)\n");}
1207 void wrapglPolygonOffset(GLfloat factor, GLfloat units) {glPolygonOffset(factor, units);}
1208 void wrapglPolygonStipple(const GLubyte *mask) {Con_Printf("glPolygonStipple(mask)\n");}
1209 void wrapglReadBuffer(GLenum mode) {Con_Printf("glReadBuffer(mode)\n");}
1210 void wrapglReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {glReadPixels(x, y, width, height, format, type, pixels);}
1211 void wrapglRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {glRenderbufferStorage(target, internalformat, width, height);}
1212 void wrapglScissor(GLint x, GLint y, GLsizei width, GLsizei height) {glScissor(x, y, width, height);}
1213 void wrapglShaderSource(GLuint shaderObj, GLsizei count, const GLchar **string, const GLint *length) {glShaderSource(shaderObj, count, string, length);}
1214 void wrapglStencilFunc(GLenum func, GLint ref, GLuint mask) {glStencilFunc(func, ref, mask);}
1215 void wrapglStencilFuncSeparate(GLenum func1, GLenum func2, GLint ref, GLuint mask) {Con_Printf("glStencilFuncSeparate(func1, func2, ref, mask)\n");}
1216 void wrapglStencilMask(GLuint mask) {glStencilMask(mask);}
1217 void wrapglStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {glStencilOp(fail, zfail, zpass);}
1218 void wrapglStencilOpSeparate(GLenum e1, GLenum e2, GLenum e3, GLenum e4) {Con_Printf("glStencilOpSeparate(e1, e2, e3, e4)\n");}
1219 void wrapglTexCoord1f(GLfloat s) {Con_Printf("glTexCoord1f(s)\n");}
1220 void wrapglTexCoord2f(GLfloat s, GLfloat t) {Con_Printf("glTexCoord2f(s, t)\n");}
1221 void wrapglTexCoord3f(GLfloat s, GLfloat t, GLfloat r) {Con_Printf("glTexCoord3f(s, t, r)\n");}
1222 void wrapglTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) {Con_Printf("glTexCoord4f(s, t, r, q)\n");}
1223 void wrapglTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {Con_Printf("glTexCoordPointer(size, type, stride, ptr)\n");}
1224 void wrapglTexEnvf(GLenum target, GLenum pname, GLfloat param) {Con_Printf("glTexEnvf(target, pname, param)\n");}
1225 void wrapglTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) {Con_Printf("glTexEnvfv(target, pname, params)\n");}
1226 void wrapglTexEnvi(GLenum target, GLenum pname, GLint param) {Con_Printf("glTexEnvi(target, pname, param)\n");}
1227 void wrapglTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels);}
1228 void wrapglTexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {Con_Printf("glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels)\n");}
1229 void wrapglTexParameterf(GLenum target, GLenum pname, GLfloat param) {glTexParameterf(target, pname, param);}
1230 void wrapglTexParameterfv(GLenum target, GLenum pname, GLfloat *params) {glTexParameterfv(target, pname, params);}
1231 void wrapglTexParameteri(GLenum target, GLenum pname, GLint param) {glTexParameteri(target, pname, param);}
1232 void wrapglTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);}
1233 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) {Con_Printf("glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels)\n");}
1234 void wrapglUniform1f(GLint location, GLfloat v0) {glUniform1f(location, v0);}
1235 void wrapglUniform1fv(GLint location, GLsizei count, const GLfloat *value) {glUniform1fv(location, count, value);}
1236 void wrapglUniform1i(GLint location, GLint v0) {glUniform1i(location, v0);}
1237 void wrapglUniform1iv(GLint location, GLsizei count, const GLint *value) {glUniform1iv(location, count, value);}
1238 void wrapglUniform2f(GLint location, GLfloat v0, GLfloat v1) {glUniform2f(location, v0, v1);}
1239 void wrapglUniform2fv(GLint location, GLsizei count, const GLfloat *value) {glUniform2fv(location, count, value);}
1240 void wrapglUniform2i(GLint location, GLint v0, GLint v1) {glUniform2i(location, v0, v1);}
1241 void wrapglUniform2iv(GLint location, GLsizei count, const GLint *value) {glUniform2iv(location, count, value);}
1242 void wrapglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {glUniform3f(location, v0, v1, v2);}
1243 void wrapglUniform3fv(GLint location, GLsizei count, const GLfloat *value) {glUniform3fv(location, count, value);}
1244 void wrapglUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {glUniform3i(location, v0, v1, v2);}
1245 void wrapglUniform3iv(GLint location, GLsizei count, const GLint *value) {glUniform3iv(location, count, value);}
1246 void wrapglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {glUniform4f(location, v0, v1, v2, v3);}
1247 void wrapglUniform4fv(GLint location, GLsizei count, const GLfloat *value) {glUniform4fv(location, count, value);}
1248 void wrapglUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {glUniform4i(location, v0, v1, v2, v3);}
1249 void wrapglUniform4iv(GLint location, GLsizei count, const GLint *value) {glUniform4iv(location, count, value);}
1250 void wrapglUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {glUniformMatrix2fv(location, count, transpose, value);}
1251 void wrapglUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {glUniformMatrix3fv(location, count, transpose, value);}
1252 void wrapglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {glUniformMatrix4fv(location, count, transpose, value);}
1253 void wrapglUseProgram(GLuint programObj) {glUseProgram(programObj);}
1254 void wrapglValidateProgram(GLuint programObj) {glValidateProgram(programObj);}
1255 void wrapglVertex2f(GLfloat x, GLfloat y) {Con_Printf("glVertex2f(x, y)\n");}
1256 void wrapglVertex3f(GLfloat x, GLfloat y, GLfloat z) {Con_Printf("glVertex3f(x, y, z)\n");}
1257 void wrapglVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {Con_Printf("glVertex4f(x, y, z, w)\n");}
1258 void wrapglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) {glVertexAttribPointer(index, size, type, normalized, stride, pointer);}
1259 void wrapglVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {Con_Printf("glVertexPointer(size, type, stride, ptr)\n");}
1260 void wrapglViewport(GLint x, GLint y, GLsizei width, GLsizei height) {glViewport(x, y, width, height);}
1261 void wrapglVertexAttrib1f(GLuint index, GLfloat v0) {glVertexAttrib1f(index, v0);}
1262 //void wrapglVertexAttrib1s(GLuint index, GLshort v0) {glVertexAttrib1s(index, v0);}
1263 //void wrapglVertexAttrib1d(GLuint index, GLdouble v0) {glVertexAttrib1d(index, v0);}
1264 void wrapglVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {glVertexAttrib2f(index, v0, v1);}
1265 //void wrapglVertexAttrib2s(GLuint index, GLshort v0, GLshort v1) {glVertexAttrib2s(index, v0, v1);}
1266 //void wrapglVertexAttrib2d(GLuint index, GLdouble v0, GLdouble v1) {glVertexAttrib2d(index, v0, v1);}
1267 void wrapglVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {glVertexAttrib3f(index, v0, v1, v2);}
1268 //void wrapglVertexAttrib3s(GLuint index, GLshort v0, GLshort v1, GLshort v2) {glVertexAttrib3s(index, v0, v1, v2);}
1269 //void wrapglVertexAttrib3d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2) {glVertexAttrib3d(index, v0, v1, v2);}
1270 void wrapglVertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {glVertexAttrib4f(index, v0, v1, v2, v3);}
1271 //void wrapglVertexAttrib4s(GLuint index, GLshort v0, GLshort v1, GLshort v2, GLshort v3) {glVertexAttrib4s(index, v0, v1, v2, v3);}
1272 //void wrapglVertexAttrib4d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) {glVertexAttrib4d(index, v0, v1, v2, v3);}
1273 //void wrapglVertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) {glVertexAttrib4Nub(index, x, y, z, w);}
1274 void wrapglVertexAttrib1fv(GLuint index, const GLfloat *v) {glVertexAttrib1fv(index, v);}
1275 //void wrapglVertexAttrib1sv(GLuint index, const GLshort *v) {glVertexAttrib1sv(index, v);}
1276 //void wrapglVertexAttrib1dv(GLuint index, const GLdouble *v) {glVertexAttrib1dv(index, v);}
1277 void wrapglVertexAttrib2fv(GLuint index, const GLfloat *v) {glVertexAttrib2fv(index, v);}
1278 //void wrapglVertexAttrib2sv(GLuint index, const GLshort *v) {glVertexAttrib2sv(index, v);}
1279 //void wrapglVertexAttrib2dv(GLuint index, const GLdouble *v) {glVertexAttrib2dv(index, v);}
1280 void wrapglVertexAttrib3fv(GLuint index, const GLfloat *v) {glVertexAttrib3fv(index, v);}
1281 //void wrapglVertexAttrib3sv(GLuint index, const GLshort *v) {glVertexAttrib3sv(index, v);}
1282 //void wrapglVertexAttrib3dv(GLuint index, const GLdouble *v) {glVertexAttrib3dv(index, v);}
1283 void wrapglVertexAttrib4fv(GLuint index, const GLfloat *v) {glVertexAttrib4fv(index, v);}
1284 //void wrapglVertexAttrib4sv(GLuint index, const GLshort *v) {glVertexAttrib4sv(index, v);}
1285 //void wrapglVertexAttrib4dv(GLuint index, const GLdouble *v) {glVertexAttrib4dv(index, v);}
1286 //void wrapglVertexAttrib4iv(GLuint index, const GLint *v) {glVertexAttrib4iv(index, v);}
1287 //void wrapglVertexAttrib4bv(GLuint index, const GLbyte *v) {glVertexAttrib4bv(index, v);}
1288 //void wrapglVertexAttrib4ubv(GLuint index, const GLubyte *v) {glVertexAttrib4ubv(index, v);}
1289 //void wrapglVertexAttrib4usv(GLuint index, const GLushort *v) {glVertexAttrib4usv(index, GLushort v);}
1290 //void wrapglVertexAttrib4uiv(GLuint index, const GLuint *v) {glVertexAttrib4uiv(index, v);}
1291 //void wrapglVertexAttrib4Nbv(GLuint index, const GLbyte *v) {glVertexAttrib4Nbv(index, v);}
1292 //void wrapglVertexAttrib4Nsv(GLuint index, const GLshort *v) {glVertexAttrib4Nsv(index, v);}
1293 //void wrapglVertexAttrib4Niv(GLuint index, const GLint *v) {glVertexAttrib4Niv(index, v);}
1294 //void wrapglVertexAttrib4Nubv(GLuint index, const GLubyte *v) {glVertexAttrib4Nubv(index, v);}
1295 //void wrapglVertexAttrib4Nusv(GLuint index, const GLushort *v) {glVertexAttrib4Nusv(index, GLushort v);}
1296 //void wrapglVertexAttrib4Nuiv(GLuint index, const GLuint *v) {glVertexAttrib4Nuiv(index, v);}
1297 //void wrapglGetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params) {glGetVertexAttribdv(index, pname, params);}
1298 void wrapglGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) {glGetVertexAttribfv(index, pname, params);}
1299 void wrapglGetVertexAttribiv(GLuint index, GLenum pname, GLint *params) {glGetVertexAttribiv(index, pname, params);}
1300 void wrapglGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) {glGetVertexAttribPointerv(index, pname, pointer);}
1301
1302 void GLES_Init(void)
1303 {
1304         qglIsBufferARB = wrapglIsBuffer;
1305         qglIsEnabled = wrapglIsEnabled;
1306         qglIsFramebufferEXT = wrapglIsFramebuffer;
1307 //      qglIsQueryARB = wrapglIsQuery;
1308         qglIsRenderbufferEXT = wrapglIsRenderbuffer;
1309 //      qglUnmapBufferARB = wrapglUnmapBuffer;
1310         qglCheckFramebufferStatusEXT = wrapglCheckFramebufferStatus;
1311         qglGetError = wrapglGetError;
1312         qglCreateProgram = wrapglCreateProgram;
1313         qglCreateShader = wrapglCreateShader;
1314 //      qglGetHandleARB = wrapglGetHandle;
1315         qglGetAttribLocation = wrapglGetAttribLocation;
1316         qglGetUniformLocation = wrapglGetUniformLocation;
1317 //      qglMapBufferARB = wrapglMapBuffer;
1318         qglGetString = wrapglGetString;
1319 //      qglActiveStencilFaceEXT = wrapglActiveStencilFace;
1320         qglActiveTexture = wrapglActiveTexture;
1321         qglAlphaFunc = wrapglAlphaFunc;
1322         qglArrayElement = wrapglArrayElement;
1323         qglAttachShader = wrapglAttachShader;
1324 //      qglBegin = wrapglBegin;
1325 //      qglBeginQueryARB = wrapglBeginQuery;
1326         qglBindAttribLocation = wrapglBindAttribLocation;
1327         qglBindFragDataLocation = wrapglBindFragDataLocation;
1328         qglBindBufferARB = wrapglBindBuffer;
1329         qglBindFramebufferEXT = wrapglBindFramebuffer;
1330         qglBindRenderbufferEXT = wrapglBindRenderbuffer;
1331         qglBindTexture = wrapglBindTexture;
1332         qglBlendEquationEXT = wrapglBlendEquation;
1333         qglBlendFunc = wrapglBlendFunc;
1334         qglBufferDataARB = wrapglBufferData;
1335         qglBufferSubDataARB = wrapglBufferSubData;
1336         qglClear = wrapglClear;
1337         qglClearColor = wrapglClearColor;
1338         qglClearDepth = wrapglClearDepth;
1339         qglClearStencil = wrapglClearStencil;
1340         qglClientActiveTexture = wrapglClientActiveTexture;
1341         qglColor4f = wrapglColor4f;
1342         qglColor4ub = wrapglColor4ub;
1343         qglColorMask = wrapglColorMask;
1344         qglColorPointer = wrapglColorPointer;
1345         qglCompileShader = wrapglCompileShader;
1346         qglCompressedTexImage2DARB = wrapglCompressedTexImage2D;
1347         qglCompressedTexImage3DARB = wrapglCompressedTexImage3D;
1348         qglCompressedTexSubImage2DARB = wrapglCompressedTexSubImage2D;
1349         qglCompressedTexSubImage3DARB = wrapglCompressedTexSubImage3D;
1350         qglCopyTexImage2D = wrapglCopyTexImage2D;
1351         qglCopyTexSubImage2D = wrapglCopyTexSubImage2D;
1352         qglCopyTexSubImage3D = wrapglCopyTexSubImage3D;
1353         qglCullFace = wrapglCullFace;
1354         qglDeleteBuffersARB = wrapglDeleteBuffers;
1355         qglDeleteFramebuffersEXT = wrapglDeleteFramebuffers;
1356         qglDeleteProgram = wrapglDeleteProgram;
1357         qglDeleteShader = wrapglDeleteShader;
1358 //      qglDeleteQueriesARB = wrapglDeleteQueries;
1359         qglDeleteRenderbuffersEXT = wrapglDeleteRenderbuffers;
1360         qglDeleteTextures = wrapglDeleteTextures;
1361         qglDepthFunc = wrapglDepthFunc;
1362         qglDepthMask = wrapglDepthMask;
1363         qglDepthRange = wrapglDepthRange;
1364         qglDetachShader = wrapglDetachShader;
1365         qglDisable = wrapglDisable;
1366         qglDisableClientState = wrapglDisableClientState;
1367         qglDisableVertexAttribArray = wrapglDisableVertexAttribArray;
1368         qglDrawArrays = wrapglDrawArrays;
1369 //      qglDrawBuffer = wrapglDrawBuffer;
1370 //      qglDrawBuffersARB = wrapglDrawBuffers;
1371         qglDrawElements = wrapglDrawElements;
1372 //      qglDrawRangeElements = wrapglDrawRangeElements;
1373         qglEnable = wrapglEnable;
1374         qglEnableClientState = wrapglEnableClientState;
1375         qglEnableVertexAttribArray = wrapglEnableVertexAttribArray;
1376 //      qglEnd = wrapglEnd;
1377 //      qglEndQueryARB = wrapglEndQuery;
1378         qglFinish = wrapglFinish;
1379         qglFlush = wrapglFlush;
1380         qglFramebufferRenderbufferEXT = wrapglFramebufferRenderbuffer;
1381         qglFramebufferTexture2DEXT = wrapglFramebufferTexture2D;
1382         qglFramebufferTexture3DEXT = wrapglFramebufferTexture3D;
1383         qglGenBuffersARB = wrapglGenBuffers;
1384         qglGenFramebuffersEXT = wrapglGenFramebuffers;
1385 //      qglGenQueriesARB = wrapglGenQueries;
1386         qglGenRenderbuffersEXT = wrapglGenRenderbuffers;
1387         qglGenTextures = wrapglGenTextures;
1388         qglGenerateMipmapEXT = wrapglGenerateMipmap;
1389         qglGetActiveAttrib = wrapglGetActiveAttrib;
1390         qglGetActiveUniform = wrapglGetActiveUniform;
1391         qglGetAttachedShaders = wrapglGetAttachedShaders;
1392         qglGetBooleanv = wrapglGetBooleanv;
1393 //      qglGetCompressedTexImageARB = wrapglGetCompressedTexImage;
1394         qglGetDoublev = wrapglGetDoublev;
1395         qglGetFloatv = wrapglGetFloatv;
1396         qglGetFramebufferAttachmentParameterivEXT = wrapglGetFramebufferAttachmentParameteriv;
1397         qglGetProgramInfoLog = wrapglGetProgramInfoLog;
1398         qglGetShaderInfoLog = wrapglGetShaderInfoLog;
1399         qglGetIntegerv = wrapglGetIntegerv;
1400         qglGetShaderiv = wrapglGetShaderiv;
1401         qglGetProgramiv = wrapglGetProgramiv;
1402 //      qglGetQueryObjectivARB = wrapglGetQueryObjectiv;
1403 //      qglGetQueryObjectuivARB = wrapglGetQueryObjectuiv;
1404 //      qglGetQueryivARB = wrapglGetQueryiv;
1405         qglGetRenderbufferParameterivEXT = wrapglGetRenderbufferParameteriv;
1406         qglGetShaderSource = wrapglGetShaderSource;
1407         qglGetTexImage = wrapglGetTexImage;
1408         qglGetTexLevelParameterfv = wrapglGetTexLevelParameterfv;
1409         qglGetTexLevelParameteriv = wrapglGetTexLevelParameteriv;
1410         qglGetTexParameterfv = wrapglGetTexParameterfv;
1411         qglGetTexParameteriv = wrapglGetTexParameteriv;
1412         qglGetUniformfv = wrapglGetUniformfv;
1413         qglGetUniformiv = wrapglGetUniformiv;
1414         qglHint = wrapglHint;
1415         qglLineWidth = wrapglLineWidth;
1416         qglLinkProgram = wrapglLinkProgram;
1417         qglLoadIdentity = wrapglLoadIdentity;
1418         qglLoadMatrixf = wrapglLoadMatrixf;
1419         qglMatrixMode = wrapglMatrixMode;
1420         qglMultiTexCoord1f = wrapglMultiTexCoord1f;
1421         qglMultiTexCoord2f = wrapglMultiTexCoord2f;
1422         qglMultiTexCoord3f = wrapglMultiTexCoord3f;
1423         qglMultiTexCoord4f = wrapglMultiTexCoord4f;
1424         qglNormalPointer = wrapglNormalPointer;
1425         qglPixelStorei = wrapglPixelStorei;
1426         qglPointSize = wrapglPointSize;
1427 //      qglPolygonMode = wrapglPolygonMode;
1428         qglPolygonOffset = wrapglPolygonOffset;
1429 //      qglPolygonStipple = wrapglPolygonStipple;
1430         qglReadBuffer = wrapglReadBuffer;
1431         qglReadPixels = wrapglReadPixels;
1432         qglRenderbufferStorageEXT = wrapglRenderbufferStorage;
1433         qglScissor = wrapglScissor;
1434         qglShaderSource = wrapglShaderSource;
1435         qglStencilFunc = wrapglStencilFunc;
1436         qglStencilFuncSeparate = wrapglStencilFuncSeparate;
1437         qglStencilMask = wrapglStencilMask;
1438         qglStencilOp = wrapglStencilOp;
1439         qglStencilOpSeparate = wrapglStencilOpSeparate;
1440         qglTexCoord1f = wrapglTexCoord1f;
1441         qglTexCoord2f = wrapglTexCoord2f;
1442         qglTexCoord3f = wrapglTexCoord3f;
1443         qglTexCoord4f = wrapglTexCoord4f;
1444         qglTexCoordPointer = wrapglTexCoordPointer;
1445         qglTexEnvf = wrapglTexEnvf;
1446         qglTexEnvfv = wrapglTexEnvfv;
1447         qglTexEnvi = wrapglTexEnvi;
1448         qglTexImage2D = wrapglTexImage2D;
1449         qglTexImage3D = wrapglTexImage3D;
1450         qglTexParameterf = wrapglTexParameterf;
1451         qglTexParameterfv = wrapglTexParameterfv;
1452         qglTexParameteri = wrapglTexParameteri;
1453         qglTexSubImage2D = wrapglTexSubImage2D;
1454         qglTexSubImage3D = wrapglTexSubImage3D;
1455         qglUniform1f = wrapglUniform1f;
1456         qglUniform1fv = wrapglUniform1fv;
1457         qglUniform1i = wrapglUniform1i;
1458         qglUniform1iv = wrapglUniform1iv;
1459         qglUniform2f = wrapglUniform2f;
1460         qglUniform2fv = wrapglUniform2fv;
1461         qglUniform2i = wrapglUniform2i;
1462         qglUniform2iv = wrapglUniform2iv;
1463         qglUniform3f = wrapglUniform3f;
1464         qglUniform3fv = wrapglUniform3fv;
1465         qglUniform3i = wrapglUniform3i;
1466         qglUniform3iv = wrapglUniform3iv;
1467         qglUniform4f = wrapglUniform4f;
1468         qglUniform4fv = wrapglUniform4fv;
1469         qglUniform4i = wrapglUniform4i;
1470         qglUniform4iv = wrapglUniform4iv;
1471         qglUniformMatrix2fv = wrapglUniformMatrix2fv;
1472         qglUniformMatrix3fv = wrapglUniformMatrix3fv;
1473         qglUniformMatrix4fv = wrapglUniformMatrix4fv;
1474         qglUseProgram = wrapglUseProgram;
1475         qglValidateProgram = wrapglValidateProgram;
1476         qglVertex2f = wrapglVertex2f;
1477         qglVertex3f = wrapglVertex3f;
1478         qglVertex4f = wrapglVertex4f;
1479         qglVertexAttribPointer = wrapglVertexAttribPointer;
1480         qglVertexPointer = wrapglVertexPointer;
1481         qglViewport = wrapglViewport;
1482         qglVertexAttrib1f = wrapglVertexAttrib1f;
1483 //      qglVertexAttrib1s = wrapglVertexAttrib1s;
1484 //      qglVertexAttrib1d = wrapglVertexAttrib1d;
1485         qglVertexAttrib2f = wrapglVertexAttrib2f;
1486 //      qglVertexAttrib2s = wrapglVertexAttrib2s;
1487 //      qglVertexAttrib2d = wrapglVertexAttrib2d;
1488         qglVertexAttrib3f = wrapglVertexAttrib3f;
1489 //      qglVertexAttrib3s = wrapglVertexAttrib3s;
1490 //      qglVertexAttrib3d = wrapglVertexAttrib3d;
1491         qglVertexAttrib4f = wrapglVertexAttrib4f;
1492 //      qglVertexAttrib4s = wrapglVertexAttrib4s;
1493 //      qglVertexAttrib4d = wrapglVertexAttrib4d;
1494 //      qglVertexAttrib4Nub = wrapglVertexAttrib4Nub;
1495         qglVertexAttrib1fv = wrapglVertexAttrib1fv;
1496 //      qglVertexAttrib1sv = wrapglVertexAttrib1sv;
1497 //      qglVertexAttrib1dv = wrapglVertexAttrib1dv;
1498         qglVertexAttrib2fv = wrapglVertexAttrib2fv;
1499 //      qglVertexAttrib2sv = wrapglVertexAttrib2sv;
1500 //      qglVertexAttrib2dv = wrapglVertexAttrib2dv;
1501         qglVertexAttrib3fv = wrapglVertexAttrib3fv;
1502 //      qglVertexAttrib3sv = wrapglVertexAttrib3sv;
1503 //      qglVertexAttrib3dv = wrapglVertexAttrib3dv;
1504         qglVertexAttrib4fv = wrapglVertexAttrib4fv;
1505 //      qglVertexAttrib4sv = wrapglVertexAttrib4sv;
1506 //      qglVertexAttrib4dv = wrapglVertexAttrib4dv;
1507 //      qglVertexAttrib4iv = wrapglVertexAttrib4iv;
1508 //      qglVertexAttrib4bv = wrapglVertexAttrib4bv;
1509 //      qglVertexAttrib4ubv = wrapglVertexAttrib4ubv;
1510 //      qglVertexAttrib4usv = wrapglVertexAttrib4usv;
1511 //      qglVertexAttrib4uiv = wrapglVertexAttrib4uiv;
1512 //      qglVertexAttrib4Nbv = wrapglVertexAttrib4Nbv;
1513 //      qglVertexAttrib4Nsv = wrapglVertexAttrib4Nsv;
1514 //      qglVertexAttrib4Niv = wrapglVertexAttrib4Niv;
1515 //      qglVertexAttrib4Nubv = wrapglVertexAttrib4Nubv;
1516 //      qglVertexAttrib4Nusv = wrapglVertexAttrib4Nusv;
1517 //      qglVertexAttrib4Nuiv = wrapglVertexAttrib4Nuiv;
1518 //      qglGetVertexAttribdv = wrapglGetVertexAttribdv;
1519         qglGetVertexAttribfv = wrapglGetVertexAttribfv;
1520         qglGetVertexAttribiv = wrapglGetVertexAttribiv;
1521         qglGetVertexAttribPointerv = wrapglGetVertexAttribPointerv;
1522
1523         gl_renderer = (const char *)qglGetString(GL_RENDERER);
1524         gl_vendor = (const char *)qglGetString(GL_VENDOR);
1525         gl_version = (const char *)qglGetString(GL_VERSION);
1526         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
1527         
1528         if (!gl_extensions)
1529                 gl_extensions = "";
1530         if (!gl_platformextensions)
1531                 gl_platformextensions = "";
1532         
1533         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
1534         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
1535         Con_Printf("GL_VERSION: %s\n", gl_version);
1536         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
1537         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
1538         
1539         // LordHavoc: report supported extensions
1540         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1541
1542         // GLES devices in general do not like GL_BGRA, so use GL_RGBA
1543         vid.forcetextype = TEXTYPE_RGBA;
1544         
1545         vid.support.gl20shaders = true;
1546         vid.support.amd_texture_texture4 = false;
1547         vid.support.arb_depth_texture = false;
1548         vid.support.arb_draw_buffers = false;
1549         vid.support.arb_multitexture = false;
1550         vid.support.arb_occlusion_query = false;
1551         vid.support.arb_shadow = false;
1552         vid.support.arb_texture_compression = false; // different (vendor-specific) formats than on desktop OpenGL...
1553         vid.support.arb_texture_cube_map = true;
1554         vid.support.arb_texture_env_combine = false;
1555         vid.support.arb_texture_gather = false;
1556         vid.support.arb_texture_non_power_of_two = strstr(gl_extensions, "GL_OES_texture_npot") != NULL;
1557         vid.support.arb_vertex_buffer_object = true;
1558         vid.support.ati_separate_stencil = false;
1559         vid.support.ext_blend_minmax = false;
1560         vid.support.ext_blend_subtract = true;
1561         vid.support.ext_draw_range_elements = true;
1562         vid.support.ext_framebuffer_object = false;//true;
1563         vid.support.ext_stencil_two_side = false;
1564         vid.support.ext_texture_3d = false;//SDL_GL_ExtensionSupported("GL_OES_texture_3D"); // iPhoneOS does not support 3D textures, odd...
1565         vid.support.ext_texture_compression_s3tc = false;
1566         vid.support.ext_texture_edge_clamp = true;
1567         vid.support.ext_texture_filter_anisotropic = false; // probably don't want to use it...
1568         vid.support.ext_texture_srgb = false;
1569
1570         qglGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_2d);
1571         if (vid.support.ext_texture_filter_anisotropic)
1572                 qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*)&vid.max_anisotropy);
1573         if (vid.support.arb_texture_cube_map)
1574                 qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, (GLint*)&vid.maxtexturesize_cubemap);
1575         if (vid.support.ext_texture_3d)
1576                 qglGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_3d);
1577         Con_Printf("GL_MAX_CUBE_MAP_TEXTURE_SIZE = %i\n", vid.maxtexturesize_cubemap);
1578         Con_Printf("GL_MAX_3D_TEXTURE_SIZE = %i\n", vid.maxtexturesize_3d);
1579
1580         // verify that cubemap textures are really supported
1581         if (vid.support.arb_texture_cube_map && vid.maxtexturesize_cubemap < 256)
1582                 vid.support.arb_texture_cube_map = false;
1583         
1584         // verify that 3d textures are really supported
1585         if (vid.support.ext_texture_3d && vid.maxtexturesize_3d < 32)
1586         {
1587                 vid.support.ext_texture_3d = false;
1588                 Con_Printf("GL_OES_texture_3d reported bogus GL_MAX_3D_TEXTURE_SIZE, disabled\n");
1589         }
1590
1591         vid.texunits = 4;
1592         vid.teximageunits = 8;
1593         vid.texarrayunits = 5;
1594         vid.texunits = bound(1, vid.texunits, MAX_TEXTUREUNITS);
1595         vid.teximageunits = bound(1, vid.teximageunits, MAX_TEXTUREUNITS);
1596         vid.texarrayunits = bound(1, vid.texarrayunits, MAX_TEXTUREUNITS);
1597         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" : "");
1598         vid.renderpath = RENDERPATH_GLES2;
1599         vid.useinterleavedarrays = false;
1600         vid.sRGBcapable2D = false;
1601         vid.sRGBcapable3D = false;
1602
1603         // VorteX: set other info (maybe place them in VID_InitMode?)
1604         extern cvar_t gl_info_vendor;
1605         extern cvar_t gl_info_renderer;
1606         extern cvar_t gl_info_version;
1607         extern cvar_t gl_info_platform;
1608         extern cvar_t gl_info_driver;
1609         Cvar_SetQuick(&gl_info_vendor, gl_vendor);
1610         Cvar_SetQuick(&gl_info_renderer, gl_renderer);
1611         Cvar_SetQuick(&gl_info_version, gl_version);
1612         Cvar_SetQuick(&gl_info_platform, gl_platform ? gl_platform : "");
1613         Cvar_SetQuick(&gl_info_driver, gl_driver);
1614 }
1615 #endif
1616
1617 void *GL_GetProcAddress(const char *name)
1618 {
1619         void *p = NULL;
1620         p = SDL_GL_GetProcAddress(name);
1621         return p;
1622 }
1623
1624 static qboolean vid_sdl_initjoysticksystem = false;
1625
1626 void VID_Init (void)
1627 {
1628 #ifndef __IPHONEOS__
1629 #ifdef MACOSX
1630         Cvar_RegisterVariable(&apple_mouse_noaccel);
1631 #endif
1632 #endif
1633 #ifdef __IPHONEOS__
1634         Cvar_SetValueQuick(&vid_touchscreen, 1);
1635 #endif
1636
1637 #ifdef SDL_R_RESTART
1638         R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap, NULL, NULL);
1639 #endif
1640
1641         if (SDL_Init(SDL_INIT_VIDEO) < 0)
1642                 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
1643         vid_sdl_initjoysticksystem = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0;
1644         if (vid_sdl_initjoysticksystem)
1645                 Con_Printf("Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
1646         vid_isfullscreen = false;
1647 }
1648
1649 static int vid_sdljoystickindex = -1;
1650 void VID_EnableJoystick(qboolean enable)
1651 {
1652         int index = joy_enable.integer > 0 ? joy_index.integer : -1;
1653         int numsdljoysticks;
1654         qboolean success = false;
1655         int sharedcount = 0;
1656         int sdlindex = -1;
1657         sharedcount = VID_Shared_SetJoystick(index);
1658         if (index >= 0 && index < sharedcount)
1659                 success = true;
1660         sdlindex = index - sharedcount;
1661
1662         numsdljoysticks = SDL_NumJoysticks();
1663         if (sdlindex < 0 || sdlindex >= numsdljoysticks)
1664                 sdlindex = -1;
1665
1666         // update cvar containing count of XInput joysticks + SDL joysticks
1667         if (joy_detected.integer != sharedcount + numsdljoysticks)
1668                 Cvar_SetValueQuick(&joy_detected, sharedcount + numsdljoysticks);
1669
1670         if (vid_sdljoystickindex != sdlindex)
1671         {
1672                 vid_sdljoystickindex = sdlindex;
1673                 // close SDL joystick if active
1674                 if (vid_sdljoystick)
1675                         SDL_JoystickClose(vid_sdljoystick);
1676                 vid_sdljoystick = NULL;
1677                 if (sdlindex >= 0)
1678                 {
1679                         vid_sdljoystick = SDL_JoystickOpen(sdlindex);
1680                         if (vid_sdljoystick)
1681                                 Con_Printf("Joystick %i opened (SDL_Joystick %i is \"%s\" with %i axes, %i buttons, %i balls)\n", index, sdlindex, SDL_JoystickName(sdlindex), (int)SDL_JoystickNumAxes(vid_sdljoystick), (int)SDL_JoystickNumButtons(vid_sdljoystick), (int)SDL_JoystickNumBalls(vid_sdljoystick));
1682                         else
1683                         {
1684                                 Con_Printf("Joystick %i failed (SDL_JoystickOpen(%i) returned: %s)\n", index, sdlindex, SDL_GetError());
1685                                 sdlindex = -1;
1686                         }
1687                 }
1688         }
1689
1690         if (sdlindex >= 0)
1691                 success = true;
1692
1693         if (joy_active.integer != (success ? 1 : 0))
1694                 Cvar_SetValueQuick(&joy_active, success ? 1 : 0);
1695 }
1696
1697 #if SETVIDEOMODE
1698 // set the icon (we dont use SDL here since it would be too much a PITA)
1699 #ifdef WIN32
1700 #include "resource.h"
1701 #include <SDL_syswm.h>
1702 static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
1703 {
1704         SDL_Surface *screen = NULL;
1705         SDL_SysWMinfo info;
1706         HICON icon;
1707         SDL_WM_SetCaption( gamename, NULL );
1708         screen = SDL_SetVideoMode(screenwidth, screenheight, screenbpp, screenflags);
1709         if (screen)
1710         {
1711                 // get the HWND handle
1712                 SDL_VERSION( &info.version );
1713                 if (SDL_GetWMInfo(&info))
1714                 {
1715                         icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) );
1716 #ifndef _W64 //If Windows 64bit data types don't exist
1717 #ifndef SetClassLongPtr
1718 #define SetClassLongPtr SetClassLong
1719 #endif
1720 #ifndef GCLP_HICON
1721 #define GCLP_HICON GCL_HICON
1722 #endif
1723 #ifndef LONG_PTR
1724 #define LONG_PTR LONG
1725 #endif
1726 #endif
1727                         SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon );
1728                 }
1729         }
1730         return screen;
1731 }
1732 #elif defined(MACOSX)
1733 static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
1734 {
1735         SDL_Surface *screen = NULL;
1736         SDL_WM_SetCaption( gamename, NULL );
1737         screen = SDL_SetVideoMode(screenwidth, screenheight, screenbpp, screenflags);
1738         // we don't use SDL_WM_SetIcon here because the icon in the .app should be used
1739         return screen;
1740 }
1741 #else
1742 // Adding the OS independent XPM version --blub
1743 #include "darkplaces.xpm"
1744 #include "nexuiz.xpm"
1745 static SDL_Surface *icon = NULL;
1746 static SDL_Surface *VID_WrapSDL_SetVideoMode(int screenwidth, int screenheight, int screenbpp, int screenflags)
1747 {
1748         /*
1749          * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at
1750          * default settings with less than 91 colors and transparency.
1751          */
1752
1753         int width, height, colors, isize, i, j;
1754         int thenone = -1;
1755         static SDL_Color palette[256];
1756         unsigned short palenc[256]; // store color id by char
1757         char *xpm;
1758         char **idata, *data;
1759         const SDL_version *version;
1760         SDL_Surface *screen = NULL;
1761
1762         if (icon)
1763                 SDL_FreeSurface(icon);
1764         icon = NULL;
1765         version = SDL_Linked_Version();
1766         // only use non-XPM icon support in SDL v1.3 and higher
1767         // SDL v1.2 does not support "smooth" transparency, and thus is better
1768         // off the xpm way
1769         if(version->major >= 2 || (version->major == 1 && version->minor >= 3))
1770         {
1771                 data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
1772                 if(data)
1773                 {
1774                         unsigned int red = 0x00FF0000;
1775                         unsigned int green = 0x0000FF00;
1776                         unsigned int blue = 0x000000FF;
1777                         unsigned int alpha = 0xFF000000;
1778                         width = image_width;
1779                         height = image_height;
1780
1781                         // reallocate with malloc, as this is in tempmempool (do not want)
1782                         xpm = data;
1783                         data = malloc(width * height * 4);
1784                         memcpy(data, xpm, width * height * 4);
1785                         Mem_Free(xpm);
1786                         xpm = NULL;
1787
1788                         icon = SDL_CreateRGBSurface(SDL_SRCALPHA, width, height, 32, LittleLong(red), LittleLong(green), LittleLong(blue), LittleLong(alpha));
1789
1790                         if (icon)
1791                                 icon->pixels = data;
1792                         else
1793                         {
1794                                 Con_Printf(     "Failed to create surface for the window Icon!\n"
1795                                                 "%s\n", SDL_GetError());
1796                                 free(data);
1797                         }
1798                 }
1799         }
1800
1801         // we only get here if non-XPM icon was missing, or SDL version is not
1802         // sufficient for transparent non-XPM icons
1803         if(!icon)
1804         {
1805                 xpm = (char *) FS_LoadFile("darkplaces-icon.xpm", tempmempool, false, NULL);
1806                 idata = NULL;
1807                 if(xpm)
1808                         idata = XPM_DecodeString(xpm);
1809                 if(!idata)
1810                         idata = ENGINE_ICON;
1811                 if(xpm)
1812                         Mem_Free(xpm);
1813
1814                 data = idata[0];
1815
1816                 if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) == 4)
1817                 {
1818                         if(isize == 1)
1819                         {
1820                                 for(i = 0; i < colors; ++i)
1821                                 {
1822                                         unsigned int r, g, b;
1823                                         char idx;
1824
1825                                         if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4)
1826                                         {
1827                                                 char foo[2];
1828                                                 if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0
1829                                                         break;
1830                                                 else
1831                                                 {
1832                                                         palette[i].r = 255; // color key
1833                                                         palette[i].g = 0;
1834                                                         palette[i].b = 255;
1835                                                         thenone = i; // weeeee
1836                                                         palenc[(unsigned char) idx] = i;
1837                                                 }
1838                                         }
1839                                         else
1840                                         {
1841                                                 palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key
1842                                                 palette[i].g = g;
1843                                                 palette[i].b = b;
1844                                                 palenc[(unsigned char) idx] = i;
1845                                         }
1846                                 }
1847
1848                                 if (i == colors)
1849                                 {
1850                                         // allocate the image data
1851                                         data = (char*) malloc(width*height);
1852
1853                                         for(j = 0; j < height; ++j)
1854                                         {
1855                                                 for(i = 0; i < width; ++i)
1856                                                 {
1857                                                         // casting to the safest possible datatypes ^^
1858                                                         data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]];
1859                                                 }
1860                                         }
1861
1862                                         if(icon != NULL)
1863                                         {
1864                                                 // SDL_FreeSurface should free the data too
1865                                                 // but for completeness' sake...
1866                                                 if(icon->flags & SDL_PREALLOC)
1867                                                 {
1868                                                         free(icon->pixels);
1869                                                         icon->pixels = NULL; // safety
1870                                                 }
1871                                                 SDL_FreeSurface(icon);
1872                                         }
1873
1874                                         icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed
1875                                         // 8 bit surfaces get an empty palette allocated according to the docs
1876                                         // so it's a palette image for sure :) no endian check necessary for the mask
1877
1878                                         if(icon)
1879                                         {
1880                                                 icon->pixels = data;
1881                                                 SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors);
1882                                                 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone);
1883                                         }
1884                                         else
1885                                         {
1886                                                 Con_Printf(     "Failed to create surface for the window Icon!\n"
1887                                                                 "%s\n", SDL_GetError());
1888                                                 free(data);
1889                                         }
1890                                 }
1891                                 else
1892                                 {
1893                                         Con_Printf("This XPM's palette looks odd. Can't continue.\n");
1894                                 }
1895                         }
1896                         else
1897                         {
1898                                 // NOTE: Only 1-char colornames are supported
1899                                 Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize);
1900                         }
1901                 }
1902                 else
1903                 {
1904                         // NOTE: Only 1-char colornames are supported
1905                         Con_Printf("Sorry, but this does not even look similar to an XPM.\n");
1906                 }
1907         }
1908
1909         if (icon)
1910                 SDL_WM_SetIcon(icon, NULL);
1911
1912         SDL_WM_SetCaption( gamename, NULL );
1913         screen = SDL_SetVideoMode(screenwidth, screenheight, screenbpp, screenflags);
1914
1915 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
1916 // LordHavoc: info.info.x11.lock_func and accompanying code do not seem to compile with SDL 1.3
1917 #if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ
1918
1919         version = SDL_Linked_Version();
1920         // only use non-XPM icon support in SDL v1.3 and higher
1921         // SDL v1.2 does not support "smooth" transparency, and thus is better
1922         // off the xpm way
1923         if(screen && (!(version->major >= 2 || (version->major == 1 && version->minor >= 3))))
1924         {
1925                 // in this case, we did not set the good icon yet
1926                 SDL_SysWMinfo info;
1927                 SDL_VERSION(&info.version);
1928                 if(SDL_GetWMInfo(&info) == 1 && info.subsystem == SDL_SYSWM_X11)
1929                 {
1930                         data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL);
1931                         if(data)
1932                         {
1933                                 // use _NET_WM_ICON too
1934                                 static long netwm_icon[MAX_NETWM_ICON];
1935                                 int pos = 0;
1936                                 int i = 1;
1937
1938                                 while(data)
1939                                 {
1940                                         if(pos + 2 * image_width * image_height < MAX_NETWM_ICON)
1941                                         {
1942                                                 netwm_icon[pos++] = image_width;
1943                                                 netwm_icon[pos++] = image_height;
1944                                                 for(i = 0; i < image_height; ++i)
1945                                                         for(j = 0; j < image_width; ++j)
1946                                                                 netwm_icon[pos++] = BuffLittleLong((unsigned char *) &data[(i*image_width+j)*4]);
1947                                         }
1948                                         else
1949                                         {
1950                                                 Con_Printf("Skipping NETWM icon #%d because there is no space left\n", i);
1951                                         }
1952                                         ++i;
1953                                         Mem_Free(data);
1954                                         data = (char *) loadimagepixelsbgra(va("darkplaces-icon%d", i), false, false, false, NULL);
1955                                 }
1956
1957                                 info.info.x11.lock_func();
1958                                 {
1959                                         Atom net_wm_icon = XInternAtom(info.info.x11.display, "_NET_WM_ICON", false);
1960                                         XChangeProperty(info.info.x11.display, info.info.x11.wmwindow, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos);
1961                                 }
1962                                 info.info.x11.unlock_func();
1963                         }
1964                 }
1965         }
1966 #endif
1967 #endif
1968         return screen;
1969 }
1970
1971 #endif
1972 #endif
1973
1974 static void VID_OutputVersion(void)
1975 {
1976         const SDL_version *version;
1977         version = SDL_Linked_Version();
1978         Con_Printf(     "Linked against SDL version %d.%d.%d\n"
1979                                         "Using SDL library version %d.%d.%d\n",
1980                                         SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
1981                                         version->major, version->minor, version->patch );
1982 }
1983
1984 qboolean VID_InitModeGL(viddef_mode_t *mode)
1985 {
1986         int i;
1987 #if SETVIDEOMODE
1988         static int notfirstvideomode = false;
1989         int flags = SDL_OPENGL;
1990 #else
1991         int windowflags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL;
1992 #endif
1993         const char *drivername;
1994
1995         win_half_width = mode->width>>1;
1996         win_half_height = mode->height>>1;
1997
1998         if(vid_resizable.integer)
1999 #if SETVIDEOMODE
2000                 flags |= SDL_RESIZABLE;
2001 #else
2002                 windowflags |= SDL_WINDOW_RESIZABLE;
2003 #endif
2004
2005         VID_OutputVersion();
2006
2007 #if SETVIDEOMODE
2008         /*
2009         SDL 1.2 Hack
2010                 We cant switch from one OpenGL video mode to another.
2011                 Thus we first switch to some stupid 2D mode and then back to OpenGL.
2012         */
2013         if (notfirstvideomode)
2014                 SDL_SetVideoMode( 0, 0, 0, 0 );
2015         notfirstvideomode = true;
2016 #endif
2017
2018         // SDL usually knows best
2019         drivername = NULL;
2020
2021 // 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
2022         i = COM_CheckParm("-gl_driver");
2023         if (i && i < com_argc - 1)
2024                 drivername = com_argv[i + 1];
2025         if (SDL_GL_LoadLibrary(drivername) < 0)
2026         {
2027                 Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
2028                 return false;
2029         }
2030
2031 #ifdef __IPHONEOS__
2032         // mobile platforms are always fullscreen, we'll get the resolution after opening the window
2033         mode->fullscreen = true;
2034         // hide the menu with SDL_WINDOW_BORDERLESS
2035         windowflags |= SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS;
2036 #endif
2037 #ifndef USE_GLES2
2038         if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL)
2039         {
2040                 VID_Shutdown();
2041                 Con_Print("Required OpenGL function glGetString not found\n");
2042                 return false;
2043         }
2044 #endif
2045
2046         // Knghtbrd: should do platform-specific extension string function here
2047
2048         vid_isfullscreen = false;
2049         if (mode->fullscreen) {
2050 #if SETVIDEOMODE
2051                 flags |= SDL_FULLSCREEN;
2052 #else
2053                 windowflags |= SDL_WINDOW_FULLSCREEN;
2054 #endif
2055                 vid_isfullscreen = true;
2056         }
2057         //flags |= SDL_HWSURFACE;
2058
2059         SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
2060         if (mode->bitsperpixel >= 32)
2061         {
2062                 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8);
2063                 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8);
2064                 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8);
2065                 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8);
2066                 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);
2067                 SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8);
2068         }
2069         else
2070         {
2071                 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
2072                 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
2073                 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
2074                 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
2075         }
2076         if (mode->stereobuffer)
2077                 SDL_GL_SetAttribute (SDL_GL_STEREO, 1);
2078         if (mode->samples > 1)
2079         {
2080                 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
2081                 SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples);
2082         }
2083
2084 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
2085         if (vid_vsync.integer)
2086                 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
2087         else
2088                 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0);
2089 #else
2090 #ifdef USE_GLES2
2091         SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2);
2092         SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0);
2093         SDL_GL_SetAttribute (SDL_GL_RETAINED_BACKING, 1);
2094 #endif
2095 #endif
2096
2097         video_bpp = mode->bitsperpixel;
2098 #if SETVIDEOMODE
2099         video_flags = flags;
2100         screen = VID_WrapSDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
2101         if (screen == NULL)
2102         {
2103                 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
2104                 VID_Shutdown();
2105                 return false;
2106         }
2107         mode->width = screen->w;
2108         mode->height = screen->h;
2109 #else
2110         window_flags = windowflags;
2111         window = SDL_CreateWindow(gamename, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, mode->width, mode->height, windowflags);
2112         if (window == NULL)
2113         {
2114                 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
2115                 VID_Shutdown();
2116                 return false;
2117         }
2118         SDL_GetWindowSize(window, &mode->width, &mode->height);
2119         context = SDL_GL_CreateContext(window);
2120         if (context == NULL)
2121         {
2122                 Con_Printf("Failed to initialize OpenGL context: %s\n", SDL_GetError());
2123                 VID_Shutdown();
2124                 return false;
2125         }
2126 #endif
2127
2128         vid_softsurface = NULL;
2129         vid.softpixels = NULL;
2130
2131         // init keyboard
2132         SDL_EnableUNICODE( SDL_ENABLE );
2133         // enable key repeat since everyone expects it
2134         SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
2135
2136 #if !(SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2)
2137         SDL_GL_SetSwapInterval(vid_vsync.integer != 0);
2138         vid_usingvsync = (vid_vsync.integer != 0);
2139 #endif
2140
2141         gl_platform = "SDL";
2142         gl_platformextensions = "";
2143
2144 #ifdef USE_GLES2
2145         GLES_Init();
2146 #else
2147         GL_Init();
2148 #endif
2149
2150         vid_hidden = false;
2151         vid_activewindow = false;
2152         vid_hasfocus = true;
2153         vid_usingmouse = false;
2154         vid_usinghidecursor = false;
2155                 
2156 #if SETVIDEOMODE
2157         SDL_WM_GrabInput(SDL_GRAB_OFF);
2158 #endif
2159         return true;
2160 }
2161
2162 extern cvar_t gl_info_extensions;
2163 extern cvar_t gl_info_vendor;
2164 extern cvar_t gl_info_renderer;
2165 extern cvar_t gl_info_version;
2166 extern cvar_t gl_info_platform;
2167 extern cvar_t gl_info_driver;
2168
2169 qboolean VID_InitModeSoft(viddef_mode_t *mode)
2170 {
2171 #if SETVIDEOMODE
2172         int flags = SDL_HWSURFACE;
2173         if(!COM_CheckParm("-noasyncblit")) flags |= SDL_ASYNCBLIT;
2174 #else
2175         int windowflags = SDL_WINDOW_SHOWN;
2176 #endif
2177
2178         win_half_width = mode->width>>1;
2179         win_half_height = mode->height>>1;
2180
2181         if(vid_resizable.integer)
2182 #if SETVIDEOMODE
2183                 flags |= SDL_RESIZABLE;
2184 #else
2185                 windowflags |= SDL_WINDOW_RESIZABLE;
2186 #endif
2187
2188         VID_OutputVersion();
2189
2190         vid_isfullscreen = false;
2191         if (mode->fullscreen) {
2192 #if SETVIDEOMODE
2193                 flags |= SDL_FULLSCREEN;
2194 #else
2195                 windowflags |= SDL_WINDOW_FULLSCREEN;
2196 #endif
2197                 vid_isfullscreen = true;
2198         }
2199
2200         video_bpp = mode->bitsperpixel;
2201 #if SETVIDEOMODE
2202         video_flags = flags;
2203         screen = VID_WrapSDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags);
2204         if (screen == NULL)
2205         {
2206                 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
2207                 VID_Shutdown();
2208                 return false;
2209         }
2210         mode->width = screen->w;
2211         mode->height = screen->h;
2212 #else
2213         window_flags = windowflags;
2214         window = SDL_CreateWindow(gamename, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, mode->width, mode->height, windowflags);
2215         if (window == NULL)
2216         {
2217                 Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError());
2218                 VID_Shutdown();
2219                 return false;
2220         }
2221         SDL_GetWindowSize(window, &mode->width, &mode->height);
2222 #endif
2223
2224         // create a framebuffer using our specific color format, we let the SDL blit function convert it in VID_Finish
2225         vid_softsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, mode->width, mode->height, 32, 0x00FF0000, 0x0000FF00, 0x00000000FF, 0xFF000000);
2226         if (vid_softsurface == NULL)
2227         {
2228                 Con_Printf("Failed to setup software rasterizer framebuffer %ix%ix32bpp: %s\n", mode->width, mode->height, SDL_GetError());
2229                 VID_Shutdown();
2230                 return false;
2231         }
2232         SDL_SetAlpha(vid_softsurface, 0, 255);
2233
2234         vid.softpixels = (unsigned int *)vid_softsurface->pixels;
2235         vid.softdepthpixels = (unsigned int *)calloc(1, mode->width * mode->height * 4);
2236         if (DPSOFTRAST_Init(mode->width, mode->height, vid_soft_threads.integer, vid_soft_interlace.integer, (unsigned int *)vid_softsurface->pixels, (unsigned int *)vid.softdepthpixels) < 0)
2237         {
2238                 Con_Printf("Failed to initialize software rasterizer\n");
2239                 VID_Shutdown();
2240                 return false;
2241         }
2242
2243         // init keyboard
2244         SDL_EnableUNICODE( SDL_ENABLE );
2245         // enable key repeat since everyone expects it
2246         SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
2247
2248         VID_Soft_SharedSetup();
2249
2250         vid_hidden = false;
2251         vid_activewindow = false;
2252         vid_hasfocus = true;
2253         vid_usingmouse = false;
2254         vid_usinghidecursor = false;
2255
2256 #if SETVIDEOMODE
2257         SDL_WM_GrabInput(SDL_GRAB_OFF);
2258 #endif
2259         return true;
2260 }
2261
2262 qboolean VID_InitMode(viddef_mode_t *mode)
2263 {
2264         if (!SDL_WasInit(SDL_INIT_VIDEO) && SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
2265                 Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
2266 #ifdef SSE_POSSIBLE
2267         if (vid_soft.integer)
2268                 return VID_InitModeSoft(mode);
2269         else
2270 #endif
2271                 return VID_InitModeGL(mode);
2272 }
2273
2274 void VID_Shutdown (void)
2275 {
2276         VID_EnableJoystick(false);
2277         VID_SetMouse(false, false, false);
2278         VID_RestoreSystemGamma();
2279
2280 #if SETVIDEOMODE
2281 #ifndef WIN32
2282 #ifndef MACOSX
2283         if (icon)
2284                 SDL_FreeSurface(icon);
2285         icon = NULL;
2286 #endif
2287 #endif
2288 #endif
2289
2290         if (vid_softsurface)
2291                 SDL_FreeSurface(vid_softsurface);
2292         vid_softsurface = NULL;
2293         vid.softpixels = NULL;
2294         if (vid.softdepthpixels)
2295                 free(vid.softdepthpixels);
2296         vid.softdepthpixels = NULL;
2297
2298 #if SETVIDEOMODE
2299 #else
2300         SDL_DestroyWindow(window);
2301         window = NULL;
2302 #endif
2303
2304         SDL_QuitSubSystem(SDL_INIT_VIDEO);
2305
2306         gl_driver[0] = 0;
2307         gl_extensions = "";
2308         gl_platform = "";
2309         gl_platformextensions = "";
2310 }
2311
2312 int VID_SetGamma (unsigned short *ramps, int rampsize)
2313 {
2314         return !SDL_SetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
2315 }
2316
2317 int VID_GetGamma (unsigned short *ramps, int rampsize)
2318 {
2319         return !SDL_GetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
2320 }
2321
2322 void VID_Finish (void)
2323 {
2324 #if SETVIDEOMODE
2325         Uint8 appstate;
2326
2327         //react on appstate changes
2328         appstate = SDL_GetAppState();
2329
2330         vid_hidden = !(appstate & SDL_APPACTIVE);
2331         vid_hasfocus = (appstate & SDL_APPINPUTFOCUS) != 0;
2332 #endif
2333         vid_activewindow = !vid_hidden && vid_hasfocus;
2334
2335         VID_UpdateGamma(false, 256);
2336
2337         if (!vid_hidden)
2338         {
2339                 switch(vid.renderpath)
2340                 {
2341                 case RENDERPATH_GL11:
2342                 case RENDERPATH_GL13:
2343                 case RENDERPATH_GL20:
2344                 case RENDERPATH_GLES1:
2345                 case RENDERPATH_GLES2:
2346                         CHECKGLERROR
2347                         if (r_speeds.integer == 2 || gl_finish.integer)
2348                                 GL_Finish();
2349 #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
2350 #else
2351 {
2352         qboolean vid_usevsync;
2353         vid_usevsync = (vid_vsync.integer && !cls.timedemo);
2354         if (vid_usingvsync != vid_usevsync)
2355         {
2356                 if (SDL_GL_SetSwapInterval(vid_usevsync != 0) >= 0)
2357                         Con_DPrintf("Vsync %s\n", vid_usevsync ? "activated" : "deactivated");
2358                 else
2359                         Con_DPrintf("ERROR: can't %s vsync\n", vid_usevsync ? "activate" : "deactivate");
2360         }
2361 }
2362 #endif
2363 #if SETVIDEOMODE
2364                         SDL_GL_SwapBuffers();
2365 #else
2366                         SDL_GL_SwapWindow(window);
2367 #endif
2368                         break;
2369                 case RENDERPATH_SOFT:
2370                         DPSOFTRAST_Finish();
2371 #if SETVIDEOMODE
2372 //              if (!r_test.integer)
2373                 {
2374                         SDL_BlitSurface(vid_softsurface, NULL, screen, NULL);
2375                         SDL_Flip(screen);
2376                 }
2377 #else
2378                         {
2379                                 SDL_Surface *screen = SDL_GetWindowSurface(window);
2380                                 SDL_BlitSurface(vid_softsurface, NULL, screen, NULL);
2381                                 SDL_UpdateWindowSurface(window);
2382                         }
2383 #endif
2384                         break;
2385                 case RENDERPATH_D3D9:
2386                 case RENDERPATH_D3D10:
2387                 case RENDERPATH_D3D11:
2388                         if (r_speeds.integer == 2 || gl_finish.integer)
2389                                 GL_Finish();
2390                         break;
2391                 }
2392         }
2393 }
2394
2395 size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)
2396 {
2397         size_t k;
2398         SDL_Rect **vidmodes;
2399         int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
2400
2401         k = 0;
2402         for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); vidmodes && *vidmodes; ++vidmodes)
2403         {
2404                 if(k >= maxcount)
2405                         break;
2406                 modes[k].width = (*vidmodes)->w;
2407                 modes[k].height = (*vidmodes)->h;
2408                 modes[k].bpp = bpp;
2409                 modes[k].refreshrate = 60; // no support for refresh rate in SDL
2410                 modes[k].pixelheight_num = 1;
2411                 modes[k].pixelheight_denom = 1; // SDL does not provide this
2412                 ++k;
2413         }
2414         return k;
2415 }