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

Uli Schlachter <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
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 <[email protected]>
---
 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

-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.