XShm.c revision caade7cc
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/shmstr.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    shminfo->shmseg = XAllocID(dpy);
239    LockDisplay(dpy);
240    GetReq(ShmAttach, req);
241    req->reqType = info->codes->major_opcode;
242    req->shmReqType = X_ShmAttach;
243    req->shmseg = shminfo->shmseg;
244    req->shmid = shminfo->shmid;
245    req->readOnly = shminfo->readOnly ? xTrue : xFalse;
246    UnlockDisplay(dpy);
247    SyncHandle();
248    return 1;
249}
250
251
252Status XShmDetach(Display *dpy, XShmSegmentInfo *shminfo)
253{
254    XExtDisplayInfo *info = find_display (dpy);
255    register xShmDetachReq *req;
256
257    ShmCheckExtension (dpy, info, 0);
258
259    LockDisplay(dpy);
260    GetReq(ShmDetach, req);
261    req->reqType = info->codes->major_opcode;
262    req->shmReqType = X_ShmDetach;
263    req->shmseg = shminfo->shmseg;
264    UnlockDisplay(dpy);
265    SyncHandle();
266    return 1;
267}
268
269static int _XShmDestroyImage (XImage *ximage)
270{
271	Xfree((char *)ximage);
272	return 1;
273}
274
275#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad) - 1)) / (pad)) * (pad))
276
277XImage *XShmCreateImage (
278    register Display *dpy,
279    register Visual *visual,
280    unsigned int depth,
281    int format,
282    char *data,
283    XShmSegmentInfo *shminfo,
284    unsigned int width,
285    unsigned int height)
286{
287    register XImage *image;
288
289    image = (XImage *)Xcalloc(1, (unsigned)sizeof(XImage));
290    if (!image)
291	return image;
292    image->data = data;
293    image->obdata = (char *)shminfo;
294    image->width = width;
295    image->height = height;
296    image->depth = depth;
297    image->format = format;
298    image->byte_order = dpy->byte_order;
299    image->bitmap_unit = dpy->bitmap_unit;
300    image->bitmap_bit_order = dpy->bitmap_bit_order;
301    image->bitmap_pad = _XGetScanlinePad(dpy, depth);
302    image->xoffset = 0;
303    if (visual) {
304	image->red_mask = visual->red_mask;
305	image->green_mask = visual->green_mask;
306	image->blue_mask = visual->blue_mask;
307    } else {
308	image->red_mask = image->green_mask = image->blue_mask = 0;
309    }
310    if (format == ZPixmap)
311	image->bits_per_pixel = _XGetBitsPerPixel(dpy, (int)depth);
312    else
313	image->bits_per_pixel = 1;
314    image->bytes_per_line = ROUNDUP((image->bits_per_pixel * width),
315				    image->bitmap_pad) >> 3;
316    _XInitImageFuncPtrs(image);
317    image->f.destroy_image = _XShmDestroyImage;
318    return image;
319}
320
321Status XShmPutImage (
322    register Display *dpy,
323    Drawable d,
324    GC gc,
325    register XImage *image,
326    int src_x, int src_y, int dst_x, int dst_y,
327    unsigned int src_width, unsigned int src_height,
328    Bool send_event)
329{
330    XExtDisplayInfo *info = find_display (dpy);
331    XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata;
332    register xShmPutImageReq *req;
333
334    ShmCheckExtension (dpy, info, 0);
335    if (!shminfo) return 0;
336
337    LockDisplay(dpy);
338    FlushGC(dpy, gc);
339    GetReq(ShmPutImage, req);
340    req->reqType = info->codes->major_opcode;
341    req->shmReqType = X_ShmPutImage;
342    req->drawable = d;
343    req->gc = gc->gid;
344    req->srcX = src_x;
345    req->srcY = src_y;
346    req->srcWidth = src_width;
347    req->srcHeight = src_height;
348    req->dstX = dst_x;
349    req->dstY = dst_y;
350    req->totalWidth = image->width;
351    req->totalHeight = image->height;
352    req->depth = image->depth;
353    req->format = image->format;
354    req->sendEvent = send_event;
355    req->shmseg = shminfo->shmseg;
356    req->offset = image->data - shminfo->shmaddr;
357    UnlockDisplay(dpy);
358    SyncHandle();
359    return 1;
360}
361
362
363Status XShmGetImage(
364    register Display *dpy,
365    Drawable d,
366    XImage *image,
367    int x, int y,
368    unsigned long plane_mask)
369{
370    XExtDisplayInfo *info = find_display (dpy);
371    XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata;
372    register xShmGetImageReq *req;
373    xShmGetImageReply rep;
374    register Visual *visual;
375
376    ShmCheckExtension (dpy, info, 0);
377    if (!shminfo) return 0;
378
379    LockDisplay(dpy);
380    GetReq(ShmGetImage, req);
381    req->reqType = info->codes->major_opcode;
382    req->shmReqType = X_ShmGetImage;
383    req->drawable = d;
384    req->x = x;
385    req->y = y;
386    req->width = image->width;
387    req->height = image->height;
388    req->planeMask = plane_mask;
389    req->format = image->format;
390    req->shmseg = shminfo->shmseg;
391    req->offset = image->data - shminfo->shmaddr;
392    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
393	UnlockDisplay(dpy);
394	SyncHandle();
395	return 0;
396    }
397    visual = _XVIDtoVisual(dpy, rep.visual);
398    if (visual) {
399    	image->red_mask = visual->red_mask;
400    	image->green_mask = visual->green_mask;
401    	image->blue_mask = visual->blue_mask;
402    } else {
403	image->red_mask = image->green_mask = image->blue_mask = 0;
404    }
405    UnlockDisplay(dpy);
406    SyncHandle();
407    return 1;
408}
409
410Pixmap XShmCreatePixmap (
411    register Display *dpy,
412    Drawable d,
413    char *data,
414    XShmSegmentInfo *shminfo,
415    unsigned int width, unsigned int height, unsigned int depth)
416{
417    XExtDisplayInfo *info = find_display (dpy);
418    Pixmap pid;
419    register xShmCreatePixmapReq *req;
420
421    ShmCheckExtension (dpy, info, 0);
422
423    LockDisplay(dpy);
424    GetReq(ShmCreatePixmap, req);
425    req->reqType = info->codes->major_opcode;
426    req->shmReqType = X_ShmCreatePixmap;
427    req->drawable = d;
428    req->width = width;
429    req->height = height;
430    req->depth = depth;
431    req->shmseg = shminfo->shmseg;
432    req->offset = data - shminfo->shmaddr;
433    pid = req->pid = XAllocID(dpy);
434    UnlockDisplay(dpy);
435    SyncHandle();
436    return pid;
437}
438