aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2022-05-26 14:44:02 +0200
committerSimon Ser <contact@emersion.fr>2022-11-28 23:50:41 +0000
commitaaf828d3d24c79c2207e83d38a76c7f1cc33084f (patch)
treedf2db2c083766bce86e1b870909c7500859b3e73
parent10f543d5792ec0a74688c4da3781f6f84fb2ed9d (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.h26
-rw-r--r--render/dmabuf.c1
-rw-r--r--render/dmabuf_fallback.c12
-rw-r--r--render/dmabuf_linux.c75
-rw-r--r--render/meson.build6
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)