diff options
author | Kim Woelders <kim@woelders.dk> | 2008-11-01 18:11:10 +0000 |
---|---|---|
committer | Kim Woelders <kim@woelders.dk> | 2008-11-01 18:11:10 +0000 |
commit | 06a53a073d1798a883e149635dc4fc7feab5a1b6 (patch) | |
tree | 7cde702d56bccbb347ec120fe3e0d71032937fbd | |
parent | 5b60182d96fa136366e1f5ae6329edcbc886d47f (diff) | |
download | imlib2-06a53a073d1798a883e149635dc4fc7feab5a1b6.tar.gz |
Refactor shm stuff.
SVN revision: 37378
-rw-r--r-- | src/lib/grab.c | 134 | ||||
-rw-r--r-- | src/lib/ximage.c | 201 | ||||
-rw-r--r-- | src/lib/ximage.h | 8 |
3 files changed, 126 insertions, 217 deletions
diff --git a/src/lib/grab.c b/src/lib/grab.c index d38218f..39017dd 100644 --- a/src/lib/grab.c +++ b/src/lib/grab.c @@ -7,6 +7,7 @@ #include <sys/ipc.h> #include <sys/shm.h> #include "grab.h" +#include "ximage.h" static char _x_err = 0; static DATA8 rtab[256], gtab[256], btab[256]; @@ -530,7 +531,7 @@ __imlib_GrabDrawableToRGBA(DATA32 * data, int ox, int oy, int ow, int oh, int src_x, src_y, src_w, src_h, origw, origh; int width, height, clipx, clipy; XShmSegmentInfo shminfo, mshminfo; - XImage *xim = NULL, *mxim = NULL; + XImage *xim, *mxim; static signed char x_does_shm = -1; XColor cols[256]; @@ -662,62 +663,15 @@ __imlib_GrabDrawableToRGBA(DATA32 * data, int ox, int oy, int ow, int oh, /* Create an Ximage (shared or not) */ if (x_does_shm < 0) - { - if (XShmQueryExtension(d)) - x_does_shm = 1; - else - x_does_shm = 0; - } - - prev_erh = XSetErrorHandler((XErrorHandler) Tmp_HandleXError); + __imlib_ShmCheck(d); + xim = NULL; if (x_does_shm) { - _x_err = 0; - xim = XShmCreateImage(d, v, xatt.depth, ZPixmap, NULL, &shminfo, w, h); - if (xim) - { - XSync(d, False); - if (_x_err) - { - XDestroyImage(xim); - } - else - { - shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * - xim->height, IPC_CREAT | 0666); - if (shminfo.shmid < 0) - { - XDestroyImage(xim); - } - else - { - shminfo.shmaddr = xim->data = shmat(shminfo.shmid, 0, 0); - if (xim->data != (char *)-1) - { - shminfo.readOnly = False; - XShmAttach(d, &shminfo); - is_shm = 1; - XShmGetImage(d, p, xim, x, y, 0xffffffff); - XSync(d, False); - if (_x_err) - { - shmdt(shminfo.shmaddr); - shmctl(shminfo.shmid, IPC_RMID, 0); - XDestroyImage(xim); - is_shm = 0; - } - } - else - { - shmctl(shminfo.shmid, IPC_RMID, 0); - XDestroyImage(xim); - } - } - } - } + xim = __imlib_ShmGetXImage(d, v, p, xatt.depth, x, y, w, h, &shminfo); + is_shm = xim != NULL; } - if (!is_shm) + if (!xim) xim = XGetImage(d, p, x, y, w, h, 0xffffffff, ZPixmap); if (!xim) { @@ -726,62 +680,15 @@ __imlib_GrabDrawableToRGBA(DATA32 * data, int ox, int oy, int ow, int oh, return 0; } + mxim = NULL; if ((m) && (domask)) { - _x_err = 0; - if (x_does_shm) - { - mxim = XShmCreateImage(d, v, 1, ZPixmap, NULL, &mshminfo, w, h); - if (mxim) - { - XSync(d, False); - if (_x_err) - { - XDestroyImage(mxim); - } - else - { - mshminfo.shmid = shmget(IPC_PRIVATE, - mxim->bytes_per_line * - mxim->height, IPC_CREAT | 0666); - if (mshminfo.shmid < 0) - { - XDestroyImage(mxim); - } - else - { - mshminfo.shmaddr = mxim->data = - shmat(mshminfo.shmid, 0, 0); - if (mxim->data != (char *)-1) - { - mshminfo.readOnly = False; - XShmAttach(d, &mshminfo); - is_mshm = 1; - XShmGetImage(d, m, mxim, 0, 0, 0xffffffff); - XSync(d, False); - if (_x_err) - { - shmdt(mshminfo.shmaddr); - shmctl(mshminfo.shmid, IPC_RMID, 0); - XDestroyImage(mxim); - is_mshm = 0; - } - } - else - { - shmctl(mshminfo.shmid, IPC_RMID, 0); - XDestroyImage(mxim); - } - } - } - } - } - if (!is_mshm) + mxim = __imlib_ShmGetXImage(d, v, m, 1, 0, 0, w, h, &mshminfo); + is_mshm = mxim != NULL; + if (!mxim) mxim = XGetImage(d, m, 0, 0, w, h, 0xffffffff, ZPixmap); } - XSetErrorHandler((XErrorHandler) prev_erh); - if ((is_shm) || (is_mshm)) { XSync(d, False); @@ -835,23 +742,16 @@ __imlib_GrabDrawableToRGBA(DATA32 * data, int ox, int oy, int ow, int oh, /* destroy the Ximage */ if (is_shm) + __imlib_ShmDetach(d, &shminfo); + XDestroyImage(xim); + if (mxim) { - XSync(d, False); - XShmDetach(d, &shminfo); - shmdt(shminfo.shmaddr); - shmctl(shminfo.shmid, IPC_RMID, 0); - } - if ((is_mshm) && (mxim)) - { - XShmDetach(d, &mshminfo); - shmdt(mshminfo.shmaddr); - shmctl(mshminfo.shmid, IPC_RMID, 0); + if (is_mshm) + __imlib_ShmDetach(d, &mshminfo); + XDestroyImage(mxim); } - XDestroyImage(xim); if (created_mask) XFreePixmap(d, m); - if (mxim) - XDestroyImage(mxim); if (pdomask) { diff --git a/src/lib/ximage.c b/src/lib/ximage.c index 230e5b0..daa3059 100644 --- a/src/lib/ximage.c +++ b/src/lib/ximage.c @@ -31,6 +31,87 @@ TmpXError(Display * d, XErrorEvent * ev) ev = NULL; } +void +__imlib_ShmCheck(Display * d) +{ + /* if its there set x_does_shm flag */ + if (XShmQueryExtension(d)) + x_does_shm = 1; + /* clear the flag - no shm at all */ + else + x_does_shm = 0; +} + +XImage * +__imlib_ShmGetXImage(Display * d, Visual * v, Drawable draw, int depth, + int x, int y, int w, int h, XShmSegmentInfo * si) +{ + XImage *xim; + + /* try create an shm image */ + xim = XShmCreateImage(d, v, depth, ZPixmap, NULL, si, w, h); + if (!xim) + return NULL; + + /* get an shm id of this image */ + si->shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height, + IPC_CREAT | 0666); + /* if the get succeeds */ + if (si->shmid != -1) + { + /* set the params for the shm segment */ + si->readOnly = False; + si->shmaddr = xim->data = shmat(si->shmid, 0, 0); + /* get the shm addr for this data chunk */ + if (xim->data != (char *)-1) + { + XErrorHandler ph; + + /* setup a temporary error handler */ + _x_err = 0; + ph = XSetErrorHandler((XErrorHandler) TmpXError); + /* ask X to attach to the shared mem segment */ + XShmAttach(d, si); + if (draw != None) + XShmGetImage(d, draw, xim, x, y, 0xffffffff); + /* wait for X to reply and do this */ + XSync(d, False); + /* reset the error handler */ + XSetErrorHandler((XErrorHandler) ph); + + /* if we attached without an error we're set */ + if (_x_err == 0) + return xim; + + /* attach by X failed... must be remote client */ + /* flag shm forever to not work - remote */ + x_does_shm = 0; + + /* detach */ + shmdt(si->shmaddr); + } + + /* get failed - out of shm id's or shm segment too big ? */ + /* remove the shm id we created */ + shmctl(si->shmid, IPC_RMID, 0); + } + + /* couldnt create SHM image ? */ + /* destroy previous image */ + XDestroyImage(xim); + + return NULL; +} + +void +__imlib_ShmDetach(Display * d, XShmSegmentInfo * si) +{ + XSync(d, False); + XShmDetach(d, si); + shmdt(si->shmaddr); + shmctl(si->shmid, IPC_RMID, 0); +} + /* "safe" realloc allowing handling of out-of-memory situations */ static void * _safe_realloc(void *ptr, size_t size, int *err) @@ -95,14 +176,11 @@ __imlib_FlushXImage(Display * d) xim = list_xim[i]; list_mem_use -= xim->bytes_per_line * xim->height; if (list_si[i]) - XShmDetach(d, list_si[i]); - XDestroyImage(xim); - if (list_si[i]) { - shmdt(list_si[i]->shmaddr); - shmctl(list_si[i]->shmid, IPC_RMID, 0); + __imlib_ShmDetach(d, list_si[i]); free(list_si[i]); } + XDestroyImage(xim); list_num--; for (j = i; j < list_num; j++) { @@ -175,14 +253,8 @@ __imlib_ProduceXImage(Display * d, Visual * v, int depth, int w, int h, /* if we havent check the shm extension before - see if its there */ if (x_does_shm < 0) - { - /* if its there set dose_xhm flag */ - if (XShmQueryExtension(d)) - x_does_shm = 1; - /* clear the flag - no shm at all */ - else - x_does_shm = 0; - } + __imlib_ShmCheck(d); + /* find a cached XImage (to avoid server to & fro) that is big enough */ /* for our needs and the right depth */ *shared = 0; @@ -237,87 +309,15 @@ __imlib_ProduceXImage(Display * d, Visual * v, int depth, int w, int h, /* if the server does shm */ if (x_does_shm) { - /* try create an shm image */ - xim = XShmCreateImage(d, v, depth, ZPixmap, NULL, - list_si[list_num - 1], w, h); - /* if it succeeds */ - if (xim) - { - /* add to list */ - list_xim[list_num - 1] = xim; - /* get an shm id of this image */ - list_si[list_num - 1]->shmid = - shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height, - IPC_CREAT | 0777); - /* if the get succeeds */ - if (list_si[list_num - 1]->shmid != -1) - { - /* set the params for the shm segment */ - list_si[list_num - 1]->readOnly = False; - list_si[list_num - 1]->shmaddr = xim->data = - shmat(list_si[list_num - 1]->shmid, 0, 0); - /* get the shm addr for this data chunk */ - if (xim->data != (char *)-1) - { - XErrorHandler ph; - - /* setup a temporary error handler */ - _x_err = 0; - ph = XSetErrorHandler((XErrorHandler) TmpXError); - /* ask X to attach to the shared mem segment */ - XShmAttach(d, list_si[list_num - 1]); - /* wait for X to reply and do this */ - XSync(d, False); - /* reset the error handler */ - XSetErrorHandler((XErrorHandler) ph); - /* if we attached without an error we're set */ - if (!_x_err) - { - /* mark the image as used */ - list_used[list_num - 1] = 1; - /* incrument our memory count */ - list_mem_use += xim->bytes_per_line * xim->height; - /* set shared flag */ - *shared = 1; - } - /* attach by X failed... must be remote client */ - else - { - /* flag shm foevere to not work - remote */ - x_does_shm = 0; - /* destroy our previous image */ - XDestroyImage(xim); - /* detach */ - shmdt(list_si[list_num - 1]->shmaddr); - /* remove the shm id */ - shmctl(list_si[list_num - 1]->shmid, IPC_RMID, 0); - /* flag out xim as NULL */ - xim = NULL; - } - } - /* get failed - out of shm id's or shm segment too big ? */ - else - { - /* destroy previous image */ - XDestroyImage(xim); - /* remove the shm id we created */ - shmctl(list_si[list_num - 1]->shmid, IPC_RMID, 0); - /* flag xim as NULL */ - xim = NULL; - } - } - /* couldnt create SHM image ? */ - else - { - /* destroy previous image */ - XDestroyImage(xim); - /* flag xim as NULL */ - xim = NULL; - } - } + xim = __imlib_ShmGetXImage(d, v, None, depth, 0, 0, w, h, + list_si[list_num - 1]); } /* ok if xim == NULL it all failed - fall back to XImages */ - if (!xim) + if (xim) + { + *shared = 1; + } + else { /* get rid of out shm info struct */ free(list_si[list_num - 1]); @@ -336,15 +336,16 @@ __imlib_ProduceXImage(Display * d, Visual * v, int depth, int w, int h, list_num--; return NULL; } - /* add xim to our list */ - list_xim[list_num - 1] = xim; - /* incriment our memory count */ - list_mem_use += xim->bytes_per_line * xim->height; - /* mark image as used */ - list_used[list_num - 1] = 1; - /* remember what display that XImage was for */ - list_d[list_num - 1] = d; } + /* add xim to our list */ + list_xim[list_num - 1] = xim; + /* incriment our memory count */ + list_mem_use += xim->bytes_per_line * xim->height; + /* mark image as used */ + list_used[list_num - 1] = 1; + /* remember what display that XImage was for */ + list_d[list_num - 1] = d; + /* flush unused images from the image list */ __imlib_FlushXImage(d); diff --git a/src/lib/ximage.h b/src/lib/ximage.h index c1fc7ef..a690f71 100644 --- a/src/lib/ximage.h +++ b/src/lib/ximage.h @@ -1,6 +1,9 @@ #ifndef __XIMAGE #define __XIMAGE 1 +#include <X11/Xlib.h> +#include <X11/extensions/XShm.h> + void __imlib_SetMaxXImageCount(Display * d, int num); __hidden int __imlib_GetMaxXImageCount(Display * d); __hidden void __imlib_SetMaxXImageTotalSize(Display * d, int num); @@ -9,5 +12,10 @@ __hidden void __imlib_FlushXImage(Display * d); __hidden void __imlib_ConsumeXImage(Display * d, XImage * xim); __hidden XImage *__imlib_ProduceXImage(Display * d, Visual * v, int depth, int w, int h, char *shared); +__hidden void __imlib_ShmCheck(Display * d); +__hidden XImage *__imlib_ShmGetXImage(Display * d, Visual * v, Drawable draw, + int depth, int x, int y, int w, int h, + XShmSegmentInfo * si); +__hidden void __imlib_ShmDetach(Display * d, XShmSegmentInfo * si); #endif |