/* xshm.c */ /* * Example of how to use the X Shared Memory extension: MIT_SHM. * This code was lifted from my Mesa library. It hasn't been tested * in this form but should be close enough for you to get it working. * Beware that this extension isn't available on all systems. Your * application code should use #ifdef's around this code so it can be * omitted on systems that don't have it, then fallback to using a regular * XImage. * * Brian Paul Sep, 20, 1995 brianp@ssec.wisc.edu */ #include #include #include #include XShmSegmentInfo shminfo; /* * Check if the X Shared Memory extension is available. * Return: 0 = not available * 1 = shared XImage support available * 2 = shared Pixmap support available also */ int check_for_xshm( Display *display ) { int major, minor, ignore; Bool pixmaps; if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) { return (pixmaps==True) ? 2 : 1; } else { return 0; } } else { return 0; } } /* * Error handling. */ static int ErrorFlag = 0; static int HandleXError( Display *dpy, XErrorEvent *event ) { ErrorFlag = 1; return 0; } /* * Allocate a shared memory XImage. */ XImage *alloc_xshm_image( Display *dpy, Visual *vis, int width, int height, int depth ) { XImage *img; GC gc; /* * We have to do a _lot_ of error checking here to be sure we can * really use the XSHM extension. It seems different servers trigger * errors at different points if the extension won't work. Therefore * we have to be very careful... */ img = XShmCreateImage( dpy, vis, depth, ZPixmap, NULL, &shminfo, width, height ); if (img == NULL) { printf("XShmCreateImage failed!\n"); return NULL; } shminfo.shmid = shmget( IPC_PRIVATE, img->bytes_per_line * img->height, IPC_CREAT|0777 ); if (shminfo.shmid < 0) { perror("shmget"); XDestroyImage( img ); img = NULL; error( "alloc_back_buffer: Shared memory error (shmget), disabling." ); c->shm = 0; return NULL; } shminfo.shmaddr = img->data = (char*)shmat( shminfo.shmid, 0, 0 ); if (shminfo.shmaddr == (char *) -1) { perror("alloc_back_buffer"); XDestroyImage( img ); img = NULL; printf("shmat failed\n"); return NULL; } shminfo.readOnly = False; ErrorFlag = 0; XSetErrorHandler( HandleXError ); /* This may trigger the X protocol error we're ready to catch: */ XShmAttach( dpy, &shminfo ); XSync( dpy, False ); if (ErrorFlag) { /* we are on a remote display, this error is normal, don't print it */ XFlush( dpy ); ErrorFlag = 0; XDestroyImage( img ); shmdt( shminfo.shmaddr ); shmctl( shminfo.shmid, IPC_RMID, 0 ); return NULL; } shmctl( shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */ #ifdef OPTIONAL_PART /* An error may still occur upon the first XShmPutImage. So it's a */ /* good idea to test it here. However, we need a window to put the */ /* image into, etc.... */ gc = XCreateGC( dpy, window, 0, NULL ); XShmPutImage( dpy, window, gc, img, 0, 0, 0, 0, 1, 1 /*one pixel*/, False ); XSync( dpy, False ); XFreeGC( dpy, gc ); XSetErrorHandler( NULL ); if (ErrorFlag) { XFlush( dpy ); ErrorFlag = 0; XDestroyImage( img ); shmdt( shminfo.shmaddr ); shmctl( shminfo.shmid, IPC_RMID, 0 ); return NULL; } #endif return img; } void destroy_xshm_image( XImage *img ) { XShmDetach( dpy, &shminfo ); XDestroyImage( img ); shmdt( shminfo.shmaddr ); } main() { XImage *img; /* test if available */ if (!check_for_xshm(dpy)) { printf("shared memory extension not available\n"); exit(0); } /* make shared XImage */ img = alloc_xshm_image( dpy, vis, width, height, depth); if (!img) { printf("couldn't allocate shared XImage\n"); exit(0); } /* Now you can render into the img->data buffer */ /* here's how to copy the shared XImage into a window */ XShmPutImage( dpy, window, gc, img, 0, 0, 0, 0, width, height, False ); /* Destroy image */ destroy_xshm_image( img ); }