This source file includes following definitions.
- TmpXError
- __imlib_ShmCheck
- __imlib_ShmGetXImage
- __imlib_ShmDetach
- _safe_realloc
- __imlib_SetMaxXImageCount
- __imlib_GetMaxXImageCount
- __imlib_SetMaxXImageTotalSize
- __imlib_GetMaxXImageTotalSize
- __imlib_FlushXImage
- __imlib_ConsumeXImage
- __imlib_ProduceXImage
#include "common.h"
#ifdef BUILD_X11
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <X11/Xutil.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "ximage.h"
signed char x_does_shm = -1;
static int list_num = 0;
static XImage **list_xim = NULL;
static XShmSegmentInfo **list_si = NULL;
static Display **list_d = NULL;
static char *list_used = NULL;
static int list_mem_use = 0;
static int list_max_mem = 1024 * 1024 * 1024;
static int list_max_count = 0;
static char _x_err = 0;
static int
TmpXError(Display * d, XErrorEvent * ev)
{
_x_err = 1;
return 0;
d = NULL;
ev = NULL;
}
void
__imlib_ShmCheck(Display * d)
{
if (XShmQueryExtension(d))
x_does_shm = 2;
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;
xim = XShmCreateImage(d, v, depth, ZPixmap, NULL, si, w, h);
if (!xim)
return NULL;
si->shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
IPC_CREAT | 0666);
if (si->shmid != -1)
{
si->readOnly = False;
si->shmaddr = xim->data = shmat(si->shmid, 0, 0);
if (xim->data != (char *)-1)
{
XErrorHandler ph;
if (x_does_shm == 2)
{
_x_err = 0;
XSync(d, False);
ph = XSetErrorHandler(TmpXError);
}
XShmAttach(d, si);
if (draw != None)
XShmGetImage(d, draw, xim, x, y, 0xffffffff);
if (x_does_shm == 2)
{
XSync(d, False);
XSetErrorHandler(ph);
x_does_shm = 1;
}
if (_x_err == 0)
return xim;
x_does_shm = 0;
shmdt(si->shmaddr);
}
shmctl(si->shmid, IPC_RMID, 0);
}
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);
}
static void *
_safe_realloc(void *ptr, size_t size, int *err)
{
void *ptr_new;
ptr_new = realloc(ptr, size);
if (!ptr_new)
{
*err = 1;
return ptr;
}
return ptr_new;
}
void
__imlib_SetMaxXImageCount(Display * d, int num)
{
list_max_count = num;
__imlib_FlushXImage(d);
}
int
__imlib_GetMaxXImageCount(Display * d)
{
return list_max_count;
d = NULL;
}
void
__imlib_SetMaxXImageTotalSize(Display * d, int num)
{
list_max_mem = num;
__imlib_FlushXImage(d);
}
int
__imlib_GetMaxXImageTotalSize(Display * d)
{
return list_max_mem;
d = NULL;
}
void
__imlib_FlushXImage(Display * d)
{
int i;
XImage *xim;
char did_free = 1;
while (((list_mem_use > list_max_mem) || (list_num > list_max_count)) &&
(did_free))
{
did_free = 0;
for (i = 0; i < list_num; i++)
{
if (list_used[i] == 0)
{
int j;
xim = list_xim[i];
list_mem_use -= xim->bytes_per_line * xim->height;
if (list_si[i])
{
__imlib_ShmDetach(d, list_si[i]);
free(list_si[i]);
}
XDestroyImage(xim);
list_num--;
for (j = i; j < list_num; j++)
{
list_xim[j] = list_xim[j + 1];
list_si[j] = list_si[j + 1];
list_used[j] = list_used[j + 1];
list_d[j] = list_d[j + 1];
}
if (list_num == 0)
{
if (list_xim)
free(list_xim);
if (list_si)
free(list_si);
if (list_used)
free(list_used);
if (list_d)
free(list_d);
list_xim = NULL;
list_si = NULL;
list_used = NULL;
list_d = NULL;
}
else
{
list_xim =
realloc(list_xim, sizeof(XImage *) * list_num);
list_si =
realloc(list_si,
sizeof(XShmSegmentInfo *) * list_num);
list_used = realloc(list_used, sizeof(char) * list_num);
list_d = realloc(list_d, sizeof(Display *) * list_num);
}
did_free = 1;
}
}
}
}
void
__imlib_ConsumeXImage(Display * d, XImage * xim)
{
int i;
for (i = 0; i < list_num; i++)
{
if (list_xim[i] == xim)
{
list_used[i] = 0;
__imlib_FlushXImage(d);
return;
}
}
}
XImage *
__imlib_ProduceXImage(Display * d, Visual * v, int depth, int w, int h,
char *shared)
{
XImage *xim;
int i, err;
if (x_does_shm < 0)
__imlib_ShmCheck(d);
*shared = 0;
for (i = 0; i < list_num; i++)
{
int depth_ok = 0;
if (list_xim[i]->depth == depth)
depth_ok = 1;
if (depth_ok &&
(list_xim[i]->width >= w) && (list_xim[i]->height >= h) &&
(!list_used[i]))
{
list_used[i] = 1;
if (list_si[i])
*shared = 1;
return list_xim[i];
}
}
list_num++;
err = 0;
list_xim = _safe_realloc(list_xim, sizeof(XImage *) * list_num, &err);
list_si = _safe_realloc(list_si, sizeof(XShmSegmentInfo *) * list_num, &err);
list_used = _safe_realloc(list_used, sizeof(char) * list_num, &err);
list_d = _safe_realloc(list_d, sizeof(Display *) * list_num, &err);
if (err)
{
list_num--;
return NULL;
}
list_si[list_num - 1] = malloc(sizeof(XShmSegmentInfo));
if (!list_si[list_num - 1])
{
list_num--;
return NULL;
}
xim = NULL;
if (x_does_shm)
{
xim = __imlib_ShmGetXImage(d, v, None, depth, 0, 0, w, h,
list_si[list_num - 1]);
}
if (xim)
{
*shared = 1;
}
else
{
free(list_si[list_num - 1]);
list_si[list_num - 1] = NULL;
xim = XCreateImage(d, v, depth, ZPixmap, 0, NULL, w, h, 32, 0);
if (xim)
xim->data = malloc(xim->bytes_per_line * xim->height);
if (!xim || !xim->data)
{
if (xim)
XDestroyImage(xim);
list_num--;
return NULL;
}
}
list_xim[list_num - 1] = xim;
list_mem_use += xim->bytes_per_line * xim->height;
list_used[list_num - 1] = 1;
list_d[list_num - 1] = d;
__imlib_FlushXImage(d);
#ifdef WORDS_BIGENDIAN
xim->byte_order = MSBFirst;
#else
xim->byte_order = LSBFirst;
#endif
return xim;
}
#endif