|
|
1.1 root 1: /* 1.1.1.2 ! root 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: /* 1.1 root 21: ** RW_X11.C 22: ** 23: ** This file contains ALL Linux specific stuff having to do with the 24: ** software refresh. When a port is being made the following functions 25: ** must be implemented by the port: 26: ** 27: ** SWimp_EndFrame 28: ** SWimp_Init 29: ** SWimp_InitGraphics 30: ** SWimp_SetPalette 31: ** SWimp_Shutdown 32: ** SWimp_SwitchFullscreen 33: */ 34: 35: #include <ctype.h> 36: #include <sys/time.h> 37: #include <sys/types.h> 38: #include <unistd.h> 39: #include <signal.h> 40: #include <stdlib.h> 41: #include <stdio.h> 42: #include <string.h> 43: #include <sys/ipc.h> 44: #include <sys/shm.h> 45: 46: #include <X11/Xlib.h> 47: #include <X11/Xutil.h> 48: #include <X11/Xatom.h> 49: #include <X11/keysym.h> 50: #include <X11/extensions/XShm.h> 1.1.1.2 ! root 51: #include <X11/extensions/xf86dga.h> 1.1 root 52: 53: #include "../ref_soft/r_local.h" 54: #include "../client/keys.h" 55: #include "../linux/rw_linux.h" 56: 57: /*****************************************************************************/ 58: 59: static qboolean doShm; 1.1.1.2 ! root 60: static Display *dpy; 1.1 root 61: static Colormap x_cmap; 1.1.1.2 ! root 62: static Window win; 1.1 root 63: static GC x_gc; 64: static Visual *x_vis; 65: static XVisualInfo *x_visinfo; 1.1.1.2 ! root 66: static int win_x, win_y; 1.1 root 67: 1.1.1.2 ! root 68: #define KEY_MASK (KeyPressMask | KeyReleaseMask) ! 69: #define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \ ! 70: PointerMotionMask | ButtonMotionMask ) ! 71: #define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask | ExposureMask ) 1.1 root 72: 73: static int x_shmeventtype; 74: //static XShmSegmentInfo x_shminfo; 75: 76: static qboolean oktodraw = false; 1.1.1.2 ! root 77: static qboolean ignorefirst = false; ! 78: static qboolean exposureflag = false; 1.1 root 79: static qboolean X11_active = false; 80: 81: int XShmQueryExtension(Display *); 82: int XShmGetEventBase(Display *); 83: 84: int current_framebuffer; 85: static XImage *x_framebuffer[2] = { 0, 0 }; 86: static XShmSegmentInfo x_shminfo[2]; 87: 88: int config_notify=0; 89: int config_notify_width; 90: int config_notify_height; 91: 1.1.1.2 ! root 92: typedef unsigned short PIXEL16; ! 93: typedef unsigned long PIXEL24; ! 94: static PIXEL16 st2d_8to16table[256]; ! 95: static PIXEL24 st2d_8to24table[256]; ! 96: static int shiftmask_fl=0; ! 97: static long r_shift,g_shift,b_shift; ! 98: static unsigned long r_mask,g_mask,b_mask; ! 99: ! 100: void shiftmask_init(void) ! 101: { ! 102: unsigned int x; ! 103: r_mask=x_vis->red_mask; ! 104: g_mask=x_vis->green_mask; ! 105: b_mask=x_vis->blue_mask; ! 106: for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++; ! 107: for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++; ! 108: for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++; ! 109: shiftmask_fl=1; ! 110: } ! 111: ! 112: PIXEL16 xlib_rgb16(int r,int g,int b) ! 113: { ! 114: PIXEL16 p; ! 115: if(shiftmask_fl==0) shiftmask_init(); ! 116: p=0; ! 117: ! 118: if(r_shift>0) { ! 119: p=(r<<(r_shift))&r_mask; ! 120: } else if(r_shift<0) { ! 121: p=(r>>(-r_shift))&r_mask; ! 122: } else p|=(r&r_mask); ! 123: ! 124: if(g_shift>0) { ! 125: p|=(g<<(g_shift))&g_mask; ! 126: } else if(g_shift<0) { ! 127: p|=(g>>(-g_shift))&g_mask; ! 128: } else p|=(g&g_mask); ! 129: ! 130: if(b_shift>0) { ! 131: p|=(b<<(b_shift))&b_mask; ! 132: } else if(b_shift<0) { ! 133: p|=(b>>(-b_shift))&b_mask; ! 134: } else p|=(b&b_mask); ! 135: ! 136: return p; ! 137: } ! 138: ! 139: PIXEL24 xlib_rgb24(int r,int g,int b) ! 140: { ! 141: PIXEL24 p; ! 142: if(shiftmask_fl==0) shiftmask_init(); ! 143: p=0; ! 144: ! 145: if(r_shift>0) { ! 146: p=(r<<(r_shift))&r_mask; ! 147: } else if(r_shift<0) { ! 148: p=(r>>(-r_shift))&r_mask; ! 149: } else p|=(r&r_mask); ! 150: ! 151: if(g_shift>0) { ! 152: p|=(g<<(g_shift))&g_mask; ! 153: } else if(g_shift<0) { ! 154: p|=(g>>(-g_shift))&g_mask; ! 155: } else p|=(g&g_mask); ! 156: ! 157: if(b_shift>0) { ! 158: p|=(b<<(b_shift))&b_mask; ! 159: } else if(b_shift<0) { ! 160: p|=(b>>(-b_shift))&b_mask; ! 161: } else p|=(b&b_mask); ! 162: ! 163: return p; ! 164: } ! 165: ! 166: ! 167: void st2_fixup( XImage *framebuf, int x, int y, int width, int height) ! 168: { ! 169: int xi,yi; ! 170: unsigned char *src; ! 171: PIXEL16 *dest; ! 172: register int count, n; ! 173: ! 174: if( (x<0)||(y<0) )return; ! 175: ! 176: for (yi = y; yi < (y+height); yi++) { ! 177: src = &framebuf->data [yi * framebuf->bytes_per_line]; ! 178: ! 179: // Duff's Device ! 180: count = width; ! 181: n = (count + 7) / 8; ! 182: dest = ((PIXEL16 *)src) + x+width - 1; ! 183: src += x+width - 1; ! 184: ! 185: switch (count % 8) { ! 186: case 0: do { *dest-- = st2d_8to16table[*src--]; ! 187: case 7: *dest-- = st2d_8to16table[*src--]; ! 188: case 6: *dest-- = st2d_8to16table[*src--]; ! 189: case 5: *dest-- = st2d_8to16table[*src--]; ! 190: case 4: *dest-- = st2d_8to16table[*src--]; ! 191: case 3: *dest-- = st2d_8to16table[*src--]; ! 192: case 2: *dest-- = st2d_8to16table[*src--]; ! 193: case 1: *dest-- = st2d_8to16table[*src--]; ! 194: } while (--n > 0); ! 195: } ! 196: ! 197: // for(xi = (x+width-1); xi >= x; xi--) { ! 198: // dest[xi] = st2d_8to16table[src[xi]]; ! 199: // } ! 200: } ! 201: } ! 202: ! 203: void st3_fixup( XImage *framebuf, int x, int y, int width, int height) ! 204: { ! 205: int xi,yi; ! 206: unsigned char *src; ! 207: PIXEL24 *dest; ! 208: register int count, n; ! 209: ! 210: if( (x<0)||(y<0) )return; ! 211: ! 212: for (yi = y; yi < (y+height); yi++) { ! 213: src = &framebuf->data [yi * framebuf->bytes_per_line]; ! 214: ! 215: // Duff's Device ! 216: count = width; ! 217: n = (count + 7) / 8; ! 218: dest = ((PIXEL24 *)src) + x+width - 1; ! 219: src += x+width - 1; ! 220: ! 221: switch (count % 8) { ! 222: case 0: do { *dest-- = st2d_8to24table[*src--]; ! 223: case 7: *dest-- = st2d_8to24table[*src--]; ! 224: case 6: *dest-- = st2d_8to24table[*src--]; ! 225: case 5: *dest-- = st2d_8to24table[*src--]; ! 226: case 4: *dest-- = st2d_8to24table[*src--]; ! 227: case 3: *dest-- = st2d_8to24table[*src--]; ! 228: case 2: *dest-- = st2d_8to24table[*src--]; ! 229: case 1: *dest-- = st2d_8to24table[*src--]; ! 230: } while (--n > 0); ! 231: } ! 232: ! 233: // for(xi = (x+width-1); xi >= x; xi--) { ! 234: // dest[xi] = st2d_8to16table[src[xi]]; ! 235: // } ! 236: } ! 237: } ! 238: ! 239: 1.1 root 240: 241: // Console variables that we need to access from this module 242: 243: /*****************************************************************************/ 244: /* MOUSE */ 245: /*****************************************************************************/ 246: 247: // this is inside the renderer shared lib, so these are called from vid_so 248: 1.1.1.2 ! root 249: static qboolean mouse_avail; ! 250: static int mouse_buttonstate; ! 251: static int mouse_oldbuttonstate; ! 252: static int old_mouse_x, old_mouse_y; 1.1 root 253: static int mx, my; 254: 1.1.1.2 ! root 255: static qboolean mouse_active = false; ! 256: static qboolean dgamouse = false; ! 257: 1.1 root 258: static cvar_t *m_filter; 259: static cvar_t *in_mouse; 1.1.1.2 ! root 260: static cvar_t *in_dgamouse; ! 261: ! 262: static cvar_t *vid_xpos; // X coordinate of window position ! 263: static cvar_t *vid_ypos; // Y coordinate of window position 1.1 root 264: 265: static qboolean mlooking; 266: 267: // state struct passed in Init 268: static in_state_t *in_state; 269: 270: static cvar_t *sensitivity; 271: static cvar_t *lookstrafe; 272: static cvar_t *m_side; 273: static cvar_t *m_yaw; 274: static cvar_t *m_pitch; 275: static cvar_t *m_forward; 276: static cvar_t *freelook; 277: 278: static void Force_CenterView_f (void) 279: { 280: in_state->viewangles[PITCH] = 0; 281: } 282: 283: static void RW_IN_MLookDown (void) 284: { 285: mlooking = true; 286: } 287: 288: static void RW_IN_MLookUp (void) 289: { 290: mlooking = false; 291: in_state->IN_CenterView_fp (); 292: } 293: 294: void RW_IN_Init(in_state_t *in_state_p) 295: { 296: int mtype; 297: int i; 298: 299: in_state = in_state_p; 300: 301: // mouse variables 302: m_filter = ri.Cvar_Get ("m_filter", "0", 0); 1.1.1.2 ! root 303: in_mouse = ri.Cvar_Get ("in_mouse", "0", CVAR_ARCHIVE); ! 304: in_dgamouse = ri.Cvar_Get ("in_dgamouse", "1", CVAR_ARCHIVE); 1.1 root 305: freelook = ri.Cvar_Get( "freelook", "0", 0 ); 306: lookstrafe = ri.Cvar_Get ("lookstrafe", "0", 0); 307: sensitivity = ri.Cvar_Get ("sensitivity", "3", 0); 308: m_pitch = ri.Cvar_Get ("m_pitch", "0.022", 0); 309: m_yaw = ri.Cvar_Get ("m_yaw", "0.022", 0); 310: m_forward = ri.Cvar_Get ("m_forward", "1", 0); 311: m_side = ri.Cvar_Get ("m_side", "0.8", 0); 312: 313: ri.Cmd_AddCommand ("+mlook", RW_IN_MLookDown); 314: ri.Cmd_AddCommand ("-mlook", RW_IN_MLookUp); 315: 316: ri.Cmd_AddCommand ("force_centerview", Force_CenterView_f); 317: 318: mouse_avail = true; 319: } 320: 321: void RW_IN_Shutdown(void) 322: { 323: mouse_avail = false; 324: } 325: 326: /* 327: =========== 328: IN_Commands 329: =========== 330: */ 331: void RW_IN_Commands (void) 332: { 333: int i; 334: 335: if (!mouse_avail) 336: return; 337: 338: for (i=0 ; i<3 ; i++) { 339: if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) ) 340: in_state->Key_Event_fp (K_MOUSE1 + i, true); 341: 342: if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) ) 343: in_state->Key_Event_fp (K_MOUSE1 + i, false); 344: } 345: mouse_oldbuttonstate = mouse_buttonstate; 346: } 347: 348: /* 349: =========== 350: IN_Move 351: =========== 352: */ 353: void RW_IN_Move (usercmd_t *cmd) 354: { 355: if (!mouse_avail) 356: return; 357: 358: if (m_filter->value) 359: { 1.1.1.2 ! root 360: mx = (mx + old_mouse_x) * 0.5; ! 361: my = (my + old_mouse_y) * 0.5; 1.1 root 362: } 363: 364: old_mouse_x = mx; 365: old_mouse_y = my; 366: 1.1.1.2 ! root 367: mx *= sensitivity->value; ! 368: my *= sensitivity->value; 1.1 root 369: 370: // add mouse X/Y movement to cmd 371: if ( (*in_state->in_strafe_state & 1) || 372: (lookstrafe->value && mlooking )) 1.1.1.2 ! root 373: cmd->sidemove += m_side->value * mx; 1.1 root 374: else 1.1.1.2 ! root 375: in_state->viewangles[YAW] -= m_yaw->value * mx; 1.1 root 376: 377: if ( (mlooking || freelook->value) && 378: !(*in_state->in_strafe_state & 1)) 379: { 1.1.1.2 ! root 380: in_state->viewangles[PITCH] += m_pitch->value * my; 1.1 root 381: } 382: else 383: { 1.1.1.2 ! root 384: cmd->forwardmove -= m_forward->value * my; 1.1 root 385: } 386: mx = my = 0; 387: } 388: 389: // ======================================================================== 390: // makes a null cursor 391: // ======================================================================== 392: 393: static Cursor CreateNullCursor(Display *display, Window root) 394: { 395: Pixmap cursormask; 396: XGCValues xgc; 397: GC gc; 398: XColor dummycolour; 399: Cursor cursor; 400: 401: cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); 402: xgc.function = GXclear; 403: gc = XCreateGC(display, cursormask, GCFunction, &xgc); 404: XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); 405: dummycolour.pixel = 0; 406: dummycolour.red = 0; 407: dummycolour.flags = 04; 408: cursor = XCreatePixmapCursor(display, cursormask, cursormask, 409: &dummycolour,&dummycolour, 0,0); 410: XFreePixmap(display,cursormask); 411: XFreeGC(display,gc); 412: return cursor; 413: } 414: 1.1.1.2 ! root 415: static void install_grabs(void) ! 416: { ! 417: ! 418: // inviso cursor ! 419: XDefineCursor(dpy, win, CreateNullCursor(dpy, win)); ! 420: ! 421: XGrabPointer(dpy, win, ! 422: True, ! 423: 0, ! 424: GrabModeAsync, GrabModeAsync, ! 425: win, ! 426: None, ! 427: CurrentTime); ! 428: ! 429: if (in_dgamouse->value) { ! 430: int MajorVersion, MinorVersion; ! 431: ! 432: if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) { ! 433: // unable to query, probalby not supported ! 434: ri.Con_Printf( PRINT_ALL, "Failed to detect XF86DGA Mouse\n" ); ! 435: ri.Cvar_Set( "in_dgamouse", "0" ); ! 436: } else { ! 437: dgamouse = true; ! 438: XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse); ! 439: XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); ! 440: } ! 441: } else ! 442: XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); ! 443: ! 444: XGrabKeyboard(dpy, win, ! 445: False, ! 446: GrabModeAsync, GrabModeAsync, ! 447: CurrentTime); ! 448: ! 449: mouse_active = true; ! 450: ! 451: ignorefirst = true; ! 452: ! 453: // XSync(dpy, True); ! 454: } ! 455: ! 456: static void uninstall_grabs(void) ! 457: { ! 458: if (!dpy || !win) ! 459: return; ! 460: ! 461: if (dgamouse) { ! 462: dgamouse = false; ! 463: XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0); ! 464: } ! 465: ! 466: XUngrabPointer(dpy, CurrentTime); ! 467: XUngrabKeyboard(dpy, CurrentTime); ! 468: ! 469: // inviso cursor ! 470: XUndefineCursor(dpy, win); ! 471: ! 472: mouse_active = false; ! 473: } ! 474: ! 475: static void IN_DeactivateMouse( void ) ! 476: { ! 477: if (!mouse_avail || !dpy || !win) ! 478: return; ! 479: ! 480: if (mouse_active) { ! 481: uninstall_grabs(); ! 482: mouse_active = false; ! 483: } ! 484: } ! 485: ! 486: static void IN_ActivateMouse( void ) ! 487: { ! 488: if (!mouse_avail || !dpy || !win) ! 489: return; ! 490: ! 491: if (!mouse_active) { ! 492: mx = my = 0; // don't spazz ! 493: install_grabs(); ! 494: mouse_active = true; ! 495: } ! 496: } ! 497: ! 498: void RW_IN_Frame (void) ! 499: { ! 500: } ! 501: ! 502: void RW_IN_Activate(qboolean active) ! 503: { ! 504: if (active) ! 505: IN_ActivateMouse(); ! 506: else ! 507: IN_DeactivateMouse (); ! 508: } ! 509: ! 510: /*****************************************************************************/ ! 511: 1.1 root 512: void ResetFrameBuffer(void) 513: { 514: int mem; 515: int pwidth; 516: 517: if (x_framebuffer[0]) 518: { 519: free(x_framebuffer[0]->data); 520: free(x_framebuffer[0]); 521: } 522: 523: // alloc an extra line in case we want to wrap, and allocate the z-buffer 524: pwidth = x_visinfo->depth / 8; 525: if (pwidth == 3) pwidth = 4; 526: mem = ((vid.width*pwidth+7)&~7) * vid.height; 527: 1.1.1.2 ! root 528: x_framebuffer[0] = XCreateImage(dpy, 1.1 root 529: x_vis, 530: x_visinfo->depth, 531: ZPixmap, 532: 0, 533: malloc(mem), 534: vid.width, vid.height, 535: 32, 536: 0); 537: 538: if (!x_framebuffer[0]) 539: Sys_Error("VID: XCreateImage failed\n"); 540: 541: vid.buffer = (byte*) (x_framebuffer[0]); 542: } 543: 544: void ResetSharedFrameBuffers(void) 545: { 546: int size; 547: int key; 548: int minsize = getpagesize(); 549: int frm; 550: 551: for (frm=0 ; frm<2 ; frm++) 552: { 553: // free up old frame buffer memory 554: if (x_framebuffer[frm]) 555: { 1.1.1.2 ! root 556: XShmDetach(dpy, &x_shminfo[frm]); 1.1 root 557: free(x_framebuffer[frm]); 558: shmdt(x_shminfo[frm].shmaddr); 559: } 560: 561: // create the image 1.1.1.2 ! root 562: x_framebuffer[frm] = XShmCreateImage( dpy, 1.1 root 563: x_vis, 564: x_visinfo->depth, 565: ZPixmap, 566: 0, 567: &x_shminfo[frm], 568: vid.width, 569: vid.height ); 570: 571: // grab shared memory 572: 573: size = x_framebuffer[frm]->bytes_per_line 574: * x_framebuffer[frm]->height; 575: if (size < minsize) 576: Sys_Error("VID: Window must use at least %d bytes\n", minsize); 577: 578: key = random(); 579: x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777); 580: if (x_shminfo[frm].shmid==-1) 581: Sys_Error("VID: Could not get any shared memory\n"); 582: 583: // attach to the shared memory segment 584: x_shminfo[frm].shmaddr = 585: (void *) shmat(x_shminfo[frm].shmid, 0, 0); 586: 1.1.1.2 ! root 587: ri.Con_Printf(PRINT_DEVELOPER, "MITSHM shared memory (id=%d, addr=0x%lx)\n", ! 588: x_shminfo[frm].shmid, (long) x_shminfo[frm].shmaddr); 1.1 root 589: 590: x_framebuffer[frm]->data = x_shminfo[frm].shmaddr; 591: 592: // get the X server to attach to it 593: 1.1.1.2 ! root 594: if (!XShmAttach(dpy, &x_shminfo[frm])) 1.1 root 595: Sys_Error("VID: XShmAttach() failed\n"); 1.1.1.2 ! root 596: XSync(dpy, 0); 1.1 root 597: shmctl(x_shminfo[frm].shmid, IPC_RMID, 0); 598: } 599: 600: } 601: 602: // ======================================================================== 603: // Tragic death handler 604: // ======================================================================== 605: 606: void TragicDeath(int signal_num) 607: { 1.1.1.2 ! root 608: // XAutoRepeatOn(dpy); ! 609: XCloseDisplay(dpy); 1.1 root 610: Sys_Error("This death brought to you by the number %d\n", signal_num); 611: } 612: 613: int XLateKey(XKeyEvent *ev) 614: { 615: 616: int key; 617: char buf[64]; 618: KeySym keysym; 619: 620: key = 0; 621: 622: XLookupString(ev, buf, sizeof buf, &keysym, 0); 623: 624: switch(keysym) 625: { 626: case XK_KP_Page_Up: key = K_KP_PGUP; break; 627: case XK_Page_Up: key = K_PGUP; break; 628: 629: case XK_KP_Page_Down: key = K_KP_PGDN; break; 630: case XK_Page_Down: key = K_PGDN; break; 631: 632: case XK_KP_Home: key = K_KP_HOME; break; 633: case XK_Home: key = K_HOME; break; 634: 635: case XK_KP_End: key = K_KP_END; break; 636: case XK_End: key = K_END; break; 637: 638: case XK_KP_Left: key = K_KP_LEFTARROW; break; 639: case XK_Left: key = K_LEFTARROW; break; 640: 641: case XK_KP_Right: key = K_KP_RIGHTARROW; break; 642: case XK_Right: key = K_RIGHTARROW; break; 643: 644: case XK_KP_Down: key = K_KP_DOWNARROW; break; 645: case XK_Down: key = K_DOWNARROW; break; 646: 647: case XK_KP_Up: key = K_KP_UPARROW; break; 648: case XK_Up: key = K_UPARROW; break; 649: 650: case XK_Escape: key = K_ESCAPE; break; 651: 652: case XK_KP_Enter: key = K_KP_ENTER; break; 653: case XK_Return: key = K_ENTER; break; 654: 655: case XK_Tab: key = K_TAB; break; 656: 657: case XK_F1: key = K_F1; break; 658: 659: case XK_F2: key = K_F2; break; 660: 661: case XK_F3: key = K_F3; break; 662: 663: case XK_F4: key = K_F4; break; 664: 665: case XK_F5: key = K_F5; break; 666: 667: case XK_F6: key = K_F6; break; 668: 669: case XK_F7: key = K_F7; break; 670: 671: case XK_F8: key = K_F8; break; 672: 673: case XK_F9: key = K_F9; break; 674: 675: case XK_F10: key = K_F10; break; 676: 677: case XK_F11: key = K_F11; break; 678: 679: case XK_F12: key = K_F12; break; 680: 681: case XK_BackSpace: key = K_BACKSPACE; break; 682: 683: case XK_KP_Delete: key = K_KP_DEL; break; 684: case XK_Delete: key = K_DEL; break; 685: 686: case XK_Pause: key = K_PAUSE; break; 687: 688: case XK_Shift_L: 689: case XK_Shift_R: key = K_SHIFT; break; 690: 691: case XK_Execute: 692: case XK_Control_L: 693: case XK_Control_R: key = K_CTRL; break; 694: 695: case XK_Alt_L: 696: case XK_Meta_L: 697: case XK_Alt_R: 698: case XK_Meta_R: key = K_ALT; break; 699: 700: case XK_KP_Begin: key = K_KP_5; break; 701: 702: case XK_Insert:key = K_INS; break; 703: case XK_KP_Insert: key = K_KP_INS; break; 704: 705: case XK_KP_Multiply: key = '*'; break; 706: case XK_KP_Add: key = K_KP_PLUS; break; 707: case XK_KP_Subtract: key = K_KP_MINUS; break; 708: case XK_KP_Divide: key = K_KP_SLASH; break; 709: 710: #if 0 711: case 0x021: key = '1';break;/* [!] */ 712: case 0x040: key = '2';break;/* [@] */ 713: case 0x023: key = '3';break;/* [#] */ 714: case 0x024: key = '4';break;/* [$] */ 715: case 0x025: key = '5';break;/* [%] */ 716: case 0x05e: key = '6';break;/* [^] */ 717: case 0x026: key = '7';break;/* [&] */ 718: case 0x02a: key = '8';break;/* [*] */ 719: case 0x028: key = '9';;break;/* [(] */ 720: case 0x029: key = '0';break;/* [)] */ 721: case 0x05f: key = '-';break;/* [_] */ 722: case 0x02b: key = '=';break;/* [+] */ 723: case 0x07c: key = '\'';break;/* [|] */ 724: case 0x07d: key = '[';break;/* [}] */ 725: case 0x07b: key = ']';break;/* [{] */ 726: case 0x022: key = '\'';break;/* ["] */ 727: case 0x03a: key = ';';break;/* [:] */ 728: case 0x03f: key = '/';break;/* [?] */ 729: case 0x03e: key = '.';break;/* [>] */ 730: case 0x03c: key = ',';break;/* [<] */ 731: #endif 732: 733: default: 734: key = *(unsigned char*)buf; 735: if (key >= 'A' && key <= 'Z') 736: key = key - 'A' + 'a'; 737: break; 738: } 739: 740: return key; 741: } 742: 1.1.1.2 ! root 743: void HandleEvents(void) 1.1 root 744: { 1.1.1.2 ! root 745: XEvent event; 1.1 root 746: int b; 1.1.1.2 ! root 747: qboolean dowarp = false; ! 748: int mwx = vid.width/2; ! 749: int mwy = vid.height/2; 1.1 root 750: 1.1.1.2 ! root 751: while (XPending(dpy)) { 1.1 root 752: 1.1.1.2 ! root 753: XNextEvent(dpy, &event); 1.1 root 754: 1.1.1.2 ! root 755: switch(event.type) { ! 756: case KeyPress: ! 757: case KeyRelease: ! 758: if (in_state && in_state->Key_Event_fp) ! 759: in_state->Key_Event_fp (XLateKey(&event.xkey), event.type == KeyPress); ! 760: break; ! 761: ! 762: case MotionNotify: ! 763: if (ignorefirst) { ! 764: ignorefirst = false; ! 765: break; ! 766: } ! 767: ! 768: if (mouse_active) { ! 769: if (dgamouse) { ! 770: mx += (event.xmotion.x + win_x) * 2; ! 771: my += (event.xmotion.y + win_y) * 2; ! 772: } ! 773: else ! 774: { ! 775: mx += ((int)event.xmotion.x - mwx) * 2; ! 776: my += ((int)event.xmotion.y - mwy) * 2; ! 777: mwx = event.xmotion.x; ! 778: mwy = event.xmotion.y; ! 779: ! 780: if (mx || my) ! 781: dowarp = true; ! 782: } ! 783: } ! 784: break; ! 785: ! 786: ! 787: break; ! 788: ! 789: case ButtonPress: ! 790: b=-1; ! 791: if (event.xbutton.button == 1) ! 792: b = 0; ! 793: else if (event.xbutton.button == 2) ! 794: b = 2; ! 795: else if (event.xbutton.button == 3) ! 796: b = 1; ! 797: if (b>=0) ! 798: mouse_buttonstate |= 1<<b; ! 799: break; ! 800: ! 801: case ButtonRelease: ! 802: b=-1; ! 803: if (event.xbutton.button == 1) ! 804: b = 0; ! 805: else if (event.xbutton.button == 2) ! 806: b = 2; ! 807: else if (event.xbutton.button == 3) ! 808: b = 1; ! 809: if (b>=0) ! 810: mouse_buttonstate &= ~(1<<b); ! 811: break; ! 812: ! 813: case CreateNotify : ! 814: ri.Cvar_Set( "vid_xpos", va("%d", event.xcreatewindow.x)); ! 815: ri.Cvar_Set( "vid_ypos", va("%d", event.xcreatewindow.y)); ! 816: vid_xpos->modified = false; ! 817: vid_ypos->modified = false; ! 818: win_x = event.xcreatewindow.x; ! 819: win_y = event.xcreatewindow.y; ! 820: break; ! 821: ! 822: case ConfigureNotify : ! 823: ri.Cvar_Set( "vid_xpos", va("%d", event.xcreatewindow.x)); ! 824: ri.Cvar_Set( "vid_ypos", va("%d", event.xcreatewindow.y)); ! 825: vid_xpos->modified = false; ! 826: vid_ypos->modified = false; ! 827: win_x = event.xconfigure.x; ! 828: win_y = event.xconfigure.y; ! 829: config_notify_width = event.xconfigure.width; ! 830: config_notify_height = event.xconfigure.height; ! 831: if (config_notify_width != vid.width || ! 832: config_notify_height != vid.height) ! 833: XMoveResizeWindow(dpy, win, win_x, win_y, vid.width, vid.height); ! 834: config_notify = 1; ! 835: break; ! 836: ! 837: default: ! 838: if (doShm && event.type == x_shmeventtype) ! 839: oktodraw = true; ! 840: if (event.type == Expose && !event.xexpose.count) ! 841: exposureflag = true; 1.1 root 842: } 843: } 1.1.1.2 ! root 844: ! 845: if (dowarp) { ! 846: /* move the mouse to the window center again */ ! 847: XWarpPointer(dpy,None,win,0,0,0,0, vid.width/2,vid.height/2); ! 848: } 1.1 root 849: } 850: 851: /*****************************************************************************/ 852: 853: /* 854: ** SWimp_Init 855: ** 856: ** This routine is responsible for initializing the implementation 857: ** specific stuff in a software rendering subsystem. 858: */ 859: int SWimp_Init( void *hInstance, void *wndProc ) 860: { 1.1.1.2 ! root 861: ! 862: vid_xpos = ri.Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE); ! 863: vid_ypos = ri.Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE); ! 864: 1.1 root 865: // open the display 1.1.1.2 ! root 866: dpy = XOpenDisplay(0); ! 867: if (!dpy) 1.1 root 868: { 869: if (getenv("DISPLAY")) 870: Sys_Error("VID: Could not open display [%s]\n", 871: getenv("DISPLAY")); 872: else 873: Sys_Error("VID: Could not open local display\n"); 874: } 875: 876: // catch signals so i can turn on auto-repeat 877: 878: { 879: struct sigaction sa; 880: sigaction(SIGINT, 0, &sa); 881: sa.sa_handler = TragicDeath; 882: sigaction(SIGINT, &sa, 0); 883: sigaction(SIGTERM, &sa, 0); 884: } 885: 886: return true; 887: } 888: 889: /* 890: ** SWimp_InitGraphics 891: ** 892: ** This initializes the software refresh's implementation specific 893: ** graphics subsystem. In the case of Windows it creates DIB or 894: ** DDRAW surfaces. 895: ** 896: ** The necessary width and height parameters are grabbed from 897: ** vid.width and vid.height. 898: */ 899: static qboolean SWimp_InitGraphics( qboolean fullscreen ) 900: { 901: int pnum, i; 902: XVisualInfo template; 903: int num_visuals; 904: int template_mask; 1.1.1.2 ! root 905: Window root; 1.1 root 906: 907: srandom(getpid()); 908: 909: // free resources in use 910: SWimp_Shutdown (); 911: 912: // let the sound and input subsystems know about the new window 913: ri.Vid_NewWindow (vid.width, vid.height); 914: 1.1.1.2 ! root 915: // XAutoRepeatOff(dpy); 1.1 root 916: 917: // for debugging only 1.1.1.2 ! root 918: XSynchronize(dpy, True); 1.1 root 919: 920: // check for command-line window size 921: template_mask = 0; 922: 923: #if 0 924: // specify a visual id 925: if ((pnum=COM_CheckParm("-visualid"))) 926: { 927: if (pnum >= com_argc-1) 928: Sys_Error("VID: -visualid <id#>\n"); 929: template.visualid = Q_atoi(com_argv[pnum+1]); 930: template_mask = VisualIDMask; 931: } 932: 933: // If not specified, use default visual 934: else 935: #endif 936: { 937: int screen; 1.1.1.2 ! root 938: screen = XDefaultScreen(dpy); 1.1 root 939: template.visualid = 1.1.1.2 ! root 940: XVisualIDFromVisual(XDefaultVisual(dpy, screen)); 1.1 root 941: template_mask = VisualIDMask; 942: } 943: 944: // pick a visual- warn if more than one was available 1.1.1.2 ! root 945: x_visinfo = XGetVisualInfo(dpy, template_mask, &template, &num_visuals); 1.1 root 946: if (num_visuals > 1) 947: { 948: printf("Found more than one visual id at depth %d:\n", template.depth); 949: for (i=0 ; i<num_visuals ; i++) 950: printf(" -visualid %d\n", (int)(x_visinfo[i].visualid)); 951: } 952: else if (num_visuals == 0) 953: { 954: if (template_mask == VisualIDMask) 955: Sys_Error("VID: Bad visual id %d\n", template.visualid); 956: else 957: Sys_Error("VID: No visuals at depth %d\n", template.depth); 958: } 959: 960: #if 0 1.1.1.2 ! root 961: printf("Using visualid %d:\n", (int)(x_visinfo->visualid)); ! 962: printf(" screen %d\n", x_visinfo->screen); ! 963: printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask)); ! 964: printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask)); ! 965: printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask)); ! 966: printf(" colormap_size %d\n", x_visinfo->colormap_size); ! 967: printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb); 1.1 root 968: #endif 969: 970: x_vis = x_visinfo->visual; 1.1.1.2 ! root 971: root = XRootWindow(dpy, x_visinfo->screen); 1.1 root 972: 973: // setup attributes for main window 974: { 975: int attribmask = CWEventMask | CWColormap | CWBorderPixel; 976: XSetWindowAttributes attribs; 977: Colormap tmpcmap; 978: 1.1.1.2 ! root 979: tmpcmap = XCreateColormap(dpy, root, x_vis, AllocNone); 1.1 root 980: 1.1.1.2 ! root 981: attribs.event_mask = X_MASK; 1.1 root 982: attribs.border_pixel = 0; 983: attribs.colormap = tmpcmap; 984: 985: // create the main window 1.1.1.2 ! root 986: win = XCreateWindow(dpy, root, (int)vid_xpos->value, (int)vid_ypos->value, ! 987: vid.width, vid.height, 0, x_visinfo->depth, InputOutput, x_vis, ! 988: attribmask, &attribs ); ! 989: XStoreName(dpy, win, "Quake II"); 1.1 root 990: 991: if (x_visinfo->class != TrueColor) 1.1.1.2 ! root 992: XFreeColormap(dpy, tmpcmap); 1.1 root 993: } 994: 995: if (x_visinfo->depth == 8) 996: { 997: // create and upload the palette 998: if (x_visinfo->class == PseudoColor) 999: { 1.1.1.2 ! root 1000: x_cmap = XCreateColormap(dpy, win, x_vis, AllocAll); ! 1001: XSetWindowColormap(dpy, win, x_cmap); 1.1 root 1002: } 1003: 1004: } 1005: 1006: // create the GC 1007: { 1008: XGCValues xgcvalues; 1009: int valuemask = GCGraphicsExposures; 1010: xgcvalues.graphics_exposures = False; 1.1.1.2 ! root 1011: x_gc = XCreateGC(dpy, win, valuemask, &xgcvalues ); 1.1 root 1012: } 1013: 1.1.1.2 ! root 1014: XMapWindow(dpy, win); ! 1015: XMoveWindow(dpy, win, (int)vid_xpos->value, (int)vid_ypos->value); 1.1 root 1016: 1017: // wait for first exposure event 1018: { 1019: XEvent event; 1.1.1.2 ! root 1020: exposureflag = false; 1.1 root 1021: do 1022: { 1.1.1.2 ! root 1023: HandleEvents(); ! 1024: } while (!exposureflag); 1.1 root 1025: } 1026: // now safe to draw 1027: 1028: // even if MITSHM is available, make sure it's a local connection 1.1.1.2 ! root 1029: if (XShmQueryExtension(dpy)) 1.1 root 1030: { 1031: char *displayname; 1032: doShm = true; 1033: displayname = (char *) getenv("DISPLAY"); 1034: if (displayname) 1035: { 1036: char *d = displayname; 1037: while (*d && (*d != ':')) d++; 1038: if (*d) *d = 0; 1039: if (!(!strcasecmp(displayname, "unix") || !*displayname)) 1040: doShm = false; 1041: } 1042: } 1043: 1044: if (doShm) 1045: { 1.1.1.2 ! root 1046: x_shmeventtype = XShmGetEventBase(dpy) + ShmCompletion; 1.1 root 1047: ResetSharedFrameBuffers(); 1048: } 1049: else 1050: ResetFrameBuffer(); 1051: 1052: current_framebuffer = 0; 1053: vid.rowbytes = x_framebuffer[0]->bytes_per_line; 1054: vid.buffer = x_framebuffer[0]->data; 1055: 1.1.1.2 ! root 1056: // XSynchronize(dpy, False); 1.1 root 1057: 1058: X11_active = true; 1059: 1060: return true; 1061: } 1062: 1063: /* 1064: ** SWimp_EndFrame 1065: ** 1066: ** This does an implementation specific copy from the backbuffer to the 1067: ** front buffer. In the Win32 case it uses BitBlt or BltFast depending 1068: ** on whether we're using DIB sections/GDI or DDRAW. 1069: */ 1070: void SWimp_EndFrame (void) 1071: { 1072: // if the window changes dimension, skip this frame 1073: #if 0 1074: if (config_notify) 1075: { 1076: fprintf(stderr, "config notify\n"); 1077: config_notify = 0; 1078: vid.width = config_notify_width & ~7; 1079: vid.height = config_notify_height; 1080: if (doShm) 1081: ResetSharedFrameBuffers(); 1082: else 1083: ResetFrameBuffer(); 1084: vid.rowbytes = x_framebuffer[0]->bytes_per_line; 1085: vid.buffer = x_framebuffer[current_framebuffer]->data; 1086: vid.recalc_refdef = 1; // force a surface cache flush 1087: Con_CheckResize(); 1088: Con_Clear_f(); 1089: return; 1090: } 1091: #endif 1092: 1093: if (doShm) 1094: { 1.1.1.2 ! root 1095: if (x_visinfo->depth == 16) ! 1096: st2_fixup( x_framebuffer[current_framebuffer], 0, 0, vid.width, vid.height); ! 1097: else if (x_visinfo->depth == 24) ! 1098: st3_fixup( x_framebuffer[current_framebuffer], 0, 0, vid.width, vid.height); ! 1099: if (!XShmPutImage(dpy, win, x_gc, ! 1100: x_framebuffer[current_framebuffer], 0, 0, 0, 0, vid.width, vid.height, True)) ! 1101: Sys_Error("VID_Update: XShmPutImage failed\n"); 1.1 root 1102: oktodraw = false; 1103: while (!oktodraw) 1.1.1.2 ! root 1104: HandleEvents(); 1.1 root 1105: current_framebuffer = !current_framebuffer; 1106: vid.buffer = x_framebuffer[current_framebuffer]->data; 1.1.1.2 ! root 1107: XSync(dpy, False); 1.1 root 1108: } 1109: else 1110: { 1.1.1.2 ! root 1111: if (x_visinfo->depth == 16) ! 1112: st2_fixup( x_framebuffer[current_framebuffer], 0, 0, vid.width, vid.height); ! 1113: else if (x_visinfo->depth == 24) ! 1114: st3_fixup( x_framebuffer[current_framebuffer], 0, 0, vid.width, vid.height); ! 1115: XPutImage(dpy, win, x_gc, x_framebuffer[0], 0, 0, 0, 0, vid.width, vid.height); ! 1116: XSync(dpy, False); 1.1 root 1117: } 1118: } 1119: 1120: /* 1121: ** SWimp_SetMode 1122: */ 1123: rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen ) 1124: { 1125: rserr_t retval = rserr_ok; 1126: 1127: ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode ); 1128: 1129: if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) ) 1130: { 1131: ri.Con_Printf( PRINT_ALL, " invalid mode\n" ); 1132: return rserr_invalid_mode; 1133: } 1134: 1135: ri.Con_Printf( PRINT_ALL, " %d %d\n", *pwidth, *pheight); 1136: 1137: if ( !SWimp_InitGraphics( false ) ) { 1138: // failed to set a valid mode in windowed mode 1139: return rserr_invalid_mode; 1140: } 1141: 1142: R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table ); 1143: 1144: return retval; 1145: } 1146: 1147: /* 1148: ** SWimp_SetPalette 1149: ** 1150: ** System specific palette setting routine. A NULL palette means 1151: ** to use the existing palette. The palette is expected to be in 1152: ** a padded 4-byte xRGB format. 1153: */ 1154: void SWimp_SetPalette( const unsigned char *palette ) 1155: { 1156: int i; 1157: XColor colors[256]; 1158: 1159: if (!X11_active) 1160: return; 1161: 1162: if ( !palette ) 1163: palette = ( const unsigned char * ) sw_state.currentpalette; 1164: 1.1.1.2 ! root 1165: for(i=0;i<256;i++) { ! 1166: st2d_8to16table[i]= xlib_rgb16(palette[i*4], palette[i*4+1],palette[i*4+2]); ! 1167: st2d_8to24table[i]= xlib_rgb24(palette[i*4], palette[i*4+1],palette[i*4+2]); ! 1168: } 1.1 root 1169: 1170: if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8) 1171: { 1172: for (i=0 ; i<256 ; i++) 1173: { 1174: colors[i].pixel = i; 1175: colors[i].flags = DoRed|DoGreen|DoBlue; 1176: colors[i].red = palette[i*4] * 257; 1177: colors[i].green = palette[i*4+1] * 257; 1178: colors[i].blue = palette[i*4+2] * 257; 1179: } 1.1.1.2 ! root 1180: XStoreColors(dpy, x_cmap, colors, 256); 1.1 root 1181: } 1182: } 1183: 1184: /* 1185: ** SWimp_Shutdown 1186: ** 1187: ** System specific graphics subsystem shutdown routine. Destroys 1188: ** DIBs or DDRAW surfaces as appropriate. 1189: */ 1190: void SWimp_Shutdown( void ) 1191: { 1192: int i; 1193: 1194: if (!X11_active) 1195: return; 1196: 1197: if (doShm) { 1198: for (i = 0; i < 2; i++) 1199: if (x_framebuffer[i]) { 1.1.1.2 ! root 1200: XShmDetach(dpy, &x_shminfo[i]); 1.1 root 1201: free(x_framebuffer[i]); 1202: shmdt(x_shminfo[i].shmaddr); 1203: x_framebuffer[i] = NULL; 1204: } 1205: } else if (x_framebuffer[0]) { 1206: free(x_framebuffer[0]->data); 1207: free(x_framebuffer[0]); 1208: x_framebuffer[0] = NULL; 1209: } 1210: 1.1.1.2 ! root 1211: XDestroyWindow( dpy, win ); 1.1 root 1212: 1.1.1.2 ! root 1213: // XAutoRepeatOn(dpy); ! 1214: // XCloseDisplay(dpy); 1.1 root 1215: 1216: X11_active = false; 1217: } 1218: 1219: /* 1220: ** SWimp_AppActivate 1221: */ 1222: void SWimp_AppActivate( qboolean active ) 1223: { 1224: } 1225: 1226: //=============================================================================== 1227: 1228: /* 1229: ================ 1230: Sys_MakeCodeWriteable 1231: ================ 1232: */ 1233: void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) 1234: { 1235: 1236: int r; 1237: unsigned long addr; 1238: int psize = getpagesize(); 1239: 1240: addr = (startaddr & ~(psize-1)) - psize; 1241: 1242: // fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, 1243: // addr, startaddr+length, length); 1244: 1245: r = mprotect((char*)addr, length + startaddr - addr + psize, 7); 1246: 1247: if (r < 0) 1248: Sys_Error("Protection change failed\n"); 1249: 1250: } 1251: 1252: /*****************************************************************************/ 1253: /* KEYBOARD */ 1254: /*****************************************************************************/ 1255: 1256: Key_Event_fp_t Key_Event_fp; 1257: 1258: void KBD_Init(Key_Event_fp_t fp) 1259: { 1260: Key_Event_fp = fp; 1261: } 1262: 1263: void KBD_Update(void) 1264: { 1265: // get events from x server 1.1.1.2 ! root 1266: HandleEvents(); 1.1 root 1267: } 1268: 1269: void KBD_Close(void) 1270: { 1271: } 1272: 1273:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.