Mesa (master): v3dv: Wayland WSI support

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Nov 25 07:02:39 UTC 2020


Module: Mesa
Branch: master
Commit: 472e81ed805a1f8f9e6d1b2ca39c089c674c33df
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=472e81ed805a1f8f9e6d1b2ca39c089c674c33df

Author: Ella-0 <23418164+Ella-0 at users.noreply.github.com>
Date:   Fri Nov 20 08:57:07 2020 +0000

v3dv: Wayland WSI support

Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7303>

---

 src/broadcom/vulkan/meson.build        |   7 ++
 src/broadcom/vulkan/v3dv_device.c      | 137 ++++++++++++++++++++++++++++++++-
 src/broadcom/vulkan/v3dv_wsi_wayland.c |  55 +++++++++++++
 3 files changed, 198 insertions(+), 1 deletion(-)

diff --git a/src/broadcom/vulkan/meson.build b/src/broadcom/vulkan/meson.build
index 58f4bcee989..938595afa1d 100644
--- a/src/broadcom/vulkan/meson.build
+++ b/src/broadcom/vulkan/meson.build
@@ -105,6 +105,13 @@ if with_platform_x11
   libv3dv_files += files('v3dv_wsi_x11.c')
 endif
 
+if with_platform_wayland
+  v3dv_deps += [dep_wayland_client, dep_wl_protocols]
+  v3dv_flags += '-DVK_USE_PLATFORM_WAYLAND_KHR'
+  libv3dv_files += files('v3dv_wsi_wayland.c')
+  libv3dv_files += [wayland_drm_client_protocol_h, wayland_drm_protocol_c]
+endif
+
 if system_has_kms_drm and not with_platform_android
  v3dv_flags += '-DVK_USE_PLATFORM_DISPLAY_KHR'
  libv3dv_files += files('v3dv_wsi_display.c')
diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c
index 95672c5ab06..8b299fa7491 100644
--- a/src/broadcom/vulkan/v3dv_device.c
+++ b/src/broadcom/vulkan/v3dv_device.c
@@ -52,6 +52,11 @@
 #include <X11/Xlib-xcb.h>
 #endif
 
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+#include <wayland-client.h>
+#include "wayland-drm-client-protocol.h"
+#endif
+
 #ifdef USE_V3D_SIMULATOR
 #include "drm-uapi/i915_drm.h"
 #endif
