|
|
1.1 ! root 1: /* ! 2: Copyright (C) 1997-2001 Id Software, Inc. ! 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: */ ! 20: /* ! 21: ** GLW_IMP.C ! 22: ** ! 23: ** This file contains ALL Linux specific stuff having to do with the ! 24: ** OpenGL refresh. When a port is being made the following functions ! 25: ** must be implemented by the port: ! 26: ** ! 27: ** GLimp_EndFrame ! 28: ** GLimp_Init ! 29: ** GLimp_Shutdown ! 30: ** GLimp_SwitchFullscreen ! 31: ** ! 32: */ ! 33: ! 34: #include <termios.h> ! 35: #include <sys/ioctl.h> ! 36: #include <sys/stat.h> ! 37: #include <sys/vt.h> ! 38: #include <stdarg.h> ! 39: #include <stdio.h> ! 40: #include <signal.h> ! 41: ! 42: #include "../ref_gl/gl_local.h" ! 43: ! 44: #include "../client/keys.h" ! 45: ! 46: #include "../linux/rw_linux.h" ! 47: #include "../linux/glw_linux.h" ! 48: ! 49: #include <GL/glx.h> ! 50: ! 51: #include <X11/keysym.h> ! 52: #include <X11/cursorfont.h> ! 53: ! 54: #include <X11/extensions/xf86dga.h> ! 55: #include <X11/extensions/xf86vmode.h> ! 56: ! 57: glwstate_t glw_state; ! 58: ! 59: static Display *dpy = NULL; ! 60: static int scrnum; ! 61: static Window win; ! 62: static GLXContext ctx = NULL; ! 63: ! 64: #define KEY_MASK (KeyPressMask | KeyReleaseMask) ! 65: #define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \ ! 66: PointerMotionMask | ButtonMotionMask ) ! 67: #define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask ) ! 68: ! 69: /*****************************************************************************/ ! 70: /* MOUSE */ ! 71: /*****************************************************************************/ ! 72: ! 73: // this is inside the renderer shared lib, so these are called from vid_so ! 74: ! 75: static qboolean mouse_avail; ! 76: static int mx, my; ! 77: static int old_mouse_x, old_mouse_y; ! 78: ! 79: static int win_x, win_y; ! 80: ! 81: static cvar_t *m_filter; ! 82: static cvar_t *in_mouse; ! 83: static cvar_t *in_dgamouse; ! 84: ! 85: static cvar_t *r_fakeFullscreen; ! 86: ! 87: static XF86VidModeModeInfo **vidmodes; ! 88: static int default_dotclock_vidmode; ! 89: static int num_vidmodes; ! 90: static qboolean vidmode_active = false; ! 91: ! 92: static qboolean mlooking; ! 93: ! 94: static qboolean mouse_active = false; ! 95: static qboolean dgamouse = false; ! 96: static qboolean vidmode_ext = false; ! 97: ! 98: // state struct passed in Init ! 99: static in_state_t *in_state; ! 100: ! 101: static cvar_t *sensitivity; ! 102: static cvar_t *lookstrafe; ! 103: static cvar_t *m_side; ! 104: static cvar_t *m_yaw; ! 105: static cvar_t *m_pitch; ! 106: static cvar_t *m_forward; ! 107: static cvar_t *freelook; ! 108: ! 109: static Cursor CreateNullCursor(Display *display, Window root) ! 110: { ! 111: Pixmap cursormask; ! 112: XGCValues xgc; ! 113: GC gc; ! 114: XColor dummycolour; ! 115: Cursor cursor; ! 116: ! 117: cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); ! 118: xgc.function = GXclear; ! 119: gc = XCreateGC(display, cursormask, GCFunction, &xgc); ! 120: XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); ! 121: dummycolour.pixel = 0; ! 122: dummycolour.red = 0; ! 123: dummycolour.flags = 04; ! 124: cursor = XCreatePixmapCursor(display, cursormask, cursormask, ! 125: &dummycolour,&dummycolour, 0,0); ! 126: XFreePixmap(display,cursormask); ! 127: XFreeGC(display,gc); ! 128: return cursor; ! 129: } ! 130: ! 131: static void install_grabs(void) ! 132: { ! 133: ! 134: // inviso cursor ! 135: XDefineCursor(dpy, win, CreateNullCursor(dpy, win)); ! 136: ! 137: XGrabPointer(dpy, win, ! 138: True, ! 139: 0, ! 140: GrabModeAsync, GrabModeAsync, ! 141: win, ! 142: None, ! 143: CurrentTime); ! 144: ! 145: if (in_dgamouse->value) { ! 146: int MajorVersion, MinorVersion; ! 147: ! 148: if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) { ! 149: // unable to query, probalby not supported ! 150: ri.Con_Printf( PRINT_ALL, "Failed to detect XF86DGA Mouse\n" ); ! 151: ri.Cvar_Set( "in_dgamouse", "0" ); ! 152: } else { ! 153: dgamouse = true; ! 154: XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse); ! 155: XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); ! 156: } ! 157: } else { ! 158: XWarpPointer(dpy, None, win, ! 159: 0, 0, 0, 0, ! 160: vid.width / 2, vid.height / 2); ! 161: } ! 162: ! 163: XGrabKeyboard(dpy, win, ! 164: False, ! 165: GrabModeAsync, GrabModeAsync, ! 166: CurrentTime); ! 167: ! 168: mouse_active = true; ! 169: ! 170: // XSync(dpy, True); ! 171: } ! 172: ! 173: static void uninstall_grabs(void) ! 174: { ! 175: if (!dpy || !win) ! 176: return; ! 177: ! 178: if (dgamouse) { ! 179: dgamouse = false; ! 180: XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0); ! 181: } ! 182: ! 183: XUngrabPointer(dpy, CurrentTime); ! 184: XUngrabKeyboard(dpy, CurrentTime); ! 185: ! 186: // inviso cursor ! 187: XUndefineCursor(dpy, win); ! 188: ! 189: mouse_active = false; ! 190: } ! 191: ! 192: static void Force_CenterView_f (void) ! 193: { ! 194: in_state->viewangles[PITCH] = 0; ! 195: } ! 196: ! 197: static void RW_IN_MLookDown (void) ! 198: { ! 199: mlooking = true; ! 200: } ! 201: ! 202: static void RW_IN_MLookUp (void) ! 203: { ! 204: mlooking = false; ! 205: in_state->IN_CenterView_fp (); ! 206: } ! 207: ! 208: void RW_IN_Init(in_state_t *in_state_p) ! 209: { ! 210: int mtype; ! 211: int i; ! 212: ! 213: in_state = in_state_p; ! 214: ! 215: // mouse variables ! 216: m_filter = ri.Cvar_Get ("m_filter", "0", 0); ! 217: in_mouse = ri.Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE); ! 218: in_dgamouse = ri.Cvar_Get ("in_dgamouse", "1", CVAR_ARCHIVE); ! 219: freelook = ri.Cvar_Get( "freelook", "0", 0 ); ! 220: lookstrafe = ri.Cvar_Get ("lookstrafe", "0", 0); ! 221: sensitivity = ri.Cvar_Get ("sensitivity", "3", 0); ! 222: m_pitch = ri.Cvar_Get ("m_pitch", "0.022", 0); ! 223: m_yaw = ri.Cvar_Get ("m_yaw", "0.022", 0); ! 224: m_forward = ri.Cvar_Get ("m_forward", "1", 0); ! 225: m_side = ri.Cvar_Get ("m_side", "0.8", 0); ! 226: ! 227: ri.Cmd_AddCommand ("+mlook", RW_IN_MLookDown); ! 228: ri.Cmd_AddCommand ("-mlook", RW_IN_MLookUp); ! 229: ! 230: ri.Cmd_AddCommand ("force_centerview", Force_CenterView_f); ! 231: ! 232: mx = my = 0.0; ! 233: mouse_avail = true; ! 234: } ! 235: ! 236: void RW_IN_Shutdown(void) ! 237: { ! 238: mouse_avail = false; ! 239: } ! 240: ! 241: /* ! 242: =========== ! 243: IN_Commands ! 244: =========== ! 245: */ ! 246: void RW_IN_Commands (void) ! 247: { ! 248: } ! 249: ! 250: /* ! 251: =========== ! 252: IN_Move ! 253: =========== ! 254: */ ! 255: void RW_IN_Move (usercmd_t *cmd) ! 256: { ! 257: if (!mouse_avail) ! 258: return; ! 259: ! 260: if (m_filter->value) ! 261: { ! 262: mx = (mx + old_mouse_x) * 0.5; ! 263: my = (my + old_mouse_y) * 0.5; ! 264: } ! 265: ! 266: old_mouse_x = mx; ! 267: old_mouse_y = my; ! 268: ! 269: mx *= sensitivity->value; ! 270: my *= sensitivity->value; ! 271: ! 272: // add mouse X/Y movement to cmd ! 273: if ( (*in_state->in_strafe_state & 1) || ! 274: (lookstrafe->value && mlooking )) ! 275: cmd->sidemove += m_side->value * mx; ! 276: else ! 277: in_state->viewangles[YAW] -= m_yaw->value * mx; ! 278: ! 279: if ( (mlooking || freelook->value) && ! 280: !(*in_state->in_strafe_state & 1)) ! 281: { ! 282: in_state->viewangles[PITCH] += m_pitch->value * my; ! 283: } ! 284: else ! 285: { ! 286: cmd->forwardmove -= m_forward->value * my; ! 287: } ! 288: ! 289: mx = my = 0; ! 290: } ! 291: ! 292: static void IN_DeactivateMouse( void ) ! 293: { ! 294: if (!mouse_avail || !dpy || !win) ! 295: return; ! 296: ! 297: if (mouse_active) { ! 298: uninstall_grabs(); ! 299: mouse_active = false; ! 300: } ! 301: } ! 302: ! 303: static void IN_ActivateMouse( void ) ! 304: { ! 305: if (!mouse_avail || !dpy || !win) ! 306: return; ! 307: ! 308: if (!mouse_active) { ! 309: mx = my = 0; // don't spazz ! 310: install_grabs(); ! 311: mouse_active = true; ! 312: } ! 313: } ! 314: ! 315: void RW_IN_Frame (void) ! 316: { ! 317: } ! 318: ! 319: void RW_IN_Activate(qboolean active) ! 320: { ! 321: if (active || vidmode_active) ! 322: IN_ActivateMouse(); ! 323: else ! 324: IN_DeactivateMouse (); ! 325: } ! 326: ! 327: /*****************************************************************************/ ! 328: /* KEYBOARD */ ! 329: /*****************************************************************************/ ! 330: ! 331: static int XLateKey(XKeyEvent *ev) ! 332: { ! 333: ! 334: int key; ! 335: char buf[64]; ! 336: KeySym keysym; ! 337: ! 338: key = 0; ! 339: ! 340: XLookupString(ev, buf, sizeof buf, &keysym, 0); ! 341: ! 342: switch(keysym) ! 343: { ! 344: case XK_KP_Page_Up: key = K_KP_PGUP; break; ! 345: case XK_Page_Up: key = K_PGUP; break; ! 346: ! 347: case XK_KP_Page_Down: key = K_KP_PGDN; break; ! 348: case XK_Page_Down: key = K_PGDN; break; ! 349: ! 350: case XK_KP_Home: key = K_KP_HOME; break; ! 351: case XK_Home: key = K_HOME; break; ! 352: ! 353: case XK_KP_End: key = K_KP_END; break; ! 354: case XK_End: key = K_END; break; ! 355: ! 356: case XK_KP_Left: key = K_KP_LEFTARROW; break; ! 357: case XK_Left: key = K_LEFTARROW; break; ! 358: ! 359: case XK_KP_Right: key = K_KP_RIGHTARROW; break; ! 360: case XK_Right: key = K_RIGHTARROW; break; ! 361: ! 362: case XK_KP_Down: key = K_KP_DOWNARROW; break; ! 363: case XK_Down: key = K_DOWNARROW; break; ! 364: ! 365: case XK_KP_Up: key = K_KP_UPARROW; break; ! 366: case XK_Up: key = K_UPARROW; break; ! 367: ! 368: case XK_Escape: key = K_ESCAPE; break; ! 369: ! 370: case XK_KP_Enter: key = K_KP_ENTER; break; ! 371: case XK_Return: key = K_ENTER; break; ! 372: ! 373: case XK_Tab: key = K_TAB; break; ! 374: ! 375: case XK_F1: key = K_F1; break; ! 376: ! 377: case XK_F2: key = K_F2; break; ! 378: ! 379: case XK_F3: key = K_F3; break; ! 380: ! 381: case XK_F4: key = K_F4; break; ! 382: ! 383: case XK_F5: key = K_F5; break; ! 384: ! 385: case XK_F6: key = K_F6; break; ! 386: ! 387: case XK_F7: key = K_F7; break; ! 388: ! 389: case XK_F8: key = K_F8; break; ! 390: ! 391: case XK_F9: key = K_F9; break; ! 392: ! 393: case XK_F10: key = K_F10; break; ! 394: ! 395: case XK_F11: key = K_F11; break; ! 396: ! 397: case XK_F12: key = K_F12; break; ! 398: ! 399: case XK_BackSpace: key = K_BACKSPACE; break; ! 400: ! 401: case XK_KP_Delete: key = K_KP_DEL; break; ! 402: case XK_Delete: key = K_DEL; break; ! 403: ! 404: case XK_Pause: key = K_PAUSE; break; ! 405: ! 406: case XK_Shift_L: ! 407: case XK_Shift_R: key = K_SHIFT; break; ! 408: ! 409: case XK_Execute: ! 410: case XK_Control_L: ! 411: case XK_Control_R: key = K_CTRL; break; ! 412: ! 413: case XK_Alt_L: ! 414: case XK_Meta_L: ! 415: case XK_Alt_R: ! 416: case XK_Meta_R: key = K_ALT; break; ! 417: ! 418: case XK_KP_Begin: key = K_KP_5; break; ! 419: ! 420: case XK_Insert:key = K_INS; break; ! 421: case XK_KP_Insert: key = K_KP_INS; break; ! 422: ! 423: case XK_KP_Multiply: key = '*'; break; ! 424: case XK_KP_Add: key = K_KP_PLUS; break; ! 425: case XK_KP_Subtract: key = K_KP_MINUS; break; ! 426: case XK_KP_Divide: key = K_KP_SLASH; break; ! 427: ! 428: #if 0 ! 429: case 0x021: key = '1';break;/* [!] */ ! 430: case 0x040: key = '2';break;/* [@] */ ! 431: case 0x023: key = '3';break;/* [#] */ ! 432: case 0x024: key = '4';break;/* [$] */ ! 433: case 0x025: key = '5';break;/* [%] */ ! 434: case 0x05e: key = '6';break;/* [^] */ ! 435: case 0x026: key = '7';break;/* [&] */ ! 436: case 0x02a: key = '8';break;/* [*] */ ! 437: case 0x028: key = '9';;break;/* [(] */ ! 438: case 0x029: key = '0';break;/* [)] */ ! 439: case 0x05f: key = '-';break;/* [_] */ ! 440: case 0x02b: key = '=';break;/* [+] */ ! 441: case 0x07c: key = '\'';break;/* [|] */ ! 442: case 0x07d: key = '[';break;/* [}] */ ! 443: case 0x07b: key = ']';break;/* [{] */ ! 444: case 0x022: key = '\'';break;/* ["] */ ! 445: case 0x03a: key = ';';break;/* [:] */ ! 446: case 0x03f: key = '/';break;/* [?] */ ! 447: case 0x03e: key = '.';break;/* [>] */ ! 448: case 0x03c: key = ',';break;/* [<] */ ! 449: #endif ! 450: ! 451: default: ! 452: key = *(unsigned char*)buf; ! 453: if (key >= 'A' && key <= 'Z') ! 454: key = key - 'A' + 'a'; ! 455: break; ! 456: } ! 457: ! 458: return key; ! 459: } ! 460: ! 461: ! 462: static void HandleEvents(void) ! 463: { ! 464: XEvent event; ! 465: int b; ! 466: qboolean dowarp = false; ! 467: int mwx = vid.width/2; ! 468: int mwy = vid.height/2; ! 469: ! 470: if (!dpy) ! 471: return; ! 472: ! 473: while (XPending(dpy)) { ! 474: ! 475: XNextEvent(dpy, &event); ! 476: ! 477: switch(event.type) { ! 478: case KeyPress: ! 479: case KeyRelease: ! 480: if (in_state && in_state->Key_Event_fp) ! 481: in_state->Key_Event_fp (XLateKey(&event.xkey), event.type == KeyPress); ! 482: break; ! 483: ! 484: case MotionNotify: ! 485: if (mouse_active) { ! 486: if (dgamouse) { ! 487: mx += (event.xmotion.x + win_x) * 2; ! 488: my += (event.xmotion.y + win_y) * 2; ! 489: } ! 490: else ! 491: { ! 492: mx += ((int)event.xmotion.x - mwx) * 2; ! 493: my += ((int)event.xmotion.y - mwy) * 2; ! 494: mwx = event.xmotion.x; ! 495: mwy = event.xmotion.y; ! 496: ! 497: if (mx || my) ! 498: dowarp = true; ! 499: } ! 500: } ! 501: break; ! 502: ! 503: ! 504: case ButtonPress: ! 505: b=-1; ! 506: if (event.xbutton.button == 1) ! 507: b = 0; ! 508: else if (event.xbutton.button == 2) ! 509: b = 2; ! 510: else if (event.xbutton.button == 3) ! 511: b = 1; ! 512: if (b>=0 && in_state && in_state->Key_Event_fp) ! 513: in_state->Key_Event_fp (K_MOUSE1 + b, true); ! 514: break; ! 515: ! 516: case ButtonRelease: ! 517: b=-1; ! 518: if (event.xbutton.button == 1) ! 519: b = 0; ! 520: else if (event.xbutton.button == 2) ! 521: b = 2; ! 522: else if (event.xbutton.button == 3) ! 523: b = 1; ! 524: if (b>=0 && in_state && in_state->Key_Event_fp) ! 525: in_state->Key_Event_fp (K_MOUSE1 + b, false); ! 526: break; ! 527: ! 528: case CreateNotify : ! 529: win_x = event.xcreatewindow.x; ! 530: win_y = event.xcreatewindow.y; ! 531: break; ! 532: ! 533: case ConfigureNotify : ! 534: win_x = event.xconfigure.x; ! 535: win_y = event.xconfigure.y; ! 536: break; ! 537: } ! 538: } ! 539: ! 540: if (dowarp) { ! 541: /* move the mouse to the window center again */ ! 542: XWarpPointer(dpy,None,win,0,0,0,0, vid.width/2,vid.height/2); ! 543: } ! 544: } ! 545: ! 546: Key_Event_fp_t Key_Event_fp; ! 547: ! 548: void KBD_Init(Key_Event_fp_t fp) ! 549: { ! 550: Key_Event_fp = fp; ! 551: } ! 552: ! 553: void KBD_Update(void) ! 554: { ! 555: // get events from x server ! 556: HandleEvents(); ! 557: } ! 558: ! 559: void KBD_Close(void) ! 560: { ! 561: } ! 562: ! 563: /*****************************************************************************/ ! 564: ! 565: static qboolean GLimp_SwitchFullscreen( int width, int height ); ! 566: qboolean GLimp_InitGL (void); ! 567: ! 568: static void signal_handler(int sig) ! 569: { ! 570: printf("Received signal %d, exiting...\n", sig); ! 571: GLimp_Shutdown(); ! 572: _exit(0); ! 573: } ! 574: ! 575: static void InitSig(void) ! 576: { ! 577: signal(SIGHUP, signal_handler); ! 578: signal(SIGQUIT, signal_handler); ! 579: signal(SIGILL, signal_handler); ! 580: signal(SIGTRAP, signal_handler); ! 581: signal(SIGIOT, signal_handler); ! 582: signal(SIGBUS, signal_handler); ! 583: signal(SIGFPE, signal_handler); ! 584: signal(SIGSEGV, signal_handler); ! 585: signal(SIGTERM, signal_handler); ! 586: } ! 587: ! 588: /* ! 589: ** GLimp_SetMode ! 590: */ ! 591: int GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen ) ! 592: { ! 593: int width, height; ! 594: int attrib[] = { ! 595: GLX_RGBA, ! 596: GLX_RED_SIZE, 1, ! 597: GLX_GREEN_SIZE, 1, ! 598: GLX_BLUE_SIZE, 1, ! 599: GLX_DOUBLEBUFFER, ! 600: GLX_DEPTH_SIZE, 1, ! 601: None ! 602: }; ! 603: Window root; ! 604: XVisualInfo *visinfo; ! 605: XSetWindowAttributes attr; ! 606: unsigned long mask; ! 607: int MajorVersion, MinorVersion; ! 608: int actualWidth, actualHeight; ! 609: int i; ! 610: ! 611: r_fakeFullscreen = ri.Cvar_Get( "r_fakeFullscreen", "0", CVAR_ARCHIVE); ! 612: ! 613: ri.Con_Printf( PRINT_ALL, "Initializing OpenGL display\n"); ! 614: ! 615: if (fullscreen) ! 616: ri.Con_Printf (PRINT_ALL, "...setting fullscreen mode %d:", mode ); ! 617: else ! 618: ri.Con_Printf (PRINT_ALL, "...setting mode %d:", mode ); ! 619: ! 620: if ( !ri.Vid_GetModeInfo( &width, &height, mode ) ) ! 621: { ! 622: ri.Con_Printf( PRINT_ALL, " invalid mode\n" ); ! 623: return rserr_invalid_mode; ! 624: } ! 625: ! 626: ri.Con_Printf( PRINT_ALL, " %d %d\n", width, height ); ! 627: ! 628: // destroy the existing window ! 629: GLimp_Shutdown (); ! 630: ! 631: // Mesa VooDoo hacks ! 632: if (fullscreen) ! 633: putenv("MESA_GLX_FX=fullscreen"); ! 634: else ! 635: putenv("MESA_GLX_FX=window"); ! 636: ! 637: if (!(dpy = XOpenDisplay(NULL))) { ! 638: fprintf(stderr, "Error couldn't open the X display\n"); ! 639: return rserr_invalid_mode; ! 640: } ! 641: ! 642: scrnum = DefaultScreen(dpy); ! 643: root = RootWindow(dpy, scrnum); ! 644: ! 645: // Get video mode list ! 646: MajorVersion = MinorVersion = 0; ! 647: if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { ! 648: vidmode_ext = false; ! 649: } else { ! 650: ri.Con_Printf(PRINT_ALL, "Using XFree86-VidModeExtension Version %d.%d\n", ! 651: MajorVersion, MinorVersion); ! 652: vidmode_ext = true; ! 653: } ! 654: ! 655: visinfo = qglXChooseVisual(dpy, scrnum, attrib); ! 656: if (!visinfo) { ! 657: fprintf(stderr, "Error couldn't get an RGB, Double-buffered, Depth visual\n"); ! 658: return rserr_invalid_mode; ! 659: } ! 660: ! 661: if (vidmode_ext) { ! 662: int best_fit, best_dist, dist, x, y; ! 663: ! 664: XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes); ! 665: ! 666: // Are we going fullscreen? If so, let's change video mode ! 667: if (fullscreen && !r_fakeFullscreen->value) { ! 668: best_dist = 9999999; ! 669: best_fit = -1; ! 670: ! 671: for (i = 0; i < num_vidmodes; i++) { ! 672: if (width > vidmodes[i]->hdisplay || ! 673: height > vidmodes[i]->vdisplay) ! 674: continue; ! 675: ! 676: x = width - vidmodes[i]->hdisplay; ! 677: y = height - vidmodes[i]->vdisplay; ! 678: dist = (x * x) + (y * y); ! 679: if (dist < best_dist) { ! 680: best_dist = dist; ! 681: best_fit = i; ! 682: } ! 683: } ! 684: ! 685: if (best_fit != -1) { ! 686: actualWidth = vidmodes[best_fit]->hdisplay; ! 687: actualHeight = vidmodes[best_fit]->vdisplay; ! 688: ! 689: // change to the mode ! 690: XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]); ! 691: vidmode_active = true; ! 692: ! 693: // Move the viewport to top left ! 694: XF86VidModeSetViewPort(dpy, scrnum, 0, 0); ! 695: } else ! 696: fullscreen = 0; ! 697: } ! 698: } ! 699: ! 700: /* window attributes */ ! 701: attr.background_pixel = 0; ! 702: attr.border_pixel = 0; ! 703: attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); ! 704: attr.event_mask = X_MASK; ! 705: if (vidmode_active) { ! 706: mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | ! 707: CWEventMask | CWOverrideRedirect; ! 708: attr.override_redirect = True; ! 709: attr.backing_store = NotUseful; ! 710: attr.save_under = False; ! 711: } else ! 712: mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; ! 713: ! 714: win = XCreateWindow(dpy, root, 0, 0, width, height, ! 715: 0, visinfo->depth, InputOutput, ! 716: visinfo->visual, mask, &attr); ! 717: XMapWindow(dpy, win); ! 718: ! 719: if (vidmode_active) { ! 720: XMoveWindow(dpy, win, 0, 0); ! 721: XRaiseWindow(dpy, win); ! 722: XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); ! 723: XFlush(dpy); ! 724: // Move the viewport to top left ! 725: XF86VidModeSetViewPort(dpy, scrnum, 0, 0); ! 726: } ! 727: ! 728: XFlush(dpy); ! 729: ! 730: ctx = qglXCreateContext(dpy, visinfo, NULL, True); ! 731: ! 732: qglXMakeCurrent(dpy, win, ctx); ! 733: ! 734: *pwidth = width; ! 735: *pheight = height; ! 736: ! 737: // let the sound and input subsystems know about the new window ! 738: ri.Vid_NewWindow (width, height); ! 739: ! 740: qglXMakeCurrent(dpy, win, ctx); ! 741: ! 742: return rserr_ok; ! 743: } ! 744: ! 745: /* ! 746: ** GLimp_Shutdown ! 747: ** ! 748: ** This routine does all OS specific shutdown procedures for the OpenGL ! 749: ** subsystem. Under OpenGL this means NULLing out the current DC and ! 750: ** HGLRC, deleting the rendering context, and releasing the DC acquired ! 751: ** for the window. The state structure is also nulled out. ! 752: ** ! 753: */ ! 754: void GLimp_Shutdown( void ) ! 755: { ! 756: uninstall_grabs(); ! 757: mouse_active = false; ! 758: dgamouse = false; ! 759: ! 760: if (dpy) { ! 761: if (ctx) ! 762: qglXDestroyContext(dpy, ctx); ! 763: if (win) ! 764: XDestroyWindow(dpy, win); ! 765: if (vidmode_active) ! 766: XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]); ! 767: XCloseDisplay(dpy); ! 768: } ! 769: ctx = NULL; ! 770: dpy = NULL; ! 771: win = 0; ! 772: ctx = NULL; ! 773: } ! 774: ! 775: /* ! 776: ** GLimp_Init ! 777: ** ! 778: ** This routine is responsible for initializing the OS specific portions ! 779: ** of OpenGL. ! 780: */ ! 781: int GLimp_Init( void *hinstance, void *wndproc ) ! 782: { ! 783: InitSig(); ! 784: ! 785: return true; ! 786: } ! 787: ! 788: /* ! 789: ** GLimp_BeginFrame ! 790: */ ! 791: void GLimp_BeginFrame( float camera_seperation ) ! 792: { ! 793: } ! 794: ! 795: /* ! 796: ** GLimp_EndFrame ! 797: ** ! 798: ** Responsible for doing a swapbuffers and possibly for other stuff ! 799: ** as yet to be determined. Probably better not to make this a GLimp ! 800: ** function and instead do a call to GLimp_SwapBuffers. ! 801: */ ! 802: void GLimp_EndFrame (void) ! 803: { ! 804: qglFlush(); ! 805: qglXSwapBuffers(dpy, win); ! 806: } ! 807: ! 808: /* ! 809: ** GLimp_AppActivate ! 810: */ ! 811: void GLimp_AppActivate( qboolean active ) ! 812: { ! 813: } ! 814: ! 815: void Fake_glColorTableEXT( GLenum target, GLenum internalformat, ! 816: GLsizei width, GLenum format, GLenum type, ! 817: const GLvoid *table ) ! 818: { ! 819: byte temptable[256][4]; ! 820: byte *intbl; ! 821: int i; ! 822: ! 823: for (intbl = (byte *)table, i = 0; i < 256; i++) { ! 824: temptable[i][2] = *intbl++; ! 825: temptable[i][1] = *intbl++; ! 826: temptable[i][0] = *intbl++; ! 827: temptable[i][3] = 255; ! 828: } ! 829: qgl3DfxSetPaletteEXT((GLuint *)temptable); ! 830: } ! 831: ! 832: ! 833: /*------------------------------------------------*/ ! 834: /* X11 Input Stuff ! 835: /*------------------------------------------------*/ ! 836:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.