1 /* $Id: rw_sdl.c,v 1.17 2003/02/23 12:42:34 jaq Exp $
2  *
3  * all os-specific SDL refresher code
4  *
5  * Copyright (c) 2002 The QuakeForge Project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * See the GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22 
23 /*
24 ** GL_SDL.C
25 **
26 ** This file contains ALL Unix specific stuff having to do with the
27 ** software refresh.  When a port is being made the following functions
28 ** must be implemented by the port:
29 **
30 ** GLimp_EndFrame
31 ** GLimp_Init
32 ** GLimp_InitGraphics
33 ** GLimp_SetPalette
34 ** GLimp_Shutdown
35 ** GLimp_SwitchFullscreen
36 */
37 
38 #include <unistd.h>
39 #include <stdlib.h>
40 #include <limits.h>
41 
42 #include "SDL.h"
43 #include "SDL_syswm.h"
44 #include <X11/Xlib.h>
45 
46 #include "../ref_gl/gl_local.h"
47 #include "../client/keys.h"
48 #include "../unix/rw_unix.h"
49 #include "../ref_gl/glw.h"
50 
51 /*****************************************************************************/
52 
53 int	mouse_buttonstate,
54 	mouse_oldbuttonstate,
55 	mouse_x,
56 	mouse_y,
57 	old_mouse_x,
58 	old_mouse_y,
59 	mx,
60 	my;
61 
62 cvar_t	*_windowed_mouse,
63 	*m_filter,
64 	*_windowed_mouse,
65 	*print_keymap,
66 	*sensitivity,
67 	*autosensitivity,
68 	*lookstrafe,
69 	*m_side,
70 	*m_yaw,
71 	*m_pitch,
72 	*m_forward,
73 	*freelook,
74 	*use_stencil;
75 
76 float	old_windowed_mouse;
77 
78 qboolean SDL_active = false,
79          mlooking = false,
80 	 mouse_avail = false,
81 	 mouse_active = false,
82 	 have_stencil = false;
83 
84 
85 glwstate_t	glw_state;
86 in_state_t	*in_state;
87 
88 SDL_Surface 	*surface;
89 
90 unsigned char KeyStates[SDLK_LAST];
91 unsigned short gamma_ramp[3][256];
92 
93 struct {
94 	int key, down;
95 } keyq[64];
96 
97 int	keyq_head = 0,
98         keyq_tail = 0;
99 
install_grabs(void)100 void install_grabs(void)
101 {
102 	SDL_WM_GrabInput(SDL_GRAB_ON);
103 	SDL_ShowCursor(0);
104 }
105 
uninstall_grabs(void)106 void uninstall_grabs(void)
107 {
108 	SDL_ShowCursor(1);
109 	SDL_WM_GrabInput(SDL_GRAB_OFF);
110 }
111 
Force_CenterView_f(void)112 void Force_CenterView_f(void)
113 {
114 	in_state->viewangles[PITCH] = 0;
115 }
116 
RW_IN_MLookDown(void)117 void RW_IN_MLookDown(void)
118 {
119 	mlooking = true;
120 }
121 
RW_IN_MLookUp(void)122 void RW_IN_MLookUp(void)
123 {
124 	mlooking = false;
125 	in_state->IN_CenterView_fp ();
126 }
127 
RW_IN_Init(in_state_t * in_state_p)128 void RW_IN_Init(in_state_t * in_state_p)
129 {
130 
131 	in_state = in_state_p;
132 
133 	// mouse variables
134 	m_filter = ri.Cvar_Get ("m_filter", "0", 0);
135 	_windowed_mouse = ri.Cvar_Get ("_windowed_mouse", "1", CVAR_ARCHIVE);
136 	freelook = ri.Cvar_Get( "freelook", "1", CVAR_ARCHIVE );
137 	lookstrafe = ri.Cvar_Get ("lookstrafe", "0", 0);
138 	sensitivity = ri.Cvar_Get ("sensitivity", "3", CVAR_ARCHIVE);
139 	autosensitivity = ri.Cvar_Get("autosensitivity", "1", 0);
140 	m_pitch = ri.Cvar_Get ("m_pitch", "0.022", 0);
141 	m_yaw = ri.Cvar_Get ("m_yaw", "0.022", 0);
142 	m_forward = ri.Cvar_Get ("m_forward", "1", 0);
143 	m_side = ri.Cvar_Get ("m_side", "0.8", 0);
144 	print_keymap = ri.Cvar_Get ("print_keymap", "0", 0);
145 	use_stencil = ri.Cvar_Get("use_stencil", "1", CVAR_ARCHIVE);
146 
147 	ri.Cmd_AddCommand ("+mlook", RW_IN_MLookDown);
148 	ri.Cmd_AddCommand ("-mlook", RW_IN_MLookUp);
149 	ri.Cmd_AddCommand ("force_centerview", Force_CenterView_f);
150 
151 	mx = my = 0.0;
152 
153 	#if defined(NDEBUG)
154 	mouse_avail = true;
155 	#else
156 	{
157 		Com_Printf("Fullscreen and mouse grab not allowed when running debug mode\n");
158 		ri.Cvar_Set("vid_fullscreen", "0");
159 		mouse_avail = false;
160 	}
161 	#endif
162 }
163 
RW_IN_Shutdown(void)164 void RW_IN_Shutdown(void)
165 {
166 	if (mouse_avail) {
167 		mouse_avail = false;
168 		ri.Cmd_RemoveCommand("+mlook");
169 		ri.Cmd_RemoveCommand("-mlook");
170 		ri.Cmd_RemoveCommand("force_centerview");
171 	}
172 }
173 
RW_IN_Commands(void)174 void RW_IN_Commands(void)
175 {
176 	int	i;
177 
178 	if (mouse_avail) {
179 		for (i = 0; i < 5; i++) {
180 			if ((mouse_buttonstate & (1 << i)) && !(mouse_oldbuttonstate & (1 << i)))
181 				in_state->Key_Event_fp(K_MOUSE1 + i, true);
182 			if (!(mouse_buttonstate & (1 << i)) && (mouse_oldbuttonstate & (1 << i)))
183 				in_state->Key_Event_fp(K_MOUSE1 + i, false);
184 		}
185 		mouse_oldbuttonstate = mouse_buttonstate;
186 	}
187 }
188 
RW_IN_Move(usercmd_t * cmd,int * mcoords)189 void RW_IN_Move(usercmd_t * cmd, int *mcoords)
190 {
191 	if (!mouse_avail)
192 		return;
193 
194 	if (m_filter->value)
195 	{
196 		mx = (mx + old_mouse_x) * 0.5;
197 		my = (my + old_mouse_y) * 0.5;
198 	}
199 
200 	old_mouse_x = mx;
201 	old_mouse_y = my;
202 
203 		/* raw coords for menu mouse */
204 		mcoords[0] = mx;
205 		mcoords[1] = my;
206 
207 		if (autosensitivity->value) {
208 			mx *= sensitivity->value * (r_newrefdef.fov_x / 90.0);
209 			my *= sensitivity->value * (r_newrefdef.fov_y / 90.0);
210 		} else {
211 			mx *= sensitivity->value;
212 			my *= sensitivity->value;
213 		}
214 
215 	// add mouse X/Y movement to cmd
216 	if ( (*in_state->in_strafe_state & 1) ||
217 		(lookstrafe->value && mlooking ))
218 		cmd->sidemove += m_side->value * mx;
219 	else
220 		in_state->viewangles[YAW] -= m_yaw->value * mx;
221 
222 	if ( (mlooking || freelook->value) &&
223 		!(*in_state->in_strafe_state & 1))
224 	{
225 		in_state->viewangles[PITCH] += m_pitch->value * my;
226 	}
227 	else
228 	{
229 		cmd->forwardmove -= m_forward->value * my;
230 	}
231 
232 	mx = my = 0;
233 }
234 
IN_DeactivateMouse(void)235 void IN_DeactivateMouse(void)
236 {
237 	if (!mouse_avail)
238 		return;
239 
240 	if (mouse_active) {
241 		uninstall_grabs();
242 		mouse_active = false;
243 	}
244 }
245 
IN_ActivateMouse(void)246 void IN_ActivateMouse(void)
247 {
248 	if (!mouse_avail)
249 		return;
250 
251 	if (!mouse_active) {
252 		mx = my = 0; // don't spazz
253 		install_grabs();
254 		mouse_active = true;
255 	}
256 }
257 
RW_IN_Activate(qboolean active)258 void RW_IN_Activate(qboolean active)
259 {
260 	if (active || SDL_active)
261 		IN_ActivateMouse();
262 	else
263 		IN_DeactivateMouse();
264 }
265 
RW_IN_Frame(void)266 void RW_IN_Frame (void) {}
267 
268 /*****************************************************************************/
269 
XLateKey(unsigned int keysym)270 int XLateKey(unsigned int keysym)
271 {
272 	int key;
273 
274 	key = 0;
275 	switch(keysym) {
276 		case SDLK_KP9:		key = K_KP_PGUP;       break;
277 		case SDLK_PAGEUP:	key = K_PGUP;          break;
278 		case SDLK_KP3:		key = K_KP_PGDN;       break;
279 		case SDLK_PAGEDOWN:	key = K_PGDN;          break;
280 		case SDLK_KP7:		key = K_KP_HOME;       break;
281 		case SDLK_HOME:		key = K_HOME;          break;
282 		case SDLK_KP1:		key = K_KP_END;        break;
283 		case SDLK_END:		key = K_END;           break;
284 		case SDLK_KP4:		key = K_KP_LEFTARROW;  break;
285 		case SDLK_LEFT:		key = K_LEFTARROW;     break;
286 		case SDLK_KP6:		key = K_KP_RIGHTARROW; break;
287 		case SDLK_RIGHT:	key = K_RIGHTARROW;    break;
288 		case SDLK_KP2:		key = K_KP_DOWNARROW;  break;
289 		case SDLK_DOWN:		key = K_DOWNARROW;     break;
290 		case SDLK_KP8:		key = K_KP_UPARROW;    break;
291 		case SDLK_UP:		key = K_UPARROW;       break;
292 		case SDLK_ESCAPE:	key = K_ESCAPE;        break;
293 		case SDLK_KP_ENTER:	key = K_KP_ENTER;      break;
294 		case SDLK_RETURN:	key = K_ENTER;         break;
295 		case SDLK_TAB:		key = K_TAB;           break;
296 		case SDLK_F1:		key = K_F1;            break;
297 		case SDLK_F2:		key = K_F2;            break;
298 		case SDLK_F3:		key = K_F3;            break;
299 		case SDLK_F4:		key = K_F4;            break;
300 		case SDLK_F5:		key = K_F5;            break;
301 		case SDLK_F6:		key = K_F6;            break;
302 		case SDLK_F7:		key = K_F7;            break;
303 		case SDLK_F8:		key = K_F8;            break;
304 		case SDLK_F9:		key = K_F9;            break;
305 		case SDLK_F10:		key = K_F10;           break;
306 		case SDLK_F11:		key = K_F11;           break;
307 		case SDLK_F12:		key = K_F12;           break;
308 		case SDLK_BACKSPACE:	key = K_BACKSPACE;     break;
309 		case SDLK_KP_PERIOD:	key = K_KP_DEL;        break;
310 		case SDLK_DELETE:	key = K_DEL;           break;
311 		case SDLK_PAUSE:	key = K_PAUSE;         break;
312 		case SDLK_LSHIFT:
313 		case SDLK_RSHIFT:	key = K_SHIFT;         break;
314 		case SDLK_LCTRL:
315 		case SDLK_RCTRL:	key = K_CTRL;          break;
316 		case SDLK_LMETA:
317 		case SDLK_RMETA:
318 		case SDLK_LALT:
319 		case SDLK_RALT:		key = K_ALT;           break;
320 		case SDLK_KP5:		key = K_KP_5;          break;
321 		case SDLK_INSERT:	key = K_INS;           break;
322 		case SDLK_KP0:		key = K_KP_INS;        break;
323 		case SDLK_KP_MULTIPLY:	key = '*';             break;
324 		case SDLK_KP_PLUS:	key = K_KP_PLUS;       break;
325 		case SDLK_KP_MINUS:	key = K_KP_MINUS;      break;
326 		case SDLK_KP_DIVIDE:	key = K_KP_SLASH;      break;
327 		case SDLK_WORLD_7:	key = '`';             break;
328 
329 		case 92:		key = '~';	       break; /* Italy */
330 		case 94:		key = '~';	       break; /* Deutschland */
331 		case 178:		key = '~'; 	       break; /* France */
332 		case 186:		key = '~'; 	       break; /* Spain */
333 
334 		default: /* assuming that the other sdl keys are mapped to ascii */
335 			if (keysym < 256)
336 				key = keysym;
337 			break;
338 	}
339 
340 	if (print_keymap->value)
341 		printf( "Key '%c' (%d) -> '%c' (%d)\n", keysym, keysym, key, key );
342 
343 	return key;
344 }
345 
HandleEvents(SDL_Event * event)346 void HandleEvents(SDL_Event * event)
347 {
348 	unsigned int	key;
349 
350 	switch (event->type) {
351 	case SDL_MOUSEBUTTONDOWN:
352 		if (event->button.button == 4) {
353 			keyq[keyq_head].key = K_MWHEELUP;
354 			keyq[keyq_head].down = true;
355 			keyq_head = (keyq_head + 1) & 63;
356 			keyq[keyq_head].key = K_MWHEELUP;
357 			keyq[keyq_head].down = false;
358 			keyq_head = (keyq_head + 1) & 63;
359 		} else if (event->button.button == 5) {
360 			keyq[keyq_head].key = K_MWHEELDOWN;
361 			keyq[keyq_head].down = true;
362 			keyq_head = (keyq_head + 1) & 63;
363 			keyq[keyq_head].key = K_MWHEELDOWN;
364 			keyq[keyq_head].down = false;
365 			keyq_head = (keyq_head + 1) & 63;
366 		}
367 		break;
368 
369 	case SDL_MOUSEBUTTONUP:
370 		break;
371 	case SDL_KEYDOWN:
372 		if ((KeyStates[SDLK_LALT] || KeyStates[SDLK_RALT]) &&
373 		    (event->key.keysym.sym == SDLK_RETURN)) {
374 			cvar_t         *fullscreen;
375 
376 			SDL_WM_ToggleFullScreen(surface);
377 
378 			if (surface->flags & SDL_FULLSCREEN)
379 				ri.Cvar_SetValue("vid_fullscreen", 1);
380 			else
381 				ri.Cvar_SetValue("vid_fullscreen", 0);
382 
383 			fullscreen = ri.Cvar_Get("vid_fullscreen", "0", 0);
384 			fullscreen->modified = false;	/* we just changed it with SDL. */
385 			break;	/* ignore this key */
386 		}
387 		if ((KeyStates[SDLK_LCTRL] || KeyStates[SDLK_RCTRL]) &&
388 		    (event->key.keysym.sym == SDLK_g)) {
389 			SDL_GrabMode	gm = SDL_WM_GrabInput(SDL_GRAB_QUERY);
390 			ri.Cvar_SetValue("_windowed_mouse", (gm == SDL_GRAB_ON) ? 0 : 1);
391 			break;	/* ignore this key */
392 		}
393 
394 		KeyStates[event->key.keysym.sym] = 1;
395 
396 		key = XLateKey(event->key.keysym.sym);
397 		if (key) {
398 			keyq[keyq_head].key = key;
399 			keyq[keyq_head].down = true;
400 			keyq_head = (keyq_head + 1) & 63;
401 		}
402 		break;
403 
404 	case SDL_KEYUP:
405 		if (KeyStates[event->key.keysym.sym]) {
406 			KeyStates[event->key.keysym.sym] = 0;
407 
408 			key = XLateKey(event->key.keysym.sym);
409 			if (key) {
410 				keyq[keyq_head].key = key;
411 				keyq[keyq_head].down = false;
412 				keyq_head = (keyq_head + 1) & 63;
413 			}
414 		}
415 		break;
416 
417 	case SDL_QUIT:
418 		ri.Cmd_ExecuteText(EXEC_NOW, "quit");
419 		break;
420 	}
421 
422 }
423 
424 Key_Event_fp_t	Key_Event_fp;
KBD_Init(Key_Event_fp_t fp)425 void KBD_Init(Key_Event_fp_t fp) { Key_Event_fp = fp; }
426 
KBD_Update(void)427 void KBD_Update(void)
428 {
429 	SDL_Event	event;
430 	static int	KBD_Update_Flag;
431 
432 	if (KBD_Update_Flag == 1)
433 		return;
434 
435 	KBD_Update_Flag = 1;
436 
437 	/* get events from x server */
438 	if (SDL_active) {
439 		int		bstate;
440 
441 		while (SDL_PollEvent(&event))
442 			HandleEvents(&event);
443 
444 		if (!mx && !my)
445 			SDL_GetRelativeMouseState(&mx, &my);
446 		mouse_buttonstate = 0;
447 		bstate = SDL_GetMouseState(NULL, NULL);
448 		if (SDL_BUTTON(1) & bstate)
449 			mouse_buttonstate |= (1 << 0);
450 		if (SDL_BUTTON(3) & bstate)	/* quake2 has the right button be mouse2 */
451 			mouse_buttonstate |= (1 << 1);
452 		if (SDL_BUTTON(2) & bstate)	/* quake2 has the middle button be mouse3 */
453 			mouse_buttonstate |= (1 << 2);
454 		if (SDL_BUTTON(6) & bstate)
455 			mouse_buttonstate |= (1 << 3);
456 		if (SDL_BUTTON(7) & bstate)
457 			mouse_buttonstate |= (1 << 4);
458 
459 
460 		if (old_windowed_mouse != _windowed_mouse->value) {
461 			old_windowed_mouse = _windowed_mouse->value;
462 
463 			if (!_windowed_mouse->value) {
464 				/* ungrab the pointer */
465 				SDL_WM_GrabInput(SDL_GRAB_OFF);
466 			} else {
467 				/* grab the pointer */
468 				SDL_WM_GrabInput(SDL_GRAB_ON);
469 			}
470 		}
471 		while (keyq_head != keyq_tail) {
472 			in_state->Key_Event_fp(keyq[keyq_tail].key, keyq[keyq_tail].down);
473 			keyq_tail = (keyq_tail + 1) & 63;
474 		}
475 	}
476 	KBD_Update_Flag = 0;
477 }
478 
KBD_Close(void)479 void KBD_Close(void)
480 {
481 	keyq_head = 0;
482 	keyq_tail = 0;
483 
484 	memset(keyq, 0, sizeof(keyq));
485 }
486 
RW_Sys_GetClipboardData(void)487 char *RW_Sys_GetClipboardData(void)
488 {
489 	Window		sowner;
490 	Atom		type, property;
491 	unsigned long	len, bytes_left, tmp;
492 	unsigned char  *data;
493 	int		format, result;
494 	char           *ret = NULL;
495 	SDL_SysWMinfo	info;
496 
497 	SDL_VERSION(&info.version);
498 
499 	if (SDL_GetWMInfo(&info)) {
500 		if (info.subsystem == SDL_SYSWM_X11) {
501 			Display *SDL_Display = info.info.x11.display;
502 			Window SDL_Window = info.info.x11.window;
503 
504 			/* Enable the special window hook events */
505 			SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
506 
507 			sowner = XGetSelectionOwner(SDL_Display, XA_PRIMARY);
508 			if ((sowner == None) || (sowner == SDL_Window)) {
509 				sowner = DefaultRootWindow(SDL_Display);
510 				property = XA_CUT_BUFFER0;
511 			}
512 			else {
513 				int selection_response = 0;
514 				SDL_Event event;
515 
516 				sowner = SDL_Window;
517 				property = XInternAtom(SDL_Display, "SDL_SELECTION", False);
518 				XConvertSelection(SDL_Display, XA_PRIMARY, XA_STRING,
519 						property, sowner, CurrentTime);
520 				while (!selection_response) {
521 					SDL_WaitEvent(&event);
522 					if (event.type == SDL_SYSWMEVENT) {
523 						XEvent xevent = event.syswm.msg->event.xevent;
524 
525 						if ((xevent.type == SelectionNotify) &&
526 						    (xevent.xselection.requestor == sowner))
527 							selection_response = 1;
528 					}
529 				}
530 			}
531 
532 			XFlush(SDL_Display);
533 
534 			XGetWindowProperty(SDL_Display, sowner, property,
535 				           0, 0, False, XA_STRING,
536 				           &type, &format, &len,
537 				           &bytes_left, &data);
538 
539 			if (bytes_left > 0) {
540 				result = XGetWindowProperty(SDL_Display, sowner, property,
541 				                            0, INT_MAX/4, False, XA_STRING,
542 							    &type, &format, &len,
543 							    &tmp, &data);
544 					if (result == Success) {
545 						ret = strdup((char *)data);
546 					}
547 					XFree(data);
548 			}
549 
550 			SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
551 		}
552 
553 	}
554 	return ret;
555 }
556 
557 /*
558 ** GLimp_Init
559 **
560 ** This routine is responsible for initializing the implementation
561 ** specific stuff in a software rendering subsystem.
562 */
SDL_Version(void)563 void SDL_Version(void)
564 {
565         const SDL_version *version;
566         version = SDL_Linked_Version();
567 
568         Com_Printf( "SDLGL linked against SDL version %d.%d.%d\n"
569                     "Using SDL library version %d.%d.%d\n",
570                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
571                     version->major, version->minor, version->patch );
572 }
573 
GLimp_Init(void * hinstance,void * wndproc)574 int GLimp_Init(void *hinstance, void *wndproc)
575 {
576 /*
577 	char	buffer[MAX_QPATH];
578 */
579 	if (SDL_WasInit(SDL_INIT_AUDIO | SDL_INIT_CDROM | SDL_INIT_VIDEO) == 0) {
580 		if (SDL_Init(SDL_INIT_VIDEO) < 0) {
581 			Sys_Error("SDL Init failed: %s\n", SDL_GetError());
582 			return false;
583 		}
584 	} else if (SDL_WasInit(SDL_INIT_VIDEO) == 0) {
585 		if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
586 			Sys_Error("SDL Init failed: %s\n", SDL_GetError());
587 			return false;
588 		}
589 	}
590 	SDL_Version();
591 /*
592 	if (SDL_VideoDriverName(buffer, sizeof(buffer)) != NULL)
593 		Com_Printf("Using SDL video driver: %s\n", buffer) ;
594 */
595 	return true;
596 }
597 
UpdateHardwareGamma(void)598 void UpdateHardwareGamma(void)
599 {
600 	float g = (1.3 - vid_gamma->value + 1);
601 	g = (g > 1 ? g : 1);
602 
603 	{
604 		float v, i_f;
605 		int i, o;
606 
607 		for (o = 0; o < 3; o++) {
608 			for(i = 0; i < 256; i++) {
609 				i_f = (float)i/255.0f;
610 				v = pow(i_f, vid_gamma->value);
611 				v += 0.0 * (1.0f - v);
612 
613 				if (v < 0.0f) v = 0.0f;
614 				else
615 				if (v > 1.0f) v = 1.0f;
616 				gamma_ramp[o][i] = (v * 65535.0f + 0.5f);
617 			}
618 		}
619 	}
620 	SDL_SetGamma(g, g, g);
621 }
622 
SetSDLGamma(void)623 void  SetSDLGamma(void)
624 {
625 	gl_state.hwgamma = true;
626 	vid_gamma->modified = true;
627 	Com_Printf( "Using hardware gamma\n");
628 }
629 
GLimp_InitGraphics(qboolean fullscreen)630 qboolean GLimp_InitGraphics(qboolean fullscreen)
631 {
632 	int	flags,
633 		red_bits,
634 		blue_bits,
635 		green_bits,
636 		depth_bits,
637 		color_bits,
638 		alpha_bits,
639 		stencil_bits,
640 		multisamples;
641 
642 	/* Just toggle fullscreen if that's all that has been changed */
643 	if (surface && (surface->w == vid.width) && (surface->h == vid.height)) {
644 		int		isfullscreen = (surface->flags & SDL_FULLSCREEN) ? 1 : 0;
645 
646 		if (fullscreen != isfullscreen)
647 			SDL_WM_ToggleFullScreen(surface);
648 
649 		isfullscreen = (surface->flags & SDL_FULLSCREEN) ? 1 : 0;
650 		if (fullscreen == isfullscreen)
651 			return true;
652 	}
653 
654 	srandom(getpid());
655 
656 	/* free resources in use */
657 	if (surface)
658 		SDL_FreeSurface(surface);
659 
660 	/* let the sound and input subsystems know about the new window */
661 	ri.Vid_NewWindow(vid.width, vid.height);
662 
663 	gl_state.hwgamma = false;
664 
665 	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
666 	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,1);
667 	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 1);
668 
669 	if (use_stencil) {
670 		SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
671 		SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
672 		SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
673 		SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
674 		SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
675 		SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 24);
676 		SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
677 		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
678 		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
679         }
680         else {
681 		SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 4);
682 		SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 4);
683 		SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 4);
684 		SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
685         }
686 
687 	flags = SDL_OPENGL;
688 	if (fullscreen)
689 		flags |= SDL_FULLSCREEN;
690 
691 	if ((surface = SDL_SetVideoMode(vid.width, vid.height, 0, flags)) == NULL) {
692 		Sys_Error("SDL SetVideoMode failed: %s\n", SDL_GetError());
693 		return false;
694 	}
695 
696 	Com_Printf("\n^3SDL-GL Status^r\n");
697 
698 	SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &red_bits);
699 	SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &blue_bits);
700 	SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &green_bits);
701 	SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &color_bits);
702 	SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth_bits);
703 	SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &alpha_bits);
704 	SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil_bits);
705 	SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &multisamples);
706 
707 	//Com_Printf("Color Red bits : %d\n", red_bits);
708 	//Com_Printf("Color Blue bits : %d\n", blue_bits);
709 	//Com_Printf("Color Green bits : %d\n", green_bits);
710 	Com_Printf("Color bits : %d\n", color_bits);
711 	Com_Printf("Depth bits : %d\n", depth_bits);
712 	Com_Printf("Alpha bits : %d\n", alpha_bits);
713 
714 	if (!SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil_bits)) {
715 
716 		if (stencil_bits >= 1 && use_stencil->value) {
717 			have_stencil = true;
718 			Com_Printf("Stencil bits : %d\n", stencil_bits);
719 		}
720 	}
721 
722 	Com_Printf("Double buffer enabled.\n");
723 
724 	if (!SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &multisamples)) {
725 
726 		if (multisamples >= 1) {
727 			Com_Printf("Multisample buffer enabled.\n", multisamples);
728 		}
729 	}
730 
731 	SDL_WM_SetCaption(Q2PVERSION, Q2PVERSION);
732 
733 	SDL_ShowCursor(0);
734 
735 	SetSDLGamma();
736 
737 	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
738 	SDL_EnableUNICODE(1);
739 
740 	SDL_active = true;
741 
742 	return true;
743 }
744 
745 
746 /*
747 ** GLimp_SetMode
748 */
GLimp_SetMode(int * pwidth,int * pheight,int mode,qboolean fullscreen)749 int GLimp_SetMode(int *pwidth, int *pheight, int mode, qboolean fullscreen)
750 {
751 
752 	Com_Printf("Initializing OpenGL display\n");
753 
754 	if (fullscreen)
755 		Com_Printf( "Setting fullscreen mode [%d]:", mode);
756 	else
757 		Com_Printf( "Setting windowed mode [%d]:", mode);
758 
759 	if (!ri.Vid_GetModeInfo(pwidth, pheight, mode)) {
760 		Com_Printf( " Invalid mode\n");
761 		return rserr_invalid_mode;
762 	}
763 
764 	Com_Printf( " %d %d\n", *pwidth, *pheight);
765 
766 	if (!GLimp_InitGraphics(fullscreen)) {
767 		/* failed to set a valid mode in windowed mode */
768 		return rserr_invalid_mode;
769 	}
770 
771 	// Vertex arrays
772 	qglEnableClientState (GL_VERTEX_ARRAY);
773 	qglEnableClientState (GL_TEXTURE_COORD_ARRAY);
774 
775 	qglTexCoordPointer (2, GL_FLOAT, sizeof(tex_array[0]), tex_array[0]);
776 	qglVertexPointer (3, GL_FLOAT, sizeof(vert_array[0]), vert_array[0]);
777 	qglColorPointer (4, GL_FLOAT, sizeof(col_array[0]), col_array[0]);
778 
779 	return rserr_ok;
780 }
781 
782 /*
783 ** GLimp_Shutdown
784 **
785 ** System specific graphics subsystem shutdown routine.  Destroys
786 ** DIBs or DDRAW surfaces as appropriate.
787 */
GLimp_Shutdown(void)788 void GLimp_Shutdown(void)
789 {
790 	if (surface)
791 		SDL_FreeSurface(surface);
792 	surface = NULL;
793 
794 	if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_VIDEO)
795 		SDL_Quit();
796 	else
797 		SDL_QuitSubSystem(SDL_INIT_VIDEO);
798 
799 	SDL_active = false;
800 }
801 
802 
GLimp_GetProcAddress(const char * func)803 void *GLimp_GetProcAddress(const char *func) { return SDL_GL_GetProcAddress(func);}
GLimp_BeginFrame(float camera_separation)804 void GLimp_BeginFrame(float camera_separation) {}
GLimp_EndFrame(void)805 void GLimp_EndFrame(void) { SDL_GL_SwapBuffers();}
GLimp_AppActivate(qboolean active)806 void GLimp_AppActivate(qboolean active) {}
807 
808 
809