From b790e5ea3479b0024c5bdd6ad5ad4f6fa46c89db Mon Sep 17 00:00:00 2001 From: Stephane Chauveau Date: Thu, 16 Jul 2020 18:38:35 +0000 Subject: backend/drm: don't assume possible_crtcs has only one bit set This isn't necessarily the case [1]. This should fix an assertion failure on Raspberry Pi 4 dual screen. [1]: https://lists.freedesktop.org/archives/dri-devel/2020-August/275142.html Closes: https://github.com/swaywm/wlroots/issues/1943 Co-authored-by: Simon Ser --- backend/drm/drm.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'backend') diff --git a/backend/drm/drm.c b/backend/drm/drm.c index c0186f36..cbc1ae47 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -204,23 +204,26 @@ static bool init_planes(struct wlr_drm_backend *drm) { continue; } - /* - * This is a very naive implementation of the plane matching - * logic. Primary and cursor planes should only work on a - * single CRTC, and this should be perfectly adequate, but - * overlay planes can potentially work with multiple CRTCs, - * meaning this could return inefficient/skewed results. - * - * possible_crtcs is a bitmask of crtcs, where each bit is an - * index into drmModeRes.crtcs. So if bit 0 is set (ffs starts - * counting from 1), crtc 0 is possible. - */ - int crtc_bit = ffs(plane->possible_crtcs) - 1; + assert(drm->num_crtcs <= 32); + struct wlr_drm_crtc *crtc = NULL; + for (size_t j = 0; j < drm->num_crtcs ; j++) { + uint32_t crtc_bit = 1 << j; + if ((plane->possible_crtcs & crtc_bit) == 0) { + continue; + } - // This would be a kernel bug - assert(crtc_bit >= 0 && (size_t)crtc_bit < drm->num_crtcs); + struct wlr_drm_crtc *candidate = &drm->crtcs[j]; + if ((type == DRM_PLANE_TYPE_PRIMARY && !candidate->primary) || + (type == DRM_PLANE_TYPE_CURSOR && !candidate->cursor)) { + crtc = candidate; + break; + } + } + if (!crtc) { + drmModeFreePlane(plane); + continue; + } - struct wlr_drm_crtc *crtc = &drm->crtcs[crtc_bit]; if (!add_plane(drm, crtc, plane, type, &props)) { drmModeFreePlane(plane); goto error; -- cgit v1.2.3