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
This commit is contained in:
parent
99fb2fefc3
commit
bde68b1df7
|
@ -1087,49 +1087,45 @@ static void realloc_crtcs(struct wlr_drm_backend *drm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Refuse to remove a CRTC from an enabled connector, and refuse to
|
||||||
* In the case that we add a new connector (hotplug) and we fail to
|
// change the CRTC of an enabled connector.
|
||||||
* match everything, we prefer to fail the new connector and keep all
|
|
||||||
* of the old mappings instead.
|
|
||||||
*/
|
|
||||||
for (size_t i = 0; i < num_connectors; ++i) {
|
for (size_t i = 0; i < num_connectors; ++i) {
|
||||||
struct wlr_drm_connector *conn = connectors[i];
|
struct wlr_drm_connector *conn = connectors[i];
|
||||||
if (conn->status == DRM_MODE_CONNECTED && conn->output.enabled &&
|
if (conn->status != DRM_MODE_CONNECTED || !conn->output.enabled) {
|
||||||
connector_match[i] == -1) {
|
continue;
|
||||||
|
}
|
||||||
|
if (connector_match[i] == -1) {
|
||||||
wlr_log(WLR_DEBUG, "Could not match a CRTC for previously connected output; "
|
wlr_log(WLR_DEBUG, "Could not match a CRTC for previously connected output; "
|
||||||
"keeping old configuration");
|
"keeping old configuration");
|
||||||
return;
|
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
|
// Apply new configuration
|
||||||
|
wlr_log(WLR_DEBUG, "State after reallocation:");
|
||||||
for (size_t i = 0; i < num_connectors; ++i) {
|
for (size_t i = 0; i < num_connectors; ++i) {
|
||||||
struct wlr_drm_connector *conn = connectors[i];
|
struct wlr_drm_connector *conn = connectors[i];
|
||||||
bool prev_enabled = conn->crtc;
|
|
||||||
|
|
||||||
wlr_log(WLR_DEBUG, " '%s': crtc=%zd",
|
wlr_log(WLR_DEBUG, " '%s': crtc=%zd",
|
||||||
conn->name, connector_match[i]);
|
conn->name, connector_match[i]);
|
||||||
|
|
||||||
// We don't need to change anything.
|
if (conn->crtc != NULL && connector_match[i] == conn->crtc - drm->crtcs) {
|
||||||
if (prev_enabled && connector_match[i] == conn->crtc - drm->crtcs) {
|
// We don't need to change anything
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dealloc_crtc(conn);
|
dealloc_crtc(conn);
|
||||||
|
if (connector_match[i] >= 0) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->crtc = &drm->crtcs[connector_match[i]];
|
conn->crtc = &drm->crtcs[connector_match[i]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct wlr_drm_crtc *connector_get_current_crtc(
|
static struct wlr_drm_crtc *connector_get_current_crtc(
|
||||||
struct wlr_drm_connector *wlr_conn, const drmModeConnector *drm_conn) {
|
struct wlr_drm_connector *wlr_conn, const drmModeConnector *drm_conn) {
|
||||||
|
|
Loading…
Reference in New Issue