diff options
author | Alexander Larsson <alexl@redhat.com> | 2010-04-21 12:37:38 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2010-04-23 16:36:35 +0200 |
commit | 4200c66cd7012287f03f1f5314cafae6e2a46027 (patch) | |
tree | 2d75954a1a90b519d8ebc56cb4500143f48f062b /client/x11 | |
parent | ecc51c6478f7bd379598021c2507f5cf13b21366 (diff) | |
download | spice-4200c66cd7012287f03f1f5314cafae6e2a46027.tar.gz spice-4200c66cd7012287f03f1f5314cafae6e2a46027.tar.xz spice-4200c66cd7012287f03f1f5314cafae6e2a46027.zip |
Add utility functions to create XShm images
Diffstat (limited to 'client/x11')
-rw-r--r-- | client/x11/platform.cpp | 77 | ||||
-rw-r--r-- | client/x11/x_platform.h | 6 |
2 files changed, 83 insertions, 0 deletions
diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp index 5f6c1fed..bda5e87d 100644 --- a/client/x11/platform.cpp +++ b/client/x11/platform.cpp @@ -39,6 +39,7 @@ #include <values.h> #include <signal.h> #include <config.h> +#include <sys/shm.h> #include "platform.h" #include "application.h" @@ -198,6 +199,82 @@ bool XPlatform::is_x_shm_avail() return x_shm_avail; } +XImage *XPlatform::create_x_shm_image(RedDrawable::Format format, + int width, int height, int depth, + Visual *visual, + XShmSegmentInfo **shminfo_out) +{ + XImage *image; + XShmSegmentInfo *shminfo; + + shminfo = new XShmSegmentInfo; + shminfo->shmid = -1; + shminfo->shmaddr = NULL; + + image = XShmCreateImage(XPlatform::get_display(), + format == RedDrawable::A1 ? NULL : visual, + format == RedDrawable::A1 ? 1 : depth, + format == RedDrawable::A1 ? XYBitmap : ZPixmap, + NULL, shminfo, width, height); + if (image == NULL) { + goto err1; + } + + shminfo->shmid = shmget(IPC_PRIVATE, height * image->bytes_per_line, + IPC_CREAT | 0777); + if (shminfo->shmid < 0) { + goto err2; + } + + shminfo->shmaddr = (char *)shmat(shminfo->shmid, 0, 0); + if (!shminfo->shmaddr) { + goto err2; + } + + shminfo->readOnly = False; + if (!XShmAttach(XPlatform::get_display(), shminfo)) { + goto err2; + } + + image->data = (char *)shminfo->shmaddr; + + *shminfo_out = shminfo; + return image; + +err2: + XDestroyImage(image); + if (shminfo->shmaddr != NULL) { + shmdt(shminfo->shmaddr); + } + if (shminfo->shmid != -1) { + shmctl(shminfo->shmid, IPC_RMID, 0); + } + +err1: + delete shminfo; + return NULL; +} + +void XPlatform::free_x_image(XImage *image, + XShmSegmentInfo *shminfo) +{ + char *data = image->data; + if (shminfo) { + XShmDetach(XPlatform::get_display(), shminfo); + } + if (image) { + XDestroyImage(image); + } + if (shminfo) { + XSync(XPlatform::get_display(), False); + shmdt(shminfo->shmaddr); + delete shminfo; + } else { + delete[] data; + } +} + + XVisualInfo** XPlatform::get_vinfo() { return vinfo; diff --git a/client/x11/x_platform.h b/client/x11/x_platform.h index 575ee2d4..c4f24259 100644 --- a/client/x11/x_platform.h +++ b/client/x11/x_platform.h @@ -37,6 +37,12 @@ public: static void on_focus_out(); static bool is_x_shm_avail(); + static XImage *create_x_shm_image(RedDrawable::Format format, + int width, int height, int depth, + Visual *visual, + XShmSegmentInfo **shminfo_out); + static void free_x_image(XImage *image, + XShmSegmentInfo *shminfo); }; #endif |