--- uae/src/xwin.c 2018/04/24 16:38:39 1.1 +++ uae/src/xwin.c 2018/04/24 16:38:59 1.1.1.2 @@ -5,6 +5,7 @@ * * Copyright 1995, 1996 Bernd Schmidt * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste + * DGA support by Kai Kollmorgen */ #include "sysconfig.h" @@ -28,6 +29,7 @@ #include "options.h" #include "memory.h" #include "custom.h" +#include "readcpu.h" #include "newcpu.h" #include "xwin.h" #include "keyboard.h" @@ -35,6 +37,12 @@ #include "gui.h" #include "debug.h" +#ifdef USE_DGA_EXTENSION +#include +#define DGA_MINMAJOR 0 +#define DGA_MINMINOR 0 +#endif + #ifdef __cplusplus static RETSIGTYPE sigbrkhandler(...) #else @@ -64,6 +72,11 @@ void setup_brkhandler(void) #endif } +#ifdef USE_DGA_EXTENSION +static char *fb_addr; +static int fb_width; +#endif + static Display *display; static int screen; static Window rootwin, mywin; @@ -93,6 +106,8 @@ static int use_low_bandwidth = 1; static int use_low_bandwidth = 0; #endif +static int x11_init_ok; + xcolnr xcolors[4096]; /* Keyboard and mouse */ @@ -106,25 +121,32 @@ int newmousecounters; static int inwindow; const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask |ButtonReleaseMask|PointerMotionMask +#ifndef USE_DGA_EXTENSION |FocusChangeMask|EnterWindowMask |ExposureMask - |LeaveWindowMask); + |LeaveWindowMask +#endif + ); -static int vsize, hsize, hpixels; static char *oldpixbuf; struct vidbuf_description gfxvidinfo; void flush_line(int y) { +#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); + } +#else int xs = 0, xe; int len, factor; char *linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem; char *src, *dst; - if (gfxvidinfo.maxlinetoscr) - xe = gfxvidinfo.maxlinetoscr-1; - else - xe = hsize-1; + + xe = gfxvidinfo.maxlinetoscr-1; if (!use_low_bandwidth) fprintf(stderr, "Bug!\n"); @@ -191,22 +213,24 @@ void flush_line(int y) printf("%d\n",len); DitherLine(target + xs*bit_unit/8, (UWORD *)linebuf + xs, xs, y, len, bit_unit); } + #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 } void flush_block (int ystart, int ystop) { +#ifdef USE_DGA_EXTENSION +#else int len, xs = 0; - if (gfxvidinfo.maxlinetoscr) - len = gfxvidinfo.maxlinetoscr; - else - len = hsize; + len = gfxvidinfo.maxlinetoscr; #ifndef DONT_WANT_SHM if (use_shm) XShmPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, @@ -215,29 +239,17 @@ void flush_block (int ystart, int ystop) #endif XPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, ystop - ystart + 1); +#endif } void flush_screen (int ystart, int ystop) { +#ifdef USE_DGA_EXTENSION +#else #ifndef DONT_WANT_SHM if (use_shm) XSync(display, 0); #endif -} - -void calc_adjustment(void) -{ - switch (screen_res) { - case 0: case 1: case 2: /* LoRes, 320x300 */ - gfxvidinfo.x_adjust = prev_max_diwstop - 320; - break; - - case 3: /* 640x480 */ - gfxvidinfo.x_adjust = prev_max_diwstop - 640; - break; - default: - gfxvidinfo.x_adjust = 0; - break; - } +#endif } static __inline__ int bitsInMask(unsigned long mask) @@ -332,17 +344,51 @@ int graphics_init(void) 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; - - if (screen_res < 3) { - fprintf(stderr, "Low resolution mode selected. Forcing 320x300.\n"); + +#ifdef USE_DGA_EXTENSION + if (geteuid()) { + fprintf(stderr, "You must be root to use UAE with the DGA extensions.\n"); + return(0); } +#endif display = XOpenDisplay(display_name); if (display == 0) { fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name)); return 0; } + +#ifdef USE_DGA_EXTENSION + if (!XF86DGAQueryVersion(display, &MajorVersion, &MinorVersion)) { + fprintf(stderr, "Unable to query video extension version\n"); + return(0); + } + + if (!XF86DGAQueryExtension(display, &EventBase, &ErrorBase)) { + fprintf(stderr, "Unable to query video extension information\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); + } +#endif + screen = XDefaultScreen(display); rootwin = XRootWindow(display,screen); @@ -378,19 +424,20 @@ int graphics_init(void) bit_unit = xpfvs->bits_per_pixel; fprintf(stderr, "Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit); - switch (screen_res) { - case 0: case 1: case 2: - hsize = hpixels = 320; - correct_aspect = 0; - break; - case 3: - hsize = hpixels = 640; - break; - case 4: - hpixels = 796; hsize = 800; /* ??? */ - break; - } - vsize = correct_aspect ? 2*numscrlines : numscrlines; + 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; + + 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; cmap = XCreateColormap(display, rootwin, vis, AllocNone); XParseColor(display, cmap, "#000000", &black); @@ -400,6 +447,9 @@ int graphics_init(void) if (!XAllocColor(display, cmap, &white)) fprintf(stderr, "Whoops??\n"); +#ifdef USE_DGA_EXTENSION + wattr.override_redirect = 1; +#endif wattr.event_mask = eventmask; wattr.background_pixel = black.pixel; wattr.backing_store = Always; @@ -407,13 +457,20 @@ int graphics_init(void) wattr.border_pixmap = None; wattr.border_pixel = black.pixel; wattr.colormap = cmap; - - mywin = XCreateWindow(display, rootwin, 0, 0, hpixels, vsize, 0, + + mywin = XCreateWindow(display, rootwin, 0, 0, gfx_requested_width, gfx_requested_height, 0, bitdepth, InputOutput, vis, CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore - |CWBackingPlanes|CWColormap, - &wattr); - XMapWindow(display,mywin); + |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, @@ -425,9 +482,10 @@ int graphics_init(void) whitegc = XCreateGC(display,mywin,0,0); blackgc = XCreateGC(display,mywin,0,0); - XSetForeground(display,blackgc,black.pixel); - XSetForeground(display,whitegc,white.pixel); - + 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; @@ -440,12 +498,39 @@ int graphics_init(void) : bitdepth == 12 || bitdepth == 16 ? 2 : 1); } + +#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_bankbytes_per_line, + shminfo.shmid = shmget(IPC_PRIVATE, gfx_requested_height * img->bytes_per_line, IPC_CREAT | 0777); shminfo.shmaddr = img->data = image_mem = (char *)shmat(shminfo.shmid, 0, 0); shminfo.readOnly = False; @@ -461,26 +546,30 @@ int graphics_init(void) * after creating the image and then do img->data = buffer, as above in * the SHM case? */ - image_mem = (char *)malloc(vsize * hsize * bit_unit / 8); /* ??? */ + image_mem = (char *)malloc(gfx_requested_height * gfx_requested_width * bit_unit / 8); /* ??? */ img = XCreateImage(display, vis, bitdepth, ZPixmap, 0, image_mem, - hsize, vsize, 32, 0); - if (img->bytes_per_line != hsize * bit_unit / 8) + gfx_requested_width, gfx_requested_height, 32, 0); + if (img->bytes_per_line != gfx_requested_width * bit_unit / 8) fprintf (stderr, "Possible bug here... graphics may look strange.\n"); } +#endif if (need_dither) { - gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * hsize; - gfxvidinfo.bufmem = (char *)malloc(gfxvidinfo.rowbytes * vsize); + gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * gfx_requested_width; + gfxvidinfo.bufmem = (char *)malloc(gfxvidinfo.rowbytes * gfx_requested_height); } else { +#ifdef USE_DGA_EXTENSION + gfxvidinfo.rowbytes = fb_width*gfxvidinfo.pixbytes; + gfxvidinfo.bufmem = fb_addr; +#else gfxvidinfo.rowbytes = img->bytes_per_line; gfxvidinfo.bufmem = image_mem; +#endif } - gfxvidinfo.maxline = 100000; /* no limit */ - if (use_low_bandwidth) { gfxvidinfo.maxblocklines = 0; - oldpixbuf = (char *)malloc(gfxvidinfo.rowbytes * vsize); + oldpixbuf = (char *)malloc(gfxvidinfo.rowbytes * gfx_requested_height); } else { gfxvidinfo.maxblocklines = 100; /* whatever... */ } @@ -495,19 +584,35 @@ int graphics_init(void) lastmx = lastmy = 0; newmousecounters = 0; inwindow = 0; - + +#ifndef USE_DGA_EXTENSION if (!no_xhair) - XDefineCursor(display, mywin, xhairCursor); + XDefineCursor(display, mywin, xhairCursor); else - XDefineCursor(display, mywin, blankCursor); + XDefineCursor(display, mywin, blankCursor); cursorOn = 1; - return 1; +#else + XF86DGAInstallColormap(display,screen,cmap); +#endif + + return x11_init_ok = 1; } void graphics_leave(void) { + if (!x11_init_ok) + return; + if (autorepeatoff) - XAutoRepeatOn(display); + XAutoRepeatOn(display); + XFlush(display); + XSync(display, 0); +#ifdef USE_DGA_EXTENSION + XF86DGADirectVideo(display, DefaultScreen(display), 0); + XUngrabPointer(display, CurrentTime); + XUngrabKeyboard(display, CurrentTime); + dumpcustom(); +#endif } /* Decode KeySyms. This function knows about all keys that are common @@ -534,7 +639,6 @@ static int kc_decode (KeySym ks) case XK_T: case XK_t: return AK_T; case XK_U: case XK_u: return AK_U; case XK_V: case XK_v: return AK_V; - case XK_W: case XK_w: return AK_W; case XK_X: case XK_x: return AK_X; case XK_0: return AK_0; @@ -615,7 +719,14 @@ static int kc_decode (KeySym ks) case XK_Right: return AK_RT; case XK_F11: return AK_BACKSLASH; +#ifdef USE_DGA_EXTENSION + case XK_F12: + regs.spcflags |= SPCFLAG_BRK; + quit_program = 1; + return(-1); +#else case XK_F12: return AK_mousestuff; +#endif #ifdef XK_F14 case XK_F14: #endif @@ -636,7 +747,8 @@ static int decode_fr(KeySym ks) case XK_M: case XK_m: return AK_SEMICOLON; case XK_Q: case XK_q: return AK_A; case XK_Y: case XK_y: return AK_Y; - case XK_Z: case XK_z: return AK_Z; + case XK_W: case XK_w: return AK_Z; + case XK_Z: case XK_z: return AK_W; case XK_bracketleft: return AK_LBRACKET; case XK_bracketright: return AK_RBRACKET; case XK_comma: return AK_M; @@ -660,6 +772,7 @@ static int decode_us(KeySym ks) case XK_M: case XK_m: return AK_M; case XK_Q: case XK_q: return AK_Q; case XK_Y: case XK_y: return AK_Y; + case XK_W: case XK_w: return AK_W; case XK_Z: case XK_z: return AK_Z; case XK_bracketleft: return AK_LBRACKET; case XK_bracketright: return AK_RBRACKET; @@ -685,6 +798,7 @@ static int decode_de(KeySym ks) case XK_A: case XK_a: return AK_A; case XK_M: case XK_m: return AK_M; case XK_Q: case XK_q: return AK_Q; + case XK_W: case XK_w: return AK_W; case XK_Y: case XK_y: return AK_Z; case XK_Z: case XK_z: return AK_Y; case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON; @@ -711,6 +825,7 @@ static int decode_se(KeySym ks) case XK_A: case XK_a: return AK_A; case XK_M: case XK_m: return AK_M; case XK_Q: case XK_q: return AK_Q; + case XK_W: case XK_w: return AK_W; case XK_Y: case XK_y: return AK_Y; case XK_Z: case XK_z: return AK_Z; case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON; @@ -738,6 +853,7 @@ static int decode_it(KeySym ks) case XK_A: case XK_a: return AK_A; case XK_M: case XK_m: return AK_M; case XK_Q: case XK_q: return AK_Q; + case XK_W: case XK_w: return AK_W; case XK_Y: case XK_y: return AK_Y; case XK_Z: case XK_z: return AK_Z; case XK_Ograve: case XK_ograve: return AK_SEMICOLON; @@ -757,6 +873,35 @@ static int decode_it(KeySym ks) return -1; } +static int decode_es(KeySym ks) +{ + switch(ks) { + /* ES specific */ + case XK_A: case XK_a: return AK_A; + case XK_M: case XK_m: return AK_M; + case XK_Q: case XK_q: return AK_Q; + case XK_W: case XK_w: return AK_W; + case XK_Y: case XK_y: return AK_Y; + case XK_Z: case XK_z: return AK_Z; + case XK_ntilde: case XK_Ntilde: return AK_SEMICOLON; +#ifdef XK_dead_acute + case XK_dead_acute: case XK_dead_diaeresis: return AK_QUOTE; + case XK_dead_grave: case XK_dead_circumflex: return AK_LBRACKET; +#endif + case XK_plus: case XK_asterisk: return AK_RBRACKET; + case XK_comma: return AK_COMMA; + case XK_period: return AK_PERIOD; + case XK_less: case XK_greater: return AK_LTGT; + case XK_backslash: case XK_bar: return AK_BACKQUOTE; + case XK_apostrophe: return AK_MINUS; + case XK_Igrave: case XK_igrave: return AK_EQUAL; + case XK_minus: return AK_SLASH; + case XK_numbersign: return AK_NUMBERSIGN; + } + + return -1; +} + static int keycode2amiga(XKeyEvent *event) { KeySym ks; @@ -790,6 +935,10 @@ static int keycode2amiga(XKeyEvent *even as = decode_it(ks); break; + case KBD_LANG_ES: + as = decode_es(ks); + break; + default: as = -1; break; @@ -853,6 +1002,7 @@ void handle_events(void) case ButtonRelease: buttonstate[((XButtonEvent *)&event)->button-1] = 0; break; +#ifndef USE_DGA_EXTENSION case EnterNotify: newmousecounters = 1; lastmx = ((XCrossingEvent *)&event)->x; @@ -886,16 +1036,23 @@ void handle_events(void) case Expose: refresh = 1; break; +#else + case MotionNotify: + newmousecounters = 0; + lastmx += ((XMotionEvent *)&event)->x_root; + lastmy += ((XMotionEvent *)&event)->y_root; +#endif } } +#ifndef USE_DGA_EXTENSION if(refresh) { #ifndef DONT_WANT_SHM if (use_shm) - XShmPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize, 0); + XShmPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, gfx_requested_width, gfx_requested_height, 0); else #endif - XPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize); + XPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, gfx_requested_width, gfx_requested_height); } if(cursorOn && !no_xhair) { struct timeval now; @@ -908,7 +1065,7 @@ void handle_events(void) cursorOn = 0; } } - +#endif /* "Affengriff" */ if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI]) m68k_reset(); @@ -921,11 +1078,16 @@ int debuggable(void) int needmousehack(void) { +#ifdef USE_DGA_EXTENSION + return 0; +#else return 1; +#endif } void LED(int on) { +#if 0 /* Maybe that is responsible for the joystick emulation problems on SunOS? */ static int last_on = -1; XKeyboardControl control; @@ -934,20 +1096,21 @@ void LED(int on) control.led = 1; /* implementation defined */ control.led_mode = on ? LedModeOn : LedModeOff; XChangeKeyboardControl(display, KBLed | KBLedMode, &control); +#endif } void target_specific_usage(void) { - printf(" -S n : Sound emulation accuracy (n = 0, 1, 2 or 3)\n" - " For sound emulation, n = 2 is recommended\n"); - printf(" -b n : Use n bits for sound output (8 or 16)\n"); - printf(" -R n : Use n Hz to output sound. Common values are\n" - " 22050 Hz or 44100 Hz\n"); - printf(" -B n : Use a sound buffer of n bytes (use small\n" - " values on fast machines)\n"); - printf(" -x : Use visible cross-hair cursor\n"); - printf(" -l lang : Set keyboard language to lang, where lang is\n" - " DE, SE, US, FR or IT\n"); - printf(" -p command : Use command to pipe printer output to.\n"); - printf(" -I device : Name of the used serial device (i.e. /dev/ttyS1\n"); + printf(" -S n : Sound emulation accuracy (n = 0, 1, 2 or 3)\n" + " For sound emulation, n = 2 is recommended\n"); + printf(" -b n : Use n bits for sound output (8 or 16)\n"); + printf(" -R n : Use n Hz to output sound. Common values are\n" + " 22050 Hz or 44100 Hz\n"); + printf(" -B n : Use a sound buffer of n bytes (use small\n" + " values on fast machines)\n"); + printf(" -x : Use visible cross-hair cursor\n"); + printf(" -l lang : Set keyboard language to lang, where lang is\n" + " DE, SE, US, FR or IT\n"); + printf(" -p command : Use command to pipe printer output to.\n"); + printf(" -I device : Name of the used serial device (i.e. /dev/ttyS1\n"); }