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
This commit is contained in:
Simon Ser 2024-02-28 14:08:17 +01:00
parent f6659414ba
commit 16b42bf65b
5 changed files with 18 additions and 19 deletions

View File

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

View File

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

View File

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

View File

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

View File

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