aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2020-12-25 11:12:21 +0100
committerSimon Ser <contact@emersion.fr>2021-01-03 19:35:02 +0100
commitadfb7cd35a364cfbb197720bbb821ccd3c22a613 (patch)
treeb0562b677b04e01fa3ffae22c574cb0866ab6d34
parent576ff57db09f6f4ee523a567712a3ffcf5dc45a8 (diff)
backend/drm: stash pending page-flip CRTC
wlr_drm_connector.crtc may be updated by the DRM backend while a page-flip is pending. In this case, the page-flip handler won't be able to find the right wlr_drm_connector from the CRTC ID. Save the CRTC when performing a page-flip to ensure we always find the right connector when we get the event.
-rw-r--r--backend/drm/drm.c27
-rw-r--r--include/backend/drm/drm.h5
2 files changed, 18 insertions, 14 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 4eb0eda4..1a8c2637 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -353,12 +353,13 @@ static bool drm_crtc_commit(struct wlr_drm_connector *conn, uint32_t flags) {
static bool drm_crtc_page_flip(struct wlr_drm_connector *conn) {
struct wlr_drm_crtc *crtc = conn->crtc;
+ assert(crtc != NULL);
// wlr_drm_interface.crtc_commit will perform either a non-blocking
// page-flip, either a blocking modeset. When performing a blocking modeset
// we'll wait for all queued page-flips to complete, so we don't need this
// safeguard.
- if (conn->pageflip_pending && !crtc->pending_modeset) {
+ if (conn->pending_page_flip_crtc && !crtc->pending_modeset) {
wlr_drm_conn_log(conn, WLR_ERROR, "Failed to page-flip output: "
"a page-flip is already pending");
return false;
@@ -370,7 +371,7 @@ static bool drm_crtc_page_flip(struct wlr_drm_connector *conn) {
return false;
}
- conn->pageflip_pending = true;
+ conn->pending_page_flip_crtc = crtc->id;
// wlr_output's API guarantees that submitting a buffer will schedule a
// frame event. However the DRM backend will also schedule a frame event
@@ -1017,7 +1018,7 @@ static void drm_connector_destroy_output(struct wlr_output *output) {
conn->desired_enabled = false;
conn->desired_mode = NULL;
conn->possible_crtcs = 0;
- conn->pageflip_pending = false;
+ conn->pending_page_flip_crtc = 0;
struct wlr_drm_mode *mode, *mode_tmp;
wl_list_for_each_safe(mode, mode_tmp, &conn->output.modes, wlr_mode.link) {
@@ -1443,22 +1444,24 @@ static void page_flip_handler(int fd, unsigned seq,
unsigned tv_sec, unsigned tv_usec, unsigned crtc_id, void *data) {
struct wlr_drm_backend *drm = data;
- struct wlr_drm_connector *conn = NULL;
- struct wlr_drm_connector *search;
- wl_list_for_each(search, &drm->outputs, link) {
- if (search->crtc && search->crtc->id == crtc_id) {
- conn = search;
+ bool found = false;
+ struct wlr_drm_connector *conn;
+ wl_list_for_each(conn, &drm->outputs, link) {
+ if (conn->pending_page_flip_crtc == crtc_id) {
+ found = true;
break;
}
}
- if (!conn) {
- wlr_log(WLR_DEBUG, "No connector for CRTC %u", crtc_id);
+ if (!found) {
+ wlr_log(WLR_DEBUG, "Unexpected page-flip event for CRTC %u", crtc_id);
return;
}
- conn->pageflip_pending = false;
+ conn->pending_page_flip_crtc = 0;
if (conn->state != WLR_DRM_CONN_CONNECTED || conn->crtc == NULL) {
+ wlr_drm_conn_log(conn, WLR_DEBUG,
+ "Ignoring page-flip event for disabled connector");
return;
}
@@ -1529,7 +1532,7 @@ void restore_drm_outputs(struct wlr_drm_backend *drm) {
size_t i = 0;
struct wlr_drm_connector *conn;
wl_list_for_each(conn, &drm->outputs, link) {
- if (conn->state != WLR_DRM_CONN_CLEANUP || !conn->pageflip_pending) {
+ if (conn->state != WLR_DRM_CONN_CLEANUP || !conn->pending_page_flip_crtc) {
to_close &= ~(UINT64_C(1) << i);
}
i++;
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index 3f2215fb..c3391dcf 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -129,13 +129,14 @@ struct wlr_drm_connector {
struct wl_list link;
- /*
+ /* CRTC ID if a page-flip is pending, zero otherwise.
+ *
* We've asked for a state change in the kernel, and yet to receive a
* notification for its completion. Currently, the kernel only has a
* queue length of 1, and no way to modify your submissions after
* they're sent.
*/
- bool pageflip_pending;
+ uint32_t pending_page_flip_crtc;
};
struct wlr_drm_backend *get_drm_backend_from_backend(