aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2023-02-27 16:49:43 +0100
committerSimon Zeni <simon@bl4ckb0ne.ca>2023-02-28 14:25:21 +0000
commit40117e1e0df79aaffd307a238fb973f0bf1edf78 (patch)
tree6e70a75c9c02bd2fc5d443e219e6d0990e3e03b2
parent8db0d8289087d9e63438e01f810ef01d82170eb1 (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.h1
-rw-r--r--render/vulkan/renderer.c6
-rw-r--r--render/vulkan/vulkan.c50
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);