X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=vid_glx.c;h=40cebe1b10cde7f910958db4b500a2e37be35797;hp=96bf36f26d51d0b2dd2a7e50a55ae22cc4212cb2;hb=dd0b4a35240b6b0e8612e41af439ead7981ec8cd;hpb=77d1b76d3f88c01c47d29bb507d8d9e2c398136f diff --git a/vid_glx.c b/vid_glx.c index 96bf36f2..40cebe1b 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -23,10 +23,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include +#include // TODO possibly ifdef this out on non-supporting systems... Solaris (as always)? #include +#include "quakedef.h" + #include #include +#include #include #if !defined(__APPLE__) && !defined(__MACH__) && !defined(SUNOS) @@ -34,7 +38,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #include -#include "quakedef.h" +#include "nexuiz.xpm" +#include "darkplaces.xpm" // Tell startup code that we have a client int cl_available = true; @@ -84,18 +89,18 @@ Atom wm_delete_window_atom; static qboolean mouse_avail = true; +static qboolean vid_usingmousegrab = false; static qboolean vid_usingmouse = false; +static qboolean vid_usinghidecursor = false; static qboolean vid_usingvsync = false; static qboolean vid_usevsync = false; static qboolean vid_x11_hardwaregammasupported = false; +static qboolean vid_x11_dgasupported = false; static int vid_x11_gammarampsize = 0; -static float mouse_x, mouse_y; -static int p_mouse_x, p_mouse_y; #if !defined(__APPLE__) && !defined(SUNOS) -// FIXME: vid_dga_mouseaccel is poorly named, it is actually the multiplier for mouse movement, not an acceleration (which would be a power function or something) -cvar_t vid_dga = {CVAR_SAVE, "vid_dga", "1", "make use of DGA mouse input"}; -cvar_t vid_dga_mouseaccel = {0, "vid_dga_mouseaccel", "1", "speed of mouse when using DGA mouse input"}; +cvar_t vid_dgamouse = {CVAR_SAVE, "vid_dgamouse", "1", "make use of DGA mouse input"}; +static qboolean vid_usingdgamouse = false; #endif qboolean vidmode_ext = false; @@ -202,7 +207,7 @@ static int XLateKey(XKeyEvent *ev, char *ascii) 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_Multiply: key = K_KP_MULTIPLY; 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; @@ -245,13 +250,49 @@ static Cursor CreateNullCursor(Display *display, Window root) return cursor; } -static void IN_Activate (qboolean grab) +void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor) { - if (!vidx11_display) +#if !defined(__APPLE__) && !defined(SUNOS) + qboolean usedgamouse; +#endif + + if (!vidx11_display || !win) return; - if (grab) + + if (relative) + fullscreengrab = true; + + if (!mouse_avail) + fullscreengrab = relative = hidecursor = false; + +#if !defined(__APPLE__) && !defined(SUNOS) + usedgamouse = relative && vid_dgamouse.integer; + if (!vid_x11_dgasupported) + usedgamouse = false; + if (fullscreengrab && vid_usingmouse && (vid_usingdgamouse != usedgamouse)) + VID_SetMouse(false, false, false); // ungrab first! +#endif + + if (vid_usingmousegrab != fullscreengrab) { - if (!vid_usingmouse && mouse_avail && win) + vid_usingmousegrab = fullscreengrab; + cl_ignoremousemoves = 2; + if (fullscreengrab) + { + XGrabPointer(vidx11_display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); + if (vid_grabkeyboard.integer || vid_isfullscreen) + XGrabKeyboard(vidx11_display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); + } + else + { + XUngrabPointer(vidx11_display, CurrentTime); + XUngrabKeyboard(vidx11_display, CurrentTime); + } + } + + if (relative) + { + if (!vid_usingmouse) { XWindowAttributes attribs_1; XSetWindowAttributes attribs_2; @@ -260,38 +301,18 @@ static void IN_Activate (qboolean grab) attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK; XChangeWindowAttributes(vidx11_display, win, CWEventMask, &attribs_2); - // inviso cursor - XDefineCursor(vidx11_display, win, CreateNullCursor(vidx11_display, win)); - - XGrabPointer(vidx11_display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); - #if !defined(__APPLE__) && !defined(SUNOS) - if (vid_dga.integer) + vid_usingdgamouse = usedgamouse; + if (usedgamouse) { - int MajorVersion, MinorVersion; - - if (!XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion)) - { - // unable to query, probably not supported - Con_Print( "Failed to detect XF86DGA Mouse\n" ); - Cvar_SetValueQuick(&vid_dga, 0); - XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); - } - else - { - XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), XF86DGADirectMouse); - XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0); - } + XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), XF86DGADirectMouse); + XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0); } else #endif XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); - if (vid_grabkeyboard.integer) - XGrabKeyboard(vidx11_display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); - - mouse_x = mouse_y = 0; - cl_ignoremousemove = true; + cl_ignoremousemoves = 2; vid_usingmouse = true; } } @@ -300,21 +321,23 @@ static void IN_Activate (qboolean grab) if (vid_usingmouse) { #if !defined(__APPLE__) && !defined(SUNOS) - if (vid_dga.integer) + if (vid_usingdgamouse) XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), 0); + vid_usingdgamouse = false; #endif - - XUngrabPointer(vidx11_display, CurrentTime); - XUngrabKeyboard(vidx11_display, CurrentTime); - - // inviso cursor - if (win) - XUndefineCursor(vidx11_display, win); - - cl_ignoremousemove = true; + cl_ignoremousemoves = 2; vid_usingmouse = false; } } + + if (vid_usinghidecursor != hidecursor) + { + vid_usinghidecursor = hidecursor; + if (hidecursor) + XDefineCursor(vidx11_display, win, CreateNullCursor(vidx11_display, win)); + else + XUndefineCursor(vidx11_display, win); + } } static keynum_t buttonremap[18] = @@ -372,28 +395,26 @@ static void HandleEvents(void) if (vid_usingmouse) { #if !defined(__APPLE__) && !defined(SUNOS) - if (vid_dga.integer == 1) + if (vid_usingdgamouse) { - mouse_x += event.xmotion.x_root * vid_dga_mouseaccel.value; - mouse_y += event.xmotion.y_root * vid_dga_mouseaccel.value; + in_mouse_x += event.xmotion.x_root; + in_mouse_y += event.xmotion.y_root; } else #endif { - if (!event.xmotion.send_event) { - mouse_x += event.xmotion.x - p_mouse_x; - mouse_y += event.xmotion.y - p_mouse_y; + in_mouse_x += event.xmotion.x - in_windowmouse_x; + in_mouse_y += event.xmotion.y - in_windowmouse_y; + //if (abs(vid.width/2 - event.xmotion.x) + abs(vid.height/2 - event.xmotion.y)) if (abs(vid.width/2 - event.xmotion.x) > vid.width / 4 || abs(vid.height/2 - event.xmotion.y) > vid.height / 4) dowarp = true; } - p_mouse_x = event.xmotion.x; - p_mouse_y = event.xmotion.y; } } - //else - // ui_mouseupdate(event.xmotion.x, event.xmotion.y); + in_windowmouse_x = event.xmotion.x; + in_windowmouse_y = event.xmotion.y; break; case ButtonPress: @@ -422,31 +443,44 @@ static void HandleEvents(void) // window changed size/location win_x = event.xconfigure.x; win_y = event.xconfigure.y; + if(vid_resizable.integer < 2) + { + vid.width = event.xconfigure.width; + vid.height = event.xconfigure.height; + } break; case DestroyNotify: // window has been destroyed - Sys_Quit(); + Sys_Quit(0); break; case ClientMessage: // window manager messages if ((event.xclient.format == 32) && ((unsigned int)event.xclient.data.l[0] == wm_delete_window_atom)) - Sys_Quit(); + Sys_Quit(0); break; case MapNotify: + if (vid.fullscreen) + break; // window restored vid_hidden = false; VID_RestoreSystemGamma(); break; case UnmapNotify: + if (vid.fullscreen) + break; // window iconified/rolledup/whatever vid_hidden = true; VID_RestoreSystemGamma(); break; case FocusIn: + if (vid.fullscreen) + break; // window is now the input focus vid_activewindow = true; break; case FocusOut: + if (vid.fullscreen) + break; // window is no longer the input focus vid_activewindow = false; VID_RestoreSystemGamma(); @@ -463,9 +497,16 @@ static void HandleEvents(void) if (dowarp) { /* move the mouse to the window center again */ - p_mouse_x = vid.width / 2; - p_mouse_y = vid.height / 2; - XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, p_mouse_x, p_mouse_y); + // we'll catch the warp motion by its send_event flag, updating the + // stored mouse position without adding any delta motion + XEvent event; + event.type = MotionNotify; + event.xmotion.display = vidx11_display; + event.xmotion.window = win; + event.xmotion.x = vid.width / 2; + event.xmotion.y = vid.height / 2; + XSendEvent(vidx11_display, win, False, PointerMotionMask, &event); + XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); } } @@ -487,7 +528,7 @@ static int GL_OpenLibrary(const char *name) { Con_Printf("Loading OpenGL driver %s\n", name); GL_CloseLibrary(); - if (!(prjobj = dlopen(name, RTLD_LAZY))) + if (!(prjobj = dlopen(name, RTLD_LAZY | RTLD_GLOBAL))) { Con_Printf("Unable to open symbol list for %s\n", name); return false; @@ -511,18 +552,16 @@ void VID_Shutdown(void) if (!ctx || !vidx11_display) return; - if (vidx11_display) - { - IN_Activate(false); - VID_RestoreSystemGamma(); - - // FIXME: glXDestroyContext here? - if (vid_isfullscreen) - XF86VidModeSwitchToMode(vidx11_display, vidx11_screen, &init_vidmode); - if (win) - XDestroyWindow(vidx11_display, win); - XCloseDisplay(vidx11_display); - } + VID_SetMouse(false, false, false); + VID_RestoreSystemGamma(); + + // FIXME: glXDestroyContext here? + if (vid_isfullscreen) + XF86VidModeSwitchToMode(vidx11_display, vidx11_screen, &init_vidmode); + if (win) + XDestroyWindow(vidx11_display, win); + XCloseDisplay(vidx11_display); + vid_hidden = true; vid_isfullscreen = false; vidx11_display = NULL; @@ -537,8 +576,7 @@ void signal_handler(int sig) { Con_Printf("Received signal %d, exiting...\n", sig); VID_RestoreSystemGamma(); - Sys_Quit(); - exit(0); + Sys_Quit(1); } void InitSig(void) @@ -555,10 +593,8 @@ void InitSig(void) signal(SIGTERM, signal_handler); } -void VID_Finish (qboolean allowmousegrab) +void VID_Finish (void) { - qboolean vid_usemouse; - vid_usevsync = vid_vsync.integer && !cls.timedemo && gl_videosyncavailable; if (vid_usingvsync != vid_usevsync && gl_videosyncavailable) { @@ -567,16 +603,6 @@ void VID_Finish (qboolean allowmousegrab) Con_Print("glXSwapIntervalSGI didn't accept the vid_vsync change, it will take effect on next vid_restart (GLX_SGI_swap_control does not allow turning off vsync)\n"); } - // handle the mouse state when windowed if that's changed - vid_usemouse = false; - if (allowmousegrab && vid_mouse.integer && !key_consoleactive && (key_dest != key_game || !cls.demoplayback)) - vid_usemouse = true; - if (!vid_activewindow) - vid_usemouse = false; - if (vid_isfullscreen) - vid_usemouse = true; - IN_Activate(vid_usemouse); - if (r_render.integer) { CHECKGLERROR @@ -604,39 +630,48 @@ int VID_GetGamma(unsigned short *ramps, int rampsize) void VID_Init(void) { #if !defined(__APPLE__) && !defined(SUNOS) - Cvar_RegisterVariable (&vid_dga); - Cvar_RegisterVariable (&vid_dga_mouseaccel); + Cvar_RegisterVariable (&vid_dgamouse); #endif InitSig(); // trap evil signals // COMMANDLINEOPTION: Input: -nomouse disables mouse support (see also vid_mouse cvar) - if (COM_CheckParm ("-nomouse") || COM_CheckParm("-safe")) + if (COM_CheckParm ("-nomouse")) mouse_avail = false; } -void VID_BuildGLXAttrib(int *attrib, qboolean stencil, qboolean stereobuffer) +void VID_BuildGLXAttrib(int *attrib, qboolean stencil, qboolean stereobuffer, int samples) { *attrib++ = GLX_RGBA; - *attrib++ = GLX_RED_SIZE;*attrib++ = 1; - *attrib++ = GLX_GREEN_SIZE;*attrib++ = 1; - *attrib++ = GLX_BLUE_SIZE;*attrib++ = 1; + *attrib++ = GLX_RED_SIZE;*attrib++ = stencil ? 8 : 5; + *attrib++ = GLX_GREEN_SIZE;*attrib++ = stencil ? 8 : 5; + *attrib++ = GLX_BLUE_SIZE;*attrib++ = stencil ? 8 : 5; *attrib++ = GLX_DOUBLEBUFFER; - *attrib++ = GLX_DEPTH_SIZE;*attrib++ = 1; + *attrib++ = GLX_DEPTH_SIZE;*attrib++ = stencil ? 24 : 16; // if stencil is enabled, ask for alpha too if (stencil) { *attrib++ = GLX_STENCIL_SIZE;*attrib++ = 8; - *attrib++ = GLX_ALPHA_SIZE;*attrib++ = 1; + *attrib++ = GLX_ALPHA_SIZE;*attrib++ = 8; } if (stereobuffer) *attrib++ = GLX_STEREO; + if (samples > 1) + { + *attrib++ = GLX_SAMPLE_BUFFERS_ARB; + *attrib++ = 1; + *attrib++ = GLX_SAMPLES_ARB; + *attrib++ = samples; + } *attrib++ = None; } -int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer) +int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples) { int i; int attrib[32]; XSetWindowAttributes attr; + XClassHint *clshints; + XWMHints *wmhints; + XSizeHints *szhints; unsigned long mask; Window root; XVisualInfo *visinfo; @@ -666,6 +701,9 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate return false; } + // make autorepeat send keypress/keypress/.../keyrelease instead of intervening keyrelease + XkbSetDetectableAutoRepeat(vidx11_display, true, NULL); + vidx11_screen = DefaultScreen(vidx11_display); root = RootWindow(vidx11_display, vidx11_screen); @@ -690,8 +728,15 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate return false; } - VID_BuildGLXAttrib(attrib, bpp == 32, stereobuffer); + VID_BuildGLXAttrib(attrib, bpp == 32, stereobuffer, samples); visinfo = qglXChooseVisual(vidx11_display, vidx11_screen, attrib); + if (!visinfo && (samples == 1)) + { + /* Some Mesa drivers reject sample buffers with 1 sample, so try + * entirely without one */ + VID_BuildGLXAttrib(attrib, bpp == 32, stereobuffer, 0); + visinfo = qglXChooseVisual(vidx11_display, vidx11_screen, attrib); + } if (!visinfo) { Con_Print("Couldn't get an RGB, Double-buffered, Depth visual\n"); @@ -774,7 +819,30 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow(vidx11_display, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); - XStoreName(vidx11_display, win, gamename); + + wmhints = XAllocWMHints(); + if(XpmCreatePixmapFromData(vidx11_display, win, + (gamemode == GAME_NEXUIZ) ? nexuiz_xpm : darkplaces_xpm, + &wmhints->icon_pixmap, &wmhints->icon_mask, NULL) == XpmSuccess) + wmhints->flags |= IconPixmapHint | IconMaskHint; + + clshints = XAllocClassHint(); + clshints->res_name = strdup(gamename); + clshints->res_class = strdup("DarkPlaces"); + + szhints = XAllocSizeHints(); + if(vid_resizable.integer == 0) + { + szhints->min_width = szhints->max_width = width; + szhints->min_height = szhints->max_height = height; + szhints->flags |= PMinSize | PMaxSize; + } + + XmbSetWMProperties(vidx11_display, win, gamename, gamename, (char **) com_argv, com_argc, szhints, wmhints, clshints); + XFree(clshints); + XFree(wmhints); + XFree(szhints); + //XStoreName(vidx11_display, win, gamename); XMapWindow(vidx11_display, win); // LordHavoc: making the close button on a window do the right thing @@ -815,9 +883,6 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate return false; } - gl_renderer = (const char *)qglGetString(GL_RENDERER); - gl_vendor = (const char *)qglGetString(GL_VENDOR); - gl_version = (const char *)qglGetString(GL_VERSION); gl_extensions = (const char *)qglGetString(GL_EXTENSIONS); gl_platform = "GLX"; gl_platformextensions = qglXQueryExtensionsString(vidx11_display, vidx11_screen); @@ -833,11 +898,18 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate // COMMANDLINEOPTION: MacOSX GLX: -novideosync disables GLX_SGI_swap_control gl_videosyncavailable = GL_CheckExtension("GLX_SGI_swap_control", swapcontrolfuncs, "-novideosync", false); + vid_usingmousegrab = false; vid_usingmouse = false; + vid_usinghidecursor = false; vid_usingvsync = false; vid_hidden = false; vid_activewindow = true; vid_x11_hardwaregammasupported = XF86VidModeGetGammaRampSize(vidx11_display, vidx11_screen, &vid_x11_gammarampsize) != 0; +#if !defined(__APPLE__) && !defined(SUNOS) + vid_x11_dgasupported = XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion); + if (!vid_x11_dgasupported) + Con_Print( "Failed to detect XF86DGA Mouse extension\n" ); +#endif GL_Init(); return true; } @@ -847,15 +919,21 @@ void Sys_SendKeyEvents(void) static qboolean sound_active = true; // enable/disable sound on focus gain/loss - if (!vid_activewindow && sound_active) + if (!vid_hidden && (vid_activewindow || !snd_mutewhenidle.integer)) { - S_BlockSound (); - sound_active = false; + if (!sound_active) + { + S_UnblockSound (); + sound_active = true; + } } - else if (vid_activewindow && !sound_active) + else { - S_UnblockSound (); - sound_active = true; + if (sound_active) + { + S_BlockSound (); + sound_active = false; + } } HandleEvents(); @@ -863,11 +941,4 @@ void Sys_SendKeyEvents(void) void IN_Move (void) { - if (mouse_avail) - { - in_mouse_x = mouse_x; - in_mouse_y = mouse_y; - } - mouse_x = 0; - mouse_y = 0; }