From 16b42bf65b3054d828ad6a4676d690922bb9c799 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 28 Feb 2024 14:08:17 +0100 Subject: [PATCH] backend/drm: track cursor FB in wlr_drm_connector_state Use the same logic for cursor FBs as we currently use for primary FBs. This also fixes the same bug as [1] but in a different, more robust way. The new logic integrates better with atomic and will be required anyways in the future when set_cursor will be superseded by a better API. [1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4577 --- backend/drm/atomic.c | 2 +- backend/drm/drm.c | 29 ++++++++++++++--------------- backend/drm/legacy.c | 2 +- backend/drm/libliftoff.c | 2 +- include/backend/drm/drm.h | 2 +- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index c190a9fd..03d6466f 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -362,7 +362,7 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, } if (crtc->cursor) { if (drm_connector_is_cursor_visible(conn)) { - set_plane_props(&atom, drm, crtc->cursor, get_next_cursor_fb(conn), + set_plane_props(&atom, drm, crtc->cursor, state->cursor_fb, crtc->id, conn->cursor_x, conn->cursor_y); } else { plane_disable(&atom, crtc->cursor); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index cc90e99e..73dfb82f 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -468,9 +468,10 @@ static bool drm_crtc_commit(struct wlr_drm_connector *conn, bool ok = drm->iface->crtc_commit(conn, state, page_flip, flags, test_only); if (ok && !test_only) { drm_fb_copy(&crtc->primary->queued_fb, state->primary_fb); - if (crtc->cursor != NULL && conn->cursor_pending_fb != NULL) { - drm_fb_move(&crtc->cursor->queued_fb, &conn->cursor_pending_fb); + if (crtc->cursor != NULL) { + drm_fb_copy(&crtc->cursor->queued_fb, state->cursor_fb); } + drm_fb_clear(&conn->cursor_pending_fb); struct wlr_drm_layer *layer; wl_list_for_each(layer, &crtc->layers, link) { @@ -551,10 +552,21 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state, state->primary_fb = drm_fb_lock(primary->current_fb); } } + if (conn->crtc != NULL && conn->cursor_enabled) { + struct wlr_drm_plane *cursor = conn->crtc->cursor; + if (conn->cursor_pending_fb != NULL) { + state->cursor_fb = drm_fb_lock(conn->cursor_pending_fb); + } else if (cursor->queued_fb != NULL) { + state->cursor_fb = drm_fb_lock(cursor->queued_fb); + } else if (cursor->current_fb != NULL) { + state->cursor_fb = drm_fb_lock(cursor->current_fb); + } + } } static void drm_connector_state_finish(struct wlr_drm_connector_state *state) { drm_fb_clear(&state->primary_fb); + drm_fb_clear(&state->cursor_fb); } static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn, @@ -877,19 +889,6 @@ static size_t drm_connector_get_gamma_size(struct wlr_output *output) { return drm_crtc_get_gamma_lut_size(drm, crtc); } -struct wlr_drm_fb *get_next_cursor_fb(struct wlr_drm_connector *conn) { - if (!conn->cursor_enabled || conn->crtc == NULL) { - return NULL; - } - if (conn->cursor_pending_fb != NULL) { - return conn->cursor_pending_fb; - } - if (conn->crtc->cursor->queued_fb != NULL) { - return conn->crtc->cursor->queued_fb; - } - return conn->crtc->cursor->current_fb; -} - static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_connector *want_conn); diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c index 1e62f61f..f8cabbd0 100644 --- a/backend/drm/legacy.c +++ b/backend/drm/legacy.c @@ -134,7 +134,7 @@ static bool legacy_crtc_commit(struct wlr_drm_connector *conn, } if (cursor != NULL && drm_connector_is_cursor_visible(conn)) { - struct wlr_drm_fb *cursor_fb = get_next_cursor_fb(conn); + struct wlr_drm_fb *cursor_fb = state->cursor_fb; if (cursor_fb == NULL) { wlr_drm_conn_log(conn, WLR_DEBUG, "Failed to acquire cursor FB"); return false; diff --git a/backend/drm/libliftoff.c b/backend/drm/libliftoff.c index 79f83954..1d38c8f7 100644 --- a/backend/drm/libliftoff.c +++ b/backend/drm/libliftoff.c @@ -419,7 +419,7 @@ static bool crtc_commit(struct wlr_drm_connector *conn, if (crtc->cursor) { if (drm_connector_is_cursor_visible(conn)) { ok = ok && set_plane_props(crtc->cursor, crtc->cursor->liftoff_layer, - get_next_cursor_fb(conn), conn->cursor_x, conn->cursor_y, + state->cursor_fb, conn->cursor_x, conn->cursor_y, wl_list_length(&crtc->layers) + 1); } else { ok = ok && disable_plane(crtc->cursor); diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index cea53f44..675c5db2 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -129,6 +129,7 @@ struct wlr_drm_connector_state { bool active; drmModeModeInfo mode; struct wlr_drm_fb *primary_fb; + struct wlr_drm_fb *cursor_fb; }; /** @@ -196,7 +197,6 @@ size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm, void drm_lease_destroy(struct wlr_drm_lease *lease); void drm_page_flip_destroy(struct wlr_drm_page_flip *page_flip); -struct wlr_drm_fb *get_next_cursor_fb(struct wlr_drm_connector *conn); struct wlr_drm_layer *get_drm_layer(struct wlr_drm_backend *drm, struct wlr_output_layer *layer);