diff --git a/backend/drm/drm.c b/backend/drm/drm.c index e9842bb3e..0e981d592 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -1479,6 +1480,31 @@ void destroy_drm_connector(struct wlr_drm_connector *conn) { free(conn); } +int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend) { + assert(backend); + + struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend); + char *path = drmGetDeviceNameFromFd2(drm->fd); + if (!path) { + wlr_log(WLR_ERROR, "Failed to get device name from DRM fd"); + return -1; + } + + int fd = open(path, O_RDWR | O_CLOEXEC); + if (fd < 0) { + wlr_log_errno(WLR_ERROR, "Unable to clone DRM fd for client fd"); + free(path); + return -1; + } + + if (drmIsMaster(fd) && drmDropMaster(fd) < 0) { + wlr_log_errno(WLR_ERROR, "Failed to drop master"); + return -1; + } + + return fd; +} + /* TODO: make the function return a `wlr_drm_lease` to provide a destroy event * that can be fired when the kernel notifies us through uevent that the lease * has been destroyed diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index c5351d650..0d8c51e08 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -33,6 +33,13 @@ bool wlr_output_is_drm(struct wlr_output *output); */ uint32_t wlr_drm_connector_get_id(struct wlr_output *output); +/** + * Tries to open non-master DRM FD. The compositor must not call `drmSetMaster` + * on the returned FD. + * Returns a valid opened DRM FD, or -1 on error. + */ +int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend); + /** * Leases a given output to the caller. The output must be from the associated * DRM backend.