[cairo] [PATCH] xcb: Query the display's subpixel order via RENDER

Uli Schlachter psychon at znc.in
Sat Dec 6 07:13:13 PST 2014


With commit e691d242, the xcb backend started parsing the resources, just like
cairo-xlib does. One behavior from cairo-xlib was missing: If no Xft.rgba
property was specified, cairo-xlib defaults to the screen's subpixel order.
This commit brings that last bit of functionality to cairo-xcb (but currently
disabled due to commit e0c0a673).

This commits adds a new array to cairo_xcb_connection_t that contains the
subpixel order for each screen. There is also a new member in cairo_xcb_screen_t
which contains the subpixel order of that screen and which is initialized from
the array when the screen is constructed. With this in place, the
resource-parsing code can just pick the subpixel order from the screen if
needed.

Signed-off-by: Uli Schlachter <psychon at znc.in>
---
 src/cairo-xcb-connection.c | 19 +++++++++++++++++++
 src/cairo-xcb-private.h    |  4 +++-
 src/cairo-xcb-resources.c  | 33 +++++----------------------------
 src/cairo-xcb-screen.c     | 16 ++++++++++++++++
 4 files changed, 43 insertions(+), 29 deletions(-)

diff --git a/src/cairo-xcb-connection.c b/src/cairo-xcb-connection.c
index 2d51e14..67897fa 100644
--- a/src/cairo-xcb-connection.c
+++ b/src/cairo-xcb-connection.c
@@ -79,6 +79,7 @@ typedef struct _cairo_xcb_xid {
 #define XCB_RENDER_HAS_FILTERS(surface)			XCB_RENDER_AT_LEAST((surface), 0, 6)
 #define XCB_RENDER_HAS_FILTER_GOOD(surface) FALSE
 #define XCB_RENDER_HAS_FILTER_BEST(surface) FALSE
+#define XCB_RENDER_HAS_SUBPIXEL_ORDER(surface)		XCB_RENDER_AT_LEAST((surface), 0, 6)
 
 #define XCB_RENDER_HAS_EXTENDED_REPEAT(surface)	XCB_RENDER_AT_LEAST((surface), 0, 10)
 #define XCB_RENDER_HAS_GRADIENTS(surface)	XCB_RENDER_AT_LEAST((surface), 0, 10)
@@ -407,6 +408,15 @@ _cairo_xcb_connection_query_render (cairo_xcb_connection_t *connection)
     if (XCB_RENDER_HAS_GRADIENTS (version))
 	connection->flags |= CAIRO_XCB_RENDER_HAS_GRADIENTS;
 
+    if (XCB_RENDER_HAS_SUBPIXEL_ORDER (version)) {
+	uint32_t screen;
+	uint32_t *subpixel = xcb_render_query_pict_formats_subpixels(formats);
+
+	/* The spec explicitly allows to have too few entries in the reply... */
+	for (screen = 0; screen < formats->num_subpixel && screen < connection->root->roots_len; screen++)
+	    connection->subpixel_orders[screen] = subpixel[screen];
+    }
+
     free (version);
 
     status = _cairo_xcb_connection_parse_xrender_formats (connection, formats);
@@ -581,6 +591,7 @@ _device_destroy (void *device)
     CAIRO_MUTEX_FINI (connection->shm_mutex);
     CAIRO_MUTEX_FINI (connection->screens_mutex);
 
+    free (connection->subpixel_orders);
     free (connection);
 }
 
@@ -684,6 +695,14 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection)
 
     connection->root = xcb_get_setup (xcb_connection);
     connection->render = NULL;
+    connection->subpixel_orders = calloc (connection->root->roots_len, sizeof(*connection->subpixel_orders));
+    if (unlikely (connection->subpixel_orders == NULL)) {
+	CAIRO_MUTEX_UNLOCK (connection->device.mutex);
+	_cairo_xcb_connection_destroy (connection);
+	connection = NULL;
+	goto unlock;
+    }
+
     ext = xcb_get_extension_data (xcb_connection, &xcb_render_id);
     if (ext != NULL && ext->present) {
 	status = _cairo_xcb_connection_query_render (connection);
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h
index 1e1d1ee..214fa45 100644
--- a/src/cairo-xcb-private.h
+++ b/src/cairo-xcb-private.h
@@ -181,7 +181,8 @@ struct _cairo_xcb_font {
 struct _cairo_xcb_screen {
     cairo_xcb_connection_t *connection;
 
-    xcb_screen_t	    *xcb_screen;
+    xcb_screen_t	   *xcb_screen;
+    xcb_render_sub_pixel_t  subpixel_order;
 
     xcb_gcontext_t gc[GC_CACHE_SIZE];
     uint8_t gc_depths[GC_CACHE_SIZE];
@@ -223,6 +224,7 @@ struct _cairo_xcb_connection {
     const xcb_setup_t *root;
     const xcb_query_extension_reply_t *render;
     const xcb_query_extension_reply_t *shm;
+    xcb_render_sub_pixel_t *subpixel_orders;
 
     cairo_list_t free_xids;
     cairo_freepool_t xid_pool;
diff --git a/src/cairo-xcb-resources.c b/src/cairo-xcb-resources.c
index 62c27ef..1877758 100644
--- a/src/cairo-xcb-resources.c
+++ b/src/cairo-xcb-resources.c
@@ -251,21 +251,13 @@ get_resources(xcb_connection_t *connection, xcb_screen_t *screen, cairo_xcb_reso
     resource_parser_done (&parser);
 }
 
-#if 0 && XCB_RENDER_MAJOR_VERSION > 99 && XCB_RENDER_MINOR_VERSION > 99
-static void
-get_rgba_from_render (xcb_connection_t *connection, xcb_screen_t *screen, cairo_xcb_resources_t *resources)
+void
+_cairo_xcb_resources_get (cairo_xcb_screen_t *screen, cairo_xcb_resources_t *resources)
 {
-    /* this is a mock-up of what the function might look like,
-       xcb_render_query_sub_pixel is not actually implemented in XCB (yet) */
-
-    xcb_render_query_sub_pixel_order_cookie_t cookie;
-    xcb_render_query_sub_pixel_order_reply_t *reply;
-
-    cookie = xcb_render_query_sub_pixel (connection, screen);
-    reply = xcb_render_query_sub_pixel_reply (connection, cookie, NULL);
+    get_resources (screen->connection->xcb_connection, screen->xcb_screen, resources);
 
-    if (reply) {
-	switch (reply->sub_pixel_order) {
+    if (resources->xft_rgba == FC_RGBA_UNKNOWN) {
+	switch (screen->subpixel_order) {
 	case XCB_RENDER_SUB_PIXEL_UNKNOWN:
 	    resources->xft_rgba = FC_RGBA_UNKNOWN;
 	    break;
@@ -285,20 +277,5 @@ get_rgba_from_render (xcb_connection_t *connection, xcb_screen_t *screen, cairo_
 	    resources->xft_rgba = FC_RGBA_NONE;
 	    break;
 	}
-
-	free(reply);
     }
 }
-#endif
-
-void
-_cairo_xcb_resources_get (cairo_xcb_screen_t *screen, cairo_xcb_resources_t *resources)
-{
-    get_resources (screen->connection->xcb_connection, screen->xcb_screen, resources);
-
-#if 0 && XCB_RENDER_MAJOR_VERSION > 99 && XCB_RENDER_MINOR_VERSION > 99
-    if (resources->xft_rgba == FC_RGBA_UNKNOWN) {
-	get_rgba_from_render (screen->connection->xcb_connection, screen->xcb_screen, resources);
-    }
-#endif
-}
diff --git a/src/cairo-xcb-screen.c b/src/cairo-xcb-screen.c
index 69ea459..3874965 100644
--- a/src/cairo-xcb-screen.c
+++ b/src/cairo-xcb-screen.c
@@ -207,6 +207,18 @@ _pattern_cache_entry_destroy (void *closure)
     _cairo_freelist_free (&entry->screen->pattern_cache_entry_freelist, entry);
 }
 
+static int _get_screen_index(cairo_xcb_connection_t *xcb_connection,
+			     xcb_screen_t *xcb_screen)
+{
+    int idx = 0;
+    xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_connection->root);
+    for (; iter.rem; xcb_screen_next(&iter), idx++)
+	if (iter.data == xcb_screen)
+	    return idx;
+
+    ASSERT_NOT_REACHED;
+}
+
 cairo_xcb_screen_t *
 _cairo_xcb_screen_get (xcb_connection_t *xcb_connection,
 		       xcb_screen_t *xcb_screen)
@@ -214,6 +226,7 @@ _cairo_xcb_screen_get (xcb_connection_t *xcb_connection,
     cairo_xcb_connection_t *connection;
     cairo_xcb_screen_t *screen;
     cairo_status_t status;
+    int screen_idx;
     int i;
 
     connection = _cairo_xcb_connection_get (xcb_connection);
@@ -240,9 +253,12 @@ _cairo_xcb_screen_get (xcb_connection_t *xcb_connection,
     if (unlikely (screen == NULL))
 	goto unlock;
 
+    screen_idx = _get_screen_index(connection, xcb_screen);
+
     screen->connection = connection;
     screen->xcb_screen = xcb_screen;
     screen->has_font_options = FALSE;
+    screen->subpixel_order = connection->subpixel_orders[screen_idx];
 
     _cairo_freelist_init (&screen->pattern_cache_entry_freelist,
 			  sizeof (struct pattern_cache_entry));
-- 
2.1.3



More information about the cairo mailing list