// vid_x.c -- general x video driver #include #include #include #include #include #include #include #include #include #include #include #include "quakedef.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(){}