[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