1 line
20 KiB
C++
1 line
20 KiB
C++
// I_X.c, Doom for X
|
|
|
|
#include <stdlib.h>
|
|
#include <sys/ipc.h>
|
|
#include <sys/shm.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/keysym.h>
|
|
#include <X11/extensions/XShm.h>
|
|
#include <stdarg.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include "doomdef.h"
|
|
|
|
#define POINTER_WARP_COUNTDOWN 1
|
|
|
|
Display *X_display=0;
|
|
Window X_mainWindow;
|
|
Colormap X_cmap;
|
|
Visual *X_visual;
|
|
GC X_gc;
|
|
XEvent X_event;
|
|
int X_screen;
|
|
XVisualInfo X_visualinfo;
|
|
XImage *image;
|
|
int X_width, X_height;
|
|
boolean doShm;
|
|
XShmSegmentInfo X_shminfo;
|
|
int X_shmeventtype;
|
|
boolean grabMouse;
|
|
int doPointerWarp = POINTER_WARP_COUNTDOWN;
|
|
static int multiply=1;
|
|
|
|
//
|
|
// Translates the key currently in X_event
|
|
//
|
|
|
|
int xlatekey(void)
|
|
{
|
|
|
|
int rc;
|
|
|
|
switch(rc = XKeycodeToKeysym(X_display, X_event.xkey.keycode, 0))
|
|
{
|
|
case XK_Left: rc = KEY_LEFTARROW; break;
|
|
case XK_Right: rc = KEY_RIGHTARROW; break;
|
|
case XK_Down: rc = KEY_DOWNARROW; break;
|
|
case XK_Up: rc = KEY_UPARROW; break;
|
|
case XK_Escape: rc = KEY_ESCAPE; break;
|
|
case XK_Return: rc = KEY_ENTER; break;
|
|
case XK_Tab: rc = KEY_TAB; break;
|
|
case XK_F1: rc = KEY_F1; break;
|
|
case XK_F2: rc = KEY_F2; break;
|
|
case XK_F3: rc = KEY_F3; break;
|
|
case XK_F4: rc = KEY_F4; break;
|
|
case XK_F5: rc = KEY_F5; break;
|
|
case XK_F6: rc = KEY_F6; break;
|
|
case XK_F7: rc = KEY_F7; break;
|
|
case XK_F8: rc = KEY_F8; break;
|
|
case XK_F9: rc = KEY_F9; break;
|
|
case XK_F10: rc = KEY_F10; break;
|
|
case XK_F11: rc = KEY_F11; break;
|
|
case XK_F12: rc = KEY_F12; break;
|
|
case XK_BackSpace:
|
|
case XK_Delete: rc = KEY_BACKSPACE; break;
|
|
case XK_Pause: rc = KEY_PAUSE; break;
|
|
case XK_KP_Equal:
|
|
case XK_equal: rc = KEY_EQUALS; break;
|
|
case XK_KP_Subtract:
|
|
case XK_minus: rc = KEY_MINUS; break;
|
|
case XK_Shift_L:
|
|
case XK_Shift_R: rc = KEY_RSHIFT; break;
|
|
case XK_Control_L:
|
|
case XK_Control_R: rc = KEY_RCTRL; break;
|
|
case XK_Alt_L:
|
|
case XK_Meta_L:
|
|
case XK_Alt_R:
|
|
case XK_Meta_R: rc = KEY_RALT; break;
|
|
default:
|
|
if (rc >= XK_space && rc <= XK_asciitilde)
|
|
rc = rc - XK_space + ' ';
|
|
if (rc >= 'A' && rc <= 'Z')
|
|
rc = rc - 'A' + 'a';
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
void I_ShutdownGraphics(void)
|
|
{
|
|
// get rid of shared memory
|
|
shmdt(X_shminfo.shmaddr);
|
|
shmctl(X_shminfo.shmid, IPC_RMID, 0);
|
|
}
|
|
|
|
/*
|
|
================
|
|
=
|
|
= I_Error
|
|
=
|
|
================
|
|
*/
|
|
|
|
extern boolean demorecording;
|
|
|
|
void I_Error (char *error, ...)
|
|
{
|
|
va_list argptr;
|
|
char string[1024];
|
|
|
|
if (demorecording)
|
|
G_CheckDemoStatus();
|
|
|
|
D_QuitNetGame ();
|
|
I_ShutdownGraphics();
|
|
va_start (argptr,error);
|
|
fprintf (stderr, "Error: ");
|
|
vfprintf (stderr,error,argptr);
|
|
fprintf (stderr, "\n");
|
|
va_end (argptr);
|
|
exit(-1);
|
|
}
|
|
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= I_StartFrame
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void I_StartFrame (void)
|
|
{
|
|
|
|
// er?
|
|
|
|
}
|
|
|
|
static int lastmousex = 0;
|
|
static int lastmousey = 0;
|
|
boolean mousemoved = false;
|
|
boolean shmFinished;
|
|
|
|
void I_GetEvent(void)
|
|
{
|
|
|
|
event_t event;
|
|
|
|
// put event-grabbing stuff in here
|
|
XNextEvent(X_display, &X_event);
|
|
switch (X_event.type)
|
|
{
|
|
case KeyPress:
|
|
event.type = ev_keydown;
|
|
event.data1 = xlatekey();
|
|
D_PostEvent(&event);
|
|
// fprintf(stderr, "k");
|
|
break;
|
|
case KeyRelease:
|
|
event.type = ev_keyup;
|
|
event.data1 = xlatekey();
|
|
D_PostEvent(&event);
|
|
// fprintf(stderr, "ku");
|
|
break;
|
|
case ButtonPress:
|
|
event.type = ev_mouse;
|
|
event.data1 = (X_event.xbutton.state & Button1Mask)
|
|
| (X_event.xbutton.state & Button2Mask ? 2 : 0)
|
|
| (X_event.xbutton.state & Button3Mask ? 4 : 0)
|
|
| (X_event.xbutton.button == Button1)
|
|
| (X_event.xbutton.button == Button2 ? 2 : 0)
|
|
| (X_event.xbutton.button == Button3 ? 4 : 0);
|
|
event.data2 = event.data3 = 0;
|
|
D_PostEvent(&event);
|
|
// fprintf(stderr, "b");
|
|
break;
|
|
case ButtonRelease:
|
|
event.type = ev_mouse;
|
|
event.data1 = (X_event.xbutton.state & Button1Mask)
|
|
| (X_event.xbutton.state & Button2Mask ? 2 : 0)
|
|
| (X_event.xbutton.state & Button3Mask ? 4 : 0)
|
|
^ (X_event.xbutton.button == Button1 ? 1 : 0)
|
|
^ (X_event.xbutton.button == Button2 ? 2 : 0)
|
|
^ (X_event.xbutton.button == Button3 ? 4 : 0);
|
|
event.data2 = event.data3 = 0;
|
|
D_PostEvent(&event);
|
|
// fprintf(stderr, "bu");
|
|
break;
|
|
case MotionNotify:
|
|
event.type = ev_mouse;
|
|
event.data1 = (X_event.xmotion.state & Button1Mask)
|
|
| (X_event.xmotion.state & Button2Mask ? 2 : 0)
|
|
| (X_event.xmotion.state & Button3Mask ? 4 : 0);
|
|
event.data2 = (X_event.xmotion.x - lastmousex) << 2;
|
|
event.data3 = (lastmousey - X_event.xmotion.y) << 2;
|
|
if (event.data2 || event.data3)
|
|
{
|
|
lastmousex = X_event.xmotion.x;
|
|
lastmousey = X_event.xmotion.y;
|
|
if (X_event.xmotion.x != X_width/2 &&
|
|
X_event.xmotion.y != X_height/2)
|
|
{
|
|
D_PostEvent(&event);
|
|
// fprintf(stderr, "m");
|
|
mousemoved = false;
|
|
} else
|
|
{
|
|
mousemoved = true;
|
|
}
|
|
}
|
|
break;
|
|
case Expose:
|
|
case ConfigureNotify:
|
|
break;
|
|
default:
|
|
if (doShm && X_event.type == X_shmeventtype) shmFinished = true;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= I_StartTic
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void I_StartTic (void)
|
|
{
|
|
|
|
if (!X_display) return;
|
|
|
|
while (XPending(X_display)) I_GetEvent();
|
|
|
|
// warp the pointer back to the middle of the window or it'll wander off
|
|
if (grabMouse)
|
|
{
|
|
if (!--doPointerWarp)
|
|
{
|
|
XWarpPointer( X_display,
|
|
None,
|
|
X_mainWindow,
|
|
0, 0,
|
|
0, 0,
|
|
X_width/2, X_height/2);
|
|
|
|
doPointerWarp = POINTER_WARP_COUNTDOWN;
|
|
}
|
|
}
|
|
|
|
mousemoved = false;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= I_UpdateNoBlit
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void I_UpdateNoBlit (void)
|
|
{
|
|
// what is this?
|
|
}
|
|
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= I_FinishUpdate
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void I_FinishUpdate (void)
|
|
{
|
|
|
|
static int lasttic;
|
|
int tics, i;
|
|
static unsigned char *bigscreen=0;
|
|
|
|
// draws little dots on the bottom of the screen
|
|
if (devparm)
|
|
{
|
|
|
|
i = I_GetTime();
|
|
tics = i - lasttic;
|
|
lasttic = i;
|
|
if (tics > 20) tics = 20;
|
|
|
|
for (i=0 ; i<tics*2 ; i+=2)
|
|
screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0xff;
|
|
for ( ; i<20*2 ; i+=2)
|
|
screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0x0;
|
|
|
|
}
|
|
|
|
// scales the screen size before blitting it
|
|
if (multiply == 2)
|
|
{
|
|
unsigned int *olineptrs[2];
|
|
unsigned int *ilineptr;
|
|
int x, y, i;
|
|
unsigned int twoopixels;
|
|
unsigned int twomoreopixels;
|
|
unsigned int fouripixels;
|
|
|
|
ilineptr = (unsigned int *) (screens[0]);
|
|
for (i=0 ; i<2 ; i++)
|
|
olineptrs[i] = (unsigned int *) &image->data[i*X_width];
|
|
|
|
y = SCREENHEIGHT;
|
|
while (y--)
|
|
{
|
|
x = SCREENWIDTH;
|
|
do
|
|
{
|
|
fouripixels = *ilineptr++;
|
|
twoopixels = (fouripixels & 0xff000000)
|
|
| ((fouripixels>>8) & 0xffff00)
|
|
| ((fouripixels>>16) & 0xff);
|
|
twomoreopixels = ((fouripixels<<16) & 0xff000000)
|
|
| ((fouripixels<<8) & 0xffff00)
|
|
| (fouripixels & 0xff);
|
|
#ifdef __BIG_ENDIAN__
|
|
*olineptrs[0]++ = twoopixels;
|
|
*olineptrs[1]++ = twoopixels;
|
|
*olineptrs[0]++ = twomoreopixels;
|
|
*olineptrs[1]++ = twomoreopixels;
|
|
#else
|
|
*olineptrs[0]++ = twomoreopixels;
|
|
*olineptrs[1]++ = twomoreopixels;
|
|
*olineptrs[0]++ = twoopixels;
|
|
*olineptrs[1]++ = twoopixels;
|
|
#endif
|
|
} while (x-=4);
|
|
olineptrs[0] += X_width/4;
|
|
olineptrs[1] += X_width/4;
|
|
}
|
|
|
|
}
|
|
else if (multiply == 3)
|
|
{
|
|
unsigned int *olineptrs[3];
|
|
unsigned int *ilineptr;
|
|
int x, y, i;
|
|
unsigned int fouropixels[3];
|
|
unsigned int fouripixels;
|
|
|
|
ilineptr = (unsigned int *) (screens[0]);
|
|
for (i=0 ; i<3 ; i++)
|
|
olineptrs[i] = (unsigned int *) &image->data[i*X_width];
|
|
|
|
y = SCREENHEIGHT;
|
|
while (y--)
|
|
{
|
|
x = SCREENWIDTH;
|
|
do
|
|
{
|
|
fouripixels = *ilineptr++;
|
|
fouropixels[0] = (fouripixels & 0xff000000)
|
|
| ((fouripixels>>8) & 0xff0000)
|
|
| ((fouripixels>>16) & 0xffff);
|
|
fouropixels[1] = ((fouripixels<<8) & 0xff000000)
|
|
| (fouripixels & 0xffff00)
|
|
| ((fouripixels>>8) & 0xff);
|
|
fouropixels[2] = ((fouripixels<<16) & 0xffff0000)
|
|
| ((fouripixels<<8) & 0xff00)
|
|
| (fouripixels & 0xff);
|
|
#ifdef __BIG_ENDIAN__
|
|
*olineptrs[0]++ = fouropixels[0];
|
|
*olineptrs[1]++ = fouropixels[0];
|
|
*olineptrs[2]++ = fouropixels[0];
|
|
*olineptrs[0]++ = fouropixels[1];
|
|
*olineptrs[1]++ = fouropixels[1];
|
|
*olineptrs[2]++ = fouropixels[1];
|
|
*olineptrs[0]++ = fouropixels[2];
|
|
*olineptrs[1]++ = fouropixels[2];
|
|
*olineptrs[2]++ = fouropixels[2];
|
|
#else
|
|
*olineptrs[0]++ = fouropixels[2];
|
|
*olineptrs[1]++ = fouropixels[2];
|
|
*olineptrs[2]++ = fouropixels[2];
|
|
*olineptrs[0]++ = fouropixels[1];
|
|
*olineptrs[1]++ = fouropixels[1];
|
|
*olineptrs[2]++ = fouropixels[1];
|
|
*olineptrs[0]++ = fouropixels[0];
|
|
*olineptrs[1]++ = fouropixels[0];
|
|
*olineptrs[2]++ = fouropixels[0];
|
|
#endif
|
|
} while (x-=4);
|
|
olineptrs[0] += 2*X_width/4;
|
|
olineptrs[1] += 2*X_width/4;
|
|
olineptrs[2] += 2*X_width/4;
|
|
}
|
|
|
|
}
|
|
else if (multiply == 4)
|
|
{
|
|
void Expand4(unsigned *, double *);
|
|
Expand4 ((unsigned *)(screens[0]), (double *) (image->data));
|
|
}
|
|
|
|
if (doShm)
|
|
{
|
|
|
|
if (!XShmPutImage( X_display,
|
|
X_mainWindow,
|
|
X_gc,
|
|
image,
|
|
0, 0,
|
|
0, 0,
|
|
X_width, X_height,
|
|
True ))
|
|
I_Error("XShmPutImage() failed\n");
|
|
|
|
// wait for it to finish and processes all input events
|
|
shmFinished = false;
|
|
do {
|
|
I_GetEvent();
|
|
} while (!shmFinished);
|
|
|
|
} else {
|
|
|
|
// draw the image
|
|
XPutImage( X_display,
|
|
X_mainWindow,
|
|
X_gc,
|
|
image,
|
|
0, 0,
|
|
0, 0,
|
|
X_width, X_height );
|
|
|
|
// sync up with server
|
|
XSync(X_display, False);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= I_ReadScreen
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void I_ReadScreen (byte *scr)
|
|
{
|
|
memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
|
|
}
|
|
|
|
static XColor colors[256];
|
|
|
|
void UploadNewPalette(Colormap cmap, byte *palette)
|
|
{
|
|
|
|
register int i, c;
|
|
static boolean firstcall = true;
|
|
|
|
#ifdef __cplusplus
|
|
if (X_visualinfo.c_class == PseudoColor && X_visualinfo.depth == 8)
|
|
#else
|
|
if (X_visualinfo.class == PseudoColor && X_visualinfo.depth == 8)
|
|
#endif
|
|
{
|
|
|
|
// initialize the colormap
|
|
if (firstcall)
|
|
{
|
|
firstcall = false;
|
|
for (i=0 ; i<256 ; i++)
|
|
{
|
|
colors[i].pixel = i;
|
|
colors[i].flags = DoRed|DoGreen|DoBlue;
|
|
}
|
|
}
|
|
|
|
// set the X colormap entries
|
|
for (i=0 ; i<256 ; i++)
|
|
{
|
|
c = gammatable[usegamma][*palette++];
|
|
colors[i].red = (c<<8) + c;
|
|
c = gammatable[usegamma][*palette++];
|
|
colors[i].green = (c<<8) + c;
|
|
c = gammatable[usegamma][*palette++];
|
|
colors[i].blue = (c<<8) + c;
|
|
}
|
|
|
|
// store the colors to the current colormap
|
|
XStoreColors(X_display, cmap, colors, 256);
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= I_SetPalette
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void I_SetPalette (byte *palette)
|
|
{
|
|
UploadNewPalette(X_cmap, palette);
|
|
}
|
|
|
|
void grabsharedmemory(int size)
|
|
{
|
|
|
|
int key = ('d'<<24) | ('o'<<16) | ('o'<<8) | 'm';
|
|
struct shmid_ds shminfo;
|
|
int minsize = 320*200;
|
|
int id, rc, done=0, pollution=5;
|
|
|
|
// try to use what was here before
|
|
do
|
|
{
|
|
id = shmget((key_t) key, minsize, 0777); // just get the id
|
|
if (id != -1)
|
|
{
|
|
rc=shmctl(id, IPC_STAT, &shminfo); // get stats on it
|
|
if (!rc)
|
|
{
|
|
if (shminfo.shm_nattch)
|
|
{
|
|
fprintf(stderr, "User %d appears to be running "
|
|
"DOOM. Is that wise?\n", shminfo.shm_cpid);
|
|
key++;
|
|
}
|
|
else
|
|
{
|
|
if (getuid() == shminfo.shm_perm.cuid)
|
|
{
|
|
rc = shmctl(id, IPC_RMID, 0);
|
|
if (!rc) fprintf(stderr,
|
|
"Was able to kill my old shared memory\n");
|
|
else I_Error(
|
|
"Was NOT able to kill my old shared memory");
|
|
|
|
id = shmget((key_t)key, size, IPC_CREAT|0777);
|
|
if (id==-1)
|
|
I_Error("Could not get shared memory");
|
|
|
|
rc=shmctl(id, IPC_STAT, &shminfo);
|
|
|
|
break;
|
|
|
|
}
|
|
if (size >= shminfo.shm_segsz)
|
|
{
|
|
fprintf(stderr, "will use %d's stale shared "
|
|
"memory\n", shminfo.shm_cpid);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "warning: can't use stale "
|
|
"shared memory belonging to id %d, "
|
|
"key=0x%x\n", shminfo.shm_cpid, key);
|
|
key++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
I_Error("could not get stats on key=%d", key);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
id = shmget((key_t)key, size, IPC_CREAT|0777);
|
|
if (id==-1)
|
|
{
|
|
extern int errno;
|
|
fprintf(stderr, "errno=%d\n", errno);
|
|
I_Error("Could not get any shared memory");
|
|
}
|
|
break;
|
|
}
|
|
} while (--pollution);
|
|
|
|
if (!pollution)
|
|
{
|
|
I_Error("Sorry, system too polluted with stale "
|
|
"shared memory segments.\n");
|
|
}
|
|
|
|
X_shminfo.shmid = id;
|
|
|
|
// attach to the shared memory segment
|
|
image->data = X_shminfo.shmaddr = shmat(id, 0, 0);
|
|
|
|
fprintf(stderr, "shared memory id=%d, addr=0x%x\n", id,
|
|
(int) (image->data));
|
|
|
|
}
|
|
|
|
void I_InitGraphics(void)
|
|
{
|
|
|
|
char *displayname, *d;
|
|
int n, pnum, x=0, y=0;
|
|
int xsign=1, ysign=1;
|
|
int oktodraw;
|
|
unsigned long attribmask;
|
|
XSetWindowAttributes attribs;
|
|
XGCValues xgcvalues;
|
|
int valuemask;
|
|
static int firsttime=1;
|
|
|
|
if (!firsttime) return;
|
|
firsttime = 0;
|
|
|
|
signal(SIGINT, (void (*)(int)) I_Quit);
|
|
|
|
if (M_CheckParm("-2")) multiply = 2;
|
|
if (M_CheckParm("-3")) multiply = 3;
|
|
if (M_CheckParm("-4")) multiply = 4;
|
|
|
|
X_width = SCREENWIDTH * multiply;
|
|
X_height = SCREENHEIGHT * multiply;
|
|
|
|
// check for command-line display name
|
|
if (pnum=M_CheckParm("-disp"))
|
|
displayname = myargv[pnum+1];
|
|
else
|
|
displayname = 0;
|
|
|
|
// check if the user wants to grab the mouse (quite unnice)
|
|
grabMouse = !!M_CheckParm("-grabmouse");
|
|
|
|
// check for command-line geometry
|
|
if (pnum=M_CheckParm("-geom"))
|
|
{
|
|
n = sscanf(myargv[pnum+1], "%c%d%c%d", &xsign, &x, &ysign, &y);
|
|
if (n==2) x = y = 0;
|
|
else if (n==6)
|
|
{
|
|
if (xsign == '-') x = -x;
|
|
if (ysign == '-') y = -y;
|
|
}
|
|
else I_Error("bad -geom parameter");
|
|
}
|
|
|
|
// open the display
|
|
X_display = XOpenDisplay(displayname);
|
|
if (!X_display)
|
|
{
|
|
if (displayname) I_Error("Could not open display [%s]", displayname);
|
|
else I_Error("Could not open display (DISPLAY=[%s])", getenv("DISPLAY"));
|
|
}
|
|
|
|
// use the default visual
|
|
X_screen = DefaultScreen(X_display);
|
|
if (!XMatchVisualInfo(X_display, X_screen, 8, PseudoColor, &X_visualinfo))
|
|
I_Error("xdoom currently only supports 256-color PseudoColor screens");
|
|
X_visual = X_visualinfo.visual;
|
|
|
|
// check for the MITSHM extension
|
|
doShm = XShmQueryExtension(X_display);
|
|
|
|
// even if it's available, make sure it's a local connection
|
|
if (doShm)
|
|
{
|
|
if (!displayname) displayname = (char *) getenv("DISPLAY");
|
|
if (displayname)
|
|
{
|
|
d = displayname;
|
|
while (*d && (*d != ':')) d++;
|
|
if (*d) *d = 0;
|
|
if (!(!strcasecmp(displayname, "unix") || !*displayname)) doShm = false;
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "Using MITSHM extension\n");
|
|
|
|
// create the colormap
|
|
X_cmap = XCreateColormap(X_display, RootWindow(X_display,
|
|
X_screen), X_visual, AllocAll);
|
|
|
|
// setup attributes for main window
|
|
attribmask = CWEventMask | CWColormap | CWBorderPixel;
|
|
// attribs.event_mask = KeyPressMask | KeyReleaseMask | ExposureMask
|
|
// | PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
|
|
attribs.event_mask = KeyPressMask | KeyReleaseMask | ExposureMask;
|
|
attribs.colormap = X_cmap;
|
|
attribs.border_pixel = 0;
|
|
|
|
// create the main window
|
|
X_mainWindow = XCreateWindow( X_display,
|
|
RootWindow(X_display, X_screen),
|
|
x, y,
|
|
X_width, X_height,
|
|
0, // borderwidth
|
|
8, // depth
|
|
InputOutput,
|
|
X_visual,
|
|
attribmask,
|
|
&attribs );
|
|
|
|
XDefineCursor(X_display, X_mainWindow,
|
|
createnullcursor( X_display, X_mainWindow ) );
|
|
|
|
// create the GC
|
|
valuemask = GCGraphicsExposures;
|
|
xgcvalues.graphics_exposures = False;
|
|
X_gc = XCreateGC( X_display,
|
|
X_mainWindow,
|
|
valuemask,
|
|
&xgcvalues );
|
|
|
|
// map the window
|
|
XMapWindow(X_display, X_mainWindow);
|
|
|
|
// wait until it's OK to draw
|
|
oktodraw = 0;
|
|
while (!oktodraw)
|
|
{
|
|
XNextEvent(X_display, &X_event);
|
|
if (X_event.type == Expose && !X_event.xexpose.count)
|
|
oktodraw = 1;
|
|
}
|
|
|
|
// grabs the pointer so it's restricted to this window
|
|
if (grabMouse)
|
|
XGrabPointer(X_display, X_mainWindow, True, ButtonPressMask
|
|
|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync,
|
|
X_mainWindow, None, CurrentTime);
|
|
|
|
if (doShm)
|
|
{
|
|
|
|
X_shmeventtype = XShmGetEventBase(X_display) + ShmCompletion;
|
|
|
|
// create the image
|
|
image = XShmCreateImage( X_display,
|
|
X_visual,
|
|
8,
|
|
ZPixmap,
|
|
0,
|
|
&X_shminfo,
|
|
X_width,
|
|
X_height );
|
|
|
|
grabsharedmemory(image->bytes_per_line * image->height);
|
|
|
|
/*
|
|
// create the shared memory segment
|
|
X_shminfo.shmid = shmget (IPC_PRIVATE, image->bytes_per_line
|
|
* image->height, IPC_CREAT | 0777);
|
|
if (X_shminfo.shmid < 0)
|
|
{
|
|
perror("");
|
|
I_Error("shmget() failed in InitGraphics()");
|
|
}
|
|
|
|
fprintf(stderr, "shared memory id=%d\n", X_shminfo.shmid);
|
|
|
|
// attach to the shared memory segment
|
|
image->data = X_shminfo.shmaddr = shmat(X_shminfo.shmid, 0, 0);
|
|
*/
|
|
|
|
if (!image->data)
|
|
{
|
|
perror("");
|
|
I_Error("shmat() failed in InitGraphics()");
|
|
}
|
|
|
|
// get the X server to attach to it
|
|
if (!XShmAttach(X_display, &X_shminfo))
|
|
I_Error("XShmAttach() failed in InitGraphics()");
|
|
|
|
} else {
|
|
|
|
image = XCreateImage( X_display,
|
|
X_visual,
|
|
8,
|
|
ZPixmap,
|
|
0,
|
|
malloc(X_width * X_height),
|
|
X_width, X_height,
|
|
8,
|
|
X_width );
|
|
|
|
}
|
|
|
|
if (multiply == 1)
|
|
screens[0] = (unsigned char *) (image->data);
|
|
else
|
|
screens[0] = (unsigned char *) malloc (SCREENWIDTH * SCREENHEIGHT);
|
|
|
|
}
|
|
|
|
unsigned exptable[256];
|
|
|
|
void InitExpand (void)
|
|
{
|
|
int i;
|
|
|
|
for (i=0 ; i<256 ; i++)
|
|
exptable[i] = i | (i<<8) | (i<<16) | (i<<24);
|
|
}
|
|
|
|
double exptable2[256*256];
|
|
|
|
void InitExpand2 (void)
|
|
{
|
|
int i,j;
|
|
unsigned iexp, jexp;
|
|
double *exp;
|
|
union
|
|
{
|
|
double d;
|
|
unsigned u[2];
|
|
} pixel;
|
|
|
|
printf ("building exptable2...\n");
|
|
exp = exptable2;
|
|
for (i=0 ; i<256 ; i++)
|
|
{
|
|
pixel.u[0] = i | (i<<8) | (i<<16) | (i<<24);
|
|
for (j=0 ; j<256 ; j++)
|
|
{
|
|
pixel.u[1] = j | (j<<8) | (j<<16) | (j<<24);
|
|
*exp++ = pixel.d;
|
|
}
|
|
}
|
|
printf ("done.\n");
|
|
}
|
|
|
|
int inited;
|
|
|
|
void Expand4 (unsigned *lineptr, double *xline)
|
|
{
|
|
double dpixel;
|
|
unsigned x, y;
|
|
unsigned fourpixels;
|
|
unsigned step;
|
|
double *exp;
|
|
|
|
exp = exptable2;
|
|
if (!inited)
|
|
{
|
|
inited = 1;
|
|
InitExpand2 ();
|
|
}
|
|
|
|
|
|
step = 3*SCREENWIDTH/2;
|
|
|
|
y = SCREENHEIGHT-1;
|
|
do
|
|
{
|
|
x = SCREENWIDTH;
|
|
|
|
do
|
|
{
|
|
fourpixels = lineptr[0];
|
|
|
|
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
|
|
xline[0] = dpixel;
|
|
xline[160] = dpixel;
|
|
xline[320] = dpixel;
|
|
xline[480] = dpixel;
|
|
|
|
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
|
|
xline[1] = dpixel;
|
|
xline[161] = dpixel;
|
|
xline[321] = dpixel;
|
|
xline[481] = dpixel;
|
|
|
|
fourpixels = lineptr[1];
|
|
|
|
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
|
|
xline[2] = dpixel;
|
|
xline[162] = dpixel;
|
|
xline[322] = dpixel;
|
|
xline[482] = dpixel;
|
|
|
|
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
|
|
xline[3] = dpixel;
|
|
xline[163] = dpixel;
|
|
xline[323] = dpixel;
|
|
xline[483] = dpixel;
|
|
|
|
fourpixels = lineptr[2];
|
|
|
|
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
|
|
xline[4] = dpixel;
|
|
xline[164] = dpixel;
|
|
xline[324] = dpixel;
|
|
xline[484] = dpixel;
|
|
|
|
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
|
|
xline[5] = dpixel;
|
|
xline[165] = dpixel;
|
|
xline[325] = dpixel;
|
|
xline[485] = dpixel;
|
|
|
|
fourpixels = lineptr[3];
|
|
|
|
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
|
|
xline[6] = dpixel;
|
|
xline[166] = dpixel;
|
|
xline[326] = dpixel;
|
|
xline[486] = dpixel;
|
|
|
|
dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
|
|
xline[7] = dpixel;
|
|
xline[167] = dpixel;
|
|
xline[327] = dpixel;
|
|
xline[487] = dpixel;
|
|
|
|
lineptr+=4;
|
|
xline+=8;
|
|
} while (x-=16);
|
|
xline += step;
|
|
} while (y--);
|
|
}
|