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