diff options
author | Simon Ser <contact@emersion.fr> | 2021-06-09 12:03:20 +0200 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2021-11-02 13:36:43 +0100 |
commit | e13f3f860861af4495619e05be0b1554e32362bc (patch) | |
tree | 085de17527394864385dabb3afcd788ce8713187 /backend | |
parent | 2ff4e113e237d9f461e41b994db6c53b5a66a3d0 (diff) |
backend/drm: handle per-connector hotplug events
When a connector ID is specified in a hotplug event, don't scan all
connectors. Only scan the connector that has changed.
Diffstat (limited to 'backend')
-rw-r--r-- | backend/drm/backend.c | 16 | ||||
-rw-r--r-- | backend/drm/drm.c | 39 |
2 files changed, 40 insertions, 15 deletions
diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 5e01eddf..cd5b8ee0 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -22,7 +22,7 @@ struct wlr_drm_backend *get_drm_backend_from_backend( static bool backend_start(struct wlr_backend *backend) { struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend); - scan_drm_connectors(drm); + scan_drm_connectors(drm, NULL); return true; } @@ -102,7 +102,7 @@ static void handle_session_active(struct wl_listener *listener, void *data) { if (session->active) { wlr_log(WLR_INFO, "DRM fd resumed"); - scan_drm_connectors(drm); + scan_drm_connectors(drm, NULL); struct wlr_drm_connector *conn; wl_list_for_each(conn, &drm->outputs, link) { @@ -127,13 +127,21 @@ static void handle_session_active(struct wl_listener *listener, void *data) { static void handle_dev_change(struct wl_listener *listener, void *data) { struct wlr_drm_backend *drm = wl_container_of(listener, drm, dev_change); + struct wlr_device_change_event *change = data; if (!drm->session->active) { return; } - wlr_log(WLR_DEBUG, "%s invalidated", drm->name); - scan_drm_connectors(drm); + // TODO: add and handle lease uevents + switch (change->type) { + case WLR_DEVICE_HOTPLUG:; + wlr_log(WLR_DEBUG, "Received hotplug event for %s", drm->name); + scan_drm_connectors(drm, &change->hotplug); + break; + default: + wlr_log(WLR_DEBUG, "Received unknown change event for %s", drm->name); + } } static void handle_dev_remove(struct wl_listener *listener, void *data) { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 191ad064..3031d09b 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1177,7 +1177,8 @@ static uint32_t get_possible_crtcs(int fd, const drmModeConnector *conn) { static void disconnect_drm_connector(struct wlr_drm_connector *conn); -void scan_drm_connectors(struct wlr_drm_backend *drm) { +void scan_drm_connectors(struct wlr_drm_backend *drm, + struct wlr_device_hotplug_event *event) { /* * This GPU is not really a modesetting device. * It's just being used as a renderer. @@ -1186,7 +1187,12 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { return; } - wlr_log(WLR_INFO, "Scanning DRM connectors on %s", drm->name); + if (event != NULL && event->connector_id != 0) { + wlr_log(WLR_INFO, "Scanning DRM connector %"PRIu32" on %s", + event->connector_id, drm->name); + } else { + wlr_log(WLR_INFO, "Scanning DRM connectors on %s", drm->name); + } drmModeRes *res = drmModeGetResources(drm->fd); if (!res) { @@ -1203,25 +1209,36 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { struct wlr_drm_connector *new_outputs[res->count_connectors + 1]; for (int i = 0; i < res->count_connectors; ++i) { - drmModeConnector *drm_conn = drmModeGetConnector(drm->fd, - res->connectors[i]); - if (!drm_conn) { - wlr_log_errno(WLR_ERROR, "Failed to get DRM connector"); - continue; - } - drmModeEncoder *curr_enc = drmModeGetEncoder(drm->fd, - drm_conn->encoder_id); + uint32_t conn_id = res->connectors[i]; ssize_t index = -1; struct wlr_drm_connector *c, *wlr_conn = NULL; wl_list_for_each(c, &drm->outputs, link) { index++; - if (c->id == drm_conn->connector_id) { + if (c->id == conn_id) { wlr_conn = c; break; } } + // If the hotplug event contains a connector ID, ignore any other + // connector. + if (event != NULL && event->connector_id != 0 && + event->connector_id != conn_id) { + if (wlr_conn != NULL) { + seen[index] = true; + } + continue; + } + + drmModeConnector *drm_conn = drmModeGetConnector(drm->fd, conn_id); + if (!drm_conn) { + 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) { |