1/* 2 * 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in 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 41static XExtensionInfo _shm_info_data; 42static XExtensionInfo *shm_info = &_shm_info_data; 43static 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 54static int close_display(Display *dpy, XExtCodes *codes); 55static char *error_string(Display *dpy, int code, XExtCodes *codes, 56 char *buf, int n); 57static Bool wire_to_event (Display *dpy, XEvent *re, xEvent *event); 58static Status event_to_wire (Display *dpy, XEvent *re, xEvent *event); 59static /* 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 73static const char *shm_error_list[] = { 74 "BadShmSeg", /* BadShmSeg */ 75}; 76 77static XEXT_GENERATE_FIND_DISPLAY (find_display, shm_info, shm_extension_name, 78 &shm_extension_hooks, ShmNumberEvents, NULL) 79 80static XEXT_GENERATE_CLOSE_DISPLAY (close_display, shm_info) 81 82static XEXT_GENERATE_ERROR_STRING (error_string, shm_extension_name, 83 ShmNumberErrors, shm_error_list) 84 85 86static Bool 87wire_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 113static Status 114event_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 144Bool 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 158int 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 170Bool 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 200int 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 226Bool 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 246Bool 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 263static int _XShmDestroyImage (XImage *ximage) 264{ 265 Xfree(ximage); 266 return 1; 267} 268 269#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad) - 1)) / (pad)) * (pad)) 270 271XImage *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 315Bool 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 357Bool 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 404Pixmap 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