On Wed, Feb 21, 2018 at 1:22 PM, Jason Ekstrand <ja...@jlekstrand.net> wrote:
> On Wed, Feb 21, 2018 at 6:05 AM, Daniel Stone <dani...@collabora.com> > wrote: > >> Adds support for multiple planes and buffer modifiers. >> >> v4: Rename "has_dri3_v1_1" to "has_dri3_modifiers" >> Signed-off-by: Daniel Stone <dani...@collabora.com> >> --- >> src/vulkan/wsi/wsi_common_x11.c | 185 ++++++++++++++++++++++++++++++ >> ++++++---- >> 1 file changed, 168 insertions(+), 17 deletions(-) >> >> diff --git a/src/vulkan/wsi/wsi_common_x11.c >> b/src/vulkan/wsi/wsi_common_x11.c >> index dadada82ef1..213a597a430 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_modifiers = >> + (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) >> @@ -620,6 +635,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; >> @@ -974,7 +991,9 @@ static VkResult >> x11_image_init(VkDevice device_h, struct x11_swapchain *chain, >> const VkSwapchainCreateInfoKHR *pCreateInfo, >> const VkAllocationCallbacks* pAllocator, >> - struct x11_image *image) >> + const uint64_t *const *modifiers, >> + const uint32_t *num_modifiers, >> + int num_tranches, struct x11_image *image) >> { >> xcb_void_cookie_t cookie; >> VkResult result; >> @@ -984,28 +1003,60 @@ x11_image_init(VkDevice device_h, struct >> x11_swapchain *chain, >> result = wsi_create_prime_image(&chain->base, pCreateInfo, >> &image->base); >> } else { >> result = wsi_create_native_image(&chain->base, pCreateInfo, >> - 0, NULL, NULL, &image->base); >> + num_tranches, num_modifiers, >> modifiers, >> + &image->base); >> } >> if (result < 0) >> return result; >> >> image->pixmap = xcb_generate_id(chain->conn); >> >> - /* 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.heigh >> t, >> - image->base.row_pitches[0], >> - chain->depth, bpp, >> - image->base.fds[0]); >> +#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1 >> + if (image->base.drm_modifier != DRM_FORMAT_MOD_INVALID) { >> + /* If the image has a modifier, we must have DRI3 v1.1. */ >> + assert(chain->has_dri3_modifiers); >> + >> + 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->base.fds[0] = -1; /* XCB has now taken ownership of the FD */ >> + >> + /* XCB has now taken ownership of the FDs. */ >> + for (int i = 0; i < image->base.num_planes; i++) >> + image->base.fds[i] = -1; >> >> int fence_fd = xshmfence_alloc_shm(); >> if (fence_fd < 0) >> @@ -1056,6 +1107,84 @@ x11_image_finish(struct x11_swapchain *chain, >> wsi_destroy_image(&chain->base, &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, uint32_t >> *num_modifiers_in, >> + uint32_t *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), >> > > Did we ever get a solid answer on whether or not this memcpy is really > needed? I doubt it is. > I'm an idiot. It is needed because we free mod_reply at the end of the function. We could probably restructure so it isn't needed but I doubt it's really worth it. > --Jason > > >> + 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]) { >> + if (n > 0) >> + vk_free(pAllocator, modifiers[0]); >> + 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) >> @@ -1105,8 +1234,13 @@ x11_surface_create_swapchain(VkIcdSurfaceBase >> *icd_surface, >> >> const unsigned num_images = pCreateInfo->minImageCount; >> >> - /* Check for whether or not we have a window up-front */ >> xcb_connection_t *conn = x11_surface_get_connection(icd_surface); >> + struct wsi_x11_connection *wsi_conn = >> + wsi_x11_get_connection(wsi_device, pAllocator, conn); >> + if (!wsi_conn) >> + return VK_ERROR_OUT_OF_HOST_MEMORY; >> + >> + /* Check for whether or not we have a window up-front */ >> xcb_window_t window = x11_surface_get_window(icd_surface); >> xcb_get_geometry_reply_t *geometry = >> xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), NULL); >> @@ -1140,6 +1274,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase >> *icd_surface, >> chain->last_present_msc = 0; >> chain->threaded = false; >> chain->status = VK_SUCCESS; >> + chain->has_dri3_modifiers = wsi_conn->has_dri3_modifiers; >> >> if (!wsi_x11_check_dri3_compatible(conn, local_fd)) >> chain->base.use_prime_blit = true; >> @@ -1171,9 +1306,20 @@ x11_surface_create_swapchain(VkIcdSurfaceBase >> *icd_surface, >> (uint32_t []) { 0 }); >> xcb_discard_reply(chain->conn, cookie.sequence); >> >> + uint64_t *modifiers[2] = {NULL, NULL}; >> + uint32_t num_modifiers[2] = {0, 0}; >> + uint32_t num_tranches = 0; >> + if (wsi_device->supports_modifiers) >> + wsi_x11_get_dri3_modifiers(wsi_conn, conn, window, chain->depth, >> 32, >> + pCreateInfo->compositeAlpha, >> + modifiers, num_modifiers, &num_tranches, >> + pAllocator); >> + >> uint32_t image = 0; >> for (; image < chain->base.image_count; image++) { >> result = x11_image_init(device, chain, pCreateInfo, pAllocator, >> + (const uint64_t *const *)modifiers, >> + num_modifiers, num_tranches, >> &chain->images[image]); >> if (result != VK_SUCCESS) >> goto fail_init_images; >> @@ -1210,6 +1356,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; >> @@ -1219,6 +1367,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); >> >> wsi_swapchain_finish(&chain->base); >> -- >> 2.14.3 >> >> _______________________________________________ >> mesa-dev mailing list >> mesa-dev@lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/mesa-dev >> > >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev