--- uae/src/xwin.c 2018/04/24 16:38:59 1.1.1.2 +++ uae/src/xwin.c 2018/04/24 17:21:44 1.1.1.22 @@ -1,11 +1,14 @@ - /* + /* * UAE - The Un*x Amiga Emulator - * + * * X interface - * + * * Copyright 1995, 1996 Bernd Schmidt * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste + * Copyright 1998 Marcus Sundberg * DGA support by Kai Kollmorgen + * X11/DGA merge, hotkeys and grabmouse by Marcus Sundberg + * Copyright 2003-2004 Richard Drummond */ #include "sysconfig.h" @@ -16,47 +19,77 @@ #include #include -#ifndef DONT_WANT_SHM -#include -#include -#include -#endif - #include #include -#include "config.h" #include "options.h" +#include "threaddep/thread.h" +#include "uae.h" #include "memory.h" +#include "xwin.h" #include "custom.h" -#include "readcpu.h" +#include "drawing.h" #include "newcpu.h" -#include "xwin.h" #include "keyboard.h" #include "keybuf.h" #include "gui.h" #include "debug.h" +#include "picasso96.h" +#include "inputdevice.h" +#include "hotkeys.h" + +#ifdef __cplusplus +#define VI_CLASS c_class +#else +#define VI_CLASS class +#endif #ifdef USE_DGA_EXTENSION + +#ifdef USE_VIDMODE_EXTENSION +#include +#define VidMode_MINMAJOR 0 +#define VidMode_MINMINOR 0 +#endif + #include #define DGA_MINMAJOR 0 #define DGA_MINMINOR 0 + +#endif /* USE_DGA_EXTENSION */ + +#if SHM_SUPPORT_LINKS == 1 + +#include +#include +#include + +#define DO_PUTIMAGE(IMG, SRCX, SRCY, DSTX, DSTY, WIDTH, HEIGHT) \ + do { \ + if (currprefs.x11_use_mitshm && shmavail) \ + XShmPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT), 0); \ + else \ + XPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT)); \ + } while (0) +#else +#define DO_PUTIMAGE(IMG, SRCX, SRCY, DSTX, DSTY, WIDTH, HEIGHT) \ + XPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT)) #endif #ifdef __cplusplus static RETSIGTYPE sigbrkhandler(...) #else -static RETSIGTYPE sigbrkhandler(int foo) +static RETSIGTYPE sigbrkhandler (int foo) #endif { activate_debugger(); #if !defined(__unix) || defined(__NeXT__) - signal(SIGINT, sigbrkhandler); + signal (SIGINT, sigbrkhandler); #endif } -void setup_brkhandler(void) +void setup_brkhandler (void) { #if defined(__unix) && !defined(__NeXT__) struct sigaction sa; @@ -65,1033 +98,1167 @@ void setup_brkhandler(void) #ifdef SA_RESTART sa.sa_flags = SA_RESTART; #endif - sigemptyset(&sa.sa_mask); - sigaction(SIGINT, &sa, NULL); + sigemptyset (&sa.sa_mask); + sigaction (SIGINT, &sa, NULL); #else - signal(SIGINT, sigbrkhandler); -#endif + signal (SIGINT, sigbrkhandler); +#endif } -#ifdef USE_DGA_EXTENSION -static char *fb_addr; -static int fb_width; +struct disp_info { + XImage *ximg; + char *image_mem; +#if SHM_SUPPORT_LINKS == 1 + XShmSegmentInfo shminfo; #endif +}; static Display *display; static int screen; static Window rootwin, mywin; +static Atom delete_win; -static GC whitegc,blackgc; -static XColor black,white; -static Colormap cmap; +static GC mygc; +static XColor black, white; +static Colormap cmap, cmap2; +static int red_bits, green_bits, blue_bits; +static int red_shift, green_shift, blue_shift; + +/* Kludge-O-Matic. + * Unfortunately the X server loses colormap changes in DGA mode. Switching + * back and forth between two identical colormaps fixes this problem. */ +static int dga_colormap_installed; static int need_dither; +static char picasso_invalid_lines[1201]; +static int picasso_has_invalid_lines; +static int picasso_invalid_start, picasso_invalid_stop; +static int picasso_maxw = 0, picasso_maxh = 0; + static int autorepeatoff = 0; -static char *image_mem; -static XImage *img; +static struct disp_info ami_dinfo, pic_dinfo; static Visual *vis; static XVisualInfo visualInfo; static int bitdepth, bit_unit; -#ifndef DONT_WANT_SHM -static int use_shm = 1; -static XShmSegmentInfo shminfo; -#endif static Cursor blankCursor, xhairCursor; static int cursorOn; +static int inverse_byte_order = 0; -#ifdef LOW_BANDWIDTH -static int use_low_bandwidth = 1; -#else -static int use_low_bandwidth = 0; -#endif +static int current_width, current_height; static int x11_init_ok; +static int dgaavail = 0, vidmodeavail = 0, shmavail = 0; +static int dgamode; +static int grabbed; + +void toggle_mousegrab (void); +void framerate_up (void); +void framerate_down (void); +int xkeysym2amiga (int); +struct uae_hotkeyseq *get_x11_default_hotkeys (void); -xcolnr xcolors[4096]; +int pause_emulation; - /* Keyboard and mouse */ +static int oldx, oldy; +static int inwindow; -static int keystate[256]; +#define EVENTMASK (KeyPressMask|KeyReleaseMask|ButtonPressMask \ + |ButtonReleaseMask|PointerMotionMask \ + |FocusChangeMask|EnterWindowMask \ + |ExposureMask |LeaveWindowMask) +#define DGA_EVENTMASK (KeyPressMask|KeyReleaseMask|ButtonPressMask \ + |ButtonReleaseMask|PointerMotionMask) + +#if SHM_SUPPORT_LINKS == 1 +/* Hack to detect shm-failure, probably due to displaying on a + * remote server. */ +static int shmerror; +static int (*oldshmerrorhandler) (Display *, XErrorEvent *); -int buttonstate[3]; -int lastmx, lastmy; -int newmousecounters; +static int shmerrorhandler (Display *dsp, XErrorEvent *ev) +{ + if (ev->error_code == BadAccess) + shmerror=1; + else + (*oldshmerrorhandler) (dsp, ev); + return 0; +} +#endif -static int inwindow; -const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask - |ButtonReleaseMask|PointerMotionMask -#ifndef USE_DGA_EXTENSION - |FocusChangeMask|EnterWindowMask - |ExposureMask - |LeaveWindowMask +static void get_image (int w, int h, struct disp_info *dispi) +{ + XImage *new_img; + char *p; + +#if SHM_SUPPORT_LINKS == 1 + if (currprefs.x11_use_mitshm && shmavail) { + XShmSegmentInfo *shminfo = &dispi->shminfo; + + new_img = XShmCreateImage (display, vis, bitdepth, ZPixmap, 0, shminfo, w, h); + + shminfo->shmid = shmget (IPC_PRIVATE, h * new_img->bytes_per_line, + IPC_CREAT | 0777); + shminfo->shmaddr = new_img->data = (char *)shmat (shminfo->shmid, 0, 0); + dispi->image_mem = new_img->data; + shminfo->readOnly = False; + /* Try to let the Xserver attach */ + shmerror = 0; + oldshmerrorhandler = XSetErrorHandler (shmerrorhandler); + XShmAttach (display, shminfo); + XSync (display, 0); + XSetErrorHandler (oldshmerrorhandler); + if (shmerror) { + shmdt (shminfo->shmaddr); + XDestroyImage (new_img); + shminfo->shmid = -1; + shmavail = 0; + write_log ("MIT-SHM extension failed, trying fallback.\n"); + } else { + /* now deleting means making it temporary */ + shmctl (shminfo->shmid, IPC_RMID, 0); + dispi->ximg = new_img; + write_log ("Using MIT-SHM extension.\n"); + return; + } + } #endif - ); -static char *oldpixbuf; + /* Question for people who know about X: Could we allocate the buffer + * after creating the image and then do new_img->data = buffer, as above in + * the SHM case? + */ + write_log ("Using normal image buffer.\n"); + p = (char *)xmalloc (h * w * ((bit_unit + 7) / 8)); /* ??? */ + new_img = XCreateImage (display, vis, bitdepth, ZPixmap, 0, p, + w, h, 32, 0); + if (new_img->bytes_per_line != w * ((bit_unit + 7) / 8)) + write_log ("Possible bug here... graphics may look strange.\n"); -struct vidbuf_description gfxvidinfo; + dispi->image_mem = p; + dispi->ximg = new_img; +} + +#ifdef USE_VIDMODE_EXTENSION +static XF86VidModeModeInfo **allmodes; +static int vidmodecount; + +static int sortfn (const void *a, const void *b) +{ + XF86VidModeInfo **ppa = a, *ppb = b; + XF86VidModeInfo *pa = *ppa, *pb = *ppb; + if (pa->hdisplay != pb->hdisplay) + return pa->hdisplay - pb->hdisplay; + return pa->vdisplay - pb->vdisplay; +} -void flush_line(int y) +static int get_vidmodes (void) { + int i; + + if (!XF86VidModeGetAllModeLines (display, screen, &vidmodecount, &allmodes)) + return 0; + + qsort (allmodes, vidmodecount, sizeof *allmode, sortfn); + + gfx_fullscreen_modes = sizeof (struct uae_rect) * vidmodecount; + n_fullscreen_modes = vidmodecount; + for (i = 0; i < vidmodecount; i++) { + gfx_fullscreen_modes[i].w = allmodes[i].hdisplay; + gfx_fullscreen_modes[i].h = allmodes[i].vdisplay; + } +} +#endif + #ifdef USE_DGA_EXTENSION - if (need_dither) { - char *addr = gfxvidinfo.bufmem + y*gfxvidinfo.rowbytes; - DitherLine(fb_addr + fb_width*y,(UWORD *)addr,0,y, - gfx_requested_width, bit_unit); + +static int fb_bank, fb_banks, fb_mem; +static char *fb_addr; +static int fb_width; + +static void switch_to_best_mode (void) +{ + Screen *scr = ScreenOfDisplay (display, screen); + int w = WidthOfScreen (scr); + int h = HeightOfScreen (scr); + int d = DefaultDepthOfScreen (scr); +#ifdef USE_VIDMODE_EXTENSION + int i, best; + if (vidmodeavail) { + best = 0; + for (i = 1; i < vidmodecount; i++) { + if (allmodes[i]->hdisplay >= current_width + && allmodes[i]->vdisplay >= current_height + && allmodes[i]->hdisplay <= allmodes[best]->hdisplay + && allmodes[i]->vdisplay <= allmodes[best]->vdisplay) + best = i; + } + write_log ("entering DGA mode: %dx%d (%d, %d)\n", + allmodes[best]->hdisplay, allmodes[best]->vdisplay, + current_width, current_height); + XF86VidModeSwitchToMode (display, screen, allmodes[best]); + XF86VidModeSetViewPort (display, screen, 0, 0); } -#else - int xs = 0, xe; - int len, factor; - char *linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem; - char *src, *dst; - - xe = gfxvidinfo.maxlinetoscr-1; +#endif + XMoveWindow (display, mywin, 0, 0); + XWarpPointer (display, None, rootwin, 0, 0, 0, 0, 0, 0); + XF86DGADirectVideo (display, screen, XF86DGADirectGraphics | XF86DGADirectMouse | XF86DGADirectKeyb); + XF86DGASetViewPort (display, screen, 0, 0); + memset (fb_addr, 0, (w * h) * (d / 8)); +} - if (!use_low_bandwidth) - fprintf(stderr, "Bug!\n"); - - switch(gfxvidinfo.pixbytes) { - case 4: - { - int *newp = (int *)linebuf; - int *oldp = (int *)(oldpixbuf + y*gfxvidinfo.rowbytes); - while (newp[xs] == oldp[xs]) { - if (xs == xe) - return; - xs++; +static void enter_dga_mode (void) +{ + XRaiseWindow (display, mywin); + + /* We want all the key presses */ + XGrabKeyboard (display, rootwin, 1, GrabModeAsync, + GrabModeAsync, CurrentTime); + + /* and all the mouse moves */ + XGrabPointer (display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + + switch_to_best_mode (); + + gfxvidinfo.rowbytes = fb_width*gfxvidinfo.pixbytes; + gfxvidinfo.bufmem = fb_addr; + gfxvidinfo.linemem = 0; + gfxvidinfo.emergmem = malloc (gfxvidinfo.rowbytes); + gfxvidinfo.maxblocklines = 10000; +} + +static void leave_dga_mode (void) +{ + XF86DGADirectVideo (display, screen, 0); + XUngrabPointer (display, CurrentTime); + XUngrabKeyboard (display, CurrentTime); +#ifdef USE_VIDMODE_EXTENSION + if (vidmodeavail) + XF86VidModeSwitchToMode (display, screen, allmodes[0]); +#endif +} +#endif + +static char *oldpixbuf; + +void flush_line (int y) +{ + char *linebuf = gfxvidinfo.linemem; + int xs, xe; + int len; + + if (linebuf == NULL) + linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem; + +#ifdef USE_DGA_EXTENSION + if (dgamode && need_dither) { + DitherLine ((unsigned char *)(fb_addr + fb_width*y), + (uae_u16 *)linebuf, 0, y, gfxvidinfo.width, bit_unit); + return; + } +#endif + xs = 0; + xe = gfxvidinfo.width - 1; + + if (currprefs.x11_use_low_bandwidth) { + char *src, *dst; + switch (gfxvidinfo.pixbytes) { + case 4: + { + uae_u32 *newp = (uae_u32 *)linebuf; + uae_u32 *oldp = (uae_u32 *)((uae_u8 *)ami_dinfo.image_mem + y*ami_dinfo.ximg->bytes_per_line); + while (newp[xs] == oldp[xs]) { + if (xs == xe) + return; + xs++; + } + while (newp[xe] == oldp[xe]) xe--; + + dst = (char *)(oldp + xs); src = (char *)(newp + xs); } - while (newp[xe] == oldp[xe]) xe--; - - dst = (char *)(oldp + xs); src = (char *)(newp + xs); - } - break; - case 2: - { - short *newp = (short *)linebuf; - short *oldp = (short *)(oldpixbuf + y*gfxvidinfo.rowbytes); - while (newp[xs] == oldp[xs]) { - if (xs == xe) - return; - xs++; + break; + case 2: + { + uae_u16 *newp = (uae_u16 *)linebuf; + uae_u16 *oldp = (uae_u16 *)((uae_u8 *)ami_dinfo.image_mem + y*ami_dinfo.ximg->bytes_per_line); + while (newp[xs] == oldp[xs]) { + if (xs == xe) + return; + xs++; + } + while (newp[xe] == oldp[xe]) xe--; + + dst = (char *)(oldp + xs); src = (char *)(newp + xs); } - while (newp[xe] == oldp[xe]) xe--; + break; + case 1: + { + uae_u8 *newp = (uae_u8 *)linebuf; + uae_u8 *oldp = (uae_u8 *)((uae_u8 *)ami_dinfo.image_mem + y*ami_dinfo.ximg->bytes_per_line); + while (newp[xs] == oldp[xs]) { + if (xs == xe) + return; + xs++; + } + while (newp[xe] == oldp[xe]) xe--; - dst = (char *)(oldp + xs); src = (char *)(newp + xs); - } - break; - case 1: - { - char *newp = (char *)linebuf; - char *oldp = (char *)(oldpixbuf + y*gfxvidinfo.rowbytes); - while (newp[xs] == oldp[xs]) { - if (xs == xe) - return; - xs++; + dst = (char *)(oldp + xs); src = (char *)(newp + xs); } - while (newp[xe] == oldp[xe]) xe--; + break; - dst = (char *)(oldp + xs); src = (char *)(newp + xs); + default: + abort (); + break; } - break; - - default: - abort(); - break; - } - len = xe - xs + 1; - memcpy (dst, src, len * gfxvidinfo.pixbytes); - - if (need_dither) { - UBYTE *target = (UBYTE *)image_mem + img->bytes_per_line * y; - xs &= ~(8/bit_unit - 1); len = xe - xs + 1; - len += 3; len &= ~3; - len += (8/bit_unit - 1); len &= ~(8/bit_unit-1); - if (len & 3) - printf("%d\n",len); - DitherLine(target + xs*bit_unit/8, (UWORD *)linebuf + xs, xs, y, len, bit_unit); + memcpy (dst, src, len * gfxvidinfo.pixbytes); + } else if (need_dither) { + uae_u8 *target = (uae_u8 *)ami_dinfo.image_mem + ami_dinfo.ximg->bytes_per_line * y; + len = gfxvidinfo.width; + DitherLine (target, (uae_u16 *)linebuf, 0, y, gfxvidinfo.width, bit_unit); + } else { + write_log ("Bug!\n"); + abort(); } -#ifndef DONT_WANT_SHM - if (use_shm) - XShmPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1, 0); - else -#endif - XPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1); - -#endif + DO_PUTIMAGE (ami_dinfo.ximg, xs, y, xs, y, len, 1); } void flush_block (int ystart, int ystop) { -#ifdef USE_DGA_EXTENSION -#else - int len, xs = 0; - - len = gfxvidinfo.maxlinetoscr; -#ifndef DONT_WANT_SHM - if (use_shm) - XShmPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, - ystop - ystart + 1, 0); - else -#endif - XPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, - ystop - ystart + 1); -#endif + if (dgamode) + return; + + DO_PUTIMAGE (ami_dinfo.ximg, 0, ystart, 0, ystart, gfxvidinfo.width, ystop - ystart + 1); } void flush_screen (int ystart, int ystop) { -#ifdef USE_DGA_EXTENSION -#else -#ifndef DONT_WANT_SHM - if (use_shm) XSync(display, 0); -#endif + if (dgamode) + return; + +#if SHM_SUPPORT_LINKS == 1 + if (currprefs.x11_use_mitshm && shmavail) + XSync (display, 0); #endif } -static __inline__ int bitsInMask(unsigned long mask) +void flush_clear_screen (void) +{ + flush_screen(0,0); +} + +STATIC_INLINE int bitsInMask (unsigned long mask) { /* count bits in mask */ int n = 0; - while(mask) { - n += mask&1; + while (mask) { + n += mask & 1; mask >>= 1; } return n; } -static __inline__ int maskShift(unsigned long mask) +STATIC_INLINE int maskShift (unsigned long mask) { /* determine how far mask is shifted */ int n = 0; - while(!(mask&1)) { + while (!(mask & 1)) { n++; mask >>= 1; } return n; } -static int get_color(int r, int g, int b, xcolnr *cnp) +static unsigned long pixel_return[256]; +static XColor parsed_xcolors[256]; +static int ncolors = 0; + +static int blackval = 32767; +static int whiteval = 0; + +static int get_color (int r, int g, int b, xcolnr *cnp) { - XColor col; + XColor *col = parsed_xcolors + ncolors; char str[10]; - sprintf(str, "rgb:%x/%x/%x", r, g, b); - XParseColor(display, cmap, str, &col); - if (XAllocColor(display, cmap, &col)) { - *cnp = col.pixel; - return 1; - } - return 0; + + sprintf (str, "rgb:%x/%x/%x", r, g, b); + XParseColor (display, cmap, str, col); + *cnp = col->pixel = pixel_return[ncolors]; + XStoreColor (display, cmap, col); + XStoreColor (display, cmap2, col); + + if (r + g + b < blackval) + blackval = r + g + b, black = *col; + if (r + g + b > whiteval) + whiteval = r + g + b, white = *col; + + ncolors++; + return 1; } -static int init_colors(void) +static int init_colors (void) { + int i; + + if (visualInfo.VI_CLASS == TrueColor) { + red_bits = bitsInMask (visualInfo.red_mask); + green_bits = bitsInMask (visualInfo.green_mask); + blue_bits = bitsInMask (visualInfo.blue_mask); + red_shift = maskShift (visualInfo.red_mask); + green_shift = maskShift (visualInfo.green_mask); + blue_shift = maskShift (visualInfo.blue_mask); + } + if (need_dither) { if (bitdepth == 1) setup_greydither (1, get_color); else setup_dither (bitdepth, get_color); - return 1; - } - - if (bitdepth != 8 && bitdepth != 12 - && bitdepth != 16 && bitdepth != 24) { - fprintf(stderr, "Unsupported bit depth (%d)\n", bitdepth); - return 0; - } - -#ifdef __cplusplus - switch(visualInfo.c_class) -#else - switch(visualInfo.class) -#endif - { - case TrueColor: - { - int red_bits = bitsInMask(visualInfo.red_mask); - int green_bits = bitsInMask(visualInfo.green_mask); - int blue_bits = bitsInMask(visualInfo.blue_mask); - int red_shift = maskShift(visualInfo.red_mask); - int green_shift = maskShift(visualInfo.green_mask); - int blue_shift = maskShift(visualInfo.blue_mask); - alloc_colors64k(red_bits, green_bits, blue_bits, red_shift, - green_shift, blue_shift); + } else { + if (bitdepth != 8 && bitdepth != 12 && bitdepth != 15 + && bitdepth != 16 && bitdepth != 24) { + write_log ("Unsupported bit depth (%d)\n", bitdepth); + return 0; } - break; - case GrayScale: - case PseudoColor: - alloc_colors256(get_color); + switch (visualInfo.VI_CLASS) { + case TrueColor: + alloc_colors64k (red_bits, green_bits, blue_bits, red_shift, + green_shift, blue_shift); + + XParseColor (display, cmap, "#000000", &black); + if (! XAllocColor (display, cmap, &black)) + write_log ("Whoops??\n"); + XParseColor (display, cmap, "#ffffff", &white); + if (! XAllocColor (display, cmap, &white)) + write_log ("Whoops??\n"); + break; + + case GrayScale: + case PseudoColor: + alloc_colors256 (get_color); + break; + + default: + write_log ("Unsupported visual class (%d)\n", visualInfo.VI_CLASS); + return 0; + } + } + switch (gfxvidinfo.pixbytes) { + case 2: + for (i = 0; i < 4096; i++) + xcolors[i] = xcolors[i] * 0x00010001; + gfxvidinfo.can_double = 1; + break; + case 1: + for (i = 0; i < 4096; i++) + xcolors[i] = xcolors[i] * 0x01010101; + gfxvidinfo.can_double = 1; break; - default: -#ifdef __cplusplus - fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.c_class); -#else - fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.class); -#endif - return 0; + gfxvidinfo.can_double = 0; + break; } + if (inverse_byte_order) + switch (gfxvidinfo.pixbytes) { + case 4: + for(i = 0; i < 4096; i++) + xcolors[i] = ((((xcolors[i]>>0)&255) << 24) + | (((xcolors[i]>>8)&255) << 16) + | (((xcolors[i]>>16)&255) << 8) + | (((xcolors[i]>>24)&255) << 0)); + break; + case 2: + for (i = 0; i < 4096; i++) + xcolors[i] = (xcolors[i]>>8) | ((xcolors[i]&255)<<8); + break; + default: + break; + } return 1; } -int graphics_init(void) +static int dga_available (void) { - int i,j; - char *display_name = 0; - XSetWindowAttributes wattr; - XPixmapFormatValues *xpfvs; #ifdef USE_DGA_EXTENSION int MajorVersion, MinorVersion; int EventBase, ErrorBase; - int fb_bank, fb_banks, fb_mem; -#endif - - x11_init_ok = 0; - need_dither = 0; -#ifdef USE_DGA_EXTENSION - if (geteuid()) { - fprintf(stderr, "You must be root to use UAE with the DGA extensions.\n"); - return(0); + if (! XF86DGAQueryVersion (display, &MajorVersion, &MinorVersion)) { + write_log ("Unable to query video extension version\n"); + return 0; } -#endif - - display = XOpenDisplay(display_name); - if (display == 0) { - fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name)); + if (! XF86DGAQueryExtension (display, &EventBase, &ErrorBase)) { + write_log ("Unable to query video extension information\n"); return 0; } - -#ifdef USE_DGA_EXTENSION - if (!XF86DGAQueryVersion(display, &MajorVersion, &MinorVersion)) { - fprintf(stderr, "Unable to query video extension version\n"); - return(0); + /* Fail if the extension version in the server is too old */ + if (MajorVersion < DGA_MINMAJOR + || (MajorVersion == DGA_MINMAJOR && MinorVersion < DGA_MINMINOR)) + { + write_log ( + "Xserver is running an old XFree86-DGA version" + " (%d.%d)\n", MajorVersion, MinorVersion); + write_log ("Minimum required version is %d.%d\n", + DGA_MINMAJOR, DGA_MINMINOR); + return 0; } - - if (!XF86DGAQueryExtension(display, &EventBase, &ErrorBase)) { - fprintf(stderr, "Unable to query video extension information\n"); - return(0); + if (geteuid () != 0) { + write_log ("UAE is not running as root, DGA extension disabled.\n"); + return 0; } - - /* Fail if the extension version in the server is too old */ - if (MajorVersion < DGA_MINMAJOR || - (MajorVersion == DGA_MINMAJOR && MinorVersion < DGA_MINMINOR)) { - fprintf(stderr, - "Xserver is running an old XFree86-DGA version" - " (%d.%d)\n", MajorVersion, MinorVersion); - fprintf(stderr, "Minimum required version is %d.%d\n", - DGA_MINMAJOR, DGA_MINMINOR); - return(0); + if (! XF86DGAGetVideo (display, screen, &fb_addr, &fb_width, &fb_bank, &fb_mem) + || fb_bank < fb_mem) + { + write_log ("Problems with DGA - disabling DGA extension.\n"); + return 0; } + write_log ("DGA extension: addr:%X, width %d, bank size %d mem size %d\n", + fb_addr, fb_width, fb_bank, fb_mem); + + return 1; +#else + return 0; #endif - - screen = XDefaultScreen(display); - rootwin = XRootWindow(display,screen); - - /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */ - if (XMatchVisualInfo(display, screen, 12, TrueColor, &visualInfo)) { - } else if (XMatchVisualInfo(display, screen, 16, TrueColor, &visualInfo)) { - } else if (XMatchVisualInfo(display, screen, 24, TrueColor, &visualInfo)) { - } else if (XMatchVisualInfo(display, screen, 8, PseudoColor, &visualInfo)) { - /* for our HP boxes */ - } else if (XMatchVisualInfo(display, screen, 8, GrayScale, &visualInfo)) { - } else if (XMatchVisualInfo(display, screen, 4, PseudoColor, &visualInfo)) { - /* VGA16 server. Argh. */ - } else if (XMatchVisualInfo(display, screen, 1, StaticGray, &visualInfo)) { - /* Mono server. Yuk */ - } else { - fprintf(stderr, "Can't obtain appropriate X visual.\n"); +} + +static int vid_mode_available (void) +{ +#ifdef USE_VIDMODE_EXTENSION + int MajorVersion, MinorVersion; + int EventBase, ErrorBase; + + if (! dgaavail) + return 0; + if (! XF86VidModeQueryVersion (display, &MajorVersion, &MinorVersion)) { + write_log ("Unable to query video extension version\n"); return 0; } - vis = visualInfo.visual; - bitdepth = visualInfo.depth; - - /* We now have the bitdepth of the display, but that doesn't tell us yet - * how many bits to use per pixel. The VGA16 server has a bitdepth of 4, - * but uses 1 byte per pixel. */ - xpfvs = XListPixmapFormats(display, &i); - for (j = 0; j < i && xpfvs->depth != bitdepth; j++, xpfvs++) - ; - if (j == i) { - fprintf(stderr, "Your X server is feeling ill.\n"); + if (! XF86VidModeQueryExtension (display, &EventBase, &ErrorBase)) { + write_log ("Unable to query video extension information\n"); return 0; } - - bit_unit = xpfvs->bits_per_pixel; - fprintf(stderr, "Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit); + if (MajorVersion < VidMode_MINMAJOR + || (MajorVersion == VidMode_MINMAJOR && MinorVersion < VidMode_MINMINOR)) { + /* Fail if the extension version in the server is too old */ + write_log ("Xserver is running an old XFree86-VidMode version (%d.%d)\n", + MajorVersion, MinorVersion); + write_log ("Minimum required version is %d.%d\n", + VidMode_MINMAJOR, VidMode_MINMINOR); + return 0; + } + if (! get_vidmodes ()) { + write_log ("Error getting video mode information\n"); + return 0; + } + return 1; +#else + return 0; +#endif +} + +static int shm_available (void) +{ +#if SHM_SUPPORT_LINKS == 1 + if (XShmQueryExtension (display)) + return 1; +#endif + return 0; +} - if (gfx_requested_width < 320) - gfx_requested_width = 320; - if (gfx_requested_height < 200) - gfx_requested_height = 200; - if (gfx_requested_height > 300 && ! gfx_requested_linedbl) - gfx_requested_height = 300; - if (gfx_requested_height > 600) - gfx_requested_height = 600; +int graphics_setup (void) +{ + char *display_name = 0; - gfx_requested_width += 7; /* X86.S wants multiples of 4 bytes, might be 8 in the future. */ - gfx_requested_width &= ~7; - - gfxvidinfo.maxlinetoscr = gfx_requested_width; - gfxvidinfo.maxline = gfx_requested_height; + display = XOpenDisplay (display_name); + if (display == 0) { + write_log ("Can't connect to X server %s\n", XDisplayName (display_name)); + return 0; + } - cmap = XCreateColormap(display, rootwin, vis, AllocNone); - XParseColor(display, cmap, "#000000", &black); - if (!XAllocColor(display, cmap, &black)) - fprintf(stderr, "Whoops??\n"); - XParseColor(display, cmap, "#ffffff", &white); - if (!XAllocColor(display, cmap, &white)) - fprintf(stderr, "Whoops??\n"); + shmavail = shm_available (); + dgaavail = dga_available (); + vidmodeavail = vid_mode_available (); -#ifdef USE_DGA_EXTENSION - wattr.override_redirect = 1; + { + int local_byte_order; + int x = 0x04030201; + char *y=(char*)&x; + + local_byte_order = y[0] == 0x04 ? MSBFirst : LSBFirst; + if (ImageByteOrder(display) != local_byte_order) + inverse_byte_order = 1; + } + + return 1; +} + +static void lock_window_size (void) +{ + XSizeHints hint; + + hint.flags = PMinSize | PMaxSize; + hint.min_width = current_width; + hint.min_height = current_height; + hint.max_width = current_width; + hint.max_height = current_height; + XSetWMNormalHints (display, mywin, &hint); +} + +static void init_dispinfo (struct disp_info *disp) +{ +#if SHM_SUPPORT_LINKS == 1 + disp->shminfo.shmid = -1; #endif - wattr.event_mask = eventmask; - wattr.background_pixel = black.pixel; + disp->ximg = 0; +} + +static void reset_cursor (void) +{ + if (! dgamode) { + if (! currprefs.x11_hide_cursor) + XDefineCursor (display, mywin, xhairCursor); + else + XDefineCursor (display, mywin, blankCursor); + cursorOn = 1; + } +} + +int graphics_subinit (void) +{ + int i, j; + XSetWindowAttributes wattr; + XClassHint classhint; + XWMHints *hints; + unsigned long valuemask; + + if (screen_is_picasso) { + // Set height, width for Picasso gfx + current_width = picasso_vidinfo.width; + current_height = picasso_vidinfo.height; + dgamode = currprefs.gfx_pfullscreen && dgaavail; + curr_gfx = 0; + } else { + // Set height, width for Amiga gfx + dgamode = currprefs.gfx_afullscreen && dgaavail; + if (dgamode) + curr_gfx = &currprefs.gfx_f; + else + curr_gfx = &currprefs.gfx_w; + + current_width = curr_gfx->width; + current_height = curr_gfx->height; + } + if (!screen_is_picasso) { + gfxvidinfo.width = current_width; + gfxvidinfo.height = current_height; + } + + wattr.background_pixel = /*black.pixel*/0; wattr.backing_store = Always; wattr.backing_planes = bitdepth; wattr.border_pixmap = None; - wattr.border_pixel = black.pixel; + wattr.border_pixel = /*black.pixel*/0; wattr.colormap = cmap; - - mywin = XCreateWindow(display, rootwin, 0, 0, gfx_requested_width, gfx_requested_height, 0, - bitdepth, InputOutput, vis, - CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore - |CWBackingPlanes|CWColormap -#ifdef USE_DGA_EXTENSION - |CWOverrideRedirect -#endif - ,&wattr); - - XMapWindow(display, mywin); -#ifdef USE_DGA_EXTENSION - XRaiseWindow(display, mywin); -#else - XStoreName(display, mywin, "UAE"); - - blankCursor = XCreatePixmapCursor(display, - XCreatePixmap(display, mywin, 1, 1, 1), - XCreatePixmap(display, mywin, 1, 1, 1), - &black, &white, 0, 0); - xhairCursor = XCreateFontCursor(display, XC_crosshair); + valuemask = (CWEventMask | CWBackPixel | CWBorderPixel + | CWBackingStore | CWBackingPlanes | CWColormap); - whitegc = XCreateGC(display,mywin,0,0); - blackgc = XCreateGC(display,mywin,0,0); - - XSetForeground(display, blackgc, black.pixel); - XSetForeground(display, whitegc, white.pixel); -#endif - - if (bitdepth < 8 || (bitdepth == 8 && color_mode == 3)) { - gfxvidinfo.pixbytes = 2; - use_low_bandwidth = 1; - need_dither = 1; -#ifndef DONT_WANT_SHM - use_shm = 0; -#endif - } else { - gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4 - : bitdepth == 12 || bitdepth == 16 ? 2 - : 1); - } + if (dgamode) { + wattr.event_mask = DGA_EVENTMASK; + wattr.override_redirect = 1; + valuemask |= CWOverrideRedirect; + } else + wattr.event_mask = EVENTMASK; -#ifdef USE_DGA_EXTENSION - /* We want all the key presses */ - - XGrabKeyboard(display, rootwin, 1, GrabModeAsync, - GrabModeAsync, CurrentTime); - - /* and all the mouse moves */ - XGrabPointer(display, rootwin, 1, PointerMotionMask | - ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - - XF86DGAGetVideo(display, screen,&fb_addr,&fb_width,&fb_bank,&fb_mem); - fprintf(stderr, "addr:%X, width %d, bank size %d mem size %d\n", - fb_addr, fb_width, fb_bank,fb_mem); - - if (fb_bank