Merge branch 'syncobj_interop' into 'master'

linux_drm_syncobj_v1: add _state_add_release_from_implicit_sync()

See merge request wlroots/wlroots!5308
This commit is contained in:
Félix Poisot 2026-04-12 12:05:49 +00:00
commit b1e771eceb
4 changed files with 116 additions and 8 deletions

View file

@ -3,6 +3,8 @@
#include <wayland-server-core.h> #include <wayland-server-core.h>
struct wlr_buffer;
/** /**
* Accumulate timeline points, to have a destination timeline point be * Accumulate timeline points, to have a destination timeline point be
* signalled when all inputs are * signalled when all inputs are
@ -41,4 +43,22 @@ bool wlr_drm_syncobj_merger_add(struct wlr_drm_syncobj_merger *merger,
struct wlr_drm_syncobj_timeline *dst_timeline, uint64_t dst_point, struct wlr_drm_syncobj_timeline *dst_timeline, uint64_t dst_point,
struct wl_event_loop *loop); struct wl_event_loop *loop);
/**
* Add a new sync file to wait for.
*
* Ownership of fd is transferred to the merger.
*/
bool wlr_drm_syncobj_merger_add_sync_file(struct wlr_drm_syncobj_merger *merger,
int fd);
/**
* Add a new DMA-BUF release to wait for.
*
* Waits for write access.
* If the platform does not support DMA-BUF<->sync file interop, the supplied
* event_loop is used to schedule a wait.
*/
bool wlr_drm_syncobj_merger_add_dmabuf(struct wlr_drm_syncobj_merger *merger,
struct wlr_buffer *buffer, struct wl_event_loop *event_loop);
#endif #endif

View file

@ -74,4 +74,21 @@ bool wlr_linux_drm_syncobj_v1_state_add_release_point(
struct wlr_drm_syncobj_timeline *release_timeline, uint64_t release_point, struct wlr_drm_syncobj_timeline *release_timeline, uint64_t release_point,
struct wl_event_loop *event_loop); struct wl_event_loop *event_loop);
/**
* Register the DMA-BUF release of a buffer for buffer usage.
* Non-dmabuf buffers are considered to be immediately available (no wait).
*
* This function may be called multiple times for the same commit. The client's
* release point will be signalled when all registered points are signalled, and
* a new buffer has been committed.
*
* Because the platform may not support DMA-BUF fence merges, a wl_event_loop
* must be supplied to schedule a wait internally, if needed
*
* Waits for write access
*/
bool wlr_linux_drm_syncobj_v1_state_add_release_from_implicit_sync(
struct wlr_linux_drm_syncobj_surface_v1_state *state,
struct wlr_buffer *buffer, struct wl_event_loop *event_loop);
#endif #endif

View file

