aboutsummaryrefslogtreecommitdiff
path: root/shmximage.cpp
diff options
context:
space:
mode:
authorRaymaekers Luca <luca@spacehb.net>2025-10-10 11:11:52 +0200
committerRaymaekers Luca <luca@spacehb.net>2025-10-10 11:11:52 +0200
commit69e5b65c5f7ed956a5223085a654e23e79080c48 (patch)
treed51ebd7ac2cea6382f2d97b372407baea0a3024b /shmximage.cpp
checkpoint
Diffstat (limited to 'shmximage.cpp')
-rw-r--r--shmximage.cpp64
1 files changed, 64 insertions, 0 deletions
diff --git a/shmximage.cpp b/shmximage.cpp
new file mode 100644
index 0000000..ea60ab0
--- /dev/null
+++ b/shmximage.cpp
@@ -0,0 +1,64 @@
+static int shm_error;
+static int (*X_handler)(Display *, XErrorEvent *) = NULL;
+
+static bool have_mitshm(Display *dpy)
+{
+ // Only use shared memory on local X servers
+ return X11_XShmQueryExtension(dpy) ? SDL_X11_HAVE_SHM : false;
+}
+
+static int shm_errhandler(Display *d, XErrorEvent *e)
+{
+ if (e->error_code == BadAccess) {
+ shm_error = True;
+ return 0;
+ }
+ return X_handler(d, e);
+}
+
+
+{
+ if (have_mitshm(display)) {
+ XShmSegmentInfo shminfo;
+
+ shminfo.shmid = shmget(IPC_PRIVATE, (size_t)h * (*pitch), IPC_CREAT | 0777);
+ if (shminfo.shmid >= 0) {
+ shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0);
+ shminfo.readOnly = False;
+ if (shminfo.shmaddr != (char *)-1) {
+ shm_error = False;
+ X_handler = X11_XSetErrorHandler(shm_errhandler);
+ X11_XShmAttach(display, shminfo);
+ XSync(display, False);
+ X11_XSetErrorHandler(X_handler);
+ if (shm_error) {
+ shmdt(shminfo.shmaddr);
+ }
+ } else {
+ shm_error = True;
+ }
+ shmctl(shminfo.shmid, IPC_RMID, NULL);
+ } else {
+ shm_error = True;
+ }
+ if (!shm_error){
+ ximage = X11_XShmCreateImage(display, data->visual,
+ vinfo.depth, ZPixmap,
+ shminfo.shmaddr, shminfo,
+ w, h);
+ if (!ximage) {
+ X11_XShmDetach(display, shminfo);
+ X11_XSync(display, False);
+ shmdt(shminfo.shmaddr);
+ } else {
+ // Done!
+ ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? MSBFirst : LSBFirst;
+ *pixels = shminfo.shmaddr;
+ return true;
+ }
+ }
+ }
+}
+
+X11_XShmPutImage(display, data->xwindow, data->gc, data->ximage, x, y, x, y, w, h, False);
+