1 //============================================================================
5 // MIT Shared Memory Extension for X
7 //============================================================================
12 #include <X11/Xutil.h>
15 //-----------------------------------------------------------------------------
18 // Shared memory error handler routine used temporarily by allocSHM().
22 static int (*_origErrorHandler)(Display*, XErrorEvent*);
24 static int _shmErrorHandler( Display* d, XErrorEvent* e )
27 if( e->error_code == BadAccess )
28 fprintf( stderr, "ShmImage: failed to attach shared memory\n" );
30 (*_origErrorHandler)( d, e );
35 static void* allocSHM( XShmSegmentInfo* si, Display* dis, int size )
38 si->shmid = shmget( IPC_PRIVATE, size, IPC_CREAT | 0777 );
41 si->shmaddr = (char*) shmat( si->shmid, 0, 0 );
42 if( si->shmaddr != (char*) -1 )
46 // Attach the memory to the X Server.
49 _origErrorHandler = XSetErrorHandler( _shmErrorHandler );
50 XShmAttach( dis, si );
51 XSync( dis, True ); // wait for error or ok
52 XSetErrorHandler( _origErrorHandler );
56 shmctl( si->shmid, IPC_RMID, 0 );
62 shmctl( si->shmid, IPC_RMID, 0 );
71 static void freeSHM( XShmSegmentInfo* si, Display* dis )
75 XShmDetach( dis, si );
76 //XSync( dis, False );//need server to detach so can remove id?
79 shmctl( si->shmid, IPC_RMID, 0 );
84 static int bytesPerLine( int width, int depth )
88 // TODO: Find out how to correctly calculate a Pixmap bytesPerLine that is
89 // guaranteed to be accurate on any X server.
90 // The important thing is that we don't calculate a value less that what
91 // is actually used by the server.
96 bpl = (width + 7) / 8;
108 // Pad to 4 byte boundary.
110 bpl += (4 - (bpl & 3));
116 //-----------------------------------------------------------------------------
120 \class ShmImage xshmext.h
121 \brief The ShmImage class is an X11 XImage allocated in shared memory.
126 \fn XImage* ShmImage::image()
127 Returns 0 if the constructor failed.
132 Check to see if the XShm extensions are supported.
133 Returns the XEvent completion type or zero if XShm is not available to
137 int ShmImage::query( Display* dis )
139 if( ! XShmQueryExtension( dis ) )
142 return completionType( dis );
146 ShmImage::ShmImage( Display* dis, int width, int height, XVisualInfo* vis )
150 // Query here for safety?
152 _XImage = XShmCreateImage( _display, vis->visual, vis->depth, ZPixmap,
153 NULL, &_si, width, height );
156 _XImage->data = (char*) allocSHM( &_si, _display,
157 _XImage->bytes_per_line * _XImage->height );
158 if( ! _XImage->data )
160 XDestroyImage( _XImage );
167 ShmImage::~ShmImage()
170 freeSHM( &_si, _display );
173 XDestroyImage( _XImage );
177 //-----------------------------------------------------------------------------
181 \class ShmPixmap xshmext.h
182 \brief The ShmPixmap class is an X11 Pixmap allocated in shared memory.
187 \fn Pixmap* ShmPixmap::pixmap()
188 Returns 0 if the constructor failed.
193 Check to see if the XShmPixmap extensions are supported.
194 Returns the XEvent completion type or zero if XShm is not available to
198 int ShmPixmap::query( Display* dis )
200 if( ! XShmPixmapFormat( dis ) )
203 return ShmImage::query( dis );
207 ShmPixmap::ShmPixmap( Display* dis, Drawable draw, int width, int height,
212 // Query here for safety?
215 depth = XDefaultDepth( _display, XDefaultScreen( _display ) );
217 allocSHM( &_si, _display, bytesPerLine( width, depth ) * height );
220 _pix = XShmCreatePixmap( _display, draw, _si.shmaddr, &_si,
221 width, height, depth );
226 ShmPixmap::~ShmPixmap()
229 freeSHM( &_si, _display );
232 XFreePixmap( _display, _pix );