[Mesa-dev] [RFC 22/22] RFC: vulkan/wsi: Add support for DRI3 v1.1

Daniel Stone daniels at collabora.com
Thu Jun 8 18:44:20 UTC 2017


Adds support for multiple planes and buffer modifiers.

Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 src/intel/vulkan/anv_wsi.c      |   7 +-
 src/vulkan/wsi/wsi_common_x11.c | 137 ++++++++++++++++++++++++++++++++++++----
 2 files changed, 131 insertions(+), 13 deletions(-)

diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 53ad7d153e..ca5611666e 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -201,8 +201,11 @@ anv_wsi_image_create(VkDevice device_h,
    for (i = 0; i < num_modifiers; i++) {
       enum isl_tiling t;
       enum isl_aux_usage a;
-      if (isl_tiling_from_drm_format_mod(modifiers[i], &t, &a))
+      if (modifiers[i] != DRM_FORMAT_MOD_LINEAR &&
+          isl_tiling_from_drm_format_mod(modifiers[i], &t, &a)) {
          vk_tiling = VK_IMAGE_TILING_OPTIMAL;
+	 break;
+      }
    }
 
    VkResult result;
@@ -231,7 +234,7 @@ anv_wsi_image_create(VkDevice device_h,
          .pNext =
       &(VkExportImageDmaBufInfoMESAX) {
          .sType = VK_STRUCTURE_TYPE_EXPORT_IMAGE_DMA_BUF_INFO_MESAX,
-         .drmFormatModifierCount = ARRAY_SIZE(modifiers),
+         .drmFormatModifierCount = num_modifiers,
          .pDrmFormatModifiers = modifiers,
       }}},
       NULL,
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index f12583db13..a8201a1601 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,22 @@ static const VkPresentModeKHR present_modes[] = {
    VK_PRESENT_MODE_FIFO_KHR,
 };
 
+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");
+   }
+}
+
 static xcb_screen_t *
 get_screen_for_root(xcb_connection_t *conn, xcb_window_t root)
 {
@@ -628,6 +660,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;
@@ -966,7 +1000,9 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
    uint32_t bpp = 32;
    int fd;
    uint32_t size;
-   uint64_t modifier;
+   uint32_t fourcc = vk_format_to_fourcc(pCreateInfo->imageFormat,
+                                         pCreateInfo->compositeAlpha);
+   uint64_t modifier = DRM_FORMAT_MOD_INVALID;
 
    result = chain->base.image_fns->create_wsi_image(device_h,
                                                     pCreateInfo,
@@ -1009,15 +1045,36 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
 
    image->pixmap = xcb_generate_id(chain->conn);
 
-   cookie =
-      xcb_dri3_pixmap_from_buffer_checked(chain->conn,
-                                          image->pixmap,
-                                          chain->window,
-                                          size,
-                                          pCreateInfo->imageExtent.width,
-                                          pCreateInfo->imageExtent.height,
-                                          row_pitch,
-                                          chain->depth, bpp, fd);
+#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1
+   if (chain->has_dri3_v1_1 && modifier != DRM_FORMAT_MOD_INVALID) {
+      cookie =
+         xcb_dri3_pixmap_from_buffers_checked(chain->conn,
+                                              image->pixmap,
+                                              chain->window,
+                                              1, /* XXX: multi-plane */
+                                              pCreateInfo->imageExtent.width,
+                                              pCreateInfo->imageExtent.height,
+                                              row_pitch, offset,
+                                              0, 0,
+                                              0, 0,
+                                              0, 0,
+                                              fourcc,
+                                              modifier >> 32,
+                                              modifier & 0xffffffff,
+                                              &fd);
+   } else
+#endif
+   {
+      cookie =
+         xcb_dri3_pixmap_from_buffer_checked(chain->conn,
+                                             image->pixmap,
+                                             chain->window,
+                                             size,
+                                             pCreateInfo->imageExtent.width,
+                                             pCreateInfo->imageExtent.height,
+                                             row_pitch,
+                                             chain->depth, bpp, fd);
+   }
    xcb_discard_reply(chain->conn, cookie.sequence);
 
    int fence_fd = xshmfence_alloc_shm();
@@ -1109,6 +1166,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,
@@ -1122,6 +1219,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);
 
@@ -1161,10 +1260,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.needs_linear_copy = false;
    if (!wsi_x11_check_dri3_compatible(conn, local_fd))
        chain->base.needs_linear_copy = 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 |
@@ -1195,7 +1305,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,
-                              NULL, 0, &chain->images[image]);
+                              modifiers, num_modifiers, &chain->images[image]);
       if (result != VK_SUCCESS)
          goto fail_init_images;
    }
@@ -1231,11 +1341,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.0



More information about the mesa-dev mailing list