summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/broadcom/vulkan/meson.build7
-rw-r--r--src/broadcom/vulkan/v3dv_device.c137
-rw-r--r--src/broadcom/vulkan/v3dv_wsi_wayland.c55
3 files changed, 198 insertions, 1 deletions
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);
+}