Mercurial > MadButterfly
changeset 691:05a453e07d01
X_supp.c uses XSHM to avoid overhead of transmission
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Mon, 09 Aug 2010 09:01:19 +0800 |
parents | 86c6ebf1de25 |
children | 201cc86720a3 |
files | src/X_supp.c |
diffstat | 1 files changed, 117 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/src/X_supp.c Sat Aug 07 23:00:16 2010 +0800 +++ b/src/X_supp.c Mon Aug 09 09:01:19 2010 +0800 @@ -8,6 +8,15 @@ #include "mb_timer.h" #include "mb_X_supp.h" +#define XSHM 1 + +#ifdef XSHM +/* \sa http://www.xfree86.org/current/mit-shm.html */ +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> +#endif + #define ERR -1 #define OK 0 @@ -52,6 +61,11 @@ /* States */ shape_t *last; #endif + +#ifdef XSHM + XImage *ximage; + XShmSegmentInfo shminfo; +#endif }; /*! \defgroup xkb X Keyboard Handling @@ -453,6 +467,94 @@ return OK; } +#ifdef XSHM +static void +xshm_destroy(X_MB_runtime_t *xmb_rt) { + XShmSegmentInfo *shminfo; + + shminfo = &xmb_rt->shminfo; + + if(xmb_rt->shminfo.shmaddr) { + XShmDetach(xmb_rt->display, shminfo); + } + + if(xmb_rt->ximage) { + XDestroyImage(xmb_rt->ximage); + xmb_rt->ximage = NULL; + } + + if(shminfo->shmaddr) { + shmdt(shminfo->shmaddr); + shminfo->shmaddr = NULL; + } + + if(shminfo->shmid) { + shmctl(shminfo->shmid, IPC_RMID, 0); + shminfo->shmid = 0; + } +} + +static void +xshm_init(X_MB_runtime_t *xmb_rt) { + Display *display; + Visual *visual; + XImage *ximage; + int screen; + int depth; + int support_shm; + int mem_sz; + XShmSegmentInfo *shminfo; + int surf_fmt; + + display = xmb_rt->display; + visual = xmb_rt->visual; + shminfo = &xmb_rt->shminfo; + + support_shm = XShmQueryExtension(display); + if(!support_shm) + return; + + screen = DefaultScreen(display); + depth = DefaultDepth(display, screen); + + if(depth != 24 && depth != 32) + return; + + xmb_rt->ximage = XShmCreateImage(display, visual, depth, + ZPixmap, NULL, shminfo, + xmb_rt->w, xmb_rt->h); + ximage = xmb_rt->ximage; + + mem_sz = ximage->bytes_per_line * ximage->height; + shminfo->shmid = shmget(IPC_PRIVATE, mem_sz, IPC_CREAT | 0777); + if(shminfo->shmid == -1) { + xshm_destroy(xmb_rt); + return; + } + + shminfo->shmaddr = shmat(shminfo->shmid, 0, 0); + ximage->data = shminfo->shmaddr; + + shminfo->readOnly = 0; + + XShmAttach(display, shminfo); + + switch(depth) { + case 24: surf_fmt = CAIRO_FORMAT_RGB24; break; + case 32: surf_fmt = CAIRO_FORMAT_ARGB32; break; + } + + xmb_rt->backend_surface = + cairo_image_surface_create_for_data(ximage->data, + surf_fmt, + xmb_rt->w, + xmb_rt->h, + ximage->bytes_per_line); + if(xmb_rt->backend_surface == NULL) + xshm_destroy(xmb_rt); +} +#endif /* XSHM */ + /*! \brief Initialize a MadButterfy runtime for Xlib. * * It setups a runtime environment to run MadButterfly with Xlib. @@ -461,13 +563,20 @@ static int X_MB_init(const char *display_name, int w, int h, X_MB_runtime_t *xmb_rt) { mb_img_ldr_t *img_ldr; + int r; memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); xmb_rt->w = w; xmb_rt->h = h; - X_init_connection(display_name, w, h, &xmb_rt->display, - &xmb_rt->visual, &xmb_rt->win); + r = X_init_connection(display_name, w, h, &xmb_rt->display, + &xmb_rt->visual, &xmb_rt->win); + if(r != OK) + return ERR; + +#ifdef XSHM + xshm_init(xmb_rt); +#endif xmb_rt->surface = mbe_image_surface_create(MB_IFMT_ARGB32, w, h); @@ -475,11 +584,12 @@ xmb_rt->surface_ptn = mbe_pattern_create_for_surface(xmb_rt->surface); - xmb_rt->backend_surface = - mbe_xlib_surface_create(xmb_rt->display, - xmb_rt->win, - xmb_rt->visual, - w, h); + if(xmb_rt->backend_surface != NULL) /* xshm_init() may create one */ + xmb_rt->backend_surface = + mbe_xlib_surface_create(xmb_rt->display, + xmb_rt->win, + xmb_rt->visual, + w, h); xmb_rt->cr = mbe_create(xmb_rt->surface); xmb_rt->backend_cr = mbe_create(xmb_rt->backend_surface);