From 5acc4e2ebfe0e482d4f612c440877601c54c8b05 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Sat, 30 Jan 2016 03:49:10 -0800 Subject: [PATCH] anv/wsi/x11: Actually pull information from the window's visual --- src/vulkan/anv_wsi_x11.c | 150 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 143 insertions(+), 7 deletions(-) diff --git a/src/vulkan/anv_wsi_x11.c b/src/vulkan/anv_wsi_x11.c index c9e61fc4cdd..ac24d927dd1 100644 --- a/src/vulkan/anv_wsi_x11.c +++ b/src/vulkan/anv_wsi_x11.c @@ -118,12 +118,115 @@ wsi_x11_get_connection(struct anv_instance *instance, xcb_connection_t *conn) static const VkSurfaceFormatKHR formats[] = { { .format = VK_FORMAT_B8G8R8A8_UNORM, }, + { .format = VK_FORMAT_B8G8R8_UNORM, }, }; static const VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, }; +static xcb_screen_t * +get_screen_for_root(xcb_connection_t *conn, xcb_window_t root) +{ + xcb_screen_iterator_t screen_iter = + xcb_setup_roots_iterator(xcb_get_setup(conn)); + + for (; screen_iter.rem; xcb_screen_next (&screen_iter)) { + if (screen_iter.data->root == root) + return screen_iter.data; + } + + return NULL; +} + +static xcb_visualtype_t * +screen_get_visualtype(xcb_screen_t *screen, xcb_visualid_t visual_id, + unsigned *depth) +{ + xcb_depth_iterator_t depth_iter = + xcb_screen_allowed_depths_iterator(screen); + + for (; depth_iter.rem; xcb_depth_next (&depth_iter)) { + xcb_visualtype_iterator_t visual_iter = + xcb_depth_visuals_iterator (depth_iter.data); + + for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) { + if (visual_iter.data->visual_id == visual_id) { + if (depth) + *depth = depth_iter.data->depth; + return visual_iter.data; + } + } + } + + return NULL; +} + +static xcb_visualtype_t * +connection_get_visualtype(xcb_connection_t *conn, xcb_visualid_t visual_id, + unsigned *depth) +{ + xcb_screen_iterator_t screen_iter = + xcb_setup_roots_iterator(xcb_get_setup(conn)); + + /* For this we have to iterate over all of the screens which is rather + * annoying. Fortunately, there is probably only 1. + */ + for (; screen_iter.rem; xcb_screen_next (&screen_iter)) { + xcb_visualtype_t *visual = screen_get_visualtype(screen_iter.data, + visual_id, depth); + if (visual) + return visual; + } + + return NULL; +} + +static xcb_visualtype_t * +get_visualtype_for_window(xcb_connection_t *conn, xcb_window_t window, + unsigned *depth) +{ + xcb_query_tree_cookie_t tree_cookie; + xcb_get_window_attributes_cookie_t attrib_cookie; + xcb_query_tree_reply_t *tree; + xcb_get_window_attributes_reply_t *attrib; + + tree_cookie = xcb_query_tree(conn, window); + attrib_cookie = xcb_get_window_attributes(conn, window); + + tree = xcb_query_tree_reply(conn, tree_cookie, NULL); + attrib = xcb_get_window_attributes_reply(conn, attrib_cookie, NULL); + if (attrib == NULL || tree == NULL) { + free(attrib); + free(tree); + return NULL; + } + + xcb_window_t root = tree->root; + xcb_visualid_t visual_id = attrib->visual; + free(attrib); + free(tree); + + xcb_screen_t *screen = get_screen_for_root(conn, root); + if (screen == NULL) + return NULL; + + return screen_get_visualtype(screen, visual_id, depth); +} + +static bool +visual_has_alpha(xcb_visualtype_t *visual, unsigned depth) +{ + uint32_t rgb_mask = visual->red_mask | + visual->green_mask | + visual->blue_mask; + + uint32_t all_mask = 0xffffffff >> (32 - depth); + + /* Do we have bits left over after RGB? */ + return (all_mask & ~rgb_mask) != 0; +} + VkBool32 anv_GetPhysicalDeviceXcbPresentationSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, @@ -140,7 +243,12 @@ VkBool32 anv_GetPhysicalDeviceXcbPresentationSupportKHR( return false; } - anv_finishme("Check visuals"); + unsigned visual_depth; + if (!connection_get_visualtype(connection, visual_id, &visual_depth)) + return false; + + if (visual_depth != 24 && visual_depth != 32) + return false; return true; } @@ -164,6 +272,18 @@ x11_surface_get_support(VkIcdSurfaceBase *icd_surface, return VK_SUCCESS; } + unsigned visual_depth; + if (!get_visualtype_for_window(surface->connection, surface->window, + &visual_depth)) { + *pSupported = false; + return VK_SUCCESS; + } + + if (visual_depth != 24 && visual_depth != 32) { + *pSupported = false; + return VK_SUCCESS; + } + *pSupported = true; return VK_SUCCESS; } @@ -174,12 +294,21 @@ x11_surface_get_capabilities(VkIcdSurfaceBase *icd_surface, VkSurfaceCapabilitiesKHR *caps) { VkIcdSurfaceXcb *surface = (VkIcdSurfaceXcb *)icd_surface; - - xcb_get_geometry_cookie_t cookie = xcb_get_geometry(surface->connection, - surface->window); + xcb_get_geometry_cookie_t geom_cookie; xcb_generic_error_t *err; - xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(surface->connection, - cookie, &err); + xcb_get_geometry_reply_t *geom; + unsigned visual_depth; + + geom_cookie = xcb_get_geometry(surface->connection, surface->window); + + /* This does a round-trip. This is why we do get_geometry first and + * wait to read the reply until after we have a visual. + */ + xcb_visualtype_t *visual = + get_visualtype_for_window(surface->connection, surface->window, + &visual_depth); + + geom = xcb_get_geometry_reply(surface->connection, geom_cookie, &err); if (geom) { VkExtent2D extent = { geom->width, geom->height }; caps->currentExtent = extent; @@ -197,12 +326,19 @@ x11_surface_get_capabilities(VkIcdSurfaceBase *icd_surface, free(err); free(geom); + if (visual_has_alpha(visual, visual_depth)) { + caps->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; + } else { + caps->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + } + caps->minImageCount = 2; caps->maxImageCount = 4; caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; caps->maxImageArrayLayers = 1; - caps->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; caps->supportedUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | -- 2.30.2