[Mesa-dev] [PATCH 13/14] RFC: vulkan/wsi/x11: Add support for DRI3 v1.1

Daniel Stone daniels at collabora.com
Fri Jul 21 13:42:16 UTC 2017


Adds support for multiple planes and buffer modifiers.

Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 src/vulkan/wsi/wsi_common_x11.c | 158 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 141 insertions(+), 17 deletions(-)

diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index db9d709992..58f9db99e5 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"
@@ -43,6 +44,10 @@
 #include "wsi_common_x11.h"
 #include "wsi_common_queue.h"
 
+#ifndef DRM_FORMAT_MOD_INVALID
+#define DRM_FORMAT_MOD_INVALID (1ULL<<56)-1
+#endif
+
 #define typed_memcpy(dest, src, count) ({ \
    STATIC_ASSERT(sizeof(*src) == sizeof(*dest)); \
    memcpy((dest), (src), (count) * sizeof(*(src))); \
@@ -50,6 +55,7 @@
 
 struct wsi_x11_connection {
    bool has_dri3;
+   bool has_dri3_v1_1;
    bool has_present;
    bool is_proprietary_x11;
 };
@@ -164,6 +170,16 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc,
    }
 
    wsi_conn->has_dri3 = dri3_reply->present != 0;
+   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;
+   }
+
    wsi_conn->has_present = pres_reply->present != 0;
    wsi_conn->is_proprietary_x11 = false;
    if (amd_reply && amd_reply->present)
@@ -247,6 +263,24 @@ static const VkPresentModeKHR present_modes[] = {
    VK_PRESENT_MODE_FIFO_KHR,
 };
 
+#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1
+static uint32_t
+vk_format_to_fourcc(VkFormat vk_format, VkCompositeAlphaFlagsKHR vk_alpha)
+{
+   bool is_alpha = (vk_alpha == VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR);
+
+   /* XXX: Real lookup table. */
+   switch (vk_format) {
+   case VK_FORMAT_B8G8R8A8_UNORM:
+   case VK_FORMAT_B8G8R8A8_SRGB:
+      return is_alpha ? DRM_FORMAT_ARGB8888 : DRM_FORMAT_XRGB8888;
+      break;
+   default:
+      unreachable("unknown format in vk_format_to_fourcc");
+   }
+}
+#endif
+
 static xcb_screen_t *
 get_screen_for_root(xcb_connection_t *conn, xcb_window_t root)
 {
@@ -625,6 +659,8 @@ struct x11_image {
 struct x11_swapchain {
    struct wsi_swapchain                        base;
 
+   bool                                         has_dri3_v1_1;
+
    xcb_connection_t *                           conn;
    xcb_window_t                                 window;
    xcb_gc_t                                     gc;
@@ -952,6 +988,8 @@ static VkResult
 x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
                const VkSwapchainCreateInfoKHR *pCreateInfo,
                const VkAllocationCallbacks* pAllocator,
+               uint64_t *modifiers,
+               int num_modifiers,
                struct x11_image *image)
 {
    xcb_void_cookie_t cookie;
@@ -962,29 +1000,57 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
                                                     pCreateInfo,
                                                     pAllocator,
                                                     chain->base.different_gpu,
-                                                    NULL,
-                                                    0,
+                                                    modifiers,
+                                                    num_modifiers,
                                                     &image->base);
    if (result != VK_SUCCESS)
       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 (chain->has_dri3_v1_1 && image->base.drm_modifier != DRM_FORMAT_MOD_INVALID) {
+      uint32_t fourcc = vk_format_to_fourcc(pCreateInfo->imageFormat,
+                                            pCreateInfo->compositeAlpha);
+      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],
+                                              fourcc,
+                                              image->base.drm_modifier >> 32,
+                                              image->base.drm_modifier & 0xffffffff,
+                                              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 */
+   for (int i = 0; i < image->base.num_planes; i++)
+      image->base.fds[i] = -1; /* XCB has now taken ownership of the FDs */
 
    int fence_fd = xshmfence_alloc_shm();
    if (fence_fd < 0)
@@ -1066,6 +1132,46 @@ x11_swapchain_destroy(struct wsi_swapchain *anv_chain,
    return VK_SUCCESS;
 }
 
+static void
+wsi_x11_get_dri3_modifiers(xcb_connection_t *conn, xcb_window_t window,
+                           VkFormat vk_format,
+                           VkCompositeAlphaFlagsKHR vk_alpha,
+                           uint64_t **modifiers_in, int *num_modifiers_in,
+                           const VkAllocationCallbacks* pAllocator)
+{
+#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1
+   uint64_t *modifiers;
+   uint32_t fourcc = vk_format_to_fourcc(vk_format, vk_alpha);
+
+   xcb_generic_error_t *error = NULL;
+   xcb_dri3_get_supported_modifiers_cookie_t mod_cookie =
+      xcb_dri3_get_supported_modifiers(conn, window, fourcc);
+   xcb_dri3_get_supported_modifiers_reply_t *mod_reply =
+      xcb_dri3_get_supported_modifiers_reply(conn, mod_cookie, &error);
+   if (!mod_reply)
+      return;
+
+   if (!mod_reply->num_modifiers)
+      return;
+
+   modifiers = vk_alloc(pAllocator, mod_reply->num_modifiers * sizeof(uint64_t),
+                        8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!modifiers)
+      return;
+
+   uint32_t *mod_parts = xcb_dri3_get_supported_modifiers_modifiers(mod_reply);
+   for (int i = 0; i < mod_reply->num_modifiers; i++) {
+      modifiers[i] = (uint64_t) mod_parts[i * 2] << 32;
+      modifiers[i] |= (uint64_t) mod_parts[i * 2 + 1] & 0xffffffff;
+   }
+
+   free(mod_reply);
+
+   *modifiers_in = modifiers;
+   *num_modifiers_in = mod_reply->num_modifiers;
+#endif
+}
+
 static VkResult
 x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
                              VkDevice device,
@@ -1079,6 +1185,8 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
    struct x11_swapchain *chain;
    xcb_void_cookie_t cookie;
    VkResult result;
+   uint64_t *modifiers = NULL;
+   int num_modifiers = 0;
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);
 
@@ -1118,10 +1226,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_v1_1 = wsi_conn->has_dri3_v1_1;
+
    chain->base.different_gpu = false;
    if (!wsi_x11_check_dri3_compatible(conn, local_fd))
        chain->base.different_gpu = true;
 
+   wsi_x11_get_dri3_modifiers(conn, window, pCreateInfo->imageFormat,
+                              pCreateInfo->compositeAlpha,
+                              &modifiers, &num_modifiers, 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 |
@@ -1152,7 +1271,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,
-                              &chain->images[image]);
+                              modifiers, num_modifiers, &chain->images[image]);
       if (result != VK_SUCCESS)
          goto fail_init_images;
    }
@@ -1188,11 +1307,16 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
       }
    }
 
+   if (modifiers)
+      vk_free(pAllocator, modifiers);
    *swapchain_out = &chain->base;
 
    return VK_SUCCESS;
 
 fail_init_images:
+   if (modifiers)
+      vk_free(pAllocator, modifiers);
+
    for (uint32_t j = 0; j < image; j++)
       x11_image_finish(chain, pAllocator, &chain->images[j]);
 
-- 
2.13.2



More information about the mesa-dev mailing list