From b47209a03feeed2172f35a6d79ba1176fedd5e17 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 6 Dec 2014 16:04:46 +0100 Subject: [PATCH] xcb: Query the display's subpixel order via RENDER 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 --- 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 2d51e1449..67897fa4e 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 1e1d1ee70..214fa458b 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 62c27efc7..1877758c2 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 69ea4599b..d0019f9cd 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->root == xcb_screen->root) + 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));