1caade7ccSmrg/*
2caade7ccSmrg *
3caade7ccSmrgCopyright 1989, 1998  The Open Group
4caade7ccSmrg
5caade7ccSmrgPermission to use, copy, modify, distribute, and sell this software and its
6caade7ccSmrgdocumentation for any purpose is hereby granted without fee, provided that
7caade7ccSmrgthe above copyright notice appear in all copies and that both that
8caade7ccSmrgcopyright notice and this permission notice appear in supporting
9caade7ccSmrgdocumentation.
10caade7ccSmrg
11caade7ccSmrgThe above copyright notice and this permission notice shall be included in
12caade7ccSmrgall copies or substantial portions of the Software.
13caade7ccSmrg
14caade7ccSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15caade7ccSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16caade7ccSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17caade7ccSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18caade7ccSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19caade7ccSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20caade7ccSmrg
21caade7ccSmrgExcept as contained in this notice, the name of The Open Group shall not be
22caade7ccSmrgused in advertising or otherwise to promote the sale, use or other dealings
23caade7ccSmrgin this Software without prior written authorization from The Open Group.
24caade7ccSmrg *
25caade7ccSmrg * Author:  Bob Scheifler and Keith Packard, MIT X Consortium
26caade7ccSmrg */
27caade7ccSmrg
28caade7ccSmrg/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */
29caade7ccSmrg
30caade7ccSmrg#ifdef HAVE_CONFIG_H
31caade7ccSmrg#include <config.h>
32caade7ccSmrg#endif
33caade7ccSmrg#include <stdio.h>
34caade7ccSmrg#include <X11/Xlibint.h>
35caade7ccSmrg#include <X11/ImUtil.h>
36caade7ccSmrg#include <X11/extensions/XShm.h>
37485f0483Smrg#include <X11/extensions/shmproto.h>
38caade7ccSmrg#include <X11/extensions/Xext.h>
39caade7ccSmrg#include <X11/extensions/extutil.h>
40caade7ccSmrg
41caade7ccSmrgstatic XExtensionInfo _shm_info_data;
42caade7ccSmrgstatic XExtensionInfo *shm_info = &_shm_info_data;
43af9a7ee5Smrgstatic const char *shm_extension_name = SHMNAME;
44caade7ccSmrg
45caade7ccSmrg#define ShmCheckExtension(dpy,i,val) \
46caade7ccSmrg  XextCheckExtension (dpy, i, shm_extension_name, val)
47caade7ccSmrg
48caade7ccSmrg/*****************************************************************************
49caade7ccSmrg *                                                                           *
50caade7ccSmrg *			   private utility routines                          *
51caade7ccSmrg *                                                                           *
52caade7ccSmrg *****************************************************************************/
53caade7ccSmrg
54caade7ccSmrgstatic int close_display(Display *dpy, XExtCodes *codes);
55caade7ccSmrgstatic char *error_string(Display *dpy, int code, XExtCodes *codes,
56caade7ccSmrg			  char *buf, int n);
57caade7ccSmrgstatic Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event);
58caade7ccSmrgstatic Status event_to_wire (Display *dpy, XEvent *re, xEvent *event);
59caade7ccSmrgstatic /* const */ XExtensionHooks shm_extension_hooks = {
60caade7ccSmrg    NULL,				/* create_gc */
61caade7ccSmrg    NULL,				/* copy_gc */
62caade7ccSmrg    NULL,				/* flush_gc */
63caade7ccSmrg    NULL,				/* free_gc */
64caade7ccSmrg    NULL,				/* create_font */
65caade7ccSmrg    NULL,				/* free_font */
66caade7ccSmrg    close_display,			/* close_display */
67caade7ccSmrg    wire_to_event,			/* wire_to_event */
68caade7ccSmrg    event_to_wire,			/* event_to_wire */
69caade7ccSmrg    NULL,				/* error */
70caade7ccSmrg    error_string,			/* error_string */
71caade7ccSmrg};
72caade7ccSmrg
73af9a7ee5Smrgstatic const char *shm_error_list[] = {
74caade7ccSmrg    "BadShmSeg",			/* BadShmSeg */
75caade7ccSmrg};
76caade7ccSmrg
77af9a7ee5Smrgstatic XEXT_GENERATE_FIND_DISPLAY (find_display, shm_info, shm_extension_name,
78caade7ccSmrg				   &shm_extension_hooks, ShmNumberEvents, NULL)
79caade7ccSmrg
80caade7ccSmrgstatic XEXT_GENERATE_CLOSE_DISPLAY (close_display, shm_info)
81caade7ccSmrg
82caade7ccSmrgstatic XEXT_GENERATE_ERROR_STRING (error_string, shm_extension_name,
83caade7ccSmrg				   ShmNumberErrors, shm_error_list)
84caade7ccSmrg
85caade7ccSmrg
86caade7ccSmrgstatic Bool
87caade7ccSmrgwire_to_event (Display *dpy, XEvent *re, xEvent *event)
88caade7ccSmrg{
89caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
90caade7ccSmrg    XShmCompletionEvent	*se;
91caade7ccSmrg    xShmCompletionEvent	*sevent;
92caade7ccSmrg
93caade7ccSmrg    ShmCheckExtension (dpy, info, False);
94caade7ccSmrg
95caade7ccSmrg    switch ((event->u.u.type & 0x7f) - info->codes->first_event) {
96caade7ccSmrg    case ShmCompletion:
97caade7ccSmrg	se = (XShmCompletionEvent *) re;
98caade7ccSmrg	sevent = (xShmCompletionEvent *) event;
99caade7ccSmrg	se->type = sevent->type & 0x7f;
100caade7ccSmrg	se->serial = _XSetLastRequestRead(dpy,(xGenericReply *) event);
101caade7ccSmrg	se->send_event = (sevent->type & 0x80) != 0;
102caade7ccSmrg	se->display = dpy;
103caade7ccSmrg	se->drawable = sevent->drawable;
104caade7ccSmrg	se->major_code = sevent->majorEvent;
105caade7ccSmrg	se->minor_code = sevent->minorEvent;
106caade7ccSmrg	se->shmseg = sevent->shmseg;
107caade7ccSmrg	se->offset = sevent->offset;
108caade7ccSmrg    	return True;
109caade7ccSmrg    }
110caade7ccSmrg    return False;
111caade7ccSmrg}
112caade7ccSmrg
113caade7ccSmrgstatic Status
114caade7ccSmrgevent_to_wire (Display *dpy, XEvent *re, xEvent *event)
115caade7ccSmrg{
116caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
117caade7ccSmrg    XShmCompletionEvent	*se;
118caade7ccSmrg    xShmCompletionEvent	*sevent;
119caade7ccSmrg
120caade7ccSmrg    ShmCheckExtension (dpy, info, 0);
121caade7ccSmrg
122caade7ccSmrg    switch ((re->type & 0x7f) - info->codes->first_event) {
123caade7ccSmrg    case ShmCompletion:
124caade7ccSmrg    	se = (XShmCompletionEvent *) re;
125caade7ccSmrg	sevent = (xShmCompletionEvent *) event;
126caade7ccSmrg    	sevent->type = se->type | (se->send_event ? 0x80 : 0);
127caade7ccSmrg    	sevent->sequenceNumber = se->serial & 0xffff;
128caade7ccSmrg    	sevent->drawable = se->drawable;
129caade7ccSmrg    	sevent->majorEvent = se->major_code;
130caade7ccSmrg    	sevent->minorEvent = se->minor_code;
131caade7ccSmrg    	sevent->shmseg = se->shmseg;
132caade7ccSmrg    	sevent->offset = se->offset;
133caade7ccSmrg    	return True;
134caade7ccSmrg    }
135caade7ccSmrg    return False;
136caade7ccSmrg}
137caade7ccSmrg
138caade7ccSmrg/*****************************************************************************
139caade7ccSmrg *                                                                           *
140caade7ccSmrg *		    public Shared Memory Extension routines                  *
141caade7ccSmrg *                                                                           *
142caade7ccSmrg *****************************************************************************/
143caade7ccSmrg
144caade7ccSmrgBool XShmQueryExtension (Display *dpy /*  int *event_basep, *error_basep */)
145caade7ccSmrg{
146caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
147caade7ccSmrg
148caade7ccSmrg    if (XextHasExtension(info)) {
149caade7ccSmrg/*	*event_basep = info->codes->first_event;
150caade7ccSmrg	*error_basep = info->codes->error_event; */
151caade7ccSmrg	return True;
152caade7ccSmrg    } else {
153caade7ccSmrg	return False;
154caade7ccSmrg    }
155caade7ccSmrg}
156caade7ccSmrg
157caade7ccSmrg
158caade7ccSmrgint XShmGetEventBase(Display *dpy)
159caade7ccSmrg{
160caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
161caade7ccSmrg
162caade7ccSmrg    if (XextHasExtension(info)) {
163caade7ccSmrg	return info->codes->first_event;
164caade7ccSmrg    } else {
165caade7ccSmrg	return -1;
166caade7ccSmrg    }
167caade7ccSmrg}
168caade7ccSmrg
169caade7ccSmrg
170caade7ccSmrgBool XShmQueryVersion(
171caade7ccSmrg    Display *dpy,
172caade7ccSmrg    int *majorVersion,
173caade7ccSmrg    int *minorVersion,
174caade7ccSmrg    Bool *sharedPixmaps)
175caade7ccSmrg{
176caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
177caade7ccSmrg    xShmQueryVersionReply rep;
178caade7ccSmrg    register xShmQueryVersionReq *req;
179caade7ccSmrg
180caade7ccSmrg    ShmCheckExtension (dpy, info, False);
181caade7ccSmrg
182caade7ccSmrg    LockDisplay(dpy);
183caade7ccSmrg    GetReq(ShmQueryVersion, req);
184caade7ccSmrg    req->reqType = info->codes->major_opcode;
185caade7ccSmrg    req->shmReqType = X_ShmQueryVersion;
186caade7ccSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
187caade7ccSmrg	UnlockDisplay(dpy);
188caade7ccSmrg	SyncHandle();
189caade7ccSmrg	return False;
190caade7ccSmrg    }
191caade7ccSmrg    *majorVersion = rep.majorVersion;
192caade7ccSmrg    *minorVersion = rep.minorVersion;
193caade7ccSmrg    *sharedPixmaps = rep.sharedPixmaps ? True : False;
194caade7ccSmrg    UnlockDisplay(dpy);
195caade7ccSmrg    SyncHandle();
196caade7ccSmrg    return True;
197caade7ccSmrg}
198caade7ccSmrg
199caade7ccSmrg
200caade7ccSmrgint XShmPixmapFormat(Display *dpy)
201caade7ccSmrg{
202caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
203caade7ccSmrg    xShmQueryVersionReply rep;
204caade7ccSmrg    register xShmQueryVersionReq *req;
205caade7ccSmrg
206caade7ccSmrg    ShmCheckExtension (dpy, info, False);
207caade7ccSmrg
208caade7ccSmrg    LockDisplay(dpy);
209caade7ccSmrg    GetReq(ShmQueryVersion, req);
210caade7ccSmrg    req->reqType = info->codes->major_opcode;
211caade7ccSmrg    req->shmReqType = X_ShmQueryVersion;
212caade7ccSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
213caade7ccSmrg	UnlockDisplay(dpy);
214caade7ccSmrg	SyncHandle();
215caade7ccSmrg	return 0;
216caade7ccSmrg    }
217caade7ccSmrg    UnlockDisplay(dpy);
218caade7ccSmrg    SyncHandle();
219caade7ccSmrg    if (rep.sharedPixmaps &&
220caade7ccSmrg	(rep.majorVersion > 1 || rep.minorVersion > 0))
221caade7ccSmrg	return rep.pixmapFormat;
222caade7ccSmrg    return 0;
223caade7ccSmrg}
224caade7ccSmrg
225caade7ccSmrg
226a5602400SmrgBool XShmAttach(Display *dpy, XShmSegmentInfo *shminfo)
227caade7ccSmrg{
228caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
229caade7ccSmrg    register xShmAttachReq *req;
230caade7ccSmrg
231caade7ccSmrg    ShmCheckExtension (dpy, info, 0);
232caade7ccSmrg
233caade7ccSmrg    LockDisplay(dpy);
234caade7ccSmrg    GetReq(ShmAttach, req);
235caade7ccSmrg    req->reqType = info->codes->major_opcode;
236caade7ccSmrg    req->shmReqType = X_ShmAttach;
237485f0483Smrg    req->shmseg = shminfo->shmseg = XAllocID(dpy);
238caade7ccSmrg    req->shmid = shminfo->shmid;
239caade7ccSmrg    req->readOnly = shminfo->readOnly ? xTrue : xFalse;
240caade7ccSmrg    UnlockDisplay(dpy);
241caade7ccSmrg    SyncHandle();
242caade7ccSmrg    return 1;
243caade7ccSmrg}
244caade7ccSmrg
245caade7ccSmrg
246a5602400SmrgBool XShmDetach(Display *dpy, XShmSegmentInfo *shminfo)
247caade7ccSmrg{
248caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
249caade7ccSmrg    register xShmDetachReq *req;
250caade7ccSmrg
251caade7ccSmrg    ShmCheckExtension (dpy, info, 0);
252caade7ccSmrg
253caade7ccSmrg    LockDisplay(dpy);
254caade7ccSmrg    GetReq(ShmDetach, req);
255caade7ccSmrg    req->reqType = info->codes->major_opcode;
256caade7ccSmrg    req->shmReqType = X_ShmDetach;
257caade7ccSmrg    req->shmseg = shminfo->shmseg;
258caade7ccSmrg    UnlockDisplay(dpy);
259caade7ccSmrg    SyncHandle();
260caade7ccSmrg    return 1;
261caade7ccSmrg}
262caade7ccSmrg
263caade7ccSmrgstatic int _XShmDestroyImage (XImage *ximage)
264caade7ccSmrg{
2650760f5d2Smrg	Xfree(ximage);
266caade7ccSmrg	return 1;
267caade7ccSmrg}
268caade7ccSmrg
269caade7ccSmrg#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad) - 1)) / (pad)) * (pad))
270caade7ccSmrg
271caade7ccSmrgXImage *XShmCreateImage (
272caade7ccSmrg    register Display *dpy,
273caade7ccSmrg    register Visual *visual,
274caade7ccSmrg    unsigned int depth,
275caade7ccSmrg    int format,
276caade7ccSmrg    char *data,
277caade7ccSmrg    XShmSegmentInfo *shminfo,
278caade7ccSmrg    unsigned int width,
279caade7ccSmrg    unsigned int height)
280caade7ccSmrg{
281caade7ccSmrg    register XImage *image;
282caade7ccSmrg
2830760f5d2Smrg    image = Xcalloc(1, sizeof(XImage));
284caade7ccSmrg    if (!image)
285caade7ccSmrg	return image;
286caade7ccSmrg    image->data = data;
287caade7ccSmrg    image->obdata = (char *)shminfo;
288caade7ccSmrg    image->width = width;
289caade7ccSmrg    image->height = height;
290caade7ccSmrg    image->depth = depth;
291caade7ccSmrg    image->format = format;
292caade7ccSmrg    image->byte_order = dpy->byte_order;
293caade7ccSmrg    image->bitmap_unit = dpy->bitmap_unit;
294caade7ccSmrg    image->bitmap_bit_order = dpy->bitmap_bit_order;
295caade7ccSmrg    image->bitmap_pad = _XGetScanlinePad(dpy, depth);
296caade7ccSmrg    image->xoffset = 0;
297caade7ccSmrg    if (visual) {
298caade7ccSmrg	image->red_mask = visual->red_mask;
299caade7ccSmrg	image->green_mask = visual->green_mask;
300caade7ccSmrg	image->blue_mask = visual->blue_mask;
301caade7ccSmrg    } else {
302caade7ccSmrg	image->red_mask = image->green_mask = image->blue_mask = 0;
303caade7ccSmrg    }
304caade7ccSmrg    if (format == ZPixmap)
305caade7ccSmrg	image->bits_per_pixel = _XGetBitsPerPixel(dpy, (int)depth);
306caade7ccSmrg    else
307caade7ccSmrg	image->bits_per_pixel = 1;
308caade7ccSmrg    image->bytes_per_line = ROUNDUP((image->bits_per_pixel * width),
309caade7ccSmrg				    image->bitmap_pad) >> 3;
310caade7ccSmrg    _XInitImageFuncPtrs(image);
311caade7ccSmrg    image->f.destroy_image = _XShmDestroyImage;
312caade7ccSmrg    return image;
313caade7ccSmrg}
314caade7ccSmrg
315a5602400SmrgBool XShmPutImage (
316caade7ccSmrg    register Display *dpy,
317caade7ccSmrg    Drawable d,
318caade7ccSmrg    GC gc,
319caade7ccSmrg    register XImage *image,
320caade7ccSmrg    int src_x, int src_y, int dst_x, int dst_y,
321caade7ccSmrg    unsigned int src_width, unsigned int src_height,
322caade7ccSmrg    Bool send_event)
323caade7ccSmrg{
324caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
325caade7ccSmrg    XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata;
326caade7ccSmrg    register xShmPutImageReq *req;
327caade7ccSmrg
328caade7ccSmrg    ShmCheckExtension (dpy, info, 0);
329caade7ccSmrg    if (!shminfo) return 0;
330caade7ccSmrg
331caade7ccSmrg    LockDisplay(dpy);
332caade7ccSmrg    FlushGC(dpy, gc);
333caade7ccSmrg    GetReq(ShmPutImage, req);
334caade7ccSmrg    req->reqType = info->codes->major_opcode;
335caade7ccSmrg    req->shmReqType = X_ShmPutImage;
336caade7ccSmrg    req->drawable = d;
337caade7ccSmrg    req->gc = gc->gid;
338caade7ccSmrg    req->srcX = src_x;
339caade7ccSmrg    req->srcY = src_y;
340caade7ccSmrg    req->srcWidth = src_width;
341caade7ccSmrg    req->srcHeight = src_height;
342caade7ccSmrg    req->dstX = dst_x;
343caade7ccSmrg    req->dstY = dst_y;
344caade7ccSmrg    req->totalWidth = image->width;
345caade7ccSmrg    req->totalHeight = image->height;
346caade7ccSmrg    req->depth = image->depth;
347caade7ccSmrg    req->format = image->format;
348caade7ccSmrg    req->sendEvent = send_event;
349caade7ccSmrg    req->shmseg = shminfo->shmseg;
350caade7ccSmrg    req->offset = image->data - shminfo->shmaddr;
351caade7ccSmrg    UnlockDisplay(dpy);
352caade7ccSmrg    SyncHandle();
353caade7ccSmrg    return 1;
354caade7ccSmrg}
355caade7ccSmrg
356caade7ccSmrg
357a5602400SmrgBool XShmGetImage(
358caade7ccSmrg    register Display *dpy,
359caade7ccSmrg    Drawable d,
360caade7ccSmrg    XImage *image,
361caade7ccSmrg    int x, int y,
362caade7ccSmrg    unsigned long plane_mask)
363caade7ccSmrg{
364caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
365caade7ccSmrg    XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata;
366caade7ccSmrg    register xShmGetImageReq *req;
367caade7ccSmrg    xShmGetImageReply rep;
368caade7ccSmrg    register Visual *visual;
369caade7ccSmrg
370caade7ccSmrg    ShmCheckExtension (dpy, info, 0);
371caade7ccSmrg    if (!shminfo) return 0;
372caade7ccSmrg
373caade7ccSmrg    LockDisplay(dpy);
374caade7ccSmrg    GetReq(ShmGetImage, req);
375caade7ccSmrg    req->reqType = info->codes->major_opcode;
376caade7ccSmrg    req->shmReqType = X_ShmGetImage;
377caade7ccSmrg    req->drawable = d;
378caade7ccSmrg    req->x = x;
379caade7ccSmrg    req->y = y;
380caade7ccSmrg    req->width = image->width;
381caade7ccSmrg    req->height = image->height;
382caade7ccSmrg    req->planeMask = plane_mask;
383caade7ccSmrg    req->format = image->format;
384caade7ccSmrg    req->shmseg = shminfo->shmseg;
385caade7ccSmrg    req->offset = image->data - shminfo->shmaddr;
386caade7ccSmrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
387caade7ccSmrg	UnlockDisplay(dpy);
388caade7ccSmrg	SyncHandle();
389caade7ccSmrg	return 0;
390caade7ccSmrg    }
391caade7ccSmrg    visual = _XVIDtoVisual(dpy, rep.visual);
392caade7ccSmrg    if (visual) {
393caade7ccSmrg    	image->red_mask = visual->red_mask;
394caade7ccSmrg    	image->green_mask = visual->green_mask;
395caade7ccSmrg    	image->blue_mask = visual->blue_mask;
396caade7ccSmrg    } else {
397caade7ccSmrg	image->red_mask = image->green_mask = image->blue_mask = 0;
398caade7ccSmrg    }
399caade7ccSmrg    UnlockDisplay(dpy);
400caade7ccSmrg    SyncHandle();
401caade7ccSmrg    return 1;
402caade7ccSmrg}
403caade7ccSmrg
404caade7ccSmrgPixmap XShmCreatePixmap (
405caade7ccSmrg    register Display *dpy,
406caade7ccSmrg    Drawable d,
407caade7ccSmrg    char *data,
408caade7ccSmrg    XShmSegmentInfo *shminfo,
409caade7ccSmrg    unsigned int width, unsigned int height, unsigned int depth)
410caade7ccSmrg{
411caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
412caade7ccSmrg    Pixmap pid;
413caade7ccSmrg    register xShmCreatePixmapReq *req;
414caade7ccSmrg
415caade7ccSmrg    ShmCheckExtension (dpy, info, 0);
416caade7ccSmrg
417caade7ccSmrg    LockDisplay(dpy);
418caade7ccSmrg    GetReq(ShmCreatePixmap, req);
419caade7ccSmrg    req->reqType = info->codes->major_opcode;
420caade7ccSmrg    req->shmReqType = X_ShmCreatePixmap;
421caade7ccSmrg    req->drawable = d;
422caade7ccSmrg    req->width = width;
423caade7ccSmrg    req->height = height;
424caade7ccSmrg    req->depth = depth;
425caade7ccSmrg    req->shmseg = shminfo->shmseg;
426caade7ccSmrg    req->offset = data - shminfo->shmaddr;
427caade7ccSmrg    pid = req->pid = XAllocID(dpy);
428caade7ccSmrg    UnlockDisplay(dpy);
429caade7ccSmrg    SyncHandle();
430caade7ccSmrg    return pid;
431caade7ccSmrg}
432