1
0
Fork 0
forked from fte/fteqw
fteqw/engine/gl/gl_vidlinuxglx.c
Spoike f33873ddb7 committing for fixes for OMC
some minor changes. Mostly bug fixes and internal reorganisation.
Added code to provide an activex control as part of the npfte.dll plugin. If the dll is registered the regsvr32 way, the plugin can be used with IE as well.
fisheye/panoramic view enable is now controlled by rulesets instead of serverinfo.
server will list all pak files it has loaded. client will probably do the wrong thing and still needs fixing properly.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3910 fc73d0e0-1445-4013-8a0c-d673dee63da5
2011-10-27 16:16:29 +00:00

1186 lines
27 KiB
C

/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#ifdef __linux__
#include <sys/vt.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
#include <dlfcn.h>
#include "quakedef.h"
#include "glquake.h"
#include <GL/glx.h>
#ifdef USE_EGL
#include "gl_videgl.h"
#endif
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#ifdef USE_DGA
#include <X11/extensions/Xxf86dga.h>
#endif
#ifdef __linux__
#define WITH_VMODE //undefine this if the following include fails.
#endif
#ifdef WITH_VMODE
#include <X11/extensions/xf86vmode.h>
#endif
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
static Display *vid_dpy = NULL;
static Window vid_window;
static GLXContext ctx = NULL;
int scrnum;
static qboolean vidglx_fullscreen;
static float old_windowed_mouse = 0;
#ifdef USE_DGA
static int dgamouse = 0;
#endif
#define KEY_MASK (KeyPressMask | KeyReleaseMask)
#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask)
#define X_MASK (KEY_MASK | MOUSE_MASK | ResizeRequest | StructureNotifyMask | FocusChangeMask | VisibilityChangeMask)
#ifdef WITH_VMODE
static int vidmode_ext = 0;
static XF86VidModeModeInfo **vidmodes;
static int num_vidmodes;
static qboolean vidmode_active = false;
static int vidmode_usemode = -1; //so that it can be reset if they switch away.
unsigned short originalramps[3][256];
qboolean originalapplied; //states that the origionalramps arrays are valid, and contain stuff that we should revert to on close
#endif
extern cvar_t _windowed_mouse;
cvar_t m_filter = {"m_filter", "0"};
cvar_t m_accel = {"m_accel", "0"};
static float mouse_x, mouse_y;
static float old_mouse_x, old_mouse_y;
/*-----------------------------------------------------------------------*/
float gldepthmin, gldepthmax;
const char *gl_vendor;
const char *gl_renderer;
const char *gl_version;
const char *gl_extensions;
qboolean is8bit = false;
qboolean isPermedia = false;
qboolean mouseactive = false;
qboolean ActiveApp = false;
int gl_canstencil;
/*-----------------------------------------------------------------------*/
static void *gllibrary;
XVisualInfo* (*qglXChooseVisual) (Display *dpy, int screen, int *attribList);
void (*qglXSwapBuffers) (Display *dpy, GLXDrawable drawable);
Bool (*qglXMakeCurrent) (Display *dpy, GLXDrawable drawable, GLXContext ctx);
GLXContext (*qglXCreateContext) (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
void (*qglXDestroyContext) (Display *dpy, GLXContext ctx);
void *(*qglXGetProcAddress) (char *name);
void GLX_CloseLibrary(void)
{
dlclose(gllibrary);
gllibrary = NULL;
}
qboolean GLX_InitLibrary(char *driver)
{
if (driver && *driver)
gllibrary = dlopen(driver, RTLD_LAZY);
else
gllibrary = NULL;
if (!gllibrary) //I hate this.
gllibrary = dlopen("libGL.so.1", RTLD_LAZY);
if (!gllibrary)
gllibrary = dlopen("libGL.so", RTLD_LAZY);
if (!gllibrary)
return false;
qglXChooseVisual = dlsym(gllibrary, "glXChooseVisual");
qglXSwapBuffers = dlsym(gllibrary, "glXSwapBuffers");
qglXMakeCurrent = dlsym(gllibrary, "glXMakeCurrent");
qglXCreateContext = dlsym(gllibrary, "glXCreateContext");
qglXDestroyContext = dlsym(gllibrary, "glXDestroyContext");
qglXGetProcAddress = dlsym(gllibrary, "glXGetProcAddress");
if (!qglXGetProcAddress)
qglXGetProcAddress = dlsym(gllibrary, "glXGetProcAddressARB");
if (!qglXSwapBuffers && !qglXDestroyContext && !qglXCreateContext && !qglXMakeCurrent && !qglXChooseVisual)
return false;
return true;
}
void *GLX_GetSymbol(char *name)
{
void *symb;
if (qglXGetProcAddress)
symb = qglXGetProcAddress(name);
else
symb = NULL;
if (!symb)
symb = dlsym(gllibrary, name);
return symb;
}
static int XLateKey(XKeyEvent *ev, unsigned int *unicode)
{
int key;
char buf[64];
KeySym keysym, shifted;
key = 0;
keysym = XLookupKeysym(ev, 0);
XLookupString(ev, buf, sizeof buf, &shifted, 0);
if (unicode)
*unicode = buf[0];
switch(keysym)
{
case XK_KP_Page_Up:
case XK_Page_Up: key = K_PGUP; break;
case XK_KP_Page_Down:
case XK_Page_Down: key = K_PGDN; break;
case XK_KP_Home:
case XK_Home: key = K_HOME; break;
case XK_KP_End:
case XK_End: key = K_END; break;
case XK_KP_Left:
case XK_Left: key = K_LEFTARROW; break;
case XK_KP_Right:
case XK_Right: key = K_RIGHTARROW; break;
case XK_KP_Down:
case XK_Down: key = K_DOWNARROW; break;
case XK_KP_Up:
case XK_Up: key = K_UPARROW; break;
case XK_Escape: key = K_ESCAPE; break;
case XK_KP_Enter:
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:
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 = '5'; break;
case XK_KP_Insert:
case XK_Insert:key = K_INS; break;
case XK_KP_Multiply: key = '*'; break;
case XK_KP_Add: key = '+'; break;
case XK_KP_Subtract: key = '-'; break;
case XK_KP_Divide: key = '/'; 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;
}
static void install_grabs(void)
{
XGrabPointer(vid_dpy, vid_window,
True,
0,
GrabModeAsync, GrabModeAsync,
vid_window,
None,
CurrentTime);
#ifdef USE_DGA
// TODO: make this into a cvar, like "in_dgamouse", instead of parameters
// TODO: inform the user when DGA is enabled
if (!COM_CheckParm("-nodga") && !COM_CheckParm("-nomdga"))
{
XF86DGADirectVideo(vid_dpy, DefaultScreen(vid_dpy), XF86DGADirectMouse);
dgamouse = 1;
}
else
#endif
{
XWarpPointer(vid_dpy, None, vid_window,
0, 0, 0, 0,
vid.width / 2, vid.height / 2);
}
// XSync(vid_dpy, True);
}
static void uninstall_grabs(void)
{
#ifdef USE_DGA
if (dgamouse)
{
XF86DGADirectVideo(vid_dpy, DefaultScreen(vid_dpy), 0);
dgamouse = 0;
}
#endif
if (vid_dpy)
XUngrabPointer(vid_dpy, CurrentTime);
// XSync(vid_dpy, True);
}
void ClearAllStates (void)
{
int i;
// send an up event for each key, to make sure the server clears them all
for (i=0 ; i<256 ; i++)
{
Key_Event (0, i, 0, false);
}
Key_ClearStates ();
// IN_ClearStates ();
}
static void GetEvent(void)
{
XEvent event;
int b;
unsigned int uc;
qboolean wantwindowed;
qboolean x11violations = true;
if (!vid_dpy)
return;
XNextEvent(vid_dpy, &event);
switch (event.type) {
case ResizeRequest:
vid.pixelwidth = event.xresizerequest.width;
vid.pixelheight = event.xresizerequest.height;
break;
case ConfigureNotify:
vid.pixelwidth = event.xconfigurerequest.width;
vid.pixelheight = event.xconfigurerequest.height;
break;
case KeyPress:
b = XLateKey(&event.xkey, &uc);
Key_Event(0, b, uc, true);
break;
case KeyRelease:
b = XLateKey(&event.xkey, NULL);
Key_Event(0, b, 0, false);
break;
case MotionNotify:
#ifdef USE_DGA
if (dgamouse && old_windowed_mouse)
{
mouse_x += event.xmotion.x_root;
mouse_y += event.xmotion.y_root;
}
else
#endif
{
if (old_windowed_mouse)
{
mouse_x = (float) ((int)event.xmotion.x - (int)(vid.width/2));
mouse_y = (float) ((int)event.xmotion.y - (int)(vid.height/2));
/* move the mouse to the window center again */
XSelectInput(vid_dpy, vid_window, X_MASK & ~PointerMotionMask);
XWarpPointer(vid_dpy, None, vid_window, 0, 0, 0, 0,
(vid.width/2), (vid.height/2));
XSelectInput(vid_dpy, vid_window, X_MASK);
}
}
break;
case ButtonPress:
b=-1;
if (event.xbutton.button == 1)
b = K_MOUSE1;
else if (event.xbutton.button == 2)
b = K_MOUSE3;
else if (event.xbutton.button == 3)
b = K_MOUSE2;
//note, the x11 protocol does not support a mousewheel
//we only support it because we follow convention. the actual protocol specifies 4+5 as regular buttons
else if (event.xbutton.button == 4)
b = x11violations?K_MWHEELUP:K_MOUSE4;
else if (event.xbutton.button == 5)
b = x11violations?K_MWHEELDOWN:K_MOUSE5;
//note, the x11 protocol does not support more than 5 mouse buttons
//which is a bit of a shame, but hey.
else if (event.xbutton.button == 6)
b = x11violations?K_MOUSE4:-1;
else if (event.xbutton.button == 7)
b = x11violations?K_MOUSE5:-1;
else if (event.xbutton.button == 8)
b = x11violations?K_MOUSE6:-1;
else if (event.xbutton.button == 9)
b = x11violations?K_MOUSE7:-1;
else if (event.xbutton.button == 10)
b = x11violations?K_MOUSE8:-1;
else if (event.xbutton.button == 11)
b = x11violations?K_MOUSE9:-1;
else if (event.xbutton.button == 12)
b = x11violations?K_MOUSE10:-1;
if (b>=0)
Key_Event(0, b, 0, true);
#ifdef WITH_VMODE
if (vidmode_ext && vidmode_usemode>=0)
if (!ActiveApp)
{ //KDE doesn't seem to like us, in that you can't alt-tab back or click to activate.
//This allows us to steal input focus back from the window manager
XSetInputFocus(vid_dpy, vid_window, RevertToParent, CurrentTime);
}
#endif
break;
case ButtonRelease:
b=-1;
if (event.xbutton.button == 1)
b = K_MOUSE1;
else if (event.xbutton.button == 2)
b = K_MOUSE3;
else if (event.xbutton.button == 3)
b = K_MOUSE2;
//note, the x11 protocol does not support a mousewheel
//we only support it because we follow convention. the actual protocol specifies 4+5 as regular buttons
else if (event.xbutton.button == 4)
b = x11violations?K_MWHEELUP:K_MOUSE4;
else if (event.xbutton.button == 5)
b = x11violations?K_MWHEELDOWN:K_MOUSE5;
//note, the x11 protocol does not support more than 5 mouse buttons
//which is a bit of a shame, but hey.
else if (event.xbutton.button == 6)
b = x11violations?K_MOUSE4:-1;
else if (event.xbutton.button == 7)
b = x11violations?K_MOUSE5:-1;
else if (event.xbutton.button == 8)
b = x11violations?K_MOUSE6:-1;
else if (event.xbutton.button == 9)
b = x11violations?K_MOUSE7:-1;
else if (event.xbutton.button == 10)
b = x11violations?K_MOUSE8:-1;
else if (event.xbutton.button == 11)
b = x11violations?K_MOUSE9:-1;
else if (event.xbutton.button == 12)
b = x11violations?K_MOUSE10:-1;
if (b>=0)
Key_Event(0, b, 0, false);
break;
case FocusIn:
ActiveApp = true;
#ifdef WITH_VMODE
if (vidmode_ext && vidmode_usemode>=0)
{
if (!vidmode_active)
{
// change to the mode
XF86VidModeSwitchToMode(vid_dpy, scrnum, vidmodes[vidmode_usemode]);
vidmode_active = true;
// Move the viewport to top left
}
XF86VidModeSetViewPort(vid_dpy, scrnum, 0, 0);
}
#endif
Cvar_ForceCallback(&v_gamma);
break;
case FocusOut:
#ifdef WITH_VMODE
if (originalapplied)
XF86VidModeSetGammaRamp(vid_dpy, scrnum, 256, originalramps[0], originalramps[1], originalramps[2]);
if (!COM_CheckParm("-stayactive"))
{ //a parameter that leaves the program fullscreen if you taskswitch.
//sounds pointless, works great with two moniters. :D
if (originalapplied)
XF86VidModeSetGammaRamp(vid_dpy, scrnum, 256, originalramps[0], originalramps[1], originalramps[2]);
if (vidmode_active)
{
XF86VidModeSwitchToMode(vid_dpy, scrnum, vidmodes[0]);
vidmode_active = false;
}
}
#endif
ActiveApp = false;
ClearAllStates();
break;
case ClientMessage:
{
char *name = XGetAtomName(vid_dpy, event.xclient.message_type);
if (!strcmp(name, "WM_PROTOCOLS") && event.xclient.format == 32)
{
char *protname = XGetAtomName(vid_dpy, event.xclient.data.l[0]);
if (!strcmp(protname, "WM_DELETE_WINDOW"))
Cmd_ExecuteString("menu_quit", RESTRICT_LOCAL);
else
Con_Printf("Got message %s\n", protname);
XFree(protname);
}
else
Con_Printf("Got message %s\n", name);
XFree(name);
}
break;
default:
// Con_Printf("%x\n", event.type);
break;
}
wantwindowed = !!_windowed_mouse.value;
if (!ActiveApp)
wantwindowed = false;
if (key_dest == key_console && !vidglx_fullscreen)
wantwindowed = false;
if (old_windowed_mouse != wantwindowed)
{
old_windowed_mouse = wantwindowed;
if (!wantwindowed)
{
Con_DPrintf("uninstall grabs\n");
/* ungrab the pointer */
uninstall_grabs();
}
else
{
Con_DPrintf("install grabs\n");
/* grab the pointer */
install_grabs();
}
}
}
void GLVID_Shutdown(void)
{
#ifdef USE_EGL
EGL_Shutdown();
#else
printf("GLVID_Shutdown\n");
if (!vid_dpy)
return;
XUngrabKeyboard(vid_dpy, CurrentTime);
if (old_windowed_mouse)
uninstall_grabs();
if (ctx)
{
qglXDestroyContext(vid_dpy, ctx);
ctx = NULL;
}
#ifdef WITH_VMODE
if (originalapplied)
XF86VidModeSetGammaRamp(vid_dpy, scrnum, 256, originalramps[0], originalramps[1], originalramps[2]);
#endif
if (vid_window)
XDestroyWindow(vid_dpy, vid_window);
#ifdef WITH_VMODE
if (vid_dpy) {
if (vidmode_active)
XF86VidModeSwitchToMode(vid_dpy, scrnum, vidmodes[0]);
vidmode_active = false;
if (vidmodes)
XFree(vidmodes);
vidmodes = NULL;
num_vidmodes = 0;
}
#endif
XCloseDisplay(vid_dpy);
vid_dpy = NULL;
vid_window = (Window)NULL;
#endif
}
void GLVID_DeInit(void) //FIXME:....
{
GLVID_Shutdown();
}
void signal_handler(int sig)
{
printf("Received signal %d, exiting...\n", sig);
Sys_Quit();
exit(0);
}
void InitSig(void)
{
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGILL, signal_handler);
signal(SIGTRAP, signal_handler);
#ifndef __CYGWIN__
signal(SIGIOT, signal_handler);
#endif
signal(SIGBUS, signal_handler);
signal(SIGFPE, signal_handler);
signal(SIGSEGV, signal_handler);
signal(SIGTERM, signal_handler);
}
static Cursor CreateNullCursor(Display *display, Window root)
{
Pixmap cursormask;
XGCValues xgc;
GC gc;
XColor dummycolour;
Cursor cursor;
cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
xgc.function = GXclear;
gc = XCreateGC(display, cursormask, GCFunction, &xgc);
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
dummycolour.pixel = 0;
dummycolour.red = 0;
dummycolour.flags = 04;
cursor = XCreatePixmapCursor(display, cursormask, cursormask,
&dummycolour,&dummycolour, 0,0);
XFreePixmap(display,cursormask);
XFreeGC(display,gc);
return cursor;
}
void GLVID_ShiftPalette (unsigned char *palette)
{
#ifdef WITH_VMODE
extern qboolean gammaworks;
extern cvar_t vid_hardwaregamma;
extern unsigned short ramps[3][256];
// VID_SetPalette (palette);
if (originalapplied && ActiveApp && vid_hardwaregamma.value) //this is needed because ATI drivers don't work properly (or when task-switched out).
{
if (gammaworks)
{ //we have hardware gamma applied - if we're doing a BF, we don't want to reset to the default gamma (yuck)
XF86VidModeSetGammaRamp (vid_dpy, scrnum, 256, ramps[0], ramps[1], ramps[2]);
return;
}
gammaworks = !!XF86VidModeSetGammaRamp (vid_dpy, scrnum, 256, ramps[0], ramps[1], ramps[2]);
}
else
gammaworks = false;
#endif
}
void GLVID_SetPalette (unsigned char *palette)
{
qbyte *pal;
unsigned r,g,b;
unsigned short i;
unsigned *table;
extern qbyte gammatable[256];
//
// 8 8 8 encoding
//
Con_Printf("Converting 8to24\n");
pal = palette;
table = d_8to24rgbtable;
for (i=0 ; i<256 ; i++)
{
r = gammatable[pal[0]];
g = gammatable[pal[1]];
b = gammatable[pal[2]];
pal += 3;
*table++ = BigLong((r<<24)|(g<<16)|(b<<8)|255);
}
d_8to24rgbtable[255] &= BigLong(0xffffff00); // 255 is transparent
}
/*
=================
GL_BeginRendering
=================
*/
void GL_BeginRendering (void)
{
#ifdef USE_EGL
EGL_BeginRendering();
#endif
}
void GL_EndRendering (void)
{
#ifdef USE_EGL
EGL_EndRendering();
#else
//return;
//we don't need the flush, XSawpBuffers does it for us.
//chances are, it's version is more suitable anyway. At least there's the chance that it might be.
qglXSwapBuffers(vid_dpy, vid_window);
#endif
}
qboolean GLVID_Is8bit(void)
{
return is8bit;
}
qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
{
int i;
int attrib[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 1,
GLX_STENCIL_SIZE, 8,
None
};
XSetWindowAttributes attr;
unsigned long mask;
Window root;
#ifdef USE_EGL
XVisualInfo vinfodef;
#endif
XVisualInfo *visinfo;
qboolean fullscreen = false;
Atom prots[1];
#ifdef WITH_VMODE
int MajorVersion, MinorVersion;
if (info->fullscreen)
fullscreen = true;
#endif
S_Startup();
#ifdef USE_EGL
if (!EGL_LoadLibrary(info->glrenderer))
{
Con_Printf("couldn't load EGL library\n");
return false;
}
#else
if (!GLX_InitLibrary(info->glrenderer))
{
Con_Printf("Couldn't intialise GLX\nEither your drivers are not installed or you need to specify the library name with the gl_driver cvar\n");
return false;
}
#endif
// interpret command-line params
// set vid parameters
if ((i = COM_CheckParm("-conwidth")) != 0)
vid.width = Q_atoi(com_argv[i+1]);
else
vid.width = 640;
vid.width &= ~7; // make it a multiple of eight
if (vid.width < 320)
vid.width = 320;
// pick a conheight that matches with correct aspect
vid.height = vid.width*3 / 4;
if ((i = COM_CheckParm("-conheight")) != 0)
vid.height = Q_atoi(com_argv[i+1]);
if (vid.height < 200)
vid.height = 200;
if (!vid_dpy)
vid_dpy = XOpenDisplay(NULL);
if (!vid_dpy)
{
Con_Printf(CON_ERROR "Error: couldn't open the X display\n");
return false;
}
scrnum = DefaultScreen(vid_dpy);
root = RootWindow(vid_dpy, scrnum);
#ifdef WITH_VMODE //find out if it's supported on this pc.
MajorVersion = MinorVersion = 0;
if (COM_CheckParm("-novmode") || !XF86VidModeQueryVersion(vid_dpy, &MajorVersion, &MinorVersion))
{
vidmode_ext = 0;
}
else
{
Con_Printf("Using XF86-VidModeExtension Ver. %d.%d\n", MajorVersion, MinorVersion);
vidmode_ext = MajorVersion;
}
#endif
#ifdef WITH_VMODE
vidmode_usemode = -1;
if (vidmode_ext)
{
int best_fit, best_dist, dist, x, y;
XF86VidModeGetAllModeLines(vid_dpy, scrnum, &num_vidmodes, &vidmodes);
// Are we going fullscreen? If so, let's change video mode
if (fullscreen)
{
best_dist = 9999999;
best_fit = -1;
for (i = 0; i < num_vidmodes; i++)
{
if (info->width > vidmodes[i]->hdisplay ||
info->height > vidmodes[i]->vdisplay)
continue;
x = info->width - vidmodes[i]->hdisplay;
y = info->height - vidmodes[i]->vdisplay;
dist = (x * x) + (y * y);
if (dist < best_dist)
{
best_dist = dist;
best_fit = i;
}
}
if (best_fit != -1 && (!best_dist || COM_CheckParm("-fullscreen")))
{
// change to the mode
XF86VidModeSwitchToMode(vid_dpy, scrnum, vidmodes[vidmode_usemode=best_fit]);
vidmode_active = true;
// Move the viewport to top left
XF86VidModeSetViewPort(vid_dpy, scrnum, 0, 0);
}
else
fullscreen = 0;
}
}
#endif
vidglx_fullscreen = fullscreen;
#ifdef USE_EGL
visinfo = &vinfodef;
if (!XMatchVisualInfo(vid_dpy, scrnum, info->bpp, TrueColor, visinfo))
// if (!XMatchVisualInfo(vid_dpy, scrnum, DefaultDepth(vid_dpy, scrnum), TrueColor, &visinfo))
{
Sys_Error("Couldn't choose visual for EGL\n");
}
#else
visinfo = qglXChooseVisual(vid_dpy, scrnum, attrib);
if (!visinfo)
{
Sys_Error("qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
}
#endif
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap(vid_dpy, root, visinfo->visual, AllocNone);
attr.event_mask = X_MASK;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
#ifdef WITH_VMODE //get rid of borders
// fullscreen
if (vidmode_active) {
mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore |
CWEventMask | CWOverrideRedirect;
attr.override_redirect = True;
attr.backing_store = NotUseful;
attr.save_under = False;
}
#endif
vid_window = XCreateWindow(vid_dpy, root, 0, 0, info->width, info->height,
0, visinfo->depth, InputOutput,
visinfo->visual, mask, &attr);
ActiveApp = false;
/*ask the window manager to stop triggering bugs in Xlib*/
prots[0] = XInternAtom(vid_dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(vid_dpy, vid_window, prots, sizeof(prots)/sizeof(prots[0]));
/*set caption*/
XStoreName(vid_dpy, vid_window, "FTE QuakeWorld");
/*make it visibl*/
XMapWindow(vid_dpy, vid_window);
/*put it somewhere*/
XMoveWindow(vid_dpy, vid_window, 0, 0);
//XFree(visinfo);
#ifdef WITH_VMODE
if (vidmode_active) {
XRaiseWindow(vid_dpy, vid_window);
XWarpPointer(vid_dpy, None, vid_window, 0, 0, 0, 0, 0, 0);
XFlush(vid_dpy);
// Move the viewport to top left
XF86VidModeSetViewPort(vid_dpy, scrnum, 0, 0);
}
#endif
//hide the cursor.
XDefineCursor(vid_dpy, vid_window, CreateNullCursor(vid_dpy, vid_window));
XFlush(vid_dpy);
#ifndef USE_EGL
#ifdef WITH_VMODE
if (vidmode_ext >= 2)
{
int rampsize = 256;
XF86VidModeGetGammaRampSize(vid_dpy, scrnum, &rampsize);
if (rampsize != 256)
{
originalapplied = false;
Con_Printf("Gamma ramps are not of 256 components (but %i).\n", rampsize);
}
else
originalapplied = XF86VidModeGetGammaRamp(vid_dpy, scrnum, 256, originalramps[0], originalramps[1], originalramps[2]);
}
else
originalapplied = false;
#endif
ctx = qglXCreateContext(vid_dpy, visinfo, NULL, True);
if (!ctx)
{
Con_Printf("Failed to create GLX context.\n");
GLVID_Shutdown();
return false;
}
if (!qglXMakeCurrent(vid_dpy, vid_window, ctx))
{
Con_Printf("glXMakeCurrent failed\n");
GLVID_Shutdown();
return false;
}
GL_Init(&GLX_GetSymbol);
#else
EGL_Init(info, palette, vid_window);
GL_Init(&EGL_Proc);
#endif
GLVID_SetPalette(palette);
GLVID_ShiftPalette(palette);
qglGetIntegerv(GL_STENCIL_BITS, &gl_canstencil);
InitSig(); // trap evil signals
vid.pixelwidth = info->width;
vid.pixelheight = info->height;
if (vid.height > info->height)
vid.height = info->height;
if (vid.width > info->width)
vid.width = info->width;
vid.numpages = 2;
Con_SafePrintf ("Video mode %dx%d initialized.\n", info->width, info->height);
vid.recalc_refdef = 1; // force a surface cache flush
if (Cvar_Get("vidx_grabkeyboard", "0", 0, "Additional video options")->value)
XGrabKeyboard(vid_dpy, vid_window,
False,
GrabModeAsync, GrabModeAsync,
CurrentTime);
else
XSetInputFocus(vid_dpy, vid_window, RevertToParent, CurrentTime);
XRaiseWindow(vid_dpy, vid_window);
return true;
}
void Sys_SendKeyEvents(void)
{
if (vid_dpy && vid_window) {
while (XPending(vid_dpy))
GetEvent();
}
}
void Force_CenterView_f (void)
{
cl.viewangles[0][PITCH] = 0;
}
void IN_ReInit(void)
{
}
void IN_Init(void)
{
IN_ReInit();
}
void IN_Shutdown(void)
{
}
/*
===========
IN_Commands
===========
*/
void IN_Commands (void)
{
}
/*
===========
IN_Move
===========
*/
void IN_MouseMove (float *movements, int pnum)
{
extern int mousecursor_x, mousecursor_y;
extern int mousemove_x, mousemove_y;
float mx, my;
mx = mouse_x;
my = mouse_y;
if (Key_MouseShouldBeFree())
{
mousemove_x += mouse_x;
mousemove_y += mouse_y;
mousecursor_x += mouse_x;
mousecursor_y += mouse_y;
if (mousecursor_y<0)
mousecursor_y=0;
if (mousecursor_x<0)
mousecursor_x=0;
if (mousecursor_x >= vid.width)
mousecursor_x = vid.width - 1;
if (mousecursor_y >= vid.height)
mousecursor_y = vid.height - 1;
mouse_x=mouse_y=0;
#ifdef VM_UI
UI_MousePosition(mousecursor_x, mousecursor_y);
#endif
#ifdef PEXT_CSQC
if (CSQC_MousePosition(mousecursor_x, mousecursor_y))
{
mx = 0;
my = 0;
}
#endif
}
else
{
#ifdef PEXT_CSQC
if (CSQC_MouseMove(mx, my))
{
mx = 0;
my = 0;
}
#endif
}
if (m_filter.value)
{
float fraction = bound(0, m_filter.value, 2) * 0.5;
mouse_x = (mouse_x*(1-fraction) + old_mouse_x*fraction);
mouse_y = (mouse_y*(1-fraction) + old_mouse_y*fraction);
}
old_mouse_x = mx;
old_mouse_y = my;
if (m_accel.value) {
float mouse_deltadist = sqrt(mx*mx + my*my);
mouse_x *= (mouse_deltadist*m_accel.value + sensitivity.value*in_sensitivityscale);
mouse_y *= (mouse_deltadist*m_accel.value + sensitivity.value*in_sensitivityscale);
} else {
mouse_x *= sensitivity.value*in_sensitivityscale;
mouse_y *= sensitivity.value*in_sensitivityscale;
}
if(in_xflip.value) mouse_x *= -1;
if (movements)
{
// add mouse X/Y movement to cmd
if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) ))
movements[1] += m_side.value * mouse_x;
else
cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state[pnum] & 1)
V_StopPitchDrift (pnum);
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1))
{
cl.viewangles[pnum][PITCH] += m_pitch.value * mouse_y;
CL_ClampPitch(pnum);
}
else
{
if ((in_strafe.state[pnum] & 1) && noclip_anglehack)
movements[2] -= m_forward.value * mouse_y;
else
movements[0] -= m_forward.value * mouse_y;
}
}
mouse_x = mouse_y = 0.0;
}
void IN_Move (float *movements, int pnum)
{
IN_MouseMove(movements, pnum);
}
void GL_DoSwap(void) {}
void GLVID_SetCaption(char *text)
{
XStoreName(vid_dpy, vid_window, text);
}