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