diff options
author | kraxel <kraxel> | 2006-10-25 14:47:11 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2006-10-25 14:47:11 +0000 |
commit | 397fcd38d34e02a73dc0d05e41562a82e608e203 (patch) | |
tree | 051bfb9d033634e8d6832cfb754a1be6a777c2e6 /x11.c | |
parent | 75e722fc76c56c56a14546ba2dc7418fec08a558 (diff) | |
download | xenwatch-397fcd38d34e02a73dc0d05e41562a82e608e203.tar.gz |
add cvs viewer
Diffstat (limited to 'x11.c')
-rw-r--r-- | x11.c | 226 |
1 files changed, 226 insertions, 0 deletions
@@ -0,0 +1,226 @@ +/* + * some X11 ximage / pixmaps rotines + * + * (c) 2006 Gerd Hoffmann <kraxel@suse.de> + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ipc.h> +#include <sys/shm.h> + +#include "x11.h" + +/* ------------------------------------------------------------------------ */ + +XVisualInfo *x11_info; +int have_shmem = 0; + +int x11_red_bits = 0; +int x11_red_shift = 0; +int x11_green_bits = 0; +int x11_green_shift = 0; +int x11_blue_bits = 0; +int x11_blue_shift = 0; + +static void +x11_find_bits(unsigned long red_mask, + unsigned long green_mask, + unsigned long blue_mask) +{ + int i; + unsigned long mask; + + for (i = 0; i < 24; i++) { + mask = (1 << i); + if (red_mask & mask) + x11_red_bits++; + else if (!x11_red_bits) + x11_red_shift++; + if (green_mask & mask) + x11_green_bits++; + else if (!x11_green_bits) + x11_green_shift++; + if (blue_mask & mask) + x11_blue_bits++; + else if (!x11_blue_bits) + x11_blue_shift++; + } + +#if 1 + printf("color: bits shift\n"); + printf("red : %04i %05i\n", x11_red_bits, x11_red_shift); + printf("green: %04i %05i\n", x11_green_bits, x11_green_shift); + printf("blue : %04i %05i\n", x11_blue_bits, x11_blue_shift); +#endif +} + +int x11_color_init(Display *dpy) +{ + Screen *scr; + XVisualInfo template; + int found; + + scr = DefaultScreenOfDisplay(dpy); + + /* Ask for visual type */ + template.screen = XDefaultScreen(dpy); + template.visualid = + XVisualIDFromVisual(DefaultVisualOfScreen(scr)); + x11_info = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &template, + &found); + if (XShmQueryExtension(dpy)) + have_shmem = 1; + + if (x11_info->class != TrueColor) { + fprintf(stderr, "sorry, can't handle visual\n"); + return -1; + } + x11_find_bits(x11_info->red_mask, x11_info->green_mask, x11_info->blue_mask); + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int mitshm_bang = 0; + +static int x11_error_dev_null(Display *dpy, XErrorEvent *event) +{ + mitshm_bang = 1; + return 0; +} + +XImage* x11_create_ximage(Display *dpy, int width, int height, void **shm) +{ + XImage *ximage = NULL; + char *ximage_data; + XShmSegmentInfo *shminfo = NULL; + void *old_handler; + Screen *scr = DefaultScreenOfDisplay(dpy); + + if (have_shmem) { + old_handler = XSetErrorHandler(x11_error_dev_null); + (*shm) = shminfo = malloc(sizeof(XShmSegmentInfo)); + memset(shminfo, 0, sizeof(XShmSegmentInfo)); + ximage = XShmCreateImage(dpy, + DefaultVisualOfScreen(scr), + DefaultDepthOfScreen(scr), + ZPixmap, NULL, + shminfo, width, height); + if (ximage) { + shminfo->shmid = shmget(IPC_PRIVATE, + ximage->bytes_per_line * ximage->height, + IPC_CREAT | 0777); + if (-1 == shminfo->shmid) { + fprintf(stderr,"shmget(%dMB): %s\n", + ximage->bytes_per_line * ximage->height / 1024 / 1024, + strerror(errno)); + goto oom; + } + shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); + if ((void *) -1 == shminfo->shmaddr) { + perror("shmat"); + goto oom; + } + ximage->data = shminfo->shmaddr; + shminfo->readOnly = False; + + XShmAttach(dpy, shminfo); + XSync(dpy, False); + shmctl(shminfo->shmid, IPC_RMID, 0); + if (mitshm_bang) { + have_shmem = 0; + shmdt(shminfo->shmaddr); + free(shminfo); + shminfo = *shm = NULL; + XDestroyImage(ximage); + ximage = NULL; + } + } else { + have_shmem = 0; + free(shminfo); + shminfo = *shm = NULL; + } + XSetErrorHandler(old_handler); + } + + if (ximage == NULL) { + (*shm) = NULL; + if (NULL == (ximage_data = malloc(width * height * 4))) { + fprintf(stderr,"Oops: out of memory\n"); + goto oom; + } + ximage = XCreateImage(dpy, + DefaultVisualOfScreen(scr), + DefaultDepthOfScreen(scr), + ZPixmap, 0, ximage_data, + width, height, + 8, 0); + } + memset(ximage->data, 0, ximage->bytes_per_line * ximage->height); + + return ximage; + + oom: + if (shminfo) { + if (shminfo->shmid && shminfo->shmid != -1) + shmctl(shminfo->shmid, IPC_RMID, 0); + free(shminfo); + } + if (ximage) + XDestroyImage(ximage); + return NULL; +} + +void x11_destroy_ximage(Display *dpy, XImage *ximage, void *shm) +{ + XShmSegmentInfo *shminfo = shm; + + if (shminfo) { + XShmDetach(dpy, shminfo); + XDestroyImage(ximage); + shmdt(shminfo->shmaddr); + free(shminfo); + } else + XDestroyImage(ximage); +} + +Pixmap x11_create_pixmap(Display *dpy, unsigned char *byte_data, + int width, int height) +{ + Pixmap pixmap; + XImage *ximage; + XGCValues values; + GC gc; + unsigned long *long_data = (unsigned long *)byte_data; + int x, y; + void *shm; + + Screen *scr = DefaultScreenOfDisplay(dpy); + + pixmap = XCreatePixmap(dpy, + RootWindowOfScreen(scr), + width, height, + DefaultDepthOfScreen(scr)); + gc = XCreateGC(dpy, pixmap, 0, &values); + + if (NULL == (ximage = x11_create_ximage(dpy, width, height, &shm))) { + XFreePixmap(dpy, pixmap); + XFreeGC(dpy, gc); + return 0; + } + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + XPutPixel(ximage, x, y, *(long_data++)); + + XPUTIMAGE(dpy, pixmap, gc, ximage, 0, 0, 0, 0, width, height); + + x11_destroy_ximage(dpy, ximage, shm); + XFreeGC(dpy, gc); + return pixmap; +} |