aboutsummaryrefslogtreecommitdiff
path: root/backend/drm
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2022-10-13 15:29:31 +0200
committerSimon Zeni <simon@bl4ckb0ne.ca>2022-10-14 15:13:14 +0000
commit9560a7eefdffcd3694827bd2c6db28696f6ac957 (patch)
tree18e3942c4289d0345753560a611b3b23eb51d1fa /backend/drm
parent3a949ea8eb0277f52d10ef0d54760323752321c9 (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')
-rw-r--r--backend/drm/drm.c55
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);
}