summaryrefslogtreecommitdiff
path: root/hw/kdrive
diff options
context:
space:
mode:
authorAlexander Volkov <a.volkov@rusbitech.ru>2018-01-31 15:36:36 +0300
committerAdam Jackson <ajax@redhat.com>2018-02-01 11:40:27 -0500
commit90996f5909aab4bc9aa4011a6a6d0555a7aa3adf (patch)
treea34b3d301206fa1a1f8ad49d4d51b4294d60cc33 /hw/kdrive
parent8a220bd83c3e23de7e07d3976bfc1248c38558d4 (diff)
Xephyr: Prefer using MIT-SHM FD-passing when possible
This makes the shared memory visible only for the Xephyr and the X server to which it is connected. Signed-off-by: Alexander Volkov <a.volkov@rusbitech.ru> Reviewed-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'hw/kdrive')
-rw-r--r--hw/kdrive/ephyr/ephyr.h1
-rw-r--r--hw/kdrive/ephyr/hostx.c109
2 files changed, 82 insertions, 28 deletions
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index d44dbc17e..fe01661dc 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -79,6 +79,7 @@ typedef struct _ephyrScrPriv {
const char *output; /* Set via -output option */
unsigned char *fb_data; /* only used when host bpp != server bpp */
xcb_shm_segment_info_t shminfo;
+ size_t shmsize;
KdScreenInfo *screen;
int mynum; /* Screen number */
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 04a8de0b1..23e1cd3bf 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -41,6 +41,7 @@
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/time.h>
+#include <sys/mman.h>
#include <X11/keysym.h>
#include <xcb/xcb.h>
@@ -75,6 +76,7 @@ struct EphyrHostXVars {
Bool use_sw_cursor;
Bool use_fullscreen;
Bool have_shm;
+ Bool have_shm_fd_passing;
int n_screens;
KdScreenInfo **screens;
@@ -417,29 +419,77 @@ hostx_set_title(char *title)
#pragma does_not_return(exit)
#endif
+static void
+hostx_init_shm(void)
+{
+ /* Try to get share memory ximages for a little bit more speed */
+ if (!hostx_has_extension(&xcb_shm_id) || getenv("XEPHYR_NO_SHM")) {
+ HostX.have_shm = FALSE;
+ } else {
+ xcb_generic_error_t *error = NULL;
+ xcb_shm_query_version_cookie_t cookie;
+ xcb_shm_query_version_reply_t *reply;
+
+ HostX.have_shm = TRUE;
+ HostX.have_shm_fd_passing = FALSE;
+ cookie = xcb_shm_query_version(HostX.conn);
+ reply = xcb_shm_query_version_reply(HostX.conn, cookie, &error);
+ if (reply) {
+ HostX.have_shm_fd_passing =
+ (reply->major_version == 1 && reply->minor_version >= 2) ||
+ reply->major_version > 1;
+ free(reply);
+ }
+ free(error);
+ }
+}
+
static Bool
hostx_create_shm_segment(xcb_shm_segment_info_t *shminfo, size_t size)
{
shminfo->shmaddr = NULL;
- shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0666);
- if (shminfo->shmid != -1) {
- shminfo->shmaddr = shmat(shminfo->shmid, 0, 0);
- if (shminfo->shmaddr == (void *)-1) {
- shminfo->shmaddr = NULL;
- } else {
- xcb_generic_error_t *error = NULL;
- xcb_void_cookie_t cookie;
- shmctl(shminfo->shmid, IPC_RMID, 0);
+ if (HostX.have_shm_fd_passing) {
+ xcb_generic_error_t *error = NULL;
+ xcb_shm_create_segment_cookie_t cookie;
+ xcb_shm_create_segment_reply_t *reply;
+
+ shminfo->shmseg = xcb_generate_id(HostX.conn);
+ cookie = xcb_shm_create_segment(HostX.conn, shminfo->shmseg, size, TRUE);
+ reply = xcb_shm_create_segment_reply(HostX.conn, cookie, &error);
+ if (!error && reply && reply->nfd == 1) {
+ int *fds = xcb_shm_create_segment_reply_fds(HostX.conn, reply);
+ if (fds) {
+ shminfo->shmaddr =
+ (uint8_t *)mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0], 0);
+ close(fds[0]);
+ if (shminfo->shmaddr == MAP_FAILED)
+ shminfo->shmaddr = NULL;
+ }
+ }
+ free(error);
+ free(reply);
+ } else {
+ shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0666);
+ if (shminfo->shmid != -1) {
+ shminfo->shmaddr = shmat(shminfo->shmid, 0, 0);
+ if (shminfo->shmaddr == (void *)-1) {
+ shminfo->shmaddr = NULL;
+ } else {
+ xcb_generic_error_t *error = NULL;
+ xcb_void_cookie_t cookie;
+
+ shmctl(shminfo->shmid, IPC_RMID, 0);
- shminfo->shmseg = xcb_generate_id(HostX.conn);
- cookie = xcb_shm_attach_checked(HostX.conn, shminfo->shmseg, shminfo->shmid, TRUE);
- error = xcb_request_check(HostX.conn, cookie);
+ shminfo->shmseg = xcb_generate_id(HostX.conn);
+ cookie = xcb_shm_attach_checked(HostX.conn, shminfo->shmseg, shminfo->shmid, TRUE);
+ error = xcb_request_check(HostX.conn, cookie);
- if (error) {
- free(error);
- shmdt(shminfo->shmaddr);
- shminfo->shmaddr = NULL;
+ if (error) {
+ free(error);
+ shmdt(shminfo->shmaddr);
+ shminfo->shmaddr = NULL;
+ }
}
}
}
@@ -448,10 +498,15 @@ hostx_create_shm_segment(xcb_shm_segment_info_t *shminfo, size_t size)
}
static void
-hostx_destroy_shm_segment(xcb_shm_segment_info_t *shminfo)
+hostx_destroy_shm_segment(xcb_shm_segment_info_t *shminfo, size_t size)
{
xcb_shm_detach(HostX.conn, shminfo->shmseg);
- shmdt(shminfo->shmaddr);
+
+ if (HostX.have_shm_fd_passing)
+ munmap(shminfo->shmaddr, size);
+ else
+ shmdt(shminfo->shmaddr);
+
shminfo->shmaddr = NULL;
}
@@ -676,21 +731,18 @@ hostx_init(void)
}
}
- /* Try to get share memory ximages for a little bit more speed */
- if (!hostx_has_extension(&xcb_shm_id) || getenv("XEPHYR_NO_SHM")) {
- fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
- HostX.have_shm = FALSE;
- }
- else {
+ hostx_init_shm();
+ if (HostX.have_shm) {
/* Really really check we have shm - better way ?*/
xcb_shm_segment_info_t shminfo;
- HostX.have_shm = TRUE;
if (!hostx_create_shm_segment(&shminfo, 1)) {
fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
HostX.have_shm = FALSE;
} else {
- hostx_destroy_shm_segment(&shminfo);
+ hostx_destroy_shm_segment(&shminfo, 1);
}
+ } else {
+ fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
}
xcb_flush(HostX.conn);
@@ -837,7 +889,7 @@ hostx_screen_init(KdScreenInfo *screen,
if (HostX.have_shm) {
xcb_shm_detach(HostX.conn, scrpriv->shminfo.shmseg);
xcb_image_destroy(scrpriv->ximg);
- hostx_destroy_shm_segment(&scrpriv->shminfo);
+ hostx_destroy_shm_segment(&scrpriv->shminfo, scrpriv->shmsize);
}
else {
free(scrpriv->ximg->data);
@@ -857,8 +909,9 @@ hostx_screen_init(KdScreenInfo *screen,
~0,
NULL);
+ scrpriv->shmsize = scrpriv->ximg->stride * buffer_height;
if (!hostx_create_shm_segment(&scrpriv->shminfo,
- scrpriv->ximg->stride * buffer_height)) {
+ scrpriv->shmsize)) {
EPHYR_DBG
("Can't create SHM Segment, falling back to plain XImages");
HostX.have_shm = FALSE;