From 81a3b6fe27567b4f91033ece69996aa6bf8d01a3 Mon Sep 17 00:00:00 2001 From: Matthew Allum Date: Mon, 8 Nov 2004 22:39:47 +0000 Subject: [PATCH] Add support to Xephyr for lower depths than hosts --- hw/kdrive/ephyr/ephyr.c | 56 ++++++++++++++-- hw/kdrive/ephyr/hostx.c | 138 ++++++++++++++++++++++++++++++++++------ hw/kdrive/ephyr/hostx.h | 11 ++++ 3 files changed, 179 insertions(+), 26 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 4c08e497e..e4f6e927a 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -85,9 +85,18 @@ ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv) if (screen->fb[0].depth && screen->fb[0].depth != hostx_get_depth()) - ErrorF("\nXephyr screen depth must match hosts, ignoring.\n"); + { + if (screen->fb[0].depth < hostx_get_depth() + && (screen->fb[0].depth == 24 || screen->fb[0].depth == 16 + || screen->fb[0].depth == 8)) + { + hostx_set_server_depth(screen->fb[0].depth); + } + else + ErrorF("\nXephyr: requested screen depth not supported, setting to match hosts.\n"); + } - screen->fb[0].depth = hostx_get_depth(); + screen->fb[0].depth = hostx_get_server_depth(); screen->rate = 72; if (screen->fb[0].depth <= 8) @@ -98,6 +107,13 @@ ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv) (1 << PseudoColor) | (1 << TrueColor) | (1 << DirectColor)); + + screen->fb[0].redMask = 0x00; + screen->fb[0].greenMask = 0x00; + screen->fb[0].blueMask = 0x00; + screen->fb[0].depth = 8; + screen->fb[0].bitsPerPixel = 8; + } else { @@ -601,18 +617,44 @@ ephyrCardFini (KdCardInfo *card) void ephyrGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) { - while (n--) + /* XXX Not sure if this is right */ + + EPHYR_DBG("mark"); + + while (n--) { - pdefs->red = 0; - pdefs->green = 0; - pdefs->blue = 0; - pdefs++; + pdefs->red = 0; + pdefs->green = 0; + pdefs->blue = 0; + pdefs++; } + } void ephyrPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) { + int min, max, p; + + /* XXX Not sure if this is right */ + + min = 256; + max = 0; + + while (n--) + { + p = pdefs->pixel; + if (p < min) + min = p; + if (p > max) + max = p; + + hostx_set_cmap_entry(p, + pdefs->red >> 8, + pdefs->green >> 8, + pdefs->blue >> 8); + pdefs++; + } } /* Mouse calls */ diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index af8b10b97..20eb74bc8 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -55,16 +55,20 @@ struct EphyrHostXVars Window win_pre_existing; /* Set via -parent option like xnest */ GC gc; int depth; + int server_depth; XImage *ximg; int win_width, win_height; Bool use_host_cursor; Bool have_shm; long damage_debug_msec; + unsigned char *fb_data; /* only used when host bpp != server bpp */ + unsigned long cmap[256]; + XShmSegmentInfo shminfo; }; -static EphyrHostXVars HostX = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /* defaults */ +static EphyrHostXVars HostX = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* memset? */ static int HostXWantDamageDebug = 0; @@ -83,6 +87,9 @@ extern int monitorResolution; static int trapped_error_code = 0; static int (*old_error_handler) (Display *d, XErrorEvent *e); +#define host_depth_matches_server() (HostX.depth == HostX.server_depth) + + static int error_handler(Display *display, XErrorEvent *error) @@ -187,15 +194,9 @@ hostx_init(void) HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL); HostX.depth = DefaultDepth(HostX.dpy, HostX.screen); HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); + + HostX.server_depth = HostX.depth; - /* old way of getting dpi - HostX.mm_per_pixel_vertical = (double)DisplayHeightMM(HostX.dpy, HostX.screen) - / DisplayHeight(HostX.dpy, HostX.screen); - - HostX.mm_per_pixel_horizontal = (double)DisplayWidthMM(HostX.dpy, HostX.screen) - / DisplayWidth(HostX.dpy, HostX.screen); - */ - if (HostX.win_pre_existing != None) { Status result; @@ -226,7 +227,7 @@ hostx_init(void) HostX.winroot, 0,0,100,100, /* will resize */ 0, - CopyFromParent, + CopyFromParent, CopyFromParent, CopyFromParent, CWEventMask, @@ -235,7 +236,6 @@ hostx_init(void) XStoreName(HostX.dpy, HostX.win, "Xephyr"); } - HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL); XParseColor(HostX.dpy, DefaultColormap(HostX.dpy,HostX.screen), "red", &col); XAllocColor(HostX.dpy, DefaultColormap(HostX.dpy, HostX.screen), &col); @@ -309,22 +309,62 @@ hostx_get_depth (void) return HostX.depth; } +int +hostx_get_server_depth (void) +{ + return HostX.server_depth; +} + +void +hostx_set_server_depth(int depth) +{ + HostX.server_depth = depth; +} + int hostx_get_bpp(void) { - return HostX.visual->bits_per_rgb; + if (host_depth_matches_server()) + return HostX.visual->bits_per_rgb; + else + return HostX.server_depth; /* XXX correct ? */ } void hostx_get_visual_masks (unsigned long *rmsk, - unsigned long *gmsk, - unsigned long *bmsk) + unsigned long *gmsk, + unsigned long *bmsk) { - *rmsk = HostX.visual->red_mask; - *gmsk = HostX.visual->green_mask; - *bmsk = HostX.visual->blue_mask; + if (host_depth_matches_server()) + { + *rmsk = HostX.visual->red_mask; + *gmsk = HostX.visual->green_mask; + *bmsk = HostX.visual->blue_mask; + } + else if (HostX.server_depth == 16) + { + /* Assume 16bpp 565 */ + *rmsk = 0xf800; + *gmsk = 0x07e0; + *bmsk = 0x001f; + } + else + { + *rmsk = 0x0; + *gmsk = 0x0; + *bmsk = 0x0; + } } +void +hostx_set_cmap_entry(unsigned char idx, + unsigned char r, + unsigned char g, + unsigned char b) +{ + /* XXX Will likely break for 8 on 16, not sure if this is correct */ + HostX.cmap[idx] = (r << 16) | (g << 8) | (b); +} void* hostx_screen_init (int width, int height) @@ -422,7 +462,17 @@ hostx_screen_init (int width, int height) HostX.win_width = width; HostX.win_height = height; - return HostX.ximg->data; + if (host_depth_matches_server()) + { + EPHYR_DBG("Host matches server"); + return HostX.ximg->data; + } + else + { + EPHYR_DBG("server bpp %i", HostX.server_depth>>3); + HostX.fb_data = malloc(width*height*(HostX.server_depth>>3)); + return HostX.fb_data; + } } void @@ -440,10 +490,60 @@ hostx_paint_rect(int sx, int sy, hostx_paint_debug_rect(dx, dy, width, height); } + /* + * If the depth of the ephyr server is less than that of the host, + * the kdrive fb does not point to the ximage data but to a buffer + * ( fb_data ), we shift the various bits from this onto the XImage + * so they match the host. + * + * Note, This code is pretty new ( and simple ) so may break on + * endian issues, 32 bpp host etc. + * Not sure if 8bpp case is right either. + * ... and it will be slower than the matching depth case. + */ + + if (!host_depth_matches_server()) + { + int x,y,idx, bytes_per_pixel = (HostX.server_depth>>3); + unsigned char r,g,b; + unsigned long host_pixel; + + for (x=sx; x> 8); + g = ((pixel & 0x07e0) >> 3); + b = ((pixel & 0x001f) << 3); + + host_pixel = (r << 16) | (g << 8) | (b); + + XPutPixel(HostX.ximg, x, y, host_pixel); + break; + } + case 8: + { + unsigned char pixel = *(unsigned char*)(HostX.fb_data+idx); + XPutPixel(HostX.ximg, x, y, HostX.cmap[pixel]); + break; + } + default: + break; + } + } + } + if (HostX.have_shm) { XShmPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, - sx, sy, dx, dy, width, height, False); + sx, sy, dx, dy, width, height, False); } else { diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 44d2d74b4..2ef38c089 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -103,6 +103,12 @@ hostx_init(void); int hostx_get_depth (void); +int +hostx_get_server_depth (void); + +void +hostx_set_server_depth(int depth); + int hostx_get_bpp(void); @@ -110,6 +116,11 @@ void hostx_get_visual_masks (unsigned long *rmsk, unsigned long *gmsk, unsigned long *bmsk); +void +hostx_set_cmap_entry(unsigned char idx, + unsigned char r, + unsigned char g, + unsigned char b); void* hostx_screen_init (int width, int height);