http://ftp.aanet.ru/pub/Linux/X11/apps/xscreensaver-2.31.tar.gz
[xscreensaver] / utils / xshm.c
1 /* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
2  *  by Jamie Zawinski <jwz@jwz.org>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  */
12
13 /* The MIT-SHM (Shared Memory) extension is pretty tricky to use.
14    This file contains the common boiler-plate for creating a shared
15    XImage structure, and for making sure that the shared memory segments
16    get allocated and shut down cleanly.
17
18    This code currently deals only with shared XImages, not with shared Pixmaps.
19    It also doesn't use "completion events", but so far that doesn't seem to
20    be a problem (and I'm not entirely clear on when they would actually be
21    needed, anyway.)
22
23    If you don't have man pages for this extension, see
24    http://www.physik.uni-regensburg.de/~scs22156/sofie-0.2/mit-shm.html
25    or in the R6 sources as "xc/doc/specs/Xext/mit-shm.ms".
26
27    (This document seems not to ever remain available on the web in one place
28    for very long; you can search for it by the title, "MIT-SHM -- The MIT
29    Shared Memory Extension".)
30
31    To monitor the system's shared memory segments, run "ipcs -m".
32   */
33
34 #include "utils.h"
35
36 #ifdef HAVE_XSHM_EXTENSION      /* whole file */
37
38 #include <errno.h>              /* for perror() */
39 #include <X11/Xutil.h>          /* for XDestroyImage() */
40
41 #include "xshm.h"
42 #include "resources.h"          /* for get_string_resource() */
43
44
45 extern char *progname;
46
47 XImage *
48 create_xshm_image (Display *dpy, Visual *visual,
49                    unsigned int depth,
50                    int format, char *data,
51                    XShmSegmentInfo *shm_info,
52                    unsigned int width, unsigned int height)
53 {
54   XImage *image = 0;
55   if (!get_boolean_resource("useSHM", "Boolean"))
56     return 0;
57
58   if (!XShmQueryExtension (dpy))
59     return 0;
60
61   image = XShmCreateImage(dpy, visual, depth,
62                               format, data, shm_info, width, height);
63 #ifdef DEBUG
64   fprintf(stderr, "\n%s: XShmCreateImage(... %d, %d)\n", progname,
65           width, height);
66 #endif
67
68   shm_info->shmid = shmget(IPC_PRIVATE,
69                            image->bytes_per_line * image->height,
70                            IPC_CREAT | 0777);
71 #ifdef DEBUG
72   fprintf(stderr, "%s: shmget(IPC_PRIVATE, %d, IPC_CREAT | 0777) ==> %d\n",
73           progname, image->bytes_per_line * image->height, shm_info->shmid);
74 #endif
75
76   if (shm_info->shmid == -1)
77     {
78       char buf[1024];
79       sprintf (buf, "%s: shmget failed", progname);
80       perror(buf);
81       XDestroyImage (image);
82       image = 0;
83       XSync(dpy, False);
84     }
85   else
86     {
87       shm_info->readOnly = False;
88       image->data = shm_info->shmaddr = shmat(shm_info->shmid, 0, 0);
89
90 #ifdef DEBUG
91       fprintf(stderr, "%s: shmat(%d, 0, 0) ==> %d\n", progname,
92               shm_info->shmid, (int) image->data);
93 #endif
94
95       if (!XShmAttach(dpy, shm_info))
96         {
97           fprintf (stderr, "%s: XShmAttach failed!\n", progname);
98           XDestroyImage (image);
99           XSync(dpy, False);
100           shmdt (shm_info->shmaddr);
101           image = 0;
102         }
103
104 #ifdef DEBUG
105       fprintf(stderr, "%s: XShmAttach(dpy, shm_info) ==> True\n", progname);
106 #endif
107
108       XSync(dpy, False);
109
110       /* Delete the shared segment right now; the segment won't actually
111          go away until both the client and server have deleted it.  The
112          server will delete it as soon as the client disconnects, so we
113          should delete our side early in case of abnormal termination.
114          (And note that, in the context of xscreensaver, abnormal
115          termination is the rule rather than the exception, so this would
116          leak like a sieve if we didn't do this...)
117
118          #### Are we leaking anyway?  Perhaps because of the window of
119          opportunity between here and the XShmAttach call above, during
120          which we might be killed?  Do we need to establish a signal
121          handler for this case?
122        */
123       shmctl (shm_info->shmid, IPC_RMID, 0);
124
125 #ifdef DEBUG
126       fprintf(stderr, "%s: shmctl(%d, IPC_RMID, 0)\n\n", progname,
127               shm_info->shmid);
128 #endif
129     }
130
131   return image;
132 }
133
134 #endif /* HAVE_XSHM_EXTENSION */