linux_drm_syncobj_v1: fix handling of empty first commit

As reported in
https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4979#note_3385626,
bfd6e619fc did not correctly handle clients
that don't immediately follow their call to
`wp_linux_drm_syncobj_manager_v1.get_surface` with a commit attaching
a buffer

Fixes: bfd6e619fc
This commit is contained in:
Félix Poisot 2026-03-20 12:35:21 +00:00
parent 4ca40004fd
commit fd870f6d27
2 changed files with 11 additions and 3 deletions

View file

@ -20,6 +20,7 @@ struct wlr_linux_drm_syncobj_surface_v1_state {
uint64_t acquire_point;
struct {
bool committed;
struct wlr_drm_syncobj_timeline *release_timeline;
uint64_t release_point;
struct wlr_drm_syncobj_merger *release_merger;

View file

@ -171,19 +171,20 @@ static void surface_synced_move_state(void *_dst, void *_src) {
}
surface_synced_finish_state(dst);
*dst = *src;
dst->committed = true;
*src = (struct wlr_linux_drm_syncobj_surface_v1_state){0};
}
static void surface_synced_commit(struct wlr_surface_synced *synced) {
struct wlr_linux_drm_syncobj_surface_v1 *surface = wl_container_of(synced, surface, synced);
if (surface->current.release_merger != NULL) {
// ignore commits that did not attach a buffer
if (!surface->current.committed) {
return;
}
surface->current.release_merger = wlr_drm_syncobj_merger_create(
surface->current.release_timeline, surface->current.release_point);
surface->current.committed = false;
}
@ -507,7 +508,7 @@ static void release_signaller_handle_buffer_release(struct wl_listener *listener
bool wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer(
struct wlr_linux_drm_syncobj_surface_v1_state *state, struct wlr_buffer *buffer) {
assert(buffer->n_locks > 0);
if (state->release_timeline == NULL) {
if (state->release_merger == NULL) {
// This can happen if an existing surface with a buffer has a
// syncobj_surface_v1_state created but no new buffer with release
// timeline committed.
@ -530,6 +531,12 @@ bool wlr_linux_drm_syncobj_v1_state_add_release_point(
struct wlr_linux_drm_syncobj_surface_v1_state *state,
struct wlr_drm_syncobj_timeline *release_timeline, uint64_t release_point,
struct wl_event_loop *event_loop) {
if (state->release_merger == NULL) {
// This can happen if an existing surface with a buffer has a
// syncobj_surface_v1_state created but no new buffer with release
// timeline committed.
return true;
}
return wlr_drm_syncobj_merger_add(state->release_merger,
release_timeline, release_point, event_loop);
}