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 | |
parent | 10f543d5792ec0a74688c4da3781f6f84fb2ed9d (diff) |
render/dmabuf: add dmabuf_import_sync_file
References: https://lore.kernel.org/dri-devel/20220506180216.2095060-1-jason@jlekstrand.net/
-rw-r--r-- | include/render/dmabuf.h | 26 | ||||
-rw-r--r-- | render/dmabuf.c | 1 | ||||
-rw-r--r-- | render/dmabuf_fallback.c | 12 | ||||
-rw-r--r-- | render/dmabuf_linux.c | 75 | ||||
-rw-r--r-- | render/meson.build | 6 |
5 files changed, 120 insertions, 0 deletions
diff --git a/include/render/dmabuf.h b/include/render/dmabuf.h new file mode 100644 index 00000000..4e82a99f --- /dev/null +++ b/include/render/dmabuf.h @@ -0,0 +1,26 @@ +#ifndef RENDER_DMABUF_H +#define RENDER_DMABUF_H + +#include <stdbool.h> +#include <stdint.h> + +// Copied from <linux/dma-buf.h> to avoid #ifdef soup +#define DMA_BUF_SYNC_READ (1 << 0) +#define DMA_BUF_SYNC_WRITE (2 << 0) +#define DMA_BUF_SYNC_RW (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE) + +/** + * Check whether DMA-BUF import/export from/to sync_file is available. + * + * If this function returns true, dmabuf_import_sync_file() is supported. + */ +bool dmabuf_check_sync_file_import_export(void); + +/** + * Import a sync_file into a DMA-BUF with DMA_BUF_IOCTL_IMPORT_SYNC_FILE. + * + * This can be used to make explicit sync interoperate with implicit sync. + */ +bool dmabuf_import_sync_file(int dmabuf_fd, uint32_t flags, int sync_file_fd); + +#endif diff --git a/render/dmabuf.c b/render/dmabuf.c index 433cb82e..44b840f2 100644 --- a/render/dmabuf.c +++ b/render/dmabuf.c @@ -3,6 +3,7 @@ #include <unistd.h> #include <wlr/render/dmabuf.h> #include <wlr/util/log.h> +#include "render/dmabuf.h" void wlr_dmabuf_attributes_finish(struct wlr_dmabuf_attributes *attribs) { for (int i = 0; i < attribs->n_planes; ++i) { diff --git a/render/dmabuf_fallback.c b/render/dmabuf_fallback.c new file mode 100644 index 00000000..8cd31384 --- /dev/null +++ b/render/dmabuf_fallback.c @@ -0,0 +1,12 @@ +#include <wlr/util/log.h> + +#include "render/dmabuf.h" + +bool dmabuf_check_sync_file_import_export(void) { + return false; +} + +bool dmabuf_import_sync_file(int dmabuf_fd, uint32_t flags, int sync_file_fd) { + wlr_log(WLR_ERROR, "DMA-BUF sync_file import IOCTL not available on this system"); + return false; +} 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; +} diff --git a/render/meson.build b/render/meson.build index c8c6032f..4c3d4522 100644 --- a/render/meson.build +++ b/render/meson.build @@ -14,6 +14,12 @@ wlr_files += files( 'wlr_texture.c', ) +if cc.has_header('linux/dma-buf.h') and target_machine.system() == 'linux' + wlr_files += files('dmabuf_linux.c') +else + wlr_files += files('dmabuf_fallback.c') +endif + if 'gles2' in renderers or 'auto' in renderers egl = dependency('egl', required: 'gles2' in renderers) gbm = dependency('gbm', required: 'gles2' in renderers) |