📄 rw_x11.c
字号:
/*
Copyright (C) 1997-2001 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.
*/
/*
** RW_X11.C
**
** This file contains ALL Linux specific stuff having to do with the
** software refresh. When a port is being made the following functions
** must be implemented by the port:
**
** SWimp_EndFrame
** SWimp_Init
** SWimp_InitGraphics
** SWimp_SetPalette
** SWimp_Shutdown
** SWimp_SwitchFullscreen
*/
#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/xf86dga.h>
#include "../ref_soft/r_local.h"
#include "../client/keys.h"
#include "../linux/rw_linux.h"
/*****************************************************************************/
static qboolean doShm;
static Display *dpy;
static Colormap x_cmap;
static Window win;
static GC x_gc;
static Visual *x_vis;
static XVisualInfo *x_visinfo;
static int win_x, win_y;
#define KEY_MASK (KeyPressMask | KeyReleaseMask)
#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask | ButtonMotionMask )
#define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask | ExposureMask )
static int x_shmeventtype;
//static XShmSegmentInfo x_shminfo;
static qboolean oktodraw = false;
static qboolean ignorefirst = false;
static qboolean exposureflag = false;
static qboolean X11_active = false;
int XShmQueryExtension(Display *);
int XShmGetEventBase(Display *);
int current_framebuffer;
static XImage *x_framebuffer[2] = { 0, 0 };
static XShmSegmentInfo x_shminfo[2];
int config_notify=0;
int config_notify_width;
int config_notify_height;
typedef unsigned short PIXEL16;
typedef unsigned long PIXEL24;
static PIXEL16 st2d_8to16table[256];
static PIXEL24 st2d_8to24table[256];
static int shiftmask_fl=0;
static long r_shift,g_shift,b_shift;
static unsigned long r_mask,g_mask,b_mask;
void shiftmask_init(void)
{
unsigned int x;
r_mask=x_vis->red_mask;
g_mask=x_vis->green_mask;
b_mask=x_vis->blue_mask;
for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++;
for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++;
for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++;
shiftmask_fl=1;
}
PIXEL16 xlib_rgb16(int r,int g,int b)
{
PIXEL16 p;
if(shiftmask_fl==0) shiftmask_init();
p=0;
if(r_shift>0) {
p=(r<<(r_shift))&r_mask;
} else if(r_shift<0) {
p=(r>>(-r_shift))&r_mask;
} else p|=(r&r_mask);
if(g_shift>0) {
p|=(g<<(g_shift))&g_mask;
} else if(g_shift<0) {
p|=(g>>(-g_shift))&g_mask;
} else p|=(g&g_mask);
if(b_shift>0) {
p|=(b<<(b_shift))&b_mask;
} else if(b_shift<0) {
p|=(b>>(-b_shift))&b_mask;
} else p|=(b&b_mask);
return p;
}
PIXEL24 xlib_rgb24(int r,int g,int b)
{
PIXEL24 p;
if(shiftmask_fl==0) shiftmask_init();
p=0;
if(r_shift>0) {
p=(r<<(r_shift))&r_mask;
} else if(r_shift<0) {
p=(r>>(-r_shift))&r_mask;
} else p|=(r&r_mask);
if(g_shift>0) {
p|=(g<<(g_shift))&g_mask;
} else if(g_shift<0) {
p|=(g>>(-g_shift))&g_mask;
} else p|=(g&g_mask);
if(b_shift>0) {
p|=(b<<(b_shift))&b_mask;
} else if(b_shift<0) {
p|=(b>>(-b_shift))&b_mask;
} else p|=(b&b_mask);
return p;
}
void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
{
int xi,yi;
unsigned char *src;
PIXEL16 *dest;
register int count, n;
if( (x<0)||(y<0) )return;
for (yi = y; yi < (y+height); yi++) {
src = &framebuf->data [yi * framebuf->bytes_per_line];
// Duff's Device
count = width;
n = (count + 7) / 8;
dest = ((PIXEL16 *)src) + x+width - 1;
src += x+width - 1;
switch (count % 8) {
case 0: do { *dest-- = st2d_8to16table[*src--];
case 7: *dest-- = st2d_8to16table[*src--];
case 6: *dest-- = st2d_8to16table[*src--];
case 5: *dest-- = st2d_8to16table[*src--];
case 4: *dest-- = st2d_8to16table[*src--];
case 3: *dest-- = st2d_8to16table[*src--];
case 2: *dest-- = st2d_8to16table[*src--];
case 1: *dest-- = st2d_8to16table[*src--];
} while (--n > 0);
}
// for(xi = (x+width-1); xi >= x; xi--) {
// dest[xi] = st2d_8to16table[src[xi]];
// }
}
}
void st3_fixup( XImage *framebuf, int x, int y, int width, int height)
{
int xi,yi;
unsigned char *src;
PIXEL24 *dest;
register int count, n;
if( (x<0)||(y<0) )return;
for (yi = y; yi < (y+height); yi++) {
src = &framebuf->data [yi * framebuf->bytes_per_line];
// Duff's Device
count = width;
n = (count + 7) / 8;
dest = ((PIXEL24 *)src) + x+width - 1;
src += x+width - 1;
switch (count % 8) {
case 0: do { *dest-- = st2d_8to24table[*src--];
case 7: *dest-- = st2d_8to24table[*src--];
case 6: *dest-- = st2d_8to24table[*src--];
case 5: *dest-- = st2d_8to24table[*src--];
case 4: *dest-- = st2d_8to24table[*src--];
case 3: *dest-- = st2d_8to24table[*src--];
case 2: *dest-- = st2d_8to24table[*src--];
case 1: *dest-- = st2d_8to24table[*src--];
} while (--n > 0);
}
// for(xi = (x+width-1); xi >= x; xi--) {
// dest[xi] = st2d_8to16table[src[xi]];
// }
}
}
// 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 old_mouse_x, old_mouse_y;
static int mx, my;
static qboolean mouse_active = false;
static qboolean dgamouse = false;
static cvar_t *m_filter;
static cvar_t *in_mouse;
static cvar_t *in_dgamouse;
static cvar_t *vid_xpos; // X coordinate of window position
static cvar_t *vid_ypos; // Y coordinate of window position
static qboolean mlooking;
// state struct passed in Init
static in_state_t *in_state;
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;
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;
in_state = in_state_p;
// mouse variables
m_filter = ri.Cvar_Get ("m_filter", "0", 0);
in_mouse = ri.Cvar_Get ("in_mouse", "0", CVAR_ARCHIVE);
in_dgamouse = ri.Cvar_Get ("in_dgamouse", "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_avail = true;
}
void RW_IN_Shutdown(void)
{
mouse_avail = false;
}
/*
===========
IN_Commands
===========
*/
void RW_IN_Commands (void)
{
int i;
if (!mouse_avail)
return;
for (i=0 ; i<3 ; i++) {
if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
in_state->Key_Event_fp (K_MOUSE1 + i, true);
if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
in_state->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)
{
mx = (mx + old_mouse_x) * 0.5;
my = (my + old_mouse_y) * 0.5;
}
old_mouse_x = mx;
old_mouse_y = my;
mx *= sensitivity->value;
my *= sensitivity->value;
// add mouse X/Y movement to cmd
if ( (*in_state->in_strafe_state & 1) ||
(lookstrafe->value && mlooking ))
cmd->sidemove += m_side->value * mx;
else
in_state->viewangles[YAW] -= m_yaw->value * mx;
if ( (mlooking || freelook->value) &&
!(*in_state->in_strafe_state & 1))
{
in_state->viewangles[PITCH] += m_pitch->value * my;
}
else
{
cmd->forwardmove -= m_forward->value * my;
}
mx = my = 0;
}
// ========================================================================
// makes a null cursor
// ========================================================================
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;
}
static void install_grabs(void)
{
// inviso cursor
XDefineCursor(dpy, win, CreateNullCursor(dpy, win));
XGrabPointer(dpy, win,
True,
0,
GrabModeAsync, GrabModeAsync,
win,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -