[cairo-commit] 2 commits - src/cairo-xlib-display.c src/cairo-xlib-private.h src/cairo-xlib-surface-shm.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Oct 26 03:33:37 PDT 2012


 src/cairo-xlib-display.c     |    2 -
 src/cairo-xlib-private.h     |    7 +++
 src/cairo-xlib-surface-shm.c |   77 ++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 77 insertions(+), 9 deletions(-)

New commits:
commit fdd2082f923012a1354be7086d03f78fb166695b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 26 10:51:31 2012 +0100

    xlib: Check for both X.org and Xorg ServerVendors
    
    Martin Husemann reported that on his NetBSD machine the vendor was being
    reported as "The Xorg Foundation", a non-conformist separatist split of
    the Peoples' Liberation Army^W^W^W "The X.Org Foundation". Simply check
    for both during initialisation.
    
    Reported-by: Martin Husemann <martin at duskware.de>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index 67c0673..04c89b2 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -315,7 +315,7 @@ _cairo_xlib_device_create (Display *dpy)
      *    safest to just blacklist all old-versioning-scheme X servers,
      *    (just using VendorRelease < 70000000), as buggy_repeat=TRUE.
      */
-    if (strstr (ServerVendor (dpy), "X.Org") != NULL) {
+    if (_cairo_xlib_vendor_is_xorg (dpy)) {
 	if (VendorRelease (dpy) >= 60700000) {
 	    if (VendorRelease (dpy) < 70000000)
 		display->buggy_repeat = TRUE;
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index d2bd588..c328302 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -216,6 +216,13 @@ struct _cairo_xlib_proxy {
     cairo_surface_t *owner;
 };
 
+inline static cairo_bool_t
+_cairo_xlib_vendor_is_xorg (Display *dpy)
+{
+    const char *const vendor = ServerVendor (dpy);
+    return strstr (vendor, "X.Org") || strstr (vendor, "Xorg");
+}
+
 cairo_private cairo_status_t
 _cairo_xlib_surface_get_gc (cairo_xlib_display_t *display,
                             cairo_xlib_surface_t *surface,
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index 17594b1..89f51a9 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -1193,7 +1193,7 @@ xorg_has_buggy_send_shm_completion_event(cairo_xlib_display_t *display,
      *
      * Remove the SendEvent bit (0x80) before doing range checks on event type.
      */
-    if (strstr (ServerVendor (dpy), "X.Org") != NULL &&
+    if (_cairo_xlib_vendor_is_xorg (dpy) &&
 	VendorRelease (dpy) < XORG_VERSION_ENCODE(1,11,0,1))
 	return TRUE;
 
commit 00feb8ce530a472abbde445b52d9ae8c99ec97f0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 26 10:51:31 2012 +0100

    xlib/shm: Sanity check that the server handles XSendEvent with ShmCompletion
    
    Uli Schlachter suggested it would be wiser to complement our blacklist
    of known broken X/libXext with an explicit roundtrip to check for a
    BadValue error return when we try to use XSendEvent.
    
    Suggested-by: Uli Schlachter <psychon at znc.in>
    Reported-by: Martin Husemann <martin at duskware.de>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index ec0d334..17594b1 100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -1128,8 +1128,60 @@ _cairo_xlib_shm_surface_is_idle (cairo_surface_t *surface)
     (((major) * 10000000) + ((minor) * 100000) + ((patch) * 1000) + snap)
 
 static cairo_bool_t
-xorg_has_buggy_send_shm_completion_event(Display *dpy)
+has_broken_send_shm_event (cairo_xlib_display_t *display,
+			   cairo_xlib_shm_display_t *shm)
 {
+    Display *dpy = display->display;
+    int (*old_handler) (Display *display, XErrorEvent *event);
+    XShmCompletionEvent ev;
+    XShmSegmentInfo info;
+
+    info.shmid = shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
+    if (info.shmid == -1)
+	return TRUE;
+
+    info.readOnly = FALSE;
+    info.shmaddr = shmat (info.shmid, NULL, 0);
+    if (info.shmaddr == (char *) -1) {
+	shmctl (info.shmid, IPC_RMID, NULL);
+	return TRUE;
+    }
+
+    ev.type = shm->event;
+    ev.drawable = shm->window;
+    ev.major_code = shm->opcode;
+    ev.minor_code = X_ShmPutImage;
+
+    ev.shmseg = info.shmid;
+    ev.offset = 0;
+
+    assert (CAIRO_MUTEX_IS_LOCKED (_cairo_xlib_display_mutex));
+    _x_error_occurred = FALSE;
+
+    XLockDisplay (dpy);
+    XSync (dpy, False);
+    old_handler = XSetErrorHandler (_check_error_handler);
+
+    XShmAttach (dpy, &info);
+    XSendEvent (dpy, ev.drawable, False, 0, (XEvent *)&ev);
+    XShmDetach (dpy, &info);
+
+    XSync (dpy, False);
+    XSetErrorHandler (old_handler);
+    XUnlockDisplay (dpy);
+
+    shmctl (info.shmid, IPC_RMID, NULL);
+    shmdt (info.shmaddr);
+
+    return _x_error_occurred;
+}
+
+static cairo_bool_t
+xorg_has_buggy_send_shm_completion_event(cairo_xlib_display_t *display,
+					 cairo_xlib_shm_display_t *shm)
+{
+    Display *dpy = display->display;
+
     /* As libXext sets the SEND_EVENT bit in the ShmCompletionEvent,
      * the Xserver may crash if it does not take care when processing
      * the event type. For instance versions of Xorg prior to 1.11.1
@@ -1141,8 +1193,12 @@ xorg_has_buggy_send_shm_completion_event(Display *dpy)
      *
      * Remove the SendEvent bit (0x80) before doing range checks on event type.
      */
-    return (strstr (ServerVendor (dpy), "X.Org") != NULL &&
-	    VendorRelease (dpy) < XORG_VERSION_ENCODE(1,11,0,1));
+    if (strstr (ServerVendor (dpy), "X.Org") != NULL &&
+	VendorRelease (dpy) < XORG_VERSION_ENCODE(1,11,0,1))
+	return TRUE;
+
+    /* For everyone else check that no error is generated */
+    return has_broken_send_shm_event (display, shm);
 }
 
 void
@@ -1162,6 +1218,15 @@ _cairo_xlib_display_init_shm (cairo_xlib_display_t *display)
     if (unlikely (shm == NULL))
 	return;
 
+    codes = XInitExtension (display->display, SHMNAME);
+    if (codes == NULL) {
+	free (shm);
+	return;
+    }
+
+    shm->opcode = codes ->major_opcode;
+    shm->event = codes->first_event;
+
     if (unlikely (_pqueue_init (&shm->info))) {
 	free (shm);
 	return;
@@ -1177,16 +1242,12 @@ _cairo_xlib_display_init_shm (cairo_xlib_display_t *display)
 				 DefaultVisual (display->display, scr),
 				 CWOverrideRedirect, &attr);
 
-    if (xorg_has_buggy_send_shm_completion_event(display->display))
+    if (xorg_has_buggy_send_shm_completion_event(display, shm))
 	has_pixmap = 0;
 
     shm->has_pixmaps = has_pixmap ? MIN_PIXMAP_SIZE : 0;
     cairo_list_init (&shm->pool);
 
-    codes = XInitExtension (display->display, SHMNAME);
-    shm->opcode = codes ->major_opcode;
-    shm->event = codes->first_event;
-
     cairo_list_init (&shm->surfaces);
 
     display->shm = shm;


More information about the cairo-commit mailing list