From de8cc83ef376579c3853eaf8353c4a3d00328d00 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 6 Dec 2022 17:57:54 +0100 Subject: [PATCH 1/7] backend/drm: pass wlr_drm_crtc in set_plane_props() This is more type-safe than passing an integer: mixing it up with coordinates will give an error, for instance. --- backend/drm/atomic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index c69d6abd5..398951237 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -171,7 +171,7 @@ static void plane_disable(struct atomic *atom, struct wlr_drm_plane *plane) { } static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm, - struct wlr_drm_plane *plane, struct wlr_drm_fb *fb, uint32_t crtc_id, + struct wlr_drm_plane *plane, struct wlr_drm_fb *fb, struct wlr_drm_crtc *crtc, int32_t x, int32_t y) { uint32_t id = plane->id; const union wlr_drm_plane_props *props = &plane->props; @@ -193,7 +193,7 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm, atomic_add(atom, id, props->crtc_w, width); atomic_add(atom, id, props->crtc_h, height); atomic_add(atom, id, props->fb_id, fb->id); - atomic_add(atom, id, props->crtc_id, crtc_id); + atomic_add(atom, id, props->crtc_id, crtc->id); atomic_add(atom, id, props->crtc_x, (uint64_t)x); atomic_add(atom, id, props->crtc_y, (uint64_t)y); } @@ -294,7 +294,7 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, if (crtc->props.vrr_enabled != 0) { atomic_add(&atom, crtc->id, crtc->props.vrr_enabled, vrr_enabled); } - set_plane_props(&atom, drm, crtc->primary, state->primary_fb, crtc->id, + set_plane_props(&atom, drm, crtc->primary, state->primary_fb, crtc, 0, 0); if (crtc->primary->props.fb_damage_clips != 0) { atomic_add(&atom, crtc->primary->id, @@ -303,7 +303,7 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, if (crtc->cursor) { if (drm_connector_is_cursor_visible(conn)) { set_plane_props(&atom, drm, crtc->cursor, get_next_cursor_fb(conn), - crtc->id, conn->cursor_x, conn->cursor_y); + crtc, conn->cursor_x, conn->cursor_y); } else { plane_disable(&atom, crtc->cursor); } From ceb041e8ce60574b15606d216d0abe12a5d5faae Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 6 Dec 2022 18:31:03 +0100 Subject: [PATCH 2/7] backend/drm: add drm_connector_status_str() Helper to stringify a connector status. --- backend/drm/util.c | 12 ++++++++++++ include/backend/drm/util.h | 1 + 2 files changed, 13 insertions(+) diff --git a/backend/drm/util.c b/backend/drm/util.c index 03c4b0b46..adb9306e6 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -119,6 +119,18 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) } } +const char *drm_connector_status_str(drmModeConnection status) { + switch (status) { + case DRM_MODE_CONNECTED: + return "connected"; + case DRM_MODE_DISCONNECTED: + return "disconnected"; + case DRM_MODE_UNKNOWNCONNECTION: + return "unknown"; + } + return ""; +} + static bool is_taken(size_t n, const uint32_t arr[static n], uint32_t key) { for (size_t i = 0; i < n; ++i) { if (arr[i] == key) { diff --git a/include/backend/drm/util.h b/include/backend/drm/util.h index 9bfe5f8af..ba48fe6a2 100644 --- a/include/backend/drm/util.h +++ b/include/backend/drm/util.h @@ -14,6 +14,7 @@ enum wlr_output_mode_aspect_ratio get_picture_aspect_ratio(const drmModeModeInfo const char *get_pnp_manufacturer(uint16_t code); // Populates the make/model/phys_{width,height} of output from the edid data void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data); +const char *drm_connector_status_str(drmModeConnection status); // Part of match_obj enum { From c46f0b034e99c747a784a95c717600a1d38a7142 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 6 Dec 2022 18:32:07 +0100 Subject: [PATCH 3/7] backend/drm: print stringified connector status in realloc_crtcs() The raw enum value wasn't informative enough. It's not trivial to tell whether 0 means connected or disconnected. Drop the status from the state after realloc, since the exact same information is printed right above. --- backend/drm/drm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 9b728bbb3..b37ac73cd 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1059,9 +1059,9 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, // connector the user wants to enable bool want_crtc = conn == want_conn || conn->output.enabled; - wlr_log(WLR_DEBUG, " '%s' crtc=%d status=%d want_crtc=%d", + wlr_log(WLR_DEBUG, " '%s': crtc=%d status=%s want_crtc=%d", conn->name, conn->crtc ? (int)(conn->crtc - drm->crtcs) : -1, - conn->status, want_crtc); + drm_connector_status_str(conn->status), want_crtc); if (conn->status == DRM_MODE_CONNECTED && want_crtc) { connector_constraints[i] = conn->possible_crtcs; @@ -1108,8 +1108,8 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_connector *conn = connectors[i]; bool prev_enabled = conn->crtc; - wlr_log(WLR_DEBUG, " '%s' crtc=%zd status=%d", - conn->name, connector_match[i], conn->status); + 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) { From 6c1355ec0bbb36dcd55c31ab854768ad745fe7c5 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 6 Dec 2022 18:50:53 +0100 Subject: [PATCH 4/7] backend/drm: rename wlr_drm_backend.outputs to connectors This list contains wlr_drm_connector entries, and there is no guarantee that the wlr_output fields are initialized. --- backend/drm/backend.c | 6 +++--- backend/drm/drm.c | 36 ++++++++++++++++++------------------ include/backend/drm/drm.h | 4 ++-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index fc3838329..1492c4d4c 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -33,7 +33,7 @@ static void backend_destroy(struct wlr_backend *backend) { struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend); struct wlr_drm_connector *conn, *next; - wl_list_for_each_safe(conn, next, &drm->outputs, link) { + wl_list_for_each_safe(conn, next, &drm->connectors, link) { destroy_drm_connector(conn); } @@ -104,7 +104,7 @@ static void handle_session_active(struct wl_listener *listener, void *data) { scan_drm_connectors(drm, NULL); struct wlr_drm_connector *conn; - wl_list_for_each(conn, &drm->outputs, link) { + wl_list_for_each(conn, &drm->connectors, link) { struct wlr_output_mode *mode = NULL; uint32_t committed = WLR_OUTPUT_STATE_ENABLED; if (conn->status != DRM_MODE_DISCONNECTED && conn->output.enabled @@ -195,7 +195,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, drm->session = session; wl_list_init(&drm->fbs); - wl_list_init(&drm->outputs); + wl_list_init(&drm->connectors); drm->dev = dev; drm->fd = dev->fd; diff --git a/backend/drm/drm.c b/backend/drm/drm.c index b37ac73cd..d3169b7d7 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1029,15 +1029,15 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_connector *want_conn) { assert(drm->num_crtcs > 0); - size_t num_outputs = wl_list_length(&drm->outputs); - if (num_outputs == 0) { + size_t num_connectors = wl_list_length(&drm->connectors); + if (num_connectors == 0) { return; } wlr_log(WLR_DEBUG, "Reallocating CRTCs"); - struct wlr_drm_connector *connectors[num_outputs]; - uint32_t connector_constraints[num_outputs]; + struct wlr_drm_connector *connectors[num_connectors]; + uint32_t connector_constraints[num_connectors]; uint32_t previous_match[drm->num_crtcs]; uint32_t new_match[drm->num_crtcs]; @@ -1048,7 +1048,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, wlr_log(WLR_DEBUG, "State before reallocation:"); size_t i = 0; struct wlr_drm_connector *conn; - wl_list_for_each(conn, &drm->outputs, link) { + wl_list_for_each(conn, &drm->connectors, link) { connectors[i] = conn; if (conn->crtc) { @@ -1073,12 +1073,12 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, ++i; } - match_obj(num_outputs, connector_constraints, + match_obj(num_connectors, connector_constraints, drm->num_crtcs, previous_match, new_match); // Converts our crtc=>connector result into a connector=>crtc one. - ssize_t connector_match[num_outputs]; - for (size_t i = 0 ; i < num_outputs; ++i) { + ssize_t connector_match[num_connectors]; + for (size_t i = 0 ; i < num_connectors; ++i) { connector_match[i] = -1; } for (size_t i = 0; i < drm->num_crtcs; ++i) { @@ -1092,7 +1092,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, * match everything, we prefer to fail the new connector and keep all * of the old mappings instead. */ - for (size_t i = 0; i < num_outputs; ++i) { + 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) { @@ -1104,7 +1104,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, wlr_log(WLR_DEBUG, "State after reallocation:"); // Apply new configuration - for (size_t i = 0; i < num_outputs; ++i) { + for (size_t i = 0; i < num_connectors; ++i) { struct wlr_drm_connector *conn = connectors[i]; bool prev_enabled = conn->crtc; @@ -1200,7 +1200,7 @@ static struct wlr_drm_connector *create_drm_connector(struct wlr_drm_backend *dr wlr_conn->crtc = connector_get_current_crtc(wlr_conn, drm_conn); - wl_list_insert(drm->outputs.prev, &wlr_conn->link); + wl_list_insert(drm->connectors.prev, &wlr_conn->link); return wlr_conn; } @@ -1364,7 +1364,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, return; } - size_t seen_len = wl_list_length(&drm->outputs); + size_t seen_len = wl_list_length(&drm->connectors); // +1 so length can never be 0, which is undefined behaviour. // Last element isn't used. bool seen[seen_len + 1]; @@ -1377,7 +1377,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, ssize_t index = -1; struct wlr_drm_connector *c, *wlr_conn = NULL; - wl_list_for_each(c, &drm->outputs, link) { + wl_list_for_each(c, &drm->connectors, link) { index++; if (c->id == conn_id) { wlr_conn = c; @@ -1448,8 +1448,8 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, // Iterate in reverse order because we'll remove items from the list and // still want indices to remain correct. struct wlr_drm_connector *conn, *tmp_conn; - size_t index = wl_list_length(&drm->outputs); - wl_list_for_each_reverse_safe(conn, tmp_conn, &drm->outputs, link) { + size_t index = wl_list_length(&drm->connectors); + wl_list_for_each_reverse_safe(conn, tmp_conn, &drm->connectors, link) { index--; if (index >= seen_len || seen[index]) { continue; @@ -1478,7 +1478,7 @@ void scan_drm_leases(struct wlr_drm_backend *drm) { } struct wlr_drm_connector *conn; - wl_list_for_each(conn, &drm->outputs, link) { + wl_list_for_each(conn, &drm->connectors, link) { if (conn->lease == NULL) { continue; } @@ -1510,7 +1510,7 @@ static void handle_page_flip(int fd, unsigned seq, bool found = false; struct wlr_drm_connector *conn; - wl_list_for_each(conn, &drm->outputs, link) { + wl_list_for_each(conn, &drm->connectors, link) { if (conn->pending_page_flip_crtc == crtc_id) { found = true; break; @@ -1721,7 +1721,7 @@ void drm_lease_destroy(struct wlr_drm_lease *lease) { wl_signal_emit_mutable(&lease->events.destroy, NULL); struct wlr_drm_connector *conn; - wl_list_for_each(conn, &drm->outputs, link) { + wl_list_for_each(conn, &drm->connectors, link) { if (conn->lease == lease) { conn->lease = NULL; } diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index fa18225c6..16126ec2e 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -75,7 +75,7 @@ struct wlr_drm_backend { struct wl_listener dev_remove; struct wl_list fbs; // wlr_drm_fb.link - struct wl_list outputs; + struct wl_list connectors; // wlr_drm_connector.link /* Only initialized on multi-GPU setups */ struct wlr_drm_renderer mgpu_renderer; @@ -122,7 +122,7 @@ struct wlr_drm_connector { /* Buffer to be submitted to the kernel on the next page-flip */ struct wlr_drm_fb *cursor_pending_fb; - struct wl_list link; + struct wl_list link; // wlr_drm_backend.connectors /* CRTC ID if a page-flip is pending, zero otherwise. * From addf4a4e7c6a941e3bb2cac67ab9d9d093a831c9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 6 Dec 2022 19:01:24 +0100 Subject: [PATCH 5/7] 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 --- backend/drm/drm.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index d3169b7d7..863dada9f 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1087,46 +1087,40 @@ 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; - } - conn->crtc = &drm->crtcs[connector_match[i]]; } } From bf5114df6fc60df3204fd1f7a6cc162d41d77321 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 6 Dec 2022 19:18:48 +0100 Subject: [PATCH 6/7] backend/drm: add wlr_drm_connector_state.conn Allows one to get back the connector from its state. Avoids having to pass both structs around as function arguments. --- backend/drm/drm.c | 1 + include/backend/drm/drm.h | 1 + 2 files changed, 2 insertions(+) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 863dada9f..845f079e7 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -354,6 +354,7 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state, struct wlr_drm_connector *conn, const struct wlr_output_state *base) { memset(state, 0, sizeof(*state)); + state->conn = conn; state->base = base; state->modeset = base->allow_artifacts; state->active = (base->committed & WLR_OUTPUT_STATE_ENABLED) ? diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 16126ec2e..12341c60a 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -93,6 +93,7 @@ struct wlr_drm_mode { }; struct wlr_drm_connector_state { + struct wlr_drm_connector *conn; const struct wlr_output_state *base; bool modeset; bool active; From 8fb34d1d00b5e9b1ad53a6902878c7469f82e87f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 6 Dec 2022 18:15:04 +0100 Subject: [PATCH 7/7] wip: backend/drm: move pending CRTC to connector state --- backend/drm/atomic.c | 2 +- backend/drm/drm.c | 37 ++++++++++++++++++------------------- backend/drm/legacy.c | 2 +- include/backend/drm/drm.h | 1 + 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 398951237..a0998a45c 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -203,10 +203,10 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, bool test_only) { struct wlr_drm_backend *drm = conn->backend; struct wlr_output *output = &conn->output; - struct wlr_drm_crtc *crtc = conn->crtc; bool modeset = state->modeset; bool active = state->active; + struct wlr_drm_crtc *crtc = state->crtc; uint32_t mode_id = crtc->mode_id; if (modeset) { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 845f079e7..babc423b2 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -329,7 +329,7 @@ static bool drm_crtc_commit(struct wlr_drm_connector *conn, assert((flags & ~DRM_MODE_PAGE_FLIP_FLAGS) == 0); struct wlr_drm_backend *drm = conn->backend; - struct wlr_drm_crtc *crtc = conn->crtc; + struct wlr_drm_crtc *crtc = state->crtc; bool ok = drm->iface->crtc_commit(conn, state, flags, test_only); if (ok && !test_only) { drm_fb_clear(&crtc->primary->queued_fb); @@ -359,6 +359,7 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state, state->modeset = base->allow_artifacts; state->active = (base->committed & WLR_OUTPUT_STATE_ENABLED) ? base->enabled : conn->output.enabled; + state->crtc = conn->crtc; if (base->committed & WLR_OUTPUT_STATE_MODE) { switch (base->mode_type) { @@ -401,9 +402,7 @@ static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn assert(state->base->committed & WLR_OUTPUT_STATE_BUFFER); - struct wlr_drm_crtc *crtc = conn->crtc; - assert(crtc != NULL); - + struct wlr_drm_crtc *crtc = state->crtc; struct wlr_drm_plane *plane = crtc->primary; struct wlr_buffer *source_buf = state->base->buffer; @@ -444,7 +443,15 @@ static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn return true; } -static bool drm_connector_alloc_crtc(struct wlr_drm_connector *conn); +static void realloc_crtcs(struct wlr_drm_backend *drm, + struct wlr_drm_connector_state *want_conn_state); + +static bool drm_connector_state_alloc_crtc(struct wlr_drm_connector_state *state) { + if (state->crtc == NULL) { + realloc_crtcs(state->conn->backend, state); + } + return state->crtc != NULL; +} static bool drm_connector_test(struct wlr_output *output, const struct wlr_output_state *state) { @@ -488,7 +495,7 @@ static bool drm_connector_test(struct wlr_output *output, goto out; } - if (!drm_connector_alloc_crtc(conn)) { + if (!drm_connector_state_alloc_crtc(&pending)) { wlr_drm_conn_log(conn, WLR_DEBUG, "No CRTC available for this connector"); goto out; @@ -508,7 +515,7 @@ static bool drm_connector_test(struct wlr_output *output, goto out; } - if (!conn->crtc) { + if (!pending.crtc) { // If the output is disabled, we don't have a crtc even after // reallocation ok = true; @@ -578,7 +585,7 @@ bool drm_connector_commit_state(struct wlr_drm_connector *conn, } if (pending.active) { - if (!drm_connector_alloc_crtc(conn)) { + if (!drm_connector_state_alloc_crtc(&pending)) { wlr_drm_conn_log(conn, WLR_ERROR, "No CRTC available for this connector"); goto out; @@ -700,16 +707,6 @@ struct wlr_drm_fb *get_next_cursor_fb(struct wlr_drm_connector *conn) { return conn->crtc->cursor->current_fb; } -static void realloc_crtcs(struct wlr_drm_backend *drm, - struct wlr_drm_connector *want_conn); - -static bool drm_connector_alloc_crtc(struct wlr_drm_connector *conn) { - if (conn->crtc == NULL) { - realloc_crtcs(conn->backend, conn); - } - return conn->crtc != NULL; -} - static struct wlr_drm_mode *drm_mode_create(const drmModeModeInfo *modeinfo) { struct wlr_drm_mode *mode = calloc(1, sizeof(*mode)); if (!mode) { @@ -1027,9 +1024,11 @@ static void dealloc_crtc(struct wlr_drm_connector *conn) { } static void realloc_crtcs(struct wlr_drm_backend *drm, - struct wlr_drm_connector *want_conn) { + struct wlr_drm_connector_state *want_conn_state) { assert(drm->num_crtcs > 0); + struct wlr_drm_connector *want_conn = want_conn_state != NULL ? want_conn_state->conn : NULL; + size_t num_connectors = wl_list_length(&drm->connectors); if (num_connectors == 0) { return; diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c index a8f618cfb..88f9e233f 100644 --- a/backend/drm/legacy.c +++ b/backend/drm/legacy.c @@ -69,7 +69,7 @@ static bool legacy_crtc_commit(struct wlr_drm_connector *conn, struct wlr_drm_backend *drm = conn->backend; struct wlr_output *output = &conn->output; - struct wlr_drm_crtc *crtc = conn->crtc; + struct wlr_drm_crtc *crtc = state->crtc; struct wlr_drm_plane *cursor = crtc->cursor; uint32_t fb_id = 0; diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 12341c60a..176c38887 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -98,6 +98,7 @@ struct wlr_drm_connector_state { bool modeset; bool active; drmModeModeInfo mode; + struct wlr_drm_crtc *crtc; struct wlr_drm_fb *primary_fb; };