diff options
author | Simon Ser <contact@emersion.fr> | 2023-02-27 16:49:43 +0100 |
---|---|---|
committer | Simon Zeni <simon@bl4ckb0ne.ca> | 2023-02-28 14:25:21 +0000 |
commit | 40117e1e0df79aaffd307a238fb973f0bf1edf78 (patch) | |
tree | 6e70a75c9c02bd2fc5d443e219e6d0990e3e03b2 | |
parent | 8db0d8289087d9e63438e01f810ef01d82170eb1 (diff) |
render/vulkan: prefer render node for wlr_renderer_get_drm_fd()
Instead of returning a primary node from wlr_renderer_get_drm_fd(),
prefer to return a render node if any.
-rw-r--r-- | include/render/vulkan.h | 1 | ||||
-rw-r--r-- | render/vulkan/renderer.c | 6 | ||||
-rw-r--r-- | render/vulkan/vulkan.c | 50 |
3 files changed, 54 insertions, 3 deletions
diff --git a/include/render/vulkan.h b/include/render/vulkan.h index 66739c40..d61db616 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -66,6 +66,7 @@ struct wlr_vk_device { // Tries to find the VkPhysicalDevice for the given drm fd. // Might find none and return VK_NULL_HANDLE. VkPhysicalDevice vulkan_find_drm_phdev(struct wlr_vk_instance *ini, int drm_fd); +int vulkan_open_phdev_drm_fd(VkPhysicalDevice phdev); // Creates a device for the given instance and physical device. struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini, diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index 4e326c69..667301f9 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -2240,10 +2240,10 @@ struct wlr_renderer *wlr_vk_renderer_create_with_drm_fd(int drm_fd) { return NULL; } - // We duplicate it so it's not closed while we still need it. - dev->drm_fd = fcntl(drm_fd, F_DUPFD_CLOEXEC, 0); + // Do not use the drm_fd that was passed in: we should prefer the render + // node even if a primary node was provided + dev->drm_fd = vulkan_open_phdev_drm_fd(phdev); if (dev->drm_fd < 0) { - wlr_log_errno(WLR_ERROR, "fcntl(F_DUPFD_CLOEXEC) failed"); vulkan_device_destroy(dev); vulkan_instance_destroy(ini); return NULL; diff --git a/render/vulkan/vulkan.c b/render/vulkan/vulkan.c index 3849da66..418b7c8c 100644 --- a/render/vulkan/vulkan.c +++ b/render/vulkan/vulkan.c @@ -1,4 +1,8 @@ +#if !defined(__FreeBSD__) +#define _POSIX_C_SOURCE 200809L +#endif #include <assert.h> +#include <fcntl.h> #include <math.h> #include <stdlib.h> #include <stdint.h> @@ -366,6 +370,52 @@ VkPhysicalDevice vulkan_find_drm_phdev(struct wlr_vk_instance *ini, int drm_fd) return VK_NULL_HANDLE; } +int vulkan_open_phdev_drm_fd(VkPhysicalDevice phdev) { + // vulkan_find_drm_phdev() already checks that VK_EXT_physical_device_drm + // is supported + VkPhysicalDeviceDrmPropertiesEXT drm_props = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT, + }; + VkPhysicalDeviceProperties2 props = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &drm_props, + }; + vkGetPhysicalDeviceProperties2(phdev, &props); + + dev_t devid; + if (drm_props.hasRender) { + devid = makedev(drm_props.renderMajor, drm_props.renderMinor); + } else if (drm_props.hasPrimary) { + devid = makedev(drm_props.primaryMajor, drm_props.primaryMinor); + } else { + wlr_log(WLR_ERROR, "Physical device is missing both render and primary nodes"); + return -1; + } + + drmDevice *device = NULL; + if (drmGetDeviceFromDevId(devid, 0, &device) != 0) { + wlr_log_errno(WLR_ERROR, "drmGetDeviceFromDevId failed"); + return -1; + } + + const char *name = NULL; + if (device->available_nodes & (1 << DRM_NODE_RENDER)) { + name = device->nodes[DRM_NODE_RENDER]; + } else { + assert(device->available_nodes & (1 << DRM_NODE_PRIMARY)); + name = device->nodes[DRM_NODE_PRIMARY]; + wlr_log(WLR_DEBUG, "DRM device %s has no render node, " + "falling back to primary node", name); + } + + int drm_fd = open(name, O_RDWR | O_NONBLOCK | O_CLOEXEC); + if (drm_fd < 0) { + wlr_log_errno(WLR_ERROR, "Failed to open DRM node %s", name); + } + drmFreeDevice(&device); + return drm_fd; +} + static void load_device_proc(struct wlr_vk_device *dev, const char *name, void *proc_ptr) { void *proc = (void *)vkGetDeviceProcAddr(dev->dev, name); |