@@ -383,6 +388,126 @@ finish:
 }
 #endif
 
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+struct v3dv_wayland_info {
+   struct wl_drm *wl_drm;
+   int fd;
+   bool is_set;
+   bool authenticated;
+};
+
+static void
+v3dv_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
+{
+   struct v3dv_wayland_info *info = data;
+   info->fd = open(device, O_RDWR | O_CLOEXEC);
+   info->is_set = info->fd != -1;
+
+   drm_magic_t magic;
+   drmGetMagic(info->fd, &magic);
+   wl_drm_authenticate(info->wl_drm, magic);
+}
+
+static void
+v3dv_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
+{
+}
+
+static void
+v3dv_drm_handle_authenticated(void *data, struct wl_drm *drm)
+{
+   struct v3dv_wayland_info *info = data;
+   info->authenticated = true;
+}
+
+static void
+v3dv_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
+{
+}
+
+struct wl_drm_listener v3dv_drm_listener = {
+   .device = v3dv_drm_handle_device,
+   .format = v3dv_drm_handle_format,
+   .authenticated = v3dv_drm_handle_authenticated,
+   .capabilities = v3dv_drm_handle_capabilities
+};
+
+static void
+v3dv_registry_global(void *data,
+                     struct wl_registry *registry,
+                     uint32_t name,
+                     const char *interface,
+                     uint32_t version)
+{
+   struct v3dv_wayland_info *info = data;
+   if (strcmp(interface, "wl_drm") == 0) {
+      info->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface,
+                                      MIN2(version, 2));
+      wl_drm_add_listener(info->wl_drm, &v3dv_drm_listener, data);
+   };
+}
+
+static void
+v3dv_registry_global_remove_cb(void *data,
+                               struct wl_registry *registry,
+                               uint32_t name)
+{
+}
+
+static int
+create_display_fd_wayland(VkIcdSurfaceBase *surface)
+{
+   struct wl_display *display;
+   struct wl_registry *registry = NULL;
+
+   struct v3dv_wayland_info info = {
+      .wl_drm = NULL,
+      .fd = -1,
+      .is_set = false,
+      .authenticated = false
+   };
+
+   if (surface)
+      display = ((VkIcdSurfaceWayland *) surface)->display;
+   else
+      display = wl_display_connect(NULL);
+
+   if (!display)
+      return -1;
+
+   registry = wl_display_get_registry(display);
+   if (!registry) {
+      if (!surface)
+         wl_display_disconnect(display);
+      return -1;
+   }
+
+   static const struct wl_registry_listener registry_listener = {
+      v3dv_registry_global,
+      v3dv_registry_global_remove_cb
+   };
+   wl_registry_add_listener(registry, &registry_listener, &info);
+
+   wl_display_roundtrip(display); /* For the registry advertisement */
+   wl_display_roundtrip(display); /* For the DRM device event */
+   wl_display_roundtrip(display); /* For the authentication event */
+
+   wl_drm_destroy(info.wl_drm);
+   wl_registry_destroy(registry);
+
+   if (!surface)
+      wl_display_disconnect(display);
+
+   if (!info.is_set)
+      return -1;
+
+   if (!info.authenticated)
+      return -1;
+
+   return info.fd;
+}
+#endif
+
 /* Acquire an authenticated display fd without a surface reference. This is the
  * case where the application is making WSI allocations outside the Vulkan
  * swapchain context (only Zink, for now). Since we lack information about the
@@ -393,8 +518,13 @@ static void
 acquire_display_device_no_surface(struct v3dv_instance *instance,
                                   struct v3dv_physical_device *pdevice)
 {
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+   pdevice->display_fd = create_display_fd_wayland(NULL);
+#endif
+
 #ifdef VK_USE_PLATFORM_XCB_KHR
-   pdevice->display_fd = create_display_fd_xcb(NULL);
+   if (pdevice->display_fd == -1)
+      pdevice->display_fd = create_display_fd_xcb(NULL);
 #endif
 
 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
@@ -424,6 +554,11 @@ acquire_display_device_surface(struct v3dv_instance *instance,
    }
 #endif
 
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+   if (surface->platform == VK_ICD_WSI_PLATFORM_WAYLAND)
+      pdevice->display_fd = create_display_fd_wayland(surface);
+#endif
+
 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
    if (surface->platform == VK_ICD_WSI_PLATFORM_DISPLAY &&
        pdevice->master_fd >= 0) {
diff --git a/src/broadcom/vulkan/v3dv_wsi_wayland.c b/src/broadcom/vulkan/v3dv_wsi_wayland.c
new file mode 100644
index 00000000000..f769449eaf8
--- /dev/null
+++ b/src/broadcom/vulkan/v3dv_wsi_wayland.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2020 Ella Stanforth
+ * based on intel anv code:
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "wsi_common_wayland.h"
+#include "v3dv_private.h"
+
+VkBool32 v3dv_GetPhysicalDeviceWaylandPresentationSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex,
+    struct wl_display*                          display)
+{
+   V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
+
+   return wsi_wl_get_presentation_support(&physical_device->wsi_device, display);
+}
+
+VkResult v3dv_CreateWaylandSurfaceKHR(
+    VkInstance                                  _instance,
+    const VkWaylandSurfaceCreateInfoKHR*        pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface)
+{
+   V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
+   const VkAllocationCallbacks *alloc;
+   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR);
+
+   if (pAllocator)
+      alloc = pAllocator;
+   else
+      alloc = &instance->alloc;
+
+   return wsi_create_wl_surface(alloc, pCreateInfo, pSurface);
+}



More information about the mesa-commit mailing list