@ -4,8 +4,10 @@
#include <unistd.h> #include <unistd.h>
#include <wayland-util.h> #include <wayland-util.h>
#include <wlr/render/drm_syncobj.h> #include <wlr/render/drm_syncobj.h>
#include <wlr/types/wlr_buffer.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include <xf86drm.h> #include <xf86drm.h>
#include "render/dmabuf.h"
#include "render/drm_syncobj_merger.h" #include "render/drm_syncobj_merger.h"
#include "config.h" #include "config.h"
@ -79,14 +81,7 @@ void wlr_drm_syncobj_merger_unref(struct wlr_drm_syncobj_merger *merger) {
static bool merger_add_exportable(struct wlr_drm_syncobj_merger *merger, static bool merger_add_exportable(struct wlr_drm_syncobj_merger *merger,
struct wlr_drm_syncobj_timeline *src_timeline, uint64_t src_point) { struct wlr_drm_syncobj_timeline *src_timeline, uint64_t src_point) {
int new_sync = wlr_drm_syncobj_timeline_export_sync_file(src_timeline, src_point); int new_sync = wlr_drm_syncobj_timeline_export_sync_file(src_timeline, src_point);
if (merger->sync_fd != -1) { return wlr_drm_syncobj_merger_add_sync_file(merger, new_sync);
int fd2 = new_sync;
new_sync = sync_file_merge(merger->sync_fd, fd2);
close(fd2);
close(merger->sync_fd);
}
merger->sync_fd = new_sync;
return true;
} }
struct export_waiter { struct export_waiter {
@ -131,3 +126,69 @@ bool wlr_drm_syncobj_merger_add(struct wlr_drm_syncobj_merger *merger,
merger->n_ref++; merger->n_ref++;
return true; return true;
} }
bool wlr_drm_syncobj_merger_add_sync_file(struct wlr_drm_syncobj_merger *merger,
int fd) {
int new_sync = fd;
if (merger->sync_fd != -1) {
new_sync = sync_file_merge(merger->sync_fd, fd);
close(fd);
close(merger->sync_fd);
}
merger->sync_fd = new_sync;
return merger->sync_fd != -1;
}
struct poll_waiter {
struct wl_event_source *event_source;
struct wlr_drm_syncobj_merger *merger;
};
static int poll_waiter_handle_done(int fd, uint32_t mask, void *data) {
struct poll_waiter *waiter = data;
wlr_drm_syncobj_merger_unref(waiter->merger);
wl_event_source_remove(waiter->event_source);
free(waiter);
return 0;
}
bool wlr_drm_syncobj_merger_add_dmabuf(struct wlr_drm_syncobj_merger *merger,
struct wlr_buffer *buffer, struct wl_event_loop *event_loop) {
struct wlr_dmabuf_attributes dmabuf_attributes;
if (!wlr_buffer_get_dmabuf(buffer, &dmabuf_attributes)) {
return true;
}
bool res = true;
for (int i = 0; i < dmabuf_attributes.n_planes; ++i) {
int sync_fd = dmabuf_export_sync_file(dmabuf_attributes.fd[i], DMA_BUF_SYNC_WRITE);
if (sync_fd == -1) {
res = false;
break;
}
if (!wlr_drm_syncobj_merger_add_sync_file(merger, sync_fd)) {
return false;
}
}
if (res) {
return true;
}
uint32_t mask = WL_EVENT_ERROR | WL_EVENT_HANGUP | WL_EVENT_WRITABLE;
for (int i = 0; i < dmabuf_attributes.n_planes; ++i) {
struct poll_waiter *waiter = calloc(1, sizeof(*waiter));
if (waiter == NULL) {
return false;
}
waiter->merger = wlr_drm_syncobj_merger_ref(merger);
waiter->event_source = wl_event_loop_add_fd(event_loop,
dmabuf_attributes.fd[i], mask, poll_waiter_handle_done, waiter);
if (waiter->event_source == NULL) {
wlr_drm_syncobj_merger_unref(waiter->merger);
free(waiter);
return false;
}
}
return true;
}

View file

@ -12,6 +12,7 @@
#include <xf86drm.h> #include <xf86drm.h>
#include "config.h" #include "config.h"
#include "linux-drm-syncobj-v1-protocol.h" #include "linux-drm-syncobj-v1-protocol.h"
#include "render/dmabuf.h"
#include "render/drm_syncobj_merger.h" #include "render/drm_syncobj_merger.h"
#define LINUX_DRM_SYNCOBJ_V1_VERSION 1 #define LINUX_DRM_SYNCOBJ_V1_VERSION 1
@ -540,3 +541,12 @@ bool wlr_linux_drm_syncobj_v1_state_add_release_point(
return wlr_drm_syncobj_merger_add(state->release_merger, return wlr_drm_syncobj_merger_add(state->release_merger,
release_timeline, release_point, event_loop); release_timeline, release_point, event_loop);
} }
bool wlr_linux_drm_syncobj_v1_state_add_release_from_implicit_sync(
struct wlr_linux_drm_syncobj_surface_v1_state *state,
struct wlr_buffer *buffer, struct wl_event_loop *event_loop) {
if (state->release_merger != NULL) {
return true;
}
return wlr_drm_syncobj_merger_add_dmabuf(state->release_merger, buffer, event_loop);
}