diff options
author | Simon Ser <contact@emersion.fr> | 2022-05-26 14:44:02 +0200 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2022-11-28 23:50:41 +0000 |
commit | aaf828d3d24c79c2207e83d38a76c7f1cc33084f (patch) | |
tree | df2db2c083766bce86e1b870909c7500859b3e73 /render/dmabuf_linux.c | |
parent | 10f543d5792ec0a74688c4da3781f6f84fb2ed9d (diff) |
render/dmabuf: add dmabuf_import_sync_file
References: https://lore.kernel.org/dri-devel/20220506180216.2095060-1-jason@jlekstrand.net/
Diffstat (limited to 'render/dmabuf_linux.c')
-rw-r--r-- | render/dmabuf_linux.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/render/dmabuf_linux.c b/render/dmabuf_linux.c new file mode 100644 index 00000000..a6bf1d42 --- /dev/null +++ b/render/dmabuf_linux.c @@ -0,0 +1,75 @@ +#include <linux/dma-buf.h> +#include <linux/version.h> +#include <stdlib.h> +#include <sys/utsname.h> +#include <wlr/util/log.h> +#include <xf86drm.h> + +#include "render/dmabuf.h" + +bool dmabuf_check_sync_file_import_export(void) { + /* Unfortunately there's no better way to check the availability of the + * IOCTL than to check the kernel version. See the discussion at: + * https://lore.kernel.org/dri-devel/20220601161303.64797-1-contact@emersion.fr/ + */ + + struct utsname utsname = {0}; + if (uname(&utsname) != 0) { + wlr_log_errno(WLR_ERROR, "uname failed"); + return false; + } + + if (strcmp(utsname.sysname, "Linux") != 0) { + return false; + } + + // Trim release suffix if any, e.g. "-arch1-1" + for (size_t i = 0; utsname.release[i] != '\0'; i++) { + char ch = utsname.release[i]; + if ((ch < '0' || ch > '9') && ch != '.') { + utsname.release[i] = '\0'; + break; + } + } + + char *rel = strtok(utsname.release, "."); + int major = atoi(rel); + + int minor = 0; + rel = strtok(NULL, "."); + if (rel != NULL) { + minor = atoi(rel); + } + + int patch = 0; + rel = strtok(NULL, "."); + if (rel != NULL) { + patch = atoi(rel); + } + + return KERNEL_VERSION(major, minor, patch) >= KERNEL_VERSION(5, 20, 0); +} + +// TODO: drop these definitions once widespread +#if !defined(DMA_BUF_IOCTL_IMPORT_SYNC_FILE) + +struct dma_buf_import_sync_file { + __u32 flags; + __s32 fd; +}; + +#define DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW(DMA_BUF_BASE, 3, struct dma_buf_import_sync_file) + +#endif + +bool dmabuf_import_sync_file(int dmabuf_fd, uint32_t flags, int sync_file_fd) { + struct dma_buf_import_sync_file data = { + .flags = flags, + .fd = sync_file_fd, + }; + if (drmIoctl(dmabuf_fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, &data) != 0) { + wlr_log_errno(WLR_ERROR, "drmIoctl(IMPORT_SYNC_FILE) failed"); + return false; + } + return true; +} |