summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2010-04-21 12:37:38 +0200
committerAlexander Larsson <alexl@redhat.com>2010-04-23 16:36:35 +0200
commit4200c66cd7012287f03f1f5314cafae6e2a46027 (patch)
tree2d75954a1a90b519d8ebc56cb4500143f48f062b /client
parentecc51c6478f7bd379598021c2507f5cf13b21366 (diff)
downloadspice-4200c66cd7012287f03f1f5314cafae6e2a46027.tar.gz
spice-4200c66cd7012287f03f1f5314cafae6e2a46027.tar.xz
spice-4200c66cd7012287f03f1f5314cafae6e2a46027.zip
Add utility functions to create XShm images
Diffstat (limited to 'client')
-rw-r--r--client/x11/platform.cpp77
-rw-r--r--client/x11/x_platform.h6
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