From 89842bdf609866303a0d7a424f4a4b6d0fadc627 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Dec 2001 08:23:10 +0000 Subject: [PATCH] hacky, but it works --- linux/Makefile | 1 - linux/gl_glx.c | 885 ++++++++++++++++++++++++++++++++++++++++++++----- linux/vid_so.c | 2 +- 3 files changed, 802 insertions(+), 86 deletions(-) diff --git a/linux/Makefile b/linux/Makefile index c38a8fc..073cf9d 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -1003,7 +1003,6 @@ REF_GL_OBJS = \ \ $(BUILDDIR)/ref_gl/qgl_linux.o \ $(BUILDDIR)/ref_gl/gl_glx.o \ - $(BUILDDIR)/ref_gl/rw_in_svgalib.o \ $(BUILDDIR)/ref_gl/q_shared.o \ $(BUILDDIR)/ref_gl/q_shlinux.o \ $(BUILDDIR)/ref_gl/glob.o diff --git a/linux/gl_glx.c b/linux/gl_glx.c index 2b29c5f..a1cc4aa 100644 --- a/linux/gl_glx.c +++ b/linux/gl_glx.c @@ -12,77 +12,134 @@ ** */ -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include + +#include + #include "../ref_gl/gl_local.h" #include "../client/keys.h" #include "../linux/rw_linux.h" -#include -#include +GLXContext gl_cx; -/*****************************************************************************/ +static qboolean doShm; +static Display *x_disp; +static Colormap x_cmap; +static Window x_win; +static GC x_gc; +static Visual *x_vis; +static XVisualInfo *x_visinfo; -static qboolean GLimp_SwitchFullscreen( int width, int height ); -qboolean GLimp_InitGL (void); - -extern cvar_t *vid_fullscreen; -extern cvar_t *vid_ref; - -static GLXContext fc = NULL; -/* -#define NUM_RESOLUTIONS 3 - -static resolutions[NUM_RESOLUTIONS][3]={ - { 512, 384, GR_RESOLUTION_512x384 }, - { 640, 400, GR_RESOLUTION_640x400 }, - { 640, 480, GR_RESOLUTION_640x480 } +static int StudlyRGBattributes[] = +{ + GLX_DOUBLEBUFFER, + GLX_RGBA, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 1, + None, }; -static int findres(int *width, int *height) +static int RGBattributes[] = { - int i; + GLX_DOUBLEBUFFER, + GLX_RGBA, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 1, + None, +}; + +#define STD_EVENT_MASK (StructureNotifyMask | KeyPressMask \ + | KeyReleaseMask | ExposureMask | PointerMotionMask | \ + ButtonPressMask | ButtonReleaseMask) + +int current_framebuffer; +static int x_shmeventtype; +//static XShmSegmentInfo x_shminfo; + +static qboolean oktodraw = false; +static qboolean X11_active = false; + +struct +{ + int key; + int down; +} keyq[64]; +int keyq_head=0; +int keyq_tail=0; + +static int mx, my; +static int p_mouse_x, p_mouse_y; +static cvar_t *_windowed_mouse; + +static cvar_t *sensitivity; +static cvar_t *lookstrafe; +static cvar_t *m_side; +static cvar_t *m_yaw; +static cvar_t *m_pitch; +static cvar_t *m_forward; +static cvar_t *freelook; + +int config_notify=0; +int config_notify_width; +int config_notify_height; + +typedef unsigned short PIXEL; + +// Console variables that we need to access from this module + +/*****************************************************************************/ +/* MOUSE */ +/*****************************************************************************/ + +// this is inside the renderer shared lib, so these are called from vid_so + +static qboolean mouse_avail; +static int mouse_buttonstate; +static int mouse_oldbuttonstate; +static int mouse_x, mouse_y; +static int old_mouse_x, old_mouse_y; +static float old_windowed_mouse; +static int p_mouse_x, p_mouse_y; + +static cvar_t *_windowed_mouse; +static cvar_t *m_filter; +static cvar_t *in_mouse; + +static qboolean mlooking; + +// state struct passed in Init +static in_state_t *in_state; + +int XShmQueryExtension(Display *); +int XShmGetEventBase(Display *); - for(i=0;i= com_argc-1) + Sys_Error("VID: -visualid \n"); + template.visualid = Q_atoi(com_argv[pnum+1]); + template_mask = VisualIDMask; + } + +// If not specified, use default visual + else +#endif + { + int screen; + screen = XDefaultScreen(x_disp); + template.visualid = + XVisualIDFromVisual(XDefaultVisual(x_disp, screen)); + template_mask = VisualIDMask; + } + +// pick a visual- warn if more than one was available + + x_visinfo = glXChooseVisual( x_disp, DefaultScreen( x_disp ), + StudlyRGBattributes ); + if (!x_visinfo) + { + fprintf(stderr, "Using non studly RGB attributes\n"); + x_visinfo = glXChooseVisual( x_disp, DefaultScreen( x_disp ), + RGBattributes ); + if (!x_visinfo) Sys_Error( "No matching visual available!\n" ); + } + + ri.Con_Printf(PRINT_ALL, "Using visualid 0x%x:\n", + (int)(x_visinfo->visualid)); +#if 0 + if (verbose) + { + printf("Using visualid %d:\n", (int)(x_visinfo->visualid)); + printf(" screen %d\n", x_visinfo->screen); + printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask)); + printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask)); + printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask)); + printf(" colormap_size %d\n", x_visinfo->colormap_size); + printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb); + } +#endif + + x_vis = x_visinfo->visual; + +// setup attributes for main window + { + int attribmask = CWEventMask | CWColormap | CWBorderPixel; + XSetWindowAttributes attribs; + Colormap tmpcmap; + + Window root_win = XRootWindow(x_disp, x_visinfo->screen); + + tmpcmap = XCreateColormap(x_disp, root_win, x_vis, AllocNone); + + + attribs.event_mask = STD_EVENT_MASK; + attribs.border_pixel = 0; + attribs.colormap = tmpcmap; + +// create the main window + x_win = XCreateWindow( x_disp, + root_win, + 0, 0, // x, y + vid.width, vid.height, + 0, // borderwidth + x_visinfo->depth, + InputOutput, + x_vis, + attribmask, + &attribs ); + XStoreName(x_disp, x_win, "Quake II"); + + if (x_visinfo->class != TrueColor) + XFreeColormap(x_disp, tmpcmap); + } + + if (x_visinfo->depth == 8) + { + // create and upload the palette + if (x_visinfo->class == PseudoColor) + { + x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll); + XSetWindowColormap(x_disp, x_win, x_cmap); + } + + } + +// inviso cursor + XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win)); + +// create the GC + { + XGCValues xgcvalues; + int valuemask = GCGraphicsExposures; + xgcvalues.graphics_exposures = False; + x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues ); + } + +// set window properties for full screen + if (fullscreen) { + //MotifWmHints wmhints; + //Atom aHints; + XSizeHints sizehints; + XWindowChanges changes; +/* + aHints = XInternAtom( x_disp, "_MOTIF_WM_HINTS", 0 ); + if (aHints == None) + { + ri.Con_Printf( PRINT_ALL, "Could not intern X atom for _MOTIF_WM_HINTS." ); +// return( false ); + } + else { + wmhints.flags = MWM_HINTS_DECORATIONS; + wmhints.decorations = 0; // Absolutely no decorations. + XChangeProperty(x_disp, x_win, aHints, aHints, 32, + PropModeReplace, (unsigned char *)&wmhints, + 4 ); + + sizehints.flags = USPosition | USSize; + sizehints.x = 0; + sizehints.y = 0; + sizehints.width = vid.width; + sizehints.height = vid.height; + XSetWMNormalHints( x_disp, x_win, &sizehints ); + + changes.x = 0; + changes.y = 0; + changes.width = vid.width; + changes.height = vid.height; + changes.stack_mode = TopIf; + XConfigureWindow(x_disp, x_win, + CWX | CWY | CWWidth | CWHeight | CWStackMode, + &changes); + } +*/ + } + +// map the window + XMapWindow(x_disp, x_win); + +// wait for first exposure event + { + XEvent event; + do + { + XNextEvent(x_disp, &event); + if (event.type == Expose && !event.xexpose.count) + oktodraw = true; + } while (!oktodraw); + } +// now safe to draw + + gl_cx = glXCreateContext( x_disp, x_visinfo, 0, True ); + if (!glXMakeCurrent( x_disp, x_win, gl_cx )) + Sys_Error( "Can't make window current to context\n" ); + +// even if MITSHM is available, make sure it's a local connection +#if 0 +// This is messing up the DISPLAY environment variable so can't close and +// reopen the window (it lops off the :0.0)... + if (XShmQueryExtension(x_disp)) + { + char *displayname; + doShm = true; + displayname = (char *) getenv("DISPLAY"); + if (displayname) + { + char *d = displayname; + while (*d && (*d != ':')) d++; + if (*d) *d = 0; + if (!(!strcasecmp(displayname, "unix") || !*displayname)) + doShm = false; + } + } +#endif + +#if 0 + if (doShm) + { + x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion; + ResetSharedFrameBuffers(); + } + else + ResetFrameBuffer(); +#endif + + current_framebuffer = 0; +/* vid.rowbytes = x_framebuffer[0]->bytes_per_line; */ +/* vid.buffer = x_framebuffer[0]->data; */ + +// XSynchronize(x_disp, False); + + X11_active = true; + + return true; +} + +/*****************************************************************************/ + +int XLateKey(XKeyEvent *ev) +{ + + int key; + char buf[64]; + KeySym keysym; + + key = 0; + + XLookupString(ev, buf, sizeof buf, &keysym, 0); + + switch(keysym) + { + case XK_KP_Page_Up: key = K_KP_PGUP; break; + case XK_Page_Up: key = K_PGUP; break; + + case XK_KP_Page_Down: key = K_KP_PGDN; break; + case XK_Page_Down: key = K_PGDN; break; + + case XK_KP_Home: key = K_KP_HOME; break; + case XK_Home: key = K_HOME; break; + + case XK_KP_End: key = K_KP_END; break; + case XK_End: key = K_END; break; + + case XK_KP_Left: key = K_KP_LEFTARROW; break; + case XK_Left: key = K_LEFTARROW; break; + + case XK_KP_Right: key = K_KP_RIGHTARROW; break; + case XK_Right: key = K_RIGHTARROW; break; + + case XK_KP_Down: key = K_KP_DOWNARROW; break; + case XK_Down: key = K_DOWNARROW; break; + + case XK_KP_Up: key = K_KP_UPARROW; break; + case XK_Up: key = K_UPARROW; break; + + case XK_Escape: key = K_ESCAPE; break; + + case XK_KP_Enter: key = K_KP_ENTER; break; + case XK_Return: key = K_ENTER; break; + + case XK_Tab: key = K_TAB; break; + + case XK_F1: key = K_F1; break; + + case XK_F2: key = K_F2; break; + + case XK_F3: key = K_F3; break; + + case XK_F4: key = K_F4; break; + + case XK_F5: key = K_F5; break; + + case XK_F6: key = K_F6; break; + + case XK_F7: key = K_F7; break; + + case XK_F8: key = K_F8; break; + + case XK_F9: key = K_F9; break; + + case XK_F10: key = K_F10; break; + + case XK_F11: key = K_F11; break; + + case XK_F12: key = K_F12; break; + + case XK_BackSpace: key = K_BACKSPACE; break; + + case XK_KP_Delete: key = K_KP_DEL; break; + case XK_Delete: key = K_DEL; break; + + case XK_Pause: key = K_PAUSE; break; + + case XK_Shift_L: + case XK_Shift_R: key = K_SHIFT; break; + + case XK_Execute: + case XK_Control_L: + case XK_Control_R: key = K_CTRL; break; + + case XK_Alt_L: + case XK_Meta_L: + case XK_Alt_R: + case XK_Meta_R: key = K_ALT; break; + + case XK_KP_Begin: key = K_KP_5; break; + + case XK_Insert:key = K_INS; break; + case XK_KP_Insert: key = K_KP_INS; break; + + case XK_KP_Multiply: key = '*'; break; + case XK_KP_Add: key = K_KP_PLUS; break; + case XK_KP_Subtract: key = K_KP_MINUS; break; + case XK_KP_Divide: key = K_KP_SLASH; break; + +#if 0 + case 0x021: key = '1';break;/* [!] */ + case 0x040: key = '2';break;/* [@] */ + case 0x023: key = '3';break;/* [#] */ + case 0x024: key = '4';break;/* [$] */ + case 0x025: key = '5';break;/* [%] */ + case 0x05e: key = '6';break;/* [^] */ + case 0x026: key = '7';break;/* [&] */ + case 0x02a: key = '8';break;/* [*] */ + case 0x028: key = '9';;break;/* [(] */ + case 0x029: key = '0';break;/* [)] */ + case 0x05f: key = '-';break;/* [_] */ + case 0x02b: key = '=';break;/* [+] */ + case 0x07c: key = '\'';break;/* [|] */ + case 0x07d: key = '[';break;/* [}] */ + case 0x07b: key = ']';break;/* [{] */ + case 0x022: key = '\'';break;/* ["] */ + case 0x03a: key = ';';break;/* [:] */ + case 0x03f: key = '/';break;/* [?] */ + case 0x03e: key = '.';break;/* [>] */ + case 0x03c: key = ',';break;/* [<] */ +#endif + + default: + key = *(unsigned char*)buf; + if (key >= 'A' && key <= 'Z') + key = key - 'A' + 'a'; + break; + } + + return key; +} + +void GetEvent(void) +{ + XEvent x_event; + int b; + + XNextEvent(x_disp, &x_event); + switch(x_event.type) { + case KeyPress: + keyq[keyq_head].key = XLateKey(&x_event.xkey); + keyq[keyq_head].down = true; + keyq_head = (keyq_head + 1) & 63; + break; + case KeyRelease: + keyq[keyq_head].key = XLateKey(&x_event.xkey); + keyq[keyq_head].down = false; + keyq_head = (keyq_head + 1) & 63; + break; + + case MotionNotify: + if (_windowed_mouse->value) { + mx += ((int)x_event.xmotion.x - (int)(vid.width/2)); + my += ((int)x_event.xmotion.y - (int)(vid.height/2)); + + /* move the mouse to the window center again */ + XSelectInput(x_disp,x_win, STD_EVENT_MASK & ~PointerMotionMask); + XWarpPointer(x_disp,None,x_win,0,0,0,0, + (vid.width/2),(vid.height/2)); + XSelectInput(x_disp,x_win, STD_EVENT_MASK); + } else { + mx = ((int)x_event.xmotion.x - (int)p_mouse_x); + my = ((int)x_event.xmotion.y - (int)p_mouse_y); + p_mouse_x=x_event.xmotion.x; + p_mouse_y=x_event.xmotion.y; + } + break; + + case ButtonPress: + b=-1; + if (x_event.xbutton.button == 1) + b = 0; + else if (x_event.xbutton.button == 2) + b = 2; + else if (x_event.xbutton.button == 3) + b = 1; + if (b>=0) + mouse_buttonstate |= 1<=0) + mouse_buttonstate &= ~(1<value) { + old_windowed_mouse = _windowed_mouse->value; + + if (!_windowed_mouse->value) { + /* ungrab the pointer */ + XUngrabPointer(x_disp,CurrentTime); + } else { + /* grab the pointer */ + XGrabPointer(x_disp,x_win,True,0,GrabModeAsync, + GrabModeAsync,x_win,None,CurrentTime); + } + } +} + +/*****************************************************************************/ + +/*****************************************************************************/ +/* KEYBOARD */ +/*****************************************************************************/ + +Key_Event_fp_t Key_Event_fp; + +void KBD_Init(Key_Event_fp_t fp) +{ + _windowed_mouse = ri.Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE); + Key_Event_fp = fp; +} + +void KBD_Update(void) +{ +// get events from x server + if (x_disp) + { + while (XPending(x_disp)) + GetEvent(); + while (keyq_head != keyq_tail) + { + Key_Event_fp(keyq[keyq_tail].key, keyq[keyq_tail].down); + keyq_tail = (keyq_tail + 1) & 63; + } + } +} + +void KBD_Close(void) +{ } +static void Force_CenterView_f (void) +{ + in_state->viewangles[PITCH] = 0; +} + +static void RW_IN_MLookDown (void) +{ + mlooking = true; +} + +static void RW_IN_MLookUp (void) +{ + mlooking = false; + in_state->IN_CenterView_fp (); +} + +void RW_IN_Init(in_state_t *in_state_p) +{ + int mtype; + int i; + + fprintf(stderr, "GL RW_IN_Init\n"); + + in_state = in_state_p; + + // mouse variables + _windowed_mouse = ri.Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE); + m_filter = ri.Cvar_Get ("m_filter", "0", 0); + in_mouse = ri.Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE); + freelook = ri.Cvar_Get( "freelook", "0", 0 ); + lookstrafe = ri.Cvar_Get ("lookstrafe", "0", 0); + sensitivity = ri.Cvar_Get ("sensitivity", "3", 0); + m_pitch = ri.Cvar_Get ("m_pitch", "0.022", 0); + m_yaw = ri.Cvar_Get ("m_yaw", "0.022", 0); + m_forward = ri.Cvar_Get ("m_forward", "1", 0); + m_side = ri.Cvar_Get ("m_side", "0.8", 0); + + ri.Cmd_AddCommand ("+mlook", RW_IN_MLookDown); + ri.Cmd_AddCommand ("-mlook", RW_IN_MLookUp); + + ri.Cmd_AddCommand ("force_centerview", Force_CenterView_f); + + mouse_x = mouse_y = 0.0; + mouse_avail = true; +} + +void RW_IN_Shutdown(void) +{ + mouse_avail = false; + + ri.Cmd_RemoveCommand ("force_centerview"); + ri.Cmd_RemoveCommand ("+mlook"); + ri.Cmd_RemoveCommand ("-mlook"); +} + +/* +=========== +IN_Commands +=========== +*/ +void RW_IN_Commands (void) +{ + int i; + + if (!mouse_avail) + return; + + for (i=0 ; i<3 ; i++) { + if ( (mouse_buttonstate & (1<Key_Event_fp (K_MOUSE1 + i, true); + + if ( !(mouse_buttonstate & (1<Key_Event_fp (K_MOUSE1 + i, false); + } + mouse_oldbuttonstate = mouse_buttonstate; +} + +/* +=========== +IN_Move +=========== +*/ +void RW_IN_Move (usercmd_t *cmd) +{ + if (!mouse_avail) + return; + + if (m_filter->value) + { + mouse_x = (mx + old_mouse_x) * 0.5; + mouse_y = (my + old_mouse_y) * 0.5; + } else { + mouse_x = mx; + mouse_y = my; + } + + old_mouse_x = mx; + old_mouse_y = my; + + if (!mouse_x && !mouse_y) + return; + + mouse_x *= sensitivity->value; + mouse_y *= sensitivity->value; + +// add mouse X/Y movement to cmd + if ( (*in_state->in_strafe_state & 1) || + (lookstrafe->value && mlooking )) + cmd->sidemove += m_side->value * mouse_x; + else + in_state->viewangles[YAW] -= m_yaw->value * mouse_x; + + if ( (mlooking || freelook->value) && + !(*in_state->in_strafe_state & 1)) + { + in_state->viewangles[PITCH] += m_pitch->value * mouse_y; + } + else + { + cmd->forwardmove -= m_forward->value * mouse_y; + } + mx = my = 0; +} + +void RW_IN_Frame (void) +{ +} + +void RW_IN_Activate(void) +{ +} + + +//=============================================================================== + +/* +================ +Sys_MakeCodeWriteable +================ +*/ +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +{ + + int r; + unsigned long addr; + int psize = getpagesize(); + + addr = (startaddr & ~(psize-1)) - psize; + +// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, +// addr, startaddr+length, length); + + r = mprotect((char*)addr, length + startaddr - addr + psize, 7); + + if (r < 0) + Sys_Error("Protection change failed\n"); + +} diff --git a/linux/vid_so.c b/linux/vid_so.c index d079b78..51b729e 100644 --- a/linux/vid_so.c +++ b/linux/vid_so.c @@ -219,7 +219,7 @@ qboolean VID_LoadRefresh( char *name ) strcat(fn, name); // permission checking - if (strstr(fn, "softx") == NULL) { // softx doesn't require root + if (0 && strstr(fn, "softx") == NULL) { // softx doesn't require root if (stat(fn, &st) == -1) { Com_Printf( "LoadLibrary(\"%s\") failed: %s\n", name, strerror(errno)); return false;