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. > height, > - 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. --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