home *** CD-ROM | disk | FTP | other *** search
- .\" Use -ms
- .de Cs
- .IP
- .nf
- .ft C
- ..
- .de Ce
- .ft P
- .fi
- ..
- .de Bu
- .br
- .ti +.5i
- .ie \\n(.$ \\$1
- .el \\(bu
- ..
- .EH ''''
- .OH ''''
- .EF ''''
- .OF ''''
- .ps 10
- .nr PS 10
- \&
- .TL
- \s+2\fBMIT-SHM\(emThe MIT Shared Memory Extension\fP\s-2
- .sp
- How the shared memory extension works
- .AU
- Jonathan Corbet
- .AI
- Atmospheric Technology Division
- National Center for Atmospheric Research
- corbet@ncar.ucar.edu
- .sp
- Formatted and edited for release 5 by
- .AU
- Keith Packard
- .AI
- MIT X Consortium
- .ps 9
- .nr PS 9
- .sp 8
- .AB
- This document briefly describes how to use the MIT-SHM shared memory
- extension. I have tried to make it accurate, but it would not surprise me
- if some errors remained. If you find anything wrong, do let me know and I
- will incorporate the corrections. Meanwhile, please take this document ``as
- is''\(eman improvement over what was there before, but certainly not the
- definitive word.
- .AE
- .LP
- .DS C
- Copyright \(co 1991 by the Massachusetts Institute of Technology
- .DE
- .sp 2
- .LP
- Permission to use, copy, modify, and distribute this documentation for any
- purpose and without fee is hereby granted, provided that the above copyright
- notice and this permission notice appear in all copies. MIT makes no
- representations about the suitability for any purpose of the information in
- this document. This documentation is provided ``as is'' without express or
- implied warranty.
- .ps 10
- .nr PS 10
- .bp 1
- .de PT
- .tl ''MIT Shared Memory Extension''
- ..
- .de BT
- .tl ''\fB % \fP''
- ..
- .NH 1
- REQUIREMENTS
- .LP
- The shared memory extension is provided only by some X servers. To find out
- if your server supports the extension, use xdpyinfo(1). In particular, to
- be able to use this extension, your system must provide the SYSV shared
- memory primitives. There is not an mmap-based version of this extension.
- To use shared memory on Sun systems, you must have built your kernel with
- SYSV shared memory enabled -- which is not the default configuration.
- Additionally, the shared memeory maximum size will need to be increased on
- both Sun and Digital systems; the defaults are far too small for any useful
- work.
- .NH 1
- WHAT IS PROVIDED
- .LP
- The basic capability provided is that of shared memory XImages. This is
- essentially a version of the ximage interface where the actual image data
- is stored in a shared memory segment, and thus need not be moved through
- the Xlib interprocess communication channel. For large images, use of this
- facility can result in some real performance increases.
- .LP
- Additionally, some implementations provided shared memory pixmaps. These
- are 2 dimensional arrays of pixels in a format specified by the X server,
- where the image data is stored in the shared memory segment. Through use of
- shared memory pixmaps, it is possible to change the contents of these
- pixmaps without using any Xlib routines at all. Shared memory pixmaps can
- only be supported when the X server can use regular virtual memory for
- pixmap data; if the pixmaps are stored in some magic graphics hardware, your
- application will not be able to share them with the server. Xdpyinfo(1)
- doesn't print this particular nugget of information.
- .NH 1
- HOW TO USE THE SHARED MEMORY EXTENSION
- .LP
- Code which uses the shared memory extension must include a number of header
- files:
- .Cs
- # include <X11/Xlib.h> /* of course */
- # include <sys/ipc.h>
- # include <sys/shm.h>
- # include <X11/extensions/XShm.h>
- .Ce
- .LP
- Of course, if the system you are building on does not support shared
- memory, the file XShm.h may not be present. You may want to make
- liberal use of #ifdefs.
- .LP
- Any code which uses the shared memory extension should first check to see
- that the server provides the extension. You could always be running over
- the net, or in some other environment where the extension will not work.
- To perform this check, call either
- .Cs
- Status XShmQueryExtension (display)
- Display *display
- .Ce
- .LP
- or
- .Cs
- Status XShmQueryVersion (display, major, minor, pixmaps)
- Display *display;
- int *major, *minor;
- Bool *pixmaps
- .Ce
- .LP
- Where ``display'' is, of course, the display on which you are running. If
- the shared memory extension may be used, the return value from either
- function will be True; otherwise your program should operate using
- conventional Xlib calls. When the extension is available,
- \fCXShmQueryVersion\fP also returns ``major'' and ``minor'' which are the
- version numbers of the extension implementation, and ``pixmaps'' which is
- True iff shared memory pixmaps are supported.
- .NH 1
- USE OF SHARED MEMORY XIMAGES
- .LP
- The basic sequence of operations for shared memory XImages is as follows:
- .LP
- .Bu "1 \-"
- Create the shared memory XImage structure
- .Bu "2 \-"
- Create a shared memory segment to store the image data
- .Bu "3 \-"
- Inform the server about the shared memory segment
- .Bu "4 \-"
- Use the shared memory XImage, much like a normal one.
- .LP
- To create a shared memory XImage, use:
- .Cs
- XImage *XShmCreateImage (display, visual, depth, format, data,
- shminfo, width, height)
- Display *display;
- Visual *visual;
- unsigned int depth, width, height;
- int format;
- char *data;
- XShmSegmentInfo *shminfo;
- .Ce
- .LP
- Most of the arguments are the same as for XCreateImage; I will not go
- through them here. Note, however, that there are no ``offset'', ``bitmap_pad'',
- or ``bytes_per_line'' arguments. These quantities will be defined by the
- server itself, and your code needs to abide by them. Unless you have already
- allocated the shared memory segment (see below), you should pass in NULL for
- the ``data'' pointer.
- .LP
- There is one additional argument: ``shminfo'', which is a pointer to a
- structure of type XShmSegmentInfo. You must allocate one of these
- structures such that it will have a lifetime at least as long as that of
- the shared memory XImage. There is no need to initialize this structure
- before the call to XShmCreateImage.
- .LP
- The return value, if all goes well, will be an XImage structure, which you
- can use for the subsequent steps.
- .LP
- The next step is to create the shared memory segment. This is
- best done after the creation of the XImage, since you need to make use of
- the information in that XImage to know how much memory to allocate. To
- create the segment, you need a call like:
- .Cs
- shminfo.shmid = shmget (IPC_PRIVATE,
- image->bytes_per_line * image->height, IPC_CREAT|0777);
- .Ce
- .LP
- (assuming that you have called your shared memory XImage ``image''). You
- should, of course, follow the Rules and do error checking on all of these
- system calls. Also, be sure to use the bytes_per_line field, not the width
- you used to create the XImage as they may well be different.
- .LP
- Note that the shared memory ID returned by the system is stored in the
- shminfo structure. The server will need that ID to attach itself to the
- segment.
- .LP
- Next, attach this shared memory segment to your process:
- .Cs
- shminfo.shmaddr = image->data = shmat (shminfo.shmid, 0, 0);
- .Ce
- .LP
- The address returned by shmat should be stored in *both* the XImage
- structure and the shminfo structure.
- .LP
- To finish filling in the shminfo structure, you need to decide how you want
- the server to attach to the shared memory segment, and set the ``readOnly''
- field as follows. Normally, you would code:
- .Cs
- shminfo.readOnly = False;
- .Ce
- .LP
- If you set it to True, the server will not be able to write to this
- segment, and thus XShmGetImage calls will fail.
- .LP
- Finally, tell the server to attach to your shared memory segment with:
- .Cs
- Status XShmAttach (display, shminfo);
- .Ce
- .LP
- If all goes well, you will get a non-zero status back, and your XImage is
- ready for use.
- .LP
- To write a shared memory XImage into an X drawable, use XShmPutImage:
- .Cs
- Status XShmPutImage (display, d, gc, image, src_x, src_y,
- dest_x, dest_y, width, height, send_event)
- Display *display;
- Drawable d;
- GC gc;
- XImage *image;
- int src_x, src_y, dest_x, dest_y;
- unsigned int width, height;
- bool send_event;
- .Ce
- .LP
- The interface is identical to that of XPutImage, so I will spare my fingers
- and not repeat that documentation here. There is one additional parameter,
- however, called ``send_event''. If this parameter is passed as True, the
- server will generate a ``completion'' event when the image write is complete;
- thus your program can know when it is safe to begin manipulating the shared
- memory segment again.
- .LP
- The completion event has type XShmCompletionEvent, which is defined as the
- following:
- .Cs
- typedef struct {
- int type; /* of event */
- unsigned long serial; /* # of last request processed */
- Bool send_event; /* true if came from a SendEvent request */
- Display *display; /* Display the event was read from */
- Drawable drawable; /* drawable of request */
- int major_code; /* ShmReqCode */
- int minor_code; /* X_ShmPutImage */
- ShmSeg shmseg; /* the ShmSeg used in the request */
- unsigned long offset; /* the offset into ShmSeg used */
- } XShmCompletionEvent;
- .Ce
- .LP
- The event type value that will be used can be determined at run time with a
- line of the form:
- .Cs
- int CompletionType = XShmGetEventBase (display) + ShmCompletion;
- .Ce
- .LP
- If you modify the shared memory segment before the arrival of the
- completion event, the results you see on the screen may be inconsistent.
- .LP
- To read image data into a shared memory XImage, use the following:
- .Cs
- Status XShmGetImage (display, d, image, x, y, plane_mask)
- Display *display;
- Drawable d;
- XImage *image;
- int x, y;
- unsigned long plane_mask;
- .Ce
- .LP
- Where ``display'' is the display of interest, ``d'' is the source drawable,
- ``image'' is the destination XImage, ``x'' and ``y'' are the offsets within
- ``d'', and ``plane_mask'' defines which planes are to be read.
- .LP
- To destroy a shared memory XImage, you should first instruct the server to
- detach from it, then destroy the segment itself, as follows:
- .Cs
- XShmDetach (display, shminfo);
- XDestroyImage (image);
- shmdt (shminfo.shmaddr);
- shmctl (shminfo.shmid, IPC_RMID, 0);
- .Ce
- .NH 1
- USE OF SHARED MEMORY PIXMAPS
- .LP
- Unlike X images, for which any image format is usable, the shared memory
- extension supports only a single format (i.e. XYPixmap or ZPixmap) for the
- data stored in a shared memory pixmap. This format is independent of the
- depth of the image (for 1-bit pixmaps it doesn't really matter what this
- format is) and independent of the screen. Use XShmPixmapFormat to get the
- format for the server:
- .Cs
- int XShmPixmapFormat (display)
- Display *display;
- .Ce
- .LP
- If your application can deal with the server pixmap data format (including
- bits-per-pixel et al.), create a shared memory segment and ``shminfo''
- structure in exactly the same way as is listed above for shared memory
- XImages. While it is, not strictly necessary to create an XImage first,
- doing so incurs little overhead and will give you an appropriate
- bytes_per_line value to use.
- .LP
- Once you have your shminfo structure filled in, simply call:
- .Cs
- Pixmap XShmCreatePixmap (display, d, data, shminfo, width,
- height, depth);
- Display *display;
- Drawable d;
- char *data;
- XShmSegmentInfo *shminfo;
- unsigned int width, height, depth;
- .Ce
- .LP
- The arguments are all the same as for XCreatePixmap, with two additions:
- ``data'' and ``shminfo''. The second of the two is the same old shminfo
- structure that has been used before. The first is the pointer to the shared
- memory segment, and should be the same as the shminfo.shmaddr field. I am
- not sure why this is a separate parameter.
- .LP
- If everything works, you will get back a pixmap, which you can manipulate in
- all of the usual ways, with the added bonus of being able to tweak its
- contents directly through the shared memory segment. Shared memory pixmaps
- are destroyed in the usual manner with XFreePixmap, though you should detach
- and destroy the shared memory segment itself as shown above.
-