From 46e5ec89cad434b1a1dd9ca49a35e1c6992c54c1 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Thu, 2 May 2024 19:11:06 +0300 Subject: [PATCH 1/2] backend-drm: Add method to import DRM fd Allow the compositor to provide a file descriptor for a DRM device. This allows the compositor to bypass the launcher backends and to get a DRM file descriptor from an external resource manager, such as one that can create DRM leases, and pass it to the DRM backend for use. Having the DRM device management in the compositor allows for integrating a platform specific resource manager without having to add extra dependencies to the generic libweston code. Signed-off-by: Marius Vlad Signed-off-by: Damian Hobson-Garcia --- include/libweston/backend-drm.h | 7 +++ libweston/backend-drm/drm.c | 78 ++++++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/include/libweston/backend-drm.h b/include/libweston/backend-drm.h index d47955c..889848a 100644 --- a/include/libweston/backend-drm.h +++ b/include/libweston/backend-drm.h @@ -258,6 +258,13 @@ struct weston_drm_backend_config { * rendering device. */ char *additional_devices; + + /** DRM device file descriptor to use + * + * An openeded DRM device file descriptor. If <0, open a DRM + * device in the backend using `specific_device` or heuristics. + */ + int device_fd; }; #ifdef __cplusplus diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index 8092789..4e78ad0 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -3431,31 +3432,22 @@ drm_device_changed(struct weston_backend *backend, wl_signal_emit(&compositor->session_signal, compositor); } -/** - * Determines whether or not a device is capable of modesetting. If successful, - * sets b->drm.fd and b->drm.filename to the opened device. - */ static bool -drm_device_is_kms(struct drm_backend *b, struct drm_device *device, - struct udev_device *udev_device) +drm_backend_update_kms_device(struct drm_backend *b, struct drm_device *device, + struct udev_device *udev_device, const char *name, int drm_fd) { struct weston_compositor *compositor = b->compositor; - const char *filename = udev_device_get_devnode(udev_device); const char *sysnum = udev_device_get_sysnum(udev_device); dev_t devnum = udev_device_get_devnum(udev_device); drmModeRes *res; - int id = -1, fd; + int id = -1; - if (!filename) - return false; - - fd = weston_launcher_open(compositor->launcher, filename, O_RDWR); - if (fd < 0) + if (!name) return false; - res = drmModeGetResources(fd); + res = drmModeGetResources(drm_fd); if (!res) - goto out_fd; + return false; if (res->count_crtcs <= 0 || res->count_connectors <= 0 || res->count_encoders <= 0) @@ -3464,7 +3456,7 @@ drm_device_is_kms(struct drm_backend *b, struct drm_device *device, if (sysnum) id = atoi(sysnum); if (!sysnum || id < 0) { - weston_log("couldn't get sysnum for device %s\n", filename); + weston_log("couldn't get sysnum for device %s\n", name); goto out_res; } @@ -3474,9 +3466,9 @@ drm_device_is_kms(struct drm_backend *b, struct drm_device *device, weston_launcher_close(compositor->launcher, device->drm.fd); free(device->drm.filename); - device->drm.fd = fd; + device->drm.fd = drm_fd; device->drm.id = id; - device->drm.filename = strdup(filename); + device->drm.filename = strdup(name); device->drm.devnum = devnum; drmModeFreeResources(res); @@ -3485,11 +3477,34 @@ drm_device_is_kms(struct drm_backend *b, struct drm_device *device, out_res: drmModeFreeResources(res); -out_fd: - weston_launcher_close(b->compositor->launcher, fd); return false; } +/** + * Determines whether or not a device is capable of modesetting. If successful, + * sets b->drm.fd and b->drm.filename to the opened device. + */ +static bool +drm_device_is_kms(struct drm_backend *b, struct drm_device *device, + struct udev_device *udev_device) +{ + int fd; + const char *filename = udev_device_get_devnode(udev_device); + if (!filename) + return false; + + fd = weston_launcher_open(b->compositor->launcher, filename, O_RDWR); + if (fd < 0) + return false; + + if (!drm_backend_update_kms_device(b, b->drm, udev_device, filename, fd)) { + weston_launcher_close(b->compositor->launcher, fd); + return false; + } + + return true; +} + /* * Find primary GPU * Some systems may have multiple DRM devices attached to a single seat. This @@ -3578,6 +3593,25 @@ find_primary_gpu(struct drm_backend *b, const char *seat) return drm_device; } +static struct udev_device * +import_drm_device_fd(struct drm_backend *b, int fd) +{ + struct udev_device *udev_device; + struct stat s; + + if (fstat(fd, &s) < 0 || !S_ISCHR(s.st_mode)) + return NULL; + + udev_device = udev_device_new_from_devnum(b->udev, 'c', s.st_rdev); + if (!udev_device) + return NULL; + + if (!drm_backend_update_kms_device(b, b->drm, udev_device, "imported DRM device fd", fd)) + return NULL; + + return udev_device; +} + static struct udev_device * open_specific_drm_device(struct drm_backend *b, struct drm_device *device, const char *name) @@ -3904,7 +3938,9 @@ drm_backend_create(struct weston_compositor *compositor, b->session_listener.notify = session_notify; wl_signal_add(&compositor->session_signal, &b->session_listener); - if (config->specific_device) + if (config->device_fd > 0) + drm_device = import_drm_device_fd(b, config->device_fd); + else if (config->specific_device) drm_device = open_specific_drm_device(b, device, config->specific_device); else -- 2.43.0