--- hostx.c.orig 2006-07-24 11:31:07.000000000 +0200 +++ hostx.c 2006-08-08 19:07:56.000000000 +0200 @@ -59,6 +59,7 @@ int depth; int server_depth; XImage *ximg; + XImage *swizzled_img; /* Only used in color swizzling & AA mode */ int win_width, win_height; Bool use_host_cursor; Bool use_fullscreen; @@ -87,6 +88,8 @@ extern int kdKeymapWidth; extern int monitorResolution; +int swizzle = 1; + static void hostx_set_fullscreen_hint(void); @@ -478,9 +481,10 @@ ZPixmap, NULL, &HostX.shminfo, width, height ); - HostX.shminfo.shmid = shmget(IPC_PRIVATE, - HostX.ximg->bytes_per_line * height, - IPC_CREAT|0777); + if (!swizzle) + HostX.shminfo.shmid = shmget(IPC_PRIVATE, + HostX.ximg->bytes_per_line * height, + IPC_CREAT|0777); HostX.shminfo.shmaddr = HostX.ximg->data = shmat(HostX.shminfo.shmid, 0, 0); @@ -553,6 +557,83 @@ } } +static unsigned long +make_24bits_pixel_from_16bits (unsigned short server_pixel) { + + unsigned char r, g, b; + + r = ((server_pixel & 0xf800) >> 8); + g = ((server_pixel & 0x07e0) >> 3); + b = ((server_pixel & 0x001f) << 3); + + return (r << 16) | (g << 8) | (b); +} + +static void +initialize_swizzled_image (void) { + int bitmap_pad; + Bool shm_success = False; + + if (HostX.swizzled_img != NULL) + { + /* Free up the image data if previously used + * i.ie called by server reset + */ + + if (HostX.have_shm) { + XShmDetach(HostX.dpy, &HostX.shminfo); + XDestroyImage (HostX.swizzled_img); + shmdt(HostX.shminfo.shmaddr); + shmctl(HostX.shminfo.shmid, IPC_RMID, 0); + } else { + if (HostX.swizzled_img->data) { + free(HostX.swizzled_img->data); + HostX.swizzled_img->data = NULL; + } + + XDestroyImage(HostX.swizzled_img); + } + } + + if (HostX.have_shm) { + HostX.ximg = XShmCreateImage (HostX.dpy, HostX.visual, HostX.depth, + ZPixmap, NULL, &HostX.shminfo, + HostX.ximg->width, HostX.ximg->height); + + HostX.shminfo.shmid = shmget (IPC_PRIVATE, + HostX.swizzled_img->bytes_per_line * HostX.swizzled_img->height, + IPC_CREAT|0777); + HostX.shminfo.shmaddr = HostX.swizzled_img->data = shmat (HostX.shminfo.shmid, + 0, 0); + if (HostX.ximg->data == (char *)-1) { + EPHYR_DBG ("Can't attach SHM Segment, falling back to plain XImages"); + HostX.have_shm = False; + XDestroyImage (HostX.swizzled_img); + shmctl (HostX.shminfo.shmid, IPC_RMID, 0); + } else { + EPHYR_DBG ("SHM segment attached"); + HostX.shminfo.readOnly = False; + XShmAttach (HostX.dpy, &HostX.shminfo); + shm_success = True; + } + } + + if (!shm_success) { + bitmap_pad = (HostX.depth > 16)? 32 : (( HostX.depth > 8)? 16 : 8); + + HostX.swizzled_img = XCreateImage (HostX.dpy, + HostX.visual, + HostX.depth, + ZPixmap, 0, 0, + HostX.ximg->width, + HostX.ximg->height, + bitmap_pad, + 0); + + HostX.swizzled_img->data = malloc (HostX.swizzled_img->bytes_per_line * HostX.swizzled_img->height); + } +} + void hostx_paint_rect(int sx, int sy, int dx, int dy, @@ -563,6 +644,19 @@ * on to the window */ + int x_min = 0, x_max = 0, y_min = 0, y_max = 0; + + static Bool swizzle_initialized = 0; + + if (swizzle && HostX.server_depth != 16) { + fprintf (stderr, "Warning: you asked for color swizzling but the server's depth is different from 16 bit, swizzling is disabled.\n"); + } + + if (swizzle && !swizzle_initialized) { + initialize_swizzled_image (); + swizzle_initialized = 1; + } + if (HostXWantDamageDebug) { hostx_paint_debug_rect(dx, dy, width, height); @@ -582,51 +676,115 @@ 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 (y=sy; y>3), host_bpp = HostX.ximg->bits_per_pixel / 8; + unsigned char r, g, b, aa_color; + unsigned char *host_pixel; + unsigned long final_host_pixel; + + if (swizzle) { + int border, sum, swizzle_position; + unsigned short server_pixel; + + border = 1; + x_min = (sx - border < 0)? 0 : sx - border; + y_min = (sy - border < 0)? 0 : sy - border; + x_max = (sx + width + border > HostX.ximg->width)? HostX.ximg->width : sx + width + border; + y_max = (sy + height + border > HostX.ximg->height)? HostX.ximg->height : sy + height + border; + + /* First, update the zone we're redrawing in the local, + * unaltered framebuffer. + */ + + for (y = sy; y < sy + height; y++) { + for (x = sx; x < sx + width; x++) { + idx = (HostX.win_width * y + x) * server_bpp; + server_pixel = *(unsigned short*)(HostX.fb_data+idx); + XPutPixel (HostX.ximg, x, y, make_24bits_pixel_from_16bits (server_pixel)); + } + } + + /* Then, perform the antialiasing. */ + + for (y = y_min; y < y_max; y++) { + for (x = x_min; x < x_max; x++) { + + swizzle_position = (x + y) % 3; + sum = 0; - switch (HostX.server_depth) + if (x > 0) { /* Left */ + host_pixel = HostX.ximg->data + ((x - 1) + y * HostX.ximg->width) * host_bpp; + sum += host_pixel[2 - swizzle_position]; + } + if (x < HostX.ximg->width - 1) { /* Right */ + host_pixel = HostX.ximg->data + ((x - 1) + y * HostX.ximg->width) * host_bpp; + sum += host_pixel[2 - swizzle_position]; + } + if (y > 0) { /* Top */ + host_pixel = HostX.ximg->data + (x + (y - 1) * HostX.ximg->width) * host_bpp; + sum += host_pixel[2 - swizzle_position]; + } + if (y < HostX.ximg->height - 1) { /* Bottom */ + host_pixel = HostX.ximg->data + (x + (y + 1) * HostX.ximg->width) * host_bpp; + sum += host_pixel[2 - swizzle_position]; + } + + host_pixel = HostX.ximg->data + (x + y * HostX.ximg->width) * host_bpp; + + aa_color = (unsigned char) ((sum + 4 * host_pixel[2 - swizzle_position]) >> 3); + + r = (swizzle_position == 0)? aa_color : 0; + g = (swizzle_position == 1)? aa_color : 0; + b = (swizzle_position == 2)? aa_color : 0; + + final_host_pixel = (r << 16) | (g << 8) | (b); + + XPutPixel (HostX.swizzled_img, x, y, final_host_pixel); + } + } + } else { + + for (y = sy; y < sy + height; y++) { + for (x = sx; x < sx + width; x++) { + idx = (HostX.win_width * y + x) * server_bpp; + + switch (HostX.server_depth) { + case 16: { - case 16: - { - unsigned short pixel = *(unsigned short*)(HostX.fb_data+idx); - - r = ((pixel & 0xf800) >> 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; + unsigned short server_pixel = *(unsigned short*) (HostX.fb_data + idx); + XPutPixel (HostX.ximg, x, y, make_24bits_pixel_from_16bits (server_pixel)); + break; + } + case 8: + { + unsigned char server_pixel = *(unsigned char*)(HostX.fb_data + idx); + XPutPixel (HostX.ximg, x, y, HostX.cmap[server_pixel]); + break; } + default: + break; + } } + } + } } - + if (HostX.have_shm) { - XShmPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, - sx, sy, dx, dy, width, height, False); + if (swizzle) + XShmPutImage (HostX.dpy, HostX.win, HostX.gc, HostX.swizzled_img, + x_min, y_min, x_min, y_min, x_max - x_min, y_max - y_min, False); + else + XShmPutImage (HostX.dpy, HostX.win, HostX.gc, HostX.ximg, + sx, sy, dx, dy, width, height, False); } else { - XPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, - sx, sy, dx, dy, width, height); + if (swizzle) + XPutImage (HostX.dpy, HostX.win, HostX.gc, HostX.swizzled_img, + x_min, y_min, x_min, y_min, x_max - x_min, y_max - y_min); + else + XPutImage (HostX.dpy, HostX.win, HostX.gc, HostX.ximg, + sx, sy, dx, dy, width, height); } XSync(HostX.dpy, False);