From: Daniel Stone <dani...@collabora.com> Adds support for multiple planes and buffer modifiers.
v4: Rename "has_dri3_v1_1" to "has_dri3_modifiers" --- src/vulkan/wsi/wsi_common_x11.c | 238 +++++++++++++++++++++++++++++++++------- 1 file changed, 199 insertions(+), 39 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index e48d746305..0417166409 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -36,6 +36,7 @@ #include <fcntl.h> #include <poll.h> #include <xf86drm.h> +#include <drm_fourcc.h> #include "util/hash_table.h" #include "vk_util.h" @@ -50,6 +51,7 @@ struct wsi_x11_connection { bool has_dri3; + bool has_dri3_modifiers; bool has_present; bool is_proprietary_x11; }; @@ -164,6 +166,19 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc, } wsi_conn->has_dri3 = dri3_reply->present != 0; +#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1 + if (wsi_conn->has_dri3) { + xcb_dri3_query_version_cookie_t ver_cookie; + xcb_dri3_query_version_reply_t *ver_reply; + + ver_cookie = xcb_dri3_query_version(conn, 1, 1); + ver_reply = xcb_dri3_query_version_reply(conn, ver_cookie, NULL); + wsi_conn->has_dri3_v1_1 = + (ver_reply->major_version > 1 || ver_reply->minor_version >= 1); + free(ver_reply); + } +#endif + wsi_conn->has_present = pres_reply->present != 0; wsi_conn->is_proprietary_x11 = false; if (amd_reply && amd_reply->present) @@ -626,6 +641,8 @@ struct x11_image { struct x11_swapchain { struct wsi_swapchain base; + bool has_dri3_modifiers; + xcb_connection_t * conn; xcb_window_t window; xcb_gc_t gc; @@ -679,7 +696,10 @@ x11_get_image_and_linear(struct wsi_swapchain *drv_chain, { struct x11_swapchain *chain = (struct x11_swapchain *)drv_chain; *image = chain->images[imageIndex].base.image; - *linear_image = chain->images[imageIndex].linear_base.image; + if (chain->images[imageIndex].base.linear_image != VK_NULL_HANDLE) + *linear_image = chain->images[imageIndex].base.linear_image; + else + *linear_image = chain->images[imageIndex].linear_base.image; } static VkResult @@ -954,56 +974,100 @@ static VkResult x11_image_init(VkDevice device_h, struct x11_swapchain *chain, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks* pAllocator, - struct x11_image *image) + uint64_t **modifiers, int *num_modifiers, + int num_tranches, struct x11_image *image) { xcb_void_cookie_t cookie; VkResult result; uint32_t bpp = 32; - - result = chain->base.image_fns->create_wsi_image(device_h, - pCreateInfo, - pAllocator, - !chain->base.needs_linear_copy, - false, - &image->base); - if (result != VK_SUCCESS) - return result; - - if (chain->base.needs_linear_copy) { + int i; + + image->linear_base.image = VK_NULL_HANDLE; + image->linear_base.memory = VK_NULL_HANDLE; + + if (chain->base.image_fns->create_wsi_image_with_modifiers) { + result = chain->base.image_fns->create_wsi_image_with_modifiers(device_h, + pCreateInfo, + pAllocator, + chain->base.needs_linear_copy, + modifiers, + num_modifiers, + num_tranches, + &image->base); + if (result != VK_SUCCESS) + return result; + } else { result = chain->base.image_fns->create_wsi_image(device_h, pCreateInfo, pAllocator, - true, - true, - &image->linear_base); - - if (result != VK_SUCCESS) { - chain->base.image_fns->free_wsi_image(device_h, pAllocator, - &image->base); + !chain->base.needs_linear_copy, + false, + &image->base); + if (result != VK_SUCCESS) return result; + + if (chain->base.needs_linear_copy) { + result = chain->base.image_fns->create_wsi_image(device_h, + pCreateInfo, + pAllocator, + true, + true, + &image->linear_base); + + if (result != VK_SUCCESS) { + chain->base.image_fns->free_wsi_image(device_h, pAllocator, + &image->base); + return result; + } } } image->pixmap = xcb_generate_id(chain->conn); - struct wsi_image_base *image_ws = - chain->base.needs_linear_copy ? &image->linear_base : &image->base; - - /* Without passing modifiers, we can't have multi-plane RGB images. */ - assert(image_ws->num_planes == 1); - - cookie = - xcb_dri3_pixmap_from_buffer_checked(chain->conn, - image->pixmap, - chain->window, - image_ws->sizes[0], - pCreateInfo->imageExtent.width, - pCreateInfo->imageExtent.height, - image_ws->row_pitches[0], - chain->depth, bpp, - image_ws->fds[0]); +#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1 + if (chain->has_dri3_modifiers && + image->base.drm_modifier != DRM_FORMAT_MOD_INVALID) { + cookie = + xcb_dri3_pixmap_from_buffers_checked(chain->conn, + image->pixmap, + chain->window, + image->base.num_planes, + pCreateInfo->imageExtent.width, + pCreateInfo->imageExtent.height, + image->base.row_pitches[0], + image->base.offsets[0], + image->base.row_pitches[1], + image->base.offsets[1], + image->base.row_pitches[2], + image->base.offsets[2], + image->base.row_pitches[3], + image->base.offsets[3], + chain->depth, bpp, + image->base.drm_modifier, + image->base.fds); + } else +#endif + { + /* Without passing modifiers, we can't have multi-plane RGB images. */ + assert(image->base.num_planes == 1); + + cookie = + xcb_dri3_pixmap_from_buffer_checked(chain->conn, + image->pixmap, + chain->window, + image->base.sizes[0], + pCreateInfo->imageExtent.width, + pCreateInfo->imageExtent.height, + image->base.row_pitches[0], + chain->depth, bpp, + image->base.fds[0]); + } + xcb_discard_reply(chain->conn, cookie.sequence); - image_ws->fds[0] = -1; /* XCB has now taken ownership of the FD */ + + /* XCB has now taken ownership of the FDs. */ + for (i = 0; i < image->base.num_planes; i++) + image->base.fds[i] = -1; int fence_fd = xshmfence_alloc_shm(); if (fence_fd < 0) @@ -1032,7 +1096,7 @@ fail_pixmap: cookie = xcb_free_pixmap(chain->conn, image->pixmap); xcb_discard_reply(chain->conn, cookie.sequence); - if (chain->base.needs_linear_copy) { + if (image->linear_base.image != VK_NULL_HANDLE) { chain->base.image_fns->free_wsi_image(device_h, pAllocator, &image->linear_base); } @@ -1055,7 +1119,7 @@ x11_image_finish(struct x11_swapchain *chain, cookie = xcb_free_pixmap(chain->conn, image->pixmap); xcb_discard_reply(chain->conn, cookie.sequence); - if (chain->base.needs_linear_copy) { + if (image->linear_base.image != VK_NULL_HANDLE) { chain->base.image_fns->free_wsi_image(chain->base.device, pAllocator, &image->linear_base); } @@ -1063,6 +1127,82 @@ x11_image_finish(struct x11_swapchain *chain, &image->base); } +static void +wsi_x11_get_dri3_modifiers(struct wsi_x11_connection *wsi_conn, + xcb_connection_t *conn, xcb_window_t window, + uint8_t depth, uint8_t bpp, + VkCompositeAlphaFlagsKHR vk_alpha, + uint64_t **modifiers_in, int *num_modifiers_in, + int *num_tranches_in, + const VkAllocationCallbacks *pAllocator) +{ +#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1 + if (!wsi_conn->has_dri3_modifiers) + goto out; + + xcb_generic_error_t *error = NULL; + xcb_dri3_get_supported_modifiers_cookie_t mod_cookie = + xcb_dri3_get_supported_modifiers(conn, window, depth, bpp); + xcb_dri3_get_supported_modifiers_reply_t *mod_reply = + xcb_dri3_get_supported_modifiers_reply(conn, mod_cookie, &error); + free(error); + + if (!mod_reply || (mod_reply->num_drawable_modifiers == 0 && + mod_reply->num_screen_modifiers == 0)) { + free(mod_reply); + goto out; + } + + uint32_t n = 0; + uint32_t counts[2]; + uint64_t *modifiers[2]; + + if (mod_reply->num_drawable_modifiers) { + counts[n] = mod_reply->num_drawable_modifiers; + modifiers[n] = vk_alloc(pAllocator, + counts[n] * sizeof(uint64_t), + 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!modifiers[n]) { + free(mod_reply); + goto out; + } + + memcpy(modifiers[n], + xcb_dri3_get_supported_modifiers_drawable_modifiers(mod_reply), + counts[n] * sizeof(uint64_t)); + n++; + } + + if (mod_reply->num_screen_modifiers) { + counts[n] = mod_reply->num_screen_modifiers; + modifiers[n] = vk_alloc(pAllocator, + counts[n] * sizeof(uint64_t), + 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!modifiers[n]) { + free(mod_reply); + goto out; + } + + memcpy(modifiers[n], + xcb_dri3_get_supported_modifiers_screen_modifiers(mod_reply), + counts[n] * sizeof(uint64_t)); + n++; + } + + for (int i = 0; i < n; i++) { + modifiers_in[i] = modifiers[i]; + num_modifiers_in[i] = counts[i]; + } + *num_tranches_in = n; + + free(mod_reply); + return; +#endif + +out: + *num_tranches_in = 0; +} + static VkResult x11_swapchain_destroy(struct wsi_swapchain *anv_chain, const VkAllocationCallbacks *pAllocator) @@ -1104,6 +1244,9 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, struct wsi_swapchain **swapchain_out) { struct x11_swapchain *chain; + uint64_t *modifiers[2] = {NULL, NULL}; + int num_modifiers[2] = {0, 0}; + int num_tranches = 0; xcb_void_cookie_t cookie; VkResult result; @@ -1145,10 +1288,21 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, free(geometry); + struct wsi_x11_connection *wsi_conn = + wsi_x11_get_connection(wsi_device, pAllocator, conn); + if (!wsi_conn) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + chain->has_dri3_modifiers = wsi_conn->has_dri3_modifiers; + chain->base.needs_linear_copy = false; if (!wsi_x11_check_dri3_compatible(conn, local_fd)) chain->base.needs_linear_copy = true; + wsi_x11_get_dri3_modifiers(wsi_conn, conn, window, chain->depth, 32, + pCreateInfo->compositeAlpha, + modifiers, num_modifiers, &num_tranches, pAllocator); + chain->event_id = xcb_generate_id(chain->conn); xcb_present_select_input(chain->conn, chain->event_id, chain->window, XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY | @@ -1179,6 +1333,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, uint32_t image = 0; for (; image < chain->base.image_count; image++) { result = x11_image_init(device, chain, pCreateInfo, pAllocator, + modifiers, num_modifiers, num_tranches, &chain->images[image]); if (result != VK_SUCCESS) goto fail_init_images; @@ -1215,6 +1370,8 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, } } + for (int i = 0; i < 2; i++) + vk_free(pAllocator, modifiers[i]); *swapchain_out = &chain->base; return VK_SUCCESS; @@ -1224,6 +1381,9 @@ fail_init_images: x11_image_finish(chain, pAllocator, &chain->images[j]); fail_register: + for (int i = 0; i < 2; i++) + vk_free(pAllocator, modifiers[i]); + xcb_unregister_for_special_event(chain->conn, chain->special_event); vk_free(pAllocator, chain); -- 2.13.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev