aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2022-12-06 19:01:24 +0100
committerSimon Zeni <simon@bl4ckb0ne.ca>2022-12-13 19:15:09 +0000
commitbde68b1df79cef058a75d28c52a1544044bf3f70 (patch)
tree499f9ecb619accb59f2d418303b0892ab4a910d3
parent99fb2fefc340278b29c3af9a53a319059599c8c7 (diff)
backend/drm: refuse to switch CRTC for enabled connector
match_obj() might return a configuration where the CRTC for an enabled connector is switched to another one. We don't support this correctly: the wlr_output common code would need to query again the supported formats, re-allocate the swapchain, etc. What's more, the kernel doesn't even support this [1]: it requires planes to be disabled to change their CRTC, it rejects commits directly switching the CRTC used by a plane. [1]: https://cgit.freedesktop.org/drm/drm-misc/tree/drivers/gpu/drm/drm_atomic.c?h=6e90293618ed476d6b11f82ce724efbb9e9a071b#n697
-rw-r--r--backend/drm/drm.c40
1 files changed, 18 insertions, 22 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 919d9821..380e5629 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -1087,47 +1087,43 @@ static void realloc_crtcs(struct wlr_drm_backend *drm,
}
}
- /*
- * In the case that we add a new connector (hotplug) and we fail to
- * match everything, we prefer to fail the new connector and keep all
- * of the old mappings instead.
- */
+ // Refuse to remove a CRTC from an enabled connector, and refuse to
+ // change the CRTC of an enabled connector.
for (size_t i = 0; i < num_connectors; ++i) {
struct wlr_drm_connector *conn = connectors[i];
- if (conn->status == DRM_MODE_CONNECTED && conn->output.enabled &&
- connector_match[i] == -1) {
+ if (conn->status != DRM_MODE_CONNECTED || !conn->output.enabled) {
+ continue;
+ }
+ if (connector_match[i] == -1) {
wlr_log(WLR_DEBUG, "Could not match a CRTC for previously connected output; "
- "keeping old configuration");
+ "keeping old configuration");
+ return;
+ }
+ assert(conn->crtc != NULL);
+ if (connector_match[i] != conn->crtc - drm->crtcs) {
+ wlr_log(WLR_DEBUG, "Cannot switch CRTC for enabled output; "
+ "keeping old configuration");
return;
}
}
- wlr_log(WLR_DEBUG, "State after reallocation:");
// Apply new configuration
+ wlr_log(WLR_DEBUG, "State after reallocation:");
for (size_t i = 0; i < num_connectors; ++i) {
struct wlr_drm_connector *conn = connectors[i];
- bool prev_enabled = conn->crtc;
wlr_log(WLR_DEBUG, " '%s': crtc=%zd",
conn->name, connector_match[i]);
- // We don't need to change anything.
- if (prev_enabled && connector_match[i] == conn->crtc - drm->crtcs) {
+ if (conn->crtc != NULL && connector_match[i] == conn->crtc - drm->crtcs) {
+ // We don't need to change anything
continue;
}
dealloc_crtc(conn);
-
- if (connector_match[i] == -1) {
- if (prev_enabled) {
- wlr_drm_conn_log(conn, WLR_DEBUG, "Output has lost its CRTC");
- wlr_output_update_enabled(&conn->output, false);
- wlr_output_update_mode(&conn->output, NULL);
- }
- continue;
+ if (connector_match[i] >= 0) {
+ conn->crtc = &drm->crtcs[connector_match[i]];
}
-
- conn->crtc = &drm->crtcs[connector_match[i]];
}
}