render/dmabuf: add dmabuf_import_sync_file

References: https://lore.kernel.org/dri-devel/20220506180216.2095060-1-jason@jlekstrand.net/
This commit is contained in:
Simon Ser 2022-05-26 14:44:02 +02:00
parent 10f543d579
commit aaf828d3d2
5 changed files with 120 additions and 0 deletions

26
include/render/dmabuf.h Normal file
View file

@ -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

View file

@ -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) {

12
render/dmabuf_fallback.c Normal file
View file

@ -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;
}

75
render/dmabuf_linux.c Normal file
View file

@ -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;
}

View file

@ -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)