[cairo-commit] 6 commits - boilerplate/cairo-boilerplate-xcb.c

Uli Schlachter psychon at kemper.freedesktop.org
Wed Jan 5 13:15:46 PST 2011


 boilerplate/cairo-boilerplate-xcb.c |   88 ++++++++++++++++++++++++++----------
 1 file changed, 64 insertions(+), 24 deletions(-)

New commits:
commit a87001c0631da31f9caccdd99f31739c6e85a4e9
Author: Uli Schlachter <psychon at znc.in>
Date:   Tue Jan 4 12:39:12 2011 +0100

    xcb: Fix premature pixmap free in boilerplate cleanup
    
    A xcb surface has to be finished before the associated drawable can be freed or
    there will be X11 errors when the surface is later finished or used again.
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index e45a2dc..b1bf4de 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -91,6 +91,7 @@ _cairo_boilerplate_xcb_cleanup (void *closure)
     xcb_target_closure_t *xtc = closure;
     cairo_status_t status;
 
+    cairo_surface_finish (xtc->surface);
     if (xtc->is_pixmap)
 	xcb_free_pixmap (xtc->c, xtc->drawable);
     else
commit 673c44d3e85e31d6411598706dc025cd474b7dcf
Author: Uli Schlachter <psychon at znc.in>
Date:   Tue Jan 4 12:36:42 2011 +0100

    xcb: Check the check for errors in boilerplate
    
    We have to make sure we received all errors that the X server sent out before we
    can be sure there are none. To do so, we just have to send some request and wait
    for its reply, because that guarantees that the replies/errors to all previous
    requests were received.
    
    _cairo_boilerplate_xcb_synchronize doesn't need this, because the GetImage
    request already makes sure we received everything.
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index 67c8163..e45a2dc 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -79,6 +79,13 @@ _cairo_boilerplate_xcb_handle_errors (xcb_target_closure_t *xtc)
 }
 
 static void
+_cairo_boilerplate_xcb_sync_server (xcb_target_closure_t *xtc)
+{
+    free (xcb_get_input_focus_reply (xtc->c,
+				     xcb_get_input_focus (xtc->c), NULL));
+}
+
+static void
 _cairo_boilerplate_xcb_cleanup (void *closure)
 {
     xcb_target_closure_t *xtc = closure;
@@ -93,6 +100,9 @@ _cairo_boilerplate_xcb_cleanup (void *closure)
     cairo_device_finish (xtc->device);
     cairo_device_destroy (xtc->device);
 
+    /* First synchronize with the X server to make sure there are no more errors
+     * in-flight which we would miss otherwise */
+    _cairo_boilerplate_xcb_sync_server (xtc);
     status = _cairo_boilerplate_xcb_handle_errors (xtc);
     assert (status == CAIRO_STATUS_SUCCESS);
 
@@ -637,6 +647,9 @@ _cairo_boilerplate_xcb_finish_surface (cairo_surface_t *surface)
     if (cairo_surface_status (surface))
 	return cairo_surface_status (surface);
 
+    /* First synchronize with the X server to make sure there are no more errors
+     * in-flight which we would miss otherwise */
+    _cairo_boilerplate_xcb_sync_server (xtc);
     status = _cairo_boilerplate_xcb_handle_errors (xtc);
     if (status)
 	return status;
commit 51626ed2eed1abd7c540160988017c101da28952
Author: Uli Schlachter <psychon at znc.in>
Date:   Tue Jan 4 12:33:28 2011 +0100

    xcb: Check harder for X11 errors in boilerplate
    
    This commit makes the boilerplate code check for errors from the X server before
    disconnecting and during synchronize. This should make sure no errors are ever
    lost and silently ignored.
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index 149ee7b..67c8163 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -43,10 +43,46 @@ typedef struct _xcb_target_closure {
     cairo_surface_t *surface;
 } xcb_target_closure_t;
 
+static cairo_status_t
+_cairo_boilerplate_xcb_handle_errors (xcb_target_closure_t *xtc)
+{
+    xcb_generic_event_t *ev;
+
+    if ((ev = xcb_poll_for_event (xtc->c)) != NULL) {
+	if (ev->response_type == CAIRO_XCB_ERROR) {
+	    xcb_generic_error_t *error = (xcb_generic_error_t *) ev;
+
+#if XCB_GENERIC_ERROR_HAS_MAJOR_MINOR_CODES
+	    fprintf (stderr,
+		     "Detected error during xcb run: %d major=%d, minor=%d\n",
+		     error->error_code, error->major_code, error->minor_code);
+#else
+	    fprintf (stderr,
+		     "Detected error during xcb run: %d\n",
+		     error->error_code);
+#endif
+	} else {
+	    fprintf (stderr,
+		     "Detected unexpected event during xcb run: %d\n",
+		     ev->response_type);
+	}
+	free (ev);
+
+	/* Silently discard all following errors */
+	while ((ev = xcb_poll_for_event (xtc->c)) != NULL)
+	    free (ev);
+
+	return CAIRO_STATUS_WRITE_ERROR;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static void
 _cairo_boilerplate_xcb_cleanup (void *closure)
 {
     xcb_target_closure_t *xtc = closure;
+    cairo_status_t status;
 
     if (xtc->is_pixmap)
 	xcb_free_pixmap (xtc->c, xtc->drawable);
@@ -57,6 +93,9 @@ _cairo_boilerplate_xcb_cleanup (void *closure)
     cairo_device_finish (xtc->device);
     cairo_device_destroy (xtc->device);
 
+    status = _cairo_boilerplate_xcb_handle_errors (xtc);
+    assert (status == CAIRO_STATUS_SUCCESS);
+
     xcb_disconnect (xtc->c);
 
     free (xtc);
@@ -66,10 +105,14 @@ static void
 _cairo_boilerplate_xcb_synchronize (void *closure)
 {
     xcb_target_closure_t *xtc = closure;
+    cairo_status_t status;
     free (xcb_get_image_reply (xtc->c,
 		xcb_get_image (xtc->c, XCB_IMAGE_FORMAT_Z_PIXMAP,
 		    xtc->drawable, 0, 0, 1, 1, /* AllPlanes */ -1),
 		0));
+
+    status = _cairo_boilerplate_xcb_handle_errors (xtc);
+    assert (status == CAIRO_STATUS_SUCCESS);
 }
 
 static xcb_render_pictforminfo_t *
@@ -575,7 +618,7 @@ _cairo_boilerplate_xcb_finish_surface (cairo_surface_t *surface)
 {
     xcb_target_closure_t *xtc = cairo_surface_get_user_data (surface,
 							     &xcb_closure_key);
-    xcb_generic_event_t *ev;
+    cairo_status_t status;
 
     if (xtc->surface != NULL) {
 	cairo_t *cr;
@@ -594,32 +637,9 @@ _cairo_boilerplate_xcb_finish_surface (cairo_surface_t *surface)
     if (cairo_surface_status (surface))
 	return cairo_surface_status (surface);
 
-    if ((ev = xcb_poll_for_event (xtc->c)) != NULL) {
-	if (ev->response_type == CAIRO_XCB_ERROR) {
-	    xcb_generic_error_t *error = (xcb_generic_error_t *) ev;
-
-#if XCB_GENERIC_ERROR_HAS_MAJOR_MINOR_CODES
-	    fprintf (stderr,
-		     "Detected error during xcb run: %d major=%d, minor=%d\n",
-		     error->error_code, error->major_code, error->minor_code);
-#else
-	    fprintf (stderr,
-		     "Detected error during xcb run: %d\n",
-		     error->error_code);
-#endif
-	} else {
-	    fprintf (stderr,
-		     "Detected unexpected event during xcb run: %d\n",
-		     ev->response_type);
-	}
-	free (ev);
-
-	/* Silently discard all following errors */
-	while ((ev = xcb_poll_for_event (xtc->c)) != NULL)
-	    free (ev);
-
-	return CAIRO_STATUS_WRITE_ERROR;
-    }
+    status = _cairo_boilerplate_xcb_handle_errors (xtc);
+    if (status)
+	return status;
 
     if (xcb_connection_has_error (xtc->c))
 	return CAIRO_STATUS_WRITE_ERROR;
commit f8277dfdaf60ebb1d6c60780cff559497780b5b6
Author: Uli Schlachter <psychon at znc.in>
Date:   Tue Jan 4 13:05:03 2011 +0100

    xcb: Only print the first error and ignore subsequent ones
    
    It is quite likely that following errors are caused by the previous ones. To
    avoid flooding users we now silently discard all the errors and events after the
    first one.
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index dee0eab..149ee7b 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -594,7 +594,7 @@ _cairo_boilerplate_xcb_finish_surface (cairo_surface_t *surface)
     if (cairo_surface_status (surface))
 	return cairo_surface_status (surface);
 
-    while ((ev = xcb_poll_for_event (xtc->c)) != NULL) {
+    if ((ev = xcb_poll_for_event (xtc->c)) != NULL) {
 	if (ev->response_type == CAIRO_XCB_ERROR) {
 	    xcb_generic_error_t *error = (xcb_generic_error_t *) ev;
 
@@ -614,6 +614,10 @@ _cairo_boilerplate_xcb_finish_surface (cairo_surface_t *surface)
 	}
 	free (ev);
 
+	/* Silently discard all following errors */
+	while ((ev = xcb_poll_for_event (xtc->c)) != NULL)
+	    free (ev);
+
 	return CAIRO_STATUS_WRITE_ERROR;
     }
 
commit 8a65279ee1a5b7170bad552691ce5f96ef6cd8bd
Author: Uli Schlachter <psychon at znc.in>
Date:   Tue Jan 4 12:29:11 2011 +0100

    xcb: Add a define for some magic number
    
    In X11, errors look like events with response_type == 0. Using a define looks
    better than just a "trust me!".
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index aebb487..dee0eab 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -30,6 +30,9 @@
 
 #include <assert.h>
 
+/* Errors have response_type == 0 */
+#define CAIRO_XCB_ERROR 0
+
 static const cairo_user_data_key_t xcb_closure_key;
 
 typedef struct _xcb_target_closure {
@@ -592,7 +595,7 @@ _cairo_boilerplate_xcb_finish_surface (cairo_surface_t *surface)
 	return cairo_surface_status (surface);
 
     while ((ev = xcb_poll_for_event (xtc->c)) != NULL) {
-	if (ev->response_type == 0 /* trust me! */) {
+	if (ev->response_type == CAIRO_XCB_ERROR) {
 	    xcb_generic_error_t *error = (xcb_generic_error_t *) ev;
 
 #if XCB_GENERIC_ERROR_HAS_MAJOR_MINOR_CODES
commit 8957e506321c4dc1ca59c8a88012801509b0d338
Author: Uli Schlachter <psychon at znc.in>
Date:   Tue Jan 4 12:27:33 2011 +0100

    xcb: Handle events in boilerplate
    
    Cairo shouldn't cause any events during a test run. Verify this by explicitly
    handling events, too.
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index c3b059c..aebb487 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -592,8 +592,6 @@ _cairo_boilerplate_xcb_finish_surface (cairo_surface_t *surface)
 	return cairo_surface_status (surface);
 
     while ((ev = xcb_poll_for_event (xtc->c)) != NULL) {
-	cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
 	if (ev->response_type == 0 /* trust me! */) {
 	    xcb_generic_error_t *error = (xcb_generic_error_t *) ev;
 
@@ -606,13 +604,14 @@ _cairo_boilerplate_xcb_finish_surface (cairo_surface_t *surface)
 		     "Detected error during xcb run: %d\n",
 		     error->error_code);
 #endif
-	    free (error);
-
-	    status = CAIRO_STATUS_WRITE_ERROR;
+	} else {
+	    fprintf (stderr,
+		     "Detected unexpected event during xcb run: %d\n",
+		     ev->response_type);
 	}
+	free (ev);
 
-	if (status)
-	    return status;
+	return CAIRO_STATUS_WRITE_ERROR;
     }
 
     if (xcb_connection_has_error (xtc->c))


More information about the cairo-commit mailing list