ngunix/video/vid_gdk.c

630 lines
16 KiB
C

// vid_x.c -- general x video driver
#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 <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include "globaldef.h"
#include "d_local.h"
static char *quake_xpm[] = {
"64 64 5 1",
" c None",
". c #000000",
"+ c #1C1C89",
"@ c #ABBAC6",
"# c #E21616",
" ",
" ",
" ",
" ",
" ....................................................... ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++#+#++#++######++###++++++++++++#++++++++++++++@ ",
" .+++++++#+#++#++#+#++#++#+#++++++++++++#++++++++++++++@ ",
" .+++++++#+#++#++#+#++#++#+#++++++++++++#++++++++++++++@ ",
" .+++++++#+#++#++#+#++#++#+#++++++++++++#++++++++++++++@ ",
" .+++++++#+#++#++#+#++#++#+#++#+#+++##++#+#++###+++++++@ ",
" .+++++++#+#++#++#+#++#++#+#++#+#++++#++#+#++#+#+++++++@ ",
" .+++++++#+#++#++#+#++#++#+#++#+#++###++##+++#+#+++++++@ ",
" .+++++++#+#++#++#+#++#++#+#++#+#++#+#++#+#++###+++++++@ ",
" .+++++++#+#++#++#+#++#++#+#++#+#++#+#++#+#++#+++++++++@ ",
" .+++++++#+#++#++#+#++#++#+#++#+#++#+#++#+#++#+#+++++++@ ",
" .+++++++######++#+#++#++###++####+####+#+#++###+++++++@ ",
" .+++++++++++++++++++++++++#+++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .++++++++++++++++++++++#++++++###+++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+++++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+##++##+##++++++++++++++++++++@ ",
" .+++++++++++++++++++++##+##+++###+++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" .+++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
" ",
" ",
" ",
" ",
" "
};
viddef_t vid; // global video state
unsigned short d_8to16table[256];
int num_shades = 32;
int gdk_initialized = 0;
int scalefactor = 0;
int d_con_indirect = 0;
int vid_buffersize;
static GdkWindow *x_win;
static GdkWindow *x_icon;
static GdkGC *x_gc;
static GdkPixmap *background;
static GdkBitmap *mask;
#if 0
static GdkRgbCmap *x_cmap = NULL;
#endif
#if 0
static qboolean oktodraw = false;
#endif
static unsigned char *x_framebuffer = NULL;
static int verbose = 0;
static byte current_palette[768];
static long X11_highhunkmark;
static long X11_buffersize;
int vid_surfcachesize;
void *vid_surfcache;
void (*vid_menudrawfn) (void);
void (*vid_menukeyfn) (int key);
void VID_MenuKey(int key);
// ========================================================================
// Tragic death handler
// ========================================================================
void TragicDeath(int signal_num)
{
Sys_Error("This death brought to you by the number %d\n", signal_num);
}
void ResetFrameBuffer(void)
{
int mem;
if (x_framebuffer)
free(x_framebuffer);
if (d_pzbuffer) {
D_FlushCaches();
Hunk_FreeToHighMark(X11_highhunkmark);
d_pzbuffer = NULL;
}
X11_highhunkmark = Hunk_HighMark();
/* alloc an extra line in case we want to wrap, and allocate the z-buffer */
X11_buffersize = vid.width * vid.height * sizeof(*d_pzbuffer);
vid_surfcachesize = D_SurfaceCacheForRes(vid.width, vid.height);
X11_buffersize += vid_surfcachesize;
d_pzbuffer = Hunk_HighAllocName(X11_buffersize, "video");
if (d_pzbuffer == NULL)
Sys_Error("Not enough memory for video mode\n");
vid_surfcache = (byte *) d_pzbuffer
+ vid.width * vid.height * sizeof(*d_pzbuffer);
D_InitCaches(vid_surfcache, vid_surfcachesize);
mem = ((vid.width + 7) & ~7) * vid.height;
x_framebuffer = malloc(vid.width * vid.height * 3);
if (!x_framebuffer)
Sys_Error("VID: gdk_image_new failed\n");
vid.buffer = (byte *) (x_framebuffer);
vid.conbuffer = vid.buffer;
}
// Called at startup to set up translation tables, takes 256 8 bit RGB values
// the palette data will go away after the call, so it must be copied off if
// the video driver will need it again
void VID_Init(unsigned char *palette)
{
GdkWindowAttr attr;
struct sigaction sa;
XWMHints wmhints;
vid.width = 320;
vid.height = 320;
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.numpages = 2;
vid.colormap = host_colormap;
/* vid.cbits = VID_CBITS;
vid.grades = VID_GRADES; */
vid.fullbright = 256 - LittleLong(*((int *) vid.colormap + 2048));
scalefactor = vid.width / 53;
srandom(getpid());
verbose = COM_CheckParm("-verbose");
/* initialize GDK */
gdk_init(NULL, NULL);
gdk_rgb_init();
gdk_initialized = 1;
sigaction(SIGINT, 0, &sa);
sa.sa_handler = TragicDeath;
sigaction(SIGINT, &sa, 0);
sigaction(SIGTERM, &sa, 0);
/* setup attributes for main window */
memset(&attr, 0, sizeof(attr));
attr.width = 64;
attr.height = 64;
attr.title = "quake";
attr.event_mask = GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK;
attr.visual = gdk_visual_get_system();
attr.colormap = gdk_colormap_get_system();
attr.wmclass_name = "quake";
attr.wmclass_class = "quake";
attr.window_type = GDK_WINDOW_TOPLEVEL;
/* create the main window */
x_win = gdk_window_new(NULL, &attr, GDK_WA_TITLE | GDK_WA_WMCLASS |
GDK_WA_VISUAL | GDK_WA_COLORMAP);
memset(&attr, 0, sizeof(attr));
attr.width = 64;
attr.height = 64;
attr.title = "quake";
attr.event_mask = GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK;
attr.visual = gdk_visual_get_system();
attr.colormap = gdk_colormap_get_system();
attr.wmclass_name = "quake";
attr.wmclass_class = "quake";
attr.window_type = GDK_WINDOW_TOPLEVEL;
x_icon = gdk_window_new(x_win, &attr, GDK_WA_TITLE | GDK_WA_WMCLASS);
wmhints.initial_state = WithdrawnState;
wmhints.icon_window = GDK_WINDOW_XWINDOW(x_icon);
wmhints.icon_x = 0;
wmhints.icon_y = 0;
wmhints.window_group = GDK_WINDOW_XWINDOW(x_win);
wmhints.flags =
StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
XSetWMHints(GDK_WINDOW_XDISPLAY(x_win), GDK_WINDOW_XWINDOW(x_win),
&wmhints);
/* create the GC */
x_gc = gdk_gc_new(x_win);
if (!x_gc)
Sys_Error("VID: Cannot make GC\n");
background =
gdk_pixmap_create_from_xpm_d(x_win, &mask, NULL, quake_xpm);
gdk_window_shape_combine_mask(x_win, mask, 0, 0);
gdk_window_shape_combine_mask(x_icon, mask, 0, 0);
gdk_window_set_back_pixmap(x_win, background, False);
gdk_window_set_back_pixmap(x_icon, background, False);
/* map the window */
gdk_window_show(x_win);
#if 0
/* wait for first exposure event */
do {
while (gdk_events_pending()) {
event = gdk_event_get();
if (event) {
if (event->type == GDK_EXPOSE && !event->expose.count)
oktodraw = true;
}
}
} while (!oktodraw);
/*now safe to draw */
#endif
ResetFrameBuffer();
vid.rowbytes = vid.width;
vid.buffer = x_framebuffer;
vid.direct = 0;
vid.conbuffer = x_framebuffer;
vid.conrowbytes = vid.rowbytes;
vid.conwidth = vid.width;
vid.conheight = vid.height;
vid.aspect =
((float) vid.height / (float) vid.width) * (320.0 / 320.0);
}
void VID_ShiftPalette(unsigned char *p)
{
VID_SetPalette(p);
}
void VID_SetPalette(unsigned char *palette)
{
int i = 768;
#if 0
unsigned char *ptr;
unsigned int colors[256];
if (x_cmap) {
gdk_rgb_cmap_free(x_cmap);
}
#endif
while (i--)
current_palette[i] = palette[i];
#if 0
ptr = current_palette;
for (i = 0; i < 256; i++) {
unsigned char r, g, b;
r = *ptr++;
g = *ptr++;
b = *ptr++;
colors[i] = r << 16 | g << 8 | b;
}
x_cmap = gdk_rgb_cmap_new(colors, 256);
#endif
}
/* Called at shutdown */
void VID_Shutdown(void)
{
Con_Printf("VID_Shutdown\n");
}
int XLateKey(int keysym)
{
int key = 0;
switch (keysym) {
case GDK_Page_Up:
key = K_PGUP;
break;
case GDK_Page_Down:
key = K_PGDN;
break;
case GDK_Home:
key = K_HOME;
break;
case GDK_End:
key = K_END;
break;
case GDK_Left:
key = K_LEFTARROW;
break;
case GDK_Right:
key = K_RIGHTARROW;
break;
case GDK_Down:
key = K_DOWNARROW;
break;
case GDK_Up:
key = K_UPARROW;
break;
case GDK_Escape:
key = K_ESCAPE;
break;
case GDK_Return:
key = K_ENTER;
break;
case GDK_Tab:
key = K_TAB;
break;
case GDK_space:
key = K_SPACE;
break;
case GDK_F1:
key = K_F1;
break;
case GDK_F2:
key = K_F2;
break;
case GDK_F3:
key = K_F3;
break;
case GDK_F4:
key = K_F4;
break;
case GDK_F5:
key = K_F5;
break;
case GDK_F6:
key = K_F6;
break;
case GDK_F7:
key = K_F7;
break;
case GDK_F8:
key = K_F8;
break;
case GDK_F9:
key = K_F9;
break;
case GDK_F10:
key = K_F10;
break;
case GDK_F11:
key = K_F11;
break;
case GDK_F12:
key = K_F12;
break;
case GDK_BackSpace:
case GDK_Delete:
key = K_BACKSPACE;
break;
case GDK_Pause:
key = K_PAUSE;
break;
case GDK_Shift_L:
case GDK_Shift_R:
key = K_SHIFT;
break;
case GDK_Execute:
case GDK_Control_L:
case GDK_Control_R:
key = K_CTRL;
break;
case GDK_Alt_L:
case GDK_Meta_L:
case GDK_Alt_R:
case GDK_Meta_R:
key = K_ALT;
break;
case GDK_grave:
key = '`';
break;
default:
if (keysym > GDK_space && keysym <= GDK_9)
key = keysym;
if (keysym >= GDK_A && keysym <= GDK_Z)
key = keysym - GDK_A + 'a';
if (keysym >= GDK_a && keysym <= GDK_z)
key = keysym - GDK_a + 'a';
break;
}
/* printf("keysym: %x, key: %x\n", keysym, key); */
return key;
}
struct {
int key;
int down;
} keyq[64];
int keyq_head = 0;
int keyq_tail = 0;
void GetEvent(void)
{
GdkEvent *event;
event = gdk_event_get();
if (event)
switch (event->type) {
case GDK_KEY_PRESS:
keyq[keyq_head].key = XLateKey(event->key.keyval);
keyq[keyq_head].down = true;
keyq_head = (keyq_head + 1) & 63;
break;
case GDK_KEY_RELEASE:
keyq[keyq_head].key = XLateKey(event->key.keyval);
keyq[keyq_head].down = false;
keyq_head = (keyq_head + 1) & 63;
break;
case GDK_ENTER_NOTIFY:
XSetInputFocus(GDK_WINDOW_XDISPLAY(x_win),
GDK_WINDOW_XWINDOW(x_icon), RevertToNone,
CurrentTime);
break;
case GDK_LEAVE_NOTIFY:
XSetInputFocus(GDK_WINDOW_XDISPLAY(x_win),
None, RevertToNone, CurrentTime);
break;
default:
break;
}
}
// flushes the given rectangles from the view buffer to the screen
void VID_Update(vrect_t * rects)
{
while (rects) {
unsigned char buf[53 * 53 * 3];
unsigned char *bufptr = buf;
unsigned char sample;
int x, y;
for (y = 0; y < 53; y++) {
for (x = 0; x < 53; x++) {
sample =
x_framebuffer[y * scalefactor * vid.width +
x * scalefactor];
*bufptr++ = current_palette[sample * 3];
*bufptr++ = current_palette[sample * 3 + 1];
*bufptr++ = current_palette[sample * 3 + 2];
}
}
/* printf("drawing: %d %d %d %d %d %d\n", rects->x, rects->y,
rects->x, rects->y, rects->width, rects->height); */
/*gdk_draw_indexed_image(x_win, x_gc, rects->x, rects->y,
rects->width, rects->height,
GDK_RGB_DITHER_NONE,
x_framebuffer,
vid.width, x_cmap); */
gdk_draw_rgb_image(x_win, x_gc, 5, 5, 53, 53, GDK_RGB_DITHER_NONE,
buf, 53 * 3);
gdk_draw_rgb_image(x_icon, x_gc, 5, 5, 53, 53, GDK_RGB_DITHER_NONE,
buf, 53 * 3);
rects = rects->pnext;
}
}
static int dither;
void VID_DitherOn(void)
{
if (dither == 0) {
vid.recalc_refdef = 1;
dither = 1;
}
}
void VID_DitherOff(void)
{
if (dither) {
vid.recalc_refdef = 1;
dither = 0;
}
}
int Sys_OpenWindow(void)
{
return 0;
}
void Sys_EraseWindow(int window)
{
}
void Sys_DrawCircle(int window, int x, int y, int r)
{
}
void Sys_DisplayWindow(int window)
{
}
void Sys_SendKeyEvents(void)
{
if (gdk_initialized) {
while (gdk_events_pending()) {
GetEvent();
while (keyq_head != keyq_tail) {
Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down);
keyq_tail = (keyq_tail + 1) & 63;
}
}
}
}
/*
char *Sys_ConsoleInput(void)
{
static char text[256];
int len;
fd_set readfds;
int ready;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
ready = select(1, &readfds, 0, 0, &timeout);
if (ready > 0) {
len = read(0, text, sizeof(text));
if (len >= 1) {
text[len - 1] = 0; // rip off the /n and terminate
return text;
}
}
return 0;
}
*/
void D_BeginDirectRect(int x, int y, byte * pbitmap, int width, int height)
{
// direct drawing of the "accessing disk" icon isn't supported under Linux
}
void D_EndDirectRect(int x, int y, int width, int height)
{
// direct drawing of the "accessing disk" icon isn't supported under Linux
}
void VID_HandlePause(qboolean pause){}
void IN_Move(usercmd_t *cmd){}
void IN_Commands(){}
void IN_Init(){}
void IN_Shutdown(){}
void VID_CreateSplash(){}
void VID_Init_Cvars(){}
void IN_Init_Cvars(){}