diff options
author | Simon Ser <contact@emersion.fr> | 2022-10-13 15:29:31 +0200 |
---|---|---|
committer | Simon Zeni <simon@bl4ckb0ne.ca> | 2022-10-14 15:13:14 +0000 |
commit | 9560a7eefdffcd3694827bd2c6db28696f6ac957 (patch) | |
tree | 18e3942c4289d0345753560a611b3b23eb51d1fa /backend/drm/drm.c | |
parent | 3a949ea8eb0277f52d10ef0d54760323752321c9 (diff) |
backend/drm: use atomic API to fetch current connector's CRTC
We were using the legacy API (with a detour through drmModeEncoder)
to find out the current CRTC for a connector. Use the atomic API
when available.
Also extract the whole logic into a separate function for better
readability, and better handle errors.
Diffstat (limited to 'backend/drm/drm.c')
-rw-r--r-- | backend/drm/drm.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c index d5e6c21e..77555aa2 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1117,6 +1117,46 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, } } +static struct wlr_drm_crtc *connector_get_current_crtc( + struct wlr_drm_connector *wlr_conn, const drmModeConnector *drm_conn) { + struct wlr_drm_backend *drm = wlr_conn->backend; + + uint32_t crtc_id = 0; + if (wlr_conn->props.crtc_id != 0) { + uint64_t value; + if (!get_drm_prop(drm->fd, wlr_conn->id, + wlr_conn->props.crtc_id, &value)) { + wlr_drm_conn_log(wlr_conn, WLR_ERROR, + "Failed to get CRTC_ID connector property"); + return NULL; + } + crtc_id = (uint32_t)value; + } else if (drm_conn->encoder_id != 0) { + // Fallback to the legacy API + drmModeEncoder *enc = drmModeGetEncoder(drm->fd, drm_conn->encoder_id); + if (enc == NULL) { + wlr_drm_conn_log(wlr_conn, WLR_ERROR, + "drmModeGetEncoder() failed"); + return NULL; + } + crtc_id = enc->crtc_id; + drmModeFreeEncoder(enc); + } + if (crtc_id == 0) { + return NULL; + } + + for (size_t i = 0; i < drm->num_crtcs; ++i) { + if (drm->crtcs[i].id == crtc_id) { + return &drm->crtcs[i]; + } + } + + wlr_drm_conn_log(wlr_conn, WLR_ERROR, + "Failed to find current CRTC ID %" PRIu32, crtc_id); + return NULL; +} + static void disconnect_drm_connector(struct wlr_drm_connector *conn); void scan_drm_connectors(struct wlr_drm_backend *drm, @@ -1170,14 +1210,11 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, wlr_log_errno(WLR_ERROR, "Failed to get DRM connector"); continue; } - drmModeEncoder *curr_enc = drmModeGetEncoder(drm->fd, - drm_conn->encoder_id); if (!wlr_conn) { wlr_conn = calloc(1, sizeof(*wlr_conn)); if (!wlr_conn) { wlr_log_errno(WLR_ERROR, "Allocation failed"); - drmModeFreeEncoder(curr_enc); drmModeFreeConnector(drm_conn); continue; } @@ -1201,16 +1238,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, seen[index] = true; } - if (curr_enc) { - for (size_t i = 0; i < drm->num_crtcs; ++i) { - if (drm->crtcs[i].id == curr_enc->crtc_id) { - wlr_conn->crtc = &drm->crtcs[i]; - break; - } - } - } else { - wlr_conn->crtc = NULL; - } + wlr_conn->crtc = connector_get_current_crtc(wlr_conn, drm_conn); // This can only happen *after* hotplug, since we haven't read the // connector properties yet @@ -1371,7 +1399,6 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, disconnect_drm_connector(wlr_conn); } - drmModeFreeEncoder(curr_enc); drmModeFreeConnector(drm_conn); } |