aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephane Chauveau <stephane@chauveau-central.net>2020-07-16 18:38:35 +0000
committerSimon Ser <contact@emersion.fr>2020-12-08 18:38:42 +0100
commitb790e5ea3479b0024c5bdd6ad5ad4f6fa46c89db (patch)
tree321d5c4a6c136e11295505d7c1f0c5f506fcce8f
parent863acb26c0326f6e0ccc6140ba86d41d2b3f09ab (diff)
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 <contact@emersion.fr>
-rw-r--r--backend/drm/drm.c33
1 files changed, 18 insertions, 15 deletions
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;