[Mesa-dev] [PATCH v11 10/15] vulkan/wsi/x11: Add support for DRI3 v1.1

Jason Ekstrand jason at jlekstrand.net
Wed Feb 21 21:24:31 UTC 2018


On Wed, Feb 21, 2018 at 1:22 PM, Jason Ekstrand <jason at jlekstrand.net>
wrote:

> On Wed, Feb 21, 2018 at 6:05 AM, Daniel Stone <daniels at 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 <daniels at 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 at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180221/f390ea3c/attachment-0001.html>


More information about the mesa-dev mailing list