/* * some X11 ximage / pixmaps rotines * * (c) 2006 Gerd Hoffmann * */ #include #include #include #include #include #include #include #include #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 0 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; }