📄 scr_x11.c
字号:
/* * Copyright (c) 2000, 2001, 2003 Greg Haerr <greg@censoft.com> * Portions Copyright (c) 2002 Koninklijke Philips Electronics * Copyright (c) 1999 Tony Rogvall <tony@bluetail.com> * Rewritten to avoid multiple function calls by Greg Haerr * Alpha blending added by Erik Hill * (brought to life in a dark laboratory on a stormy night * in an ancient castle by Dr. Frankenstein) * * X11 screen driver for Microwindows */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <assert.h>#include "device.h"#include "fb.h"#include "genmem.h"#include "genfont.h"/* SCREEN_WIDTH, SCREEN_HEIGHT and MWPIXEL_FORMAT define server X window*/#ifndef SCREEN_WIDTH#error SCREEN_WIDTH not defined#endif#ifndef SCREEN_HEIGHT#error SCREEN_HEIGHT not defined#endif#ifndef MWPIXEL_FORMAT#error MWPIXEL_FORMAT not defined#endif/* SCREEN_DEPTH is used only for palette modes*/#if !defined(SCREEN_DEPTH) && (MWPIXEL_FORMAT == MWPF_PALETTE)#error SCREEN_DEPTH not defined - must be set for palette modes#endif/* externally set override values from nanox/srvmain.c*/MWCOORD nxres; /* requested server x res*/MWCOORD nyres; /* requested server y res*//* specific x11 driver entry points*/static PSD X11_open(PSD psd);static void X11_close(PSD psd);static void X11_getscreeninfo(PSD psd, PMWSCREENINFO psi);static void X11_setpalette(PSD psd, int first, int count, MWPALENTRY * pal);static void X11_drawpixel(PSD psd, MWCOORD x, MWCOORD y, MWPIXELVAL c);static MWPIXELVAL X11_readpixel(PSD psd, MWCOORD x, MWCOORD y);static void X11_drawhline(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y, MWPIXELVAL c);static void X11_drawvline(PSD psd, MWCOORD x, MWCOORD y1, MWCOORD y2, MWPIXELVAL c);static void X11_fillrect(PSD psd, MWCOORD x1, MWCOORD y1, MWCOORD x2, MWCOORD y2, MWPIXELVAL c);static void X11_blit(PSD dstpsd, MWCOORD destx, MWCOORD desty, MWCOORD w, MWCOORD h, PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long op);static void X11_preselect(PSD psd);static void X11_drawarea(PSD psd, driver_gc_t * gc, int op);static void X11_stretchblitex(PSD dstpsd, PSD srcpsd, MWCOORD dest_x_start, MWCOORD dest_y_start, MWCOORD width, MWCOORD height, int x_denominator, int y_denominator, int src_x_fraction, int src_y_fraction, int x_step_fraction, int y_step_fraction, long op);SCREENDEVICE scrdev = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, X11_open, X11_close, X11_getscreeninfo, X11_setpalette, X11_drawpixel, X11_readpixel, X11_drawhline, X11_drawvline, X11_fillrect, gen_fonts, X11_blit, X11_preselect, X11_drawarea, NULL, /* SetIOPermissions */ gen_allocatememgc, fb_mapmemgc, gen_freememgc, NULL, /* StretchBlit subdriver */ NULL, /* SetPortrait */ 0, /* int portrait */ NULL, /* orgsubdriver */ X11_stretchblitex, /* StretchBlitEx subdriver*/};/* called from keyboard/mouse/screen */Display *x11_dpy;int x11_scr;Visual *x11_vis;Colormap x11_colormap;Window x11_win;GC x11_gc;unsigned int x11_event_mask;static int x11_width, x11_height;static int x11_depth; /* Screen depth in bpp */static int x11_is_palette; /* Nonzero for palette, zero for true color *//* For a truecolor X11 system, the following constants define the colors */static int x11_r_shift;static unsigned long x11_r_mask;static int x11_g_shift;static unsigned long x11_g_mask;static int x11_b_shift;static unsigned long x11_b_mask;static int x11_colormap_installed = 0;static SCREENDEVICE savebits; /* permanent offscreen drawing buffer *//* color palette for color indexe */static XColor x11_palette[256];static int x11_pal_max = 0;#if MWPIXEL_FORMAT != MWPF_PALETTE/* Color cache for true color lookups */#define COLOR_CACHE_SIZE 1001struct color_cache { int init; /* 1 if first use */ unsigned short r; unsigned short g; unsigned short b; XColor c;};static struct color_cache ccache[COLOR_CACHE_SIZE];static unsigned longlookup_color(unsigned short r, unsigned short g, unsigned short b){ int ix = ((r << 16) + (g << 8) + b) % COLOR_CACHE_SIZE; if (ccache[ix].init || (ccache[ix].r != r) || (ccache[ix].g != g) || (ccache[ix].b != b)) { char spec[20]; XColor exact; XColor def; ccache[ix].init = 0; ccache[ix].r = r; ccache[ix].g = g; ccache[ix].b = b; sprintf(spec, "#%02x%02x%02x", r, g, b); XLookupColor(x11_dpy, x11_colormap, spec, &exact, &def); XAllocColor(x11_dpy, x11_colormap, &def); ccache[ix].c = def; /* DPRINTF("lookup: exact(%d,%d,%d) = %d, def(%d,%d,%d)=%d\n", exact.red>>8, exact.green>>8, exact.blue>>8, exact.pixel, def.red>>8, def.green>>8, def.blue>>8, def.pixel); */ } return (unsigned long) ccache[ix].c.pixel;}#endif /* MWPIXEL_FORMAT != MWPF_PALETTE */#if MWPIXEL_FORMAT != MWPF_PALETTE#if (MWPIXEL_FORMAT == MWPF_TRUECOLOR888) || (MWPIXEL_FORMAT == MWPF_TRUECOLOR0888) || (MWPIXEL_FORMAT == MWPF_TRUECOLOR8888)#define PIXEL2RED8(p) PIXEL888RED8(p)#define PIXEL2GREEN8(p) PIXEL888GREEN8(p)#define PIXEL2BLUE8(p) PIXEL888BLUE8(p)#define PIXEL2RED32(p) PIXEL888RED32(p)#define PIXEL2GREEN32(p) PIXEL888GREEN32(p)#define PIXEL2BLUE32(p) PIXEL888BLUE32(p)#elif MWPIXEL_FORMAT == MWPF_TRUECOLOR565#define PIXEL2RED8(p) PIXEL565RED8(p)#define PIXEL2GREEN8(p) PIXEL565GREEN8(p)#define PIXEL2BLUE8(p) PIXEL565BLUE8(p)#define PIXEL2RED32(p) PIXEL565RED32(p)#define PIXEL2GREEN32(p) PIXEL565GREEN32(p)#define PIXEL2BLUE32(p) PIXEL565BLUE32(p)#elif MWPIXEL_FORMAT == MWPF_TRUECOLOR555#define PIXEL2RED8(p) PIXEL555RED8(p)#define PIXEL2GREEN8(p) PIXEL555GREEN8(p)#define PIXEL2BLUE8(p) PIXEL555BLUE8(p)#define PIXEL2RED32(p) PIXEL555RED32(p)#define PIXEL2GREEN32(p) PIXEL555GREEN32(p)#define PIXEL2BLUE32(p) PIXEL555BLUE32(p)#elif MWPIXEL_FORMAT == MWPF_TRUECOLOR332#define PIXEL2RED8(p) PIXEL332RED8(p)#define PIXEL2GREEN8(p) PIXEL332GREEN8(p)#define PIXEL2BLUE8(p) PIXEL332BLUE8(p)#define PIXEL2RED32(p) PIXEL332RED32(p)#define PIXEL2GREEN32(p) PIXEL332GREEN32(p)#define PIXEL2BLUE32(p) PIXEL332BLUE32(p)#endif/* calc truecolor conversions directly */#define PIXELVAL_to_pixel(c) (x11_is_palette \ ? lookup_color(PIXEL2RED8(c), PIXEL2GREEN8(c), PIXEL2BLUE8(c)) \ : ( ((PIXEL2RED32(c) >> x11_r_shift) & x11_r_mask) \ | ((PIXEL2GREEN32(c) >> x11_g_shift) & x11_g_mask) \ | ((PIXEL2BLUE32(c) >> x11_b_shift) & x11_b_mask) ) )#else /* MWPIXEL_FORMAT == MWPF_PALETTE */#define PIXELVAL_to_pixel(c) ((unsigned)(c) > (unsigned)x11_pal_max ? 0 : x11_palette[c].pixel)#endifstatic voidset_color(MWPIXELVAL c){ static unsigned long oldc = 0x80000001; if (c != oldc) { oldc = c; XSetForeground(x11_dpy, x11_gc, PIXELVAL_to_pixel(c)); }}/* Minor optimizations - save a function call overhead 99% of the time */static int x11_old_mode = -1;#define set_mode(new_mode) do { \ if (new_mode != x11_old_mode) { \ set_mode_2(new_mode); \ } \ } while (0)static voidset_mode_2(int new_mode){ int func = GXcopy; switch (new_mode) { case MWMODE_COPY: func = GXcopy; break; case MWMODE_XOR: func = GXxor; break; case MWMODE_OR: func = GXor; break; case MWMODE_AND: func = GXand; break; case MWMODE_CLEAR: func = GXclear; break; case MWMODE_SETTO1: func = GXset; break; case MWMODE_EQUIV: func = GXequiv; break; case MWMODE_NOR: func = GXnor; break; case MWMODE_NAND: func = GXnand; break; case MWMODE_INVERT: func = GXinvert; break; case MWMODE_COPYINVERTED: func = GXcopyInverted; break; case MWMODE_ORINVERTED: func = GXorInverted; break; case MWMODE_ANDINVERTED: func = GXandInverted; break; case MWMODE_ORREVERSE: func = GXorReverse; break; case MWMODE_ANDREVERSE: func = GXandReverse; break; case MWMODE_NOOP: func = GXnoop; break; default: return; } XSetFunction(x11_dpy, x11_gc, func); x11_old_mode = new_mode;}static voidupdate_from_savebits(int destx, int desty, int w, int h){ XImage *img; int x, y; char *data; /* allocate buffer */ if (x11_depth >= 24) data = malloc(w * 4 * h); else if (x11_depth > 8) /* 15, 16 */ data = malloc(w * 2 * h); else /* 1,2,4,8 */ data = malloc((w * x11_depth + 7) / 8 * h); /* copy from offscreen to screen */ img = XCreateImage(x11_dpy, x11_vis, x11_depth, ZPixmap, 0, data, w, h, 8, 0); /* Use optimized loops for most common framebuffer modes */#if MWPIXEL_FORMAT == MWPF_TRUECOLOR332 { ADDR8 dbuf = ((ADDR8) savebits.addr) + destx + desty * savebits.linelen; int linedelta = savebits.linelen - w; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { MWPIXELVAL c = *dbuf++; unsigned long pixel = PIXELVAL_to_pixel(c); XPutPixel(img, x, y, pixel); } dbuf += linedelta; } }#elif (MWPIXEL_FORMAT == MWPF_TRUECOLOR565) || (MWPIXEL_FORMAT == MWPF_TRUECOLOR555) { ADDR16 dbuf = ((ADDR16) savebits.addr) + destx + desty * savebits.linelen; int linedelta = savebits.linelen - w; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { MWPIXELVAL c = *dbuf++; unsigned long pixel = PIXELVAL_to_pixel(c); XPutPixel(img, x, y, pixel); } dbuf += linedelta; } }#elif MWPIXEL_FORMAT == MWPF_TRUECOLOR888 { ADDR8 dbuf = ((ADDR8) savebits.addr) + 3 * (destx + desty * savebits.linelen); int linedelta = 3 * (savebits.linelen - w); for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { MWPIXELVAL c = RGB2PIXEL888(dbuf[2], dbuf[1], dbuf[0]); unsigned long pixel = PIXELVAL_to_pixel(c); XPutPixel(img, x, y, pixel); dbuf += 3; } dbuf += linedelta; } }#elif (MWPIXEL_FORMAT == MWPF_TRUECOLOR0888) || (MWPIXEL_FORMAT == MWPF_TRUECOLOR8888) { ADDR32 dbuf = ((ADDR32) savebits.addr) + destx + desty * savebits.linelen; int linedelta = savebits.linelen - w; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { MWPIXELVAL c = *dbuf++; unsigned long pixel = PIXELVAL_to_pixel(c); XPutPixel(img, x, y, pixel); } dbuf += linedelta; } }#else { for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { MWPIXELVAL c = savebits.ReadPixel(&savebits, destx + x, desty + y); unsigned long pixel = PIXELVAL_to_pixel(c); XPutPixel(img, x, y, pixel); } } }#endif set_mode(MWMODE_COPY); XPutImage(x11_dpy, x11_win, x11_gc, img, 0, 0, destx, desty, w, h); XDestroyImage(img);}/* called from mou_x11 (handles x11_event_mask events) */voidx11_handle_event(XEvent * ev){ static int inited = 0; if (ev->type == ColormapNotify) { if (ev->xcolormap.window == x11_win) { if (ev->xcolormap.state == ColormapInstalled) { DPRINTF("colormap uninstalled\n"); x11_colormap_installed = 0; } else if (ev->xcolormap.state == ColormapInstalled) { x11_colormap_installed = 1; DPRINTF("colormap installed\n"); } } } else if (ev->type == FocusIn) { if (!x11_colormap_installed) { DPRINTF("setting colormap\n"); XInstallColormap(x11_dpy, x11_colormap); inited = 1; } } else if (ev->type == MappingNotify) { DPRINTF("Refreshing keyboard mapping\n"); XRefreshKeyboardMapping(&ev->xmapping); }#if 0 else if (ev->type == EnterNotify) { if (inited) GdShowCursor(&scrdev); } else if (ev->type == LeaveNotify) { if (inited) GdHideCursor(&scrdev); }#endif#ifdef USE_EXPOSURE else if (ev->type == Expose) { update_from_savebits(ev->xexpose.x, ev->xexpose.y, ev->xexpose.width, ev->xexpose.height); }#endif}static intx11_error(Display * dpy, XErrorEvent * ev){ char err_string[256]; XGetErrorText(dpy, ev->error_code, err_string, 256); EPRINTF("X11 error: %s\n", err_string); return 0;}char *classnm[] = { "StaticGray", "GrayScale", "StaticColor", "PseudoColor", "TrueColor", "DirectColor"};static voidshow_visual(Visual * v){ char *name = ((v->class < 0) || (v->class > 5)) ? "???" : classnm[v->class]; /* DPRINTF */ printf(" Visual class: %s (%d)\n", name, v->class); /* DPRINTF */ printf(" id: %ld\n", v->visualid); /* DPRINTF */ printf(" bits_per_rgb: %d\n", v->bits_per_rgb); /* DPRINTF */ printf(" map_entries: %d\n", v->map_entries); /* DPRINTF */ printf(" red_mask: 0x%08lx\n", v->red_mask); /* DPRINTF */ printf(" green_mask: 0x%08lx\n", v->green_mask); /* DPRINTF */ printf(" blue_mask: 0x%08lx\n", v->blue_mask);}static Visual *select_visual(Display * dpy, int scr){ Visual *vis = XDefaultVisual(dpy, scr);#if MWPIXEL_FORMAT != MWPF_PALETTE /* Patch by Jon to try for 8-bit TrueColor */ Visual *vis2 = NULL;#endif Screen *screen = XScreenOfDisplay(dpy, scr); int d; /* DPRINTF */ printf("XDefaultVisual:\n"); show_visual(vis); /* DPRINTF */ printf("Screen RootDepth: %d\n", screen->root_depth); /* DPRINTF */ printf("Screen RootVisual\n"); show_visual(screen->root_visual); /* print all depths/visuals */ for (d = 0; d < screen->ndepths; d++) { Depth *dp = screen->depths + d; int v; Visual *cur_vis; /* DPRINTF */ printf("Depth: %d\n", dp->depth); for (v = 0; v < dp->nvisuals; v++) { /* DPRINTF */ printf("Visual: %d\n", v); cur_vis = dp->visuals + v; show_visual(cur_vis);#if MWPIXEL_FORMAT != MWPF_PALETTE /* Patch by Jon to try for 8-bit TrueColor */ if ((vis->class != TrueColor) && (dp->depth == screen->root_depth) && (cur_vis->class == TrueColor)) { /* Maybe useful... */ if ((vis2 == NULL) || (vis2->bits_per_rgb < cur_vis->bits_per_rgb)) { /* Better than what we had before */ vis2 = cur_vis; } }#endif } }#if MWPIXEL_FORMAT != MWPF_PALETTE /* Patch by Jon to try for 8-bit TrueColor */ if ((vis->class != TrueColor) && (vis2 != NULL)) { vis = vis2; } /* DPRINTF */ printf("Selected Visual:\n"); show_visual(vis);#endif return vis;}intx11_setup_display(void){ static int setup_needed = 1; if (setup_needed) { char *name;#if MWPIXEL_FORMAT != MWPF_PALETTE int i;#endif if ((name = getenv("DISPLAY")) == NULL) name = ":0"; if ((x11_dpy = XOpenDisplay(name)) == NULL) return -1; XSetErrorHandler(x11_error); x11_width = nxres? nxres: SCREEN_WIDTH; x11_height = nyres? nyres: SCREEN_HEIGHT; x11_scr = XDefaultScreen(x11_dpy); x11_vis = select_visual(x11_dpy, x11_scr); if ((x11_vis->class == StaticGray) || (x11_vis->class == GrayScale)) { EPRINTF("Nano-X Error: Your X server appears to be grayscale only.\nThis is not supported.\n"); return -1; } else if (x11_vis->class == DirectColor) { EPRINTF("Nano-X Error: Your X server appears to use the 'DirectColor' format.\nThis is not supported.\n"); return -1; } else if ((x11_vis->class == PseudoColor) || (x11_vis->class == StaticColor)) { /* OK. Palette based. */ x11_is_palette = 1; } else if (x11_vis->class == TrueColor) { /* OK. True color. */ unsigned long mask; int shift; x11_is_palette = 0; /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -