diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index affb0223f..1ca1467c7 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -302,7 +302,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, plane_get_next_fb(crtc->cursor), + set_plane_props(&atom, drm, crtc->cursor, get_next_cursor_fb(conn), 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 52d455dbb..73920f0eb 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -334,7 +334,7 @@ static bool drm_crtc_commit(struct wlr_drm_connector *conn, if (ok && !test_only) { drm_fb_move(&crtc->primary->queued_fb, &crtc->primary->pending_fb); if (crtc->cursor != NULL) { - drm_fb_move(&crtc->cursor->queued_fb, &crtc->cursor->pending_fb); + drm_fb_move(&crtc->cursor->queued_fb, &conn->cursor_pending_fb); } } else { drm_fb_clear(&crtc->primary->pending_fb); @@ -659,6 +659,19 @@ 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; +} + struct wlr_drm_fb *plane_get_next_fb(struct wlr_drm_plane *plane) { if (plane->pending_fb) { return plane->pending_fb; @@ -786,7 +799,7 @@ static bool drm_connector_set_cursor(struct wlr_output *output, local_buf = wlr_buffer_lock(buffer); } - bool ok = drm_fb_import(&plane->pending_fb, drm, local_buf, + bool ok = drm_fb_import(&conn->cursor_pending_fb, drm, local_buf, &plane->formats); wlr_buffer_unlock(local_buf); if (!ok) { @@ -855,6 +868,7 @@ static void drm_connector_destroy_output(struct wlr_output *output) { conn->status = DRM_MODE_DISCONNECTED; conn->pending_page_flip_crtc = 0; + drm_fb_clear(&conn->cursor_pending_fb); struct wlr_drm_mode *mode, *mode_tmp; wl_list_for_each_safe(mode, mode_tmp, &conn->output.modes, wlr_mode.link) { diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c index c2ded98c4..6e6b33ddf 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 = plane_get_next_fb(cursor); + struct wlr_drm_fb *cursor_fb = get_next_cursor_fb(conn); if (cursor_fb == NULL) { wlr_drm_conn_log(conn, WLR_DEBUG, "Failed to acquire cursor FB"); return false; diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 1540aea4a..365f1ad2d 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -120,6 +120,8 @@ struct wlr_drm_connector { int cursor_x, cursor_y; int cursor_width, cursor_height; int cursor_hotspot_x, cursor_hotspot_y; + /* Buffer to be submitted to the kernel on the next page-flip */ + struct wlr_drm_fb *cursor_pending_fb; struct wl_list link; @@ -152,6 +154,7 @@ size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm, void drm_lease_destroy(struct wlr_drm_lease *lease); struct wlr_drm_fb *plane_get_next_fb(struct wlr_drm_plane *plane); +struct wlr_drm_fb *get_next_cursor_fb(struct wlr_drm_connector *conn); #define wlr_drm_conn_log(conn, verb, fmt, ...) \ wlr_log(verb, "connector %s: " fmt, conn->name, ##__VA_ARGS__)