#define NEED_EVENTS
#define NEED_REPLIES
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <X11/Xlibint.h>
#include <X11/ImUtil.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/shmstr.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
static XExtensionInfo _shm_info_data;
static XExtensionInfo *shm_info = &_shm_info_data;
static char *shm_extension_name = SHMNAME;
#define ShmCheckExtension(dpy,i,val) \
XextCheckExtension (dpy, i, shm_extension_name, val)
static int close_display(Display *dpy, XExtCodes *codes);
static char *error_string(Display *dpy, int code, XExtCodes *codes,
char *buf, int n);
static Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event);
static Status event_to_wire (Display *dpy, XEvent *re, xEvent *event);
static XExtensionHooks shm_extension_hooks = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
close_display,
wire_to_event,
event_to_wire,
NULL,
error_string,
};
static char *shm_error_list[] = {
"BadShmSeg",
};
static XEXT_GENERATE_FIND_DISPLAY (find_display, shm_info, shm_extension_name,
&shm_extension_hooks, ShmNumberEvents, NULL)
static XEXT_GENERATE_CLOSE_DISPLAY (close_display, shm_info)
static XEXT_GENERATE_ERROR_STRING (error_string, shm_extension_name,
ShmNumberErrors, shm_error_list)
static Bool
wire_to_event (Display *dpy, XEvent *re, xEvent *event)
{
XExtDisplayInfo *info = find_display (dpy);
XShmCompletionEvent *se;
xShmCompletionEvent *sevent;
ShmCheckExtension (dpy, info, False);
switch ((event->u.u.type & 0x7f) - info->codes->first_event) {
case ShmCompletion:
se = (XShmCompletionEvent *) re;
sevent = (xShmCompletionEvent *) event;
se->type = sevent->type & 0x7f;
se->serial = _XSetLastRequestRead(dpy,(xGenericReply *) event);
se->send_event = (sevent->type & 0x80) != 0;
se->display = dpy;
se->drawable = sevent->drawable;
se->major_code = sevent->majorEvent;
se->minor_code = sevent->minorEvent;
se->shmseg = sevent->shmseg;
se->offset = sevent->offset;
return True;
}
return False;
}
static Status
event_to_wire (Display *dpy, XEvent *re, xEvent *event)
{
XExtDisplayInfo *info = find_display (dpy);
XShmCompletionEvent *se;
xShmCompletionEvent *sevent;
ShmCheckExtension (dpy, info, 0);
switch ((re->type & 0x7f) - info->codes->first_event) {
case ShmCompletion:
se = (XShmCompletionEvent *) re;
sevent = (xShmCompletionEvent *) event;
sevent->type = se->type | (se->send_event ? 0x80 : 0);
sevent->sequenceNumber = se->serial & 0xffff;
sevent->drawable = se->drawable;
sevent->majorEvent = se->major_code;
sevent->minorEvent = se->minor_code;
sevent->shmseg = se->shmseg;
sevent->offset = se->offset;
return True;
}
return False;
}
Bool XShmQueryExtension (Display *dpy )
{
XExtDisplayInfo *info = find_display (dpy);
if (XextHasExtension(info)) {
return True;
} else {
return False;
}
}
int XShmGetEventBase(Display *dpy)
{
XExtDisplayInfo *info = find_display (dpy);
if (XextHasExtension(info)) {
return info->codes->first_event;
} else {
return -1;
}
}
Bool XShmQueryVersion(
Display *dpy,
int *majorVersion,
int *minorVersion,
Bool *sharedPixmaps)
{
XExtDisplayInfo *info = find_display (dpy);
xShmQueryVersionReply rep;
register xShmQueryVersionReq *req;
ShmCheckExtension (dpy, info, False);
LockDisplay(dpy);
GetReq(ShmQueryVersion, req);
req->reqType = info->codes->major_opcode;
req->shmReqType = X_ShmQueryVersion;
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
*majorVersion = rep.majorVersion;
*minorVersion = rep.minorVersion;
*sharedPixmaps = rep.sharedPixmaps ? True : False;
UnlockDisplay(dpy);
SyncHandle();
return True;
}
int XShmPixmapFormat(Display *dpy)
{
XExtDisplayInfo *info = find_display (dpy);
xShmQueryVersionReply rep;
register xShmQueryVersionReq *req;
ShmCheckExtension (dpy, info, False);
LockDisplay(dpy);
GetReq(ShmQueryVersion, req);
req->reqType = info->codes->major_opcode;
req->shmReqType = X_ShmQueryVersion;
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
if (rep.sharedPixmaps &&
(rep.majorVersion > 1 || rep.minorVersion > 0))
return rep.pixmapFormat;
return 0;
}
Status XShmAttach(Display *dpy, XShmSegmentInfo *shminfo)
{
XExtDisplayInfo *info = find_display (dpy);
register xShmAttachReq *req;
ShmCheckExtension (dpy, info, 0);
shminfo->shmseg = XAllocID(dpy);
LockDisplay(dpy);
GetReq(ShmAttach, req);
req->reqType = info->codes->major_opcode;
req->shmReqType = X_ShmAttach;
req->shmseg = shminfo->shmseg;
req->shmid = shminfo->shmid;
req->readOnly = shminfo->readOnly ? xTrue : xFalse;
UnlockDisplay(dpy);
SyncHandle();
return 1;
}
Status XShmDetach(Display *dpy, XShmSegmentInfo *shminfo)
{
XExtDisplayInfo *info = find_display (dpy);
register xShmDetachReq *req;
ShmCheckExtension (dpy, info, 0);
LockDisplay(dpy);
GetReq(ShmDetach, req);
req->reqType = info->codes->major_opcode;
req->shmReqType = X_ShmDetach;
req->shmseg = shminfo->shmseg;
UnlockDisplay(dpy);
SyncHandle();
return 1;
}
static int _XShmDestroyImage (XImage *ximage)
{
Xfree((char *)ximage);
return 1;
}
#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad) - 1)) / (pad)) * (pad))
XImage *XShmCreateImage (
register Display *dpy,
register Visual *visual,
unsigned int depth,
int format,
char *data,
XShmSegmentInfo *shminfo,
unsigned int width,
unsigned int height)
{
register XImage *image;
image = (XImage *)Xcalloc(1, (unsigned)sizeof(XImage));
if (!image)
return image;
image->data = data;
image->obdata = (char *)shminfo;
image->width = width;
image->height = height;
image->depth = depth;
image->format = format;
image->byte_order = dpy->byte_order;
image->bitmap_unit = dpy->bitmap_unit;
image->bitmap_bit_order = dpy->bitmap_bit_order;
image->bitmap_pad = _XGetScanlinePad(dpy, depth);
image->xoffset = 0;
if (visual) {
image->red_mask = visual->red_mask;
image->green_mask = visual->green_mask;
image->blue_mask = visual->blue_mask;
} else {
image->red_mask = image->green_mask = image->blue_mask = 0;
}
if (format == ZPixmap)
image->bits_per_pixel = _XGetBitsPerPixel(dpy, (int)depth);
else
image->bits_per_pixel = 1;
image->bytes_per_line = ROUNDUP((image->bits_per_pixel * width),
image->bitmap_pad) >> 3;
_XInitImageFuncPtrs(image);
image->f.destroy_image = _XShmDestroyImage;
return image;
}
Status XShmPutImage (
register Display *dpy,
Drawable d,
GC gc,
register XImage *image,
int src_x, int src_y, int dst_x, int dst_y,
unsigned int src_width, unsigned int src_height,
Bool send_event)
{
XExtDisplayInfo *info = find_display (dpy);
XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata;
register xShmPutImageReq *req;
ShmCheckExtension (dpy, info, 0);
if (!shminfo) return 0;
LockDisplay(dpy);
FlushGC(dpy, gc);
GetReq(ShmPutImage, req);
req->reqType = info->codes->major_opcode;
req->shmReqType = X_ShmPutImage;
req->drawable = d;
req->gc = gc->gid;
req->srcX = src_x;
req->srcY = src_y;
req->srcWidth = src_width;
req->srcHeight = src_height;
req->dstX = dst_x;
req->dstY = dst_y;
req->totalWidth = image->width;
req->totalHeight = image->height;
req->depth = image->depth;
req->format = image->format;
req->sendEvent = send_event;
req->shmseg = shminfo->shmseg;
req->offset = image->data - shminfo->shmaddr;
UnlockDisplay(dpy);
SyncHandle();
return 1;
}
Status XShmGetImage(
register Display *dpy,
Drawable d,
XImage *image,
int x, int y,
unsigned long plane_mask)
{
XExtDisplayInfo *info = find_display (dpy);
XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata;
register xShmGetImageReq *req;
xShmGetImageReply rep;
register Visual *visual;
ShmCheckExtension (dpy, info, 0);
if (!shminfo) return 0;
LockDisplay(dpy);
GetReq(ShmGetImage, req);
req->reqType = info->codes->major_opcode;
req->shmReqType = X_ShmGetImage;
req->drawable = d;
req->x = x;
req->y = y;
req->width = image->width;
req->height = image->height;
req->planeMask = plane_mask;
req->format = image->format;
req->shmseg = shminfo->shmseg;
req->offset = image->data - shminfo->shmaddr;
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
visual = _XVIDtoVisual(dpy, rep.visual);
if (visual) {
image->red_mask = visual->red_mask;
image->green_mask = visual->green_mask;
image->blue_mask = visual->blue_mask;
} else {
image->red_mask = image->green_mask = image->blue_mask = 0;
}
UnlockDisplay(dpy);
SyncHandle();
return 1;
}
Pixmap XShmCreatePixmap (
register Display *dpy,
Drawable d,
char *data,
XShmSegmentInfo *shminfo,
unsigned int width, unsigned int height, unsigned int depth)
{
XExtDisplayInfo *info = find_display (dpy);
Pixmap pid;
register xShmCreatePixmapReq *req;
ShmCheckExtension (dpy, info, 0);
LockDisplay(dpy);
GetReq(ShmCreatePixmap, req);
req->reqType = info->codes->major_opcode;
req->shmReqType = X_ShmCreatePixmap;
req->drawable = d;
req->width = width;
req->height = height;
req->depth = depth;
req->shmseg = shminfo->shmseg;
req->offset = data - shminfo->shmaddr;
pid = req->pid = XAllocID(dpy);
UnlockDisplay(dpy);
SyncHandle();
return pid;
}