Home | History | Annotate | Line # | Download | only in src
      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 Bool 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 Bool 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(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 = Xcalloc(1, 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 Bool 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 Bool 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 }
    432