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