From 49330f469f9b0c0aae97663e9a77f517d6f603ab Mon Sep 17 00:00:00 2001 From: Anton Kindestam Date: Sat, 21 Apr 2018 15:16:47 +0200 Subject: [PATCH] drm_common: Be smarter when deciding on which CRTC and Encoder to use Inspired by kmscube, first try to pick the Encoder and CRTC already associated with the selected Connector, if any. Otherwise try to find the first matching encoder & CRTC like before. This should improve behavior somewhat when run on a multi screen setup with regards to deinit and VT switching, and should allow you to do stuff like see the fbcon terminal on one screen with video playing on the other, as well as not having one of the screens go blank after deinit if it wasn't previously (still not fool-proof. Sometimes you still end up with a blank screen where you previously had a cloned display of your fbcon). This is also preparatory for switching over to atomic modesetting, as doing modesetting via drmModeAtomicCommit will fail when you're trying to use a CRTC that is currently tied up to another Encoder & Connector, while drmModeSetCrtc is able to "steal" the CRTC in this case. --- video/out/drm_common.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/video/out/drm_common.c b/video/out/drm_common.c index 68c64d4298287..86005bd975b06 100644 --- a/video/out/drm_common.c +++ b/video/out/drm_common.c @@ -167,6 +167,27 @@ static bool setup_connector(struct kms *kms, const drmModeRes *res, static bool setup_crtc(struct kms *kms, const drmModeRes *res) { + // First try to find currently connected encoder and its current CRTC + for (unsigned int i = 0; i < res->count_encoders; i++) { + drmModeEncoder *encoder = drmModeGetEncoder(kms->fd, res->encoders[i]); + if (!encoder) { + MP_WARN(kms, "Cannot retrieve encoder %u:%u: %s\n", + i, res->encoders[i], mp_strerror(errno)); + continue; + } + + if (encoder->encoder_id == kms->connector->encoder_id && encoder->crtc_id != 0) { + MP_VERBOSE(kms, "Connector %u currently connected to encoder %u\n", + kms->connector->connector_id, kms->connector->encoder_id); + kms->encoder = encoder; + kms->crtc_id = encoder->crtc_id; + goto success; + } + + drmModeFreeEncoder(encoder); + } + + // Otherwise pick first legal encoder and CRTC combo for the connector for (unsigned int i = 0; i < kms->connector->count_encoders; ++i) { drmModeEncoder *encoder = drmModeGetEncoder(kms->fd, kms->connector->encoders[i]); @@ -184,7 +205,7 @@ static bool setup_crtc(struct kms *kms, const drmModeRes *res) kms->encoder = encoder; kms->crtc_id = res->crtcs[j]; - return true; + goto success; } drmModeFreeEncoder(encoder); @@ -193,6 +214,11 @@ static bool setup_crtc(struct kms *kms, const drmModeRes *res) MP_ERR(kms, "Connector %u has no suitable CRTC\n", kms->connector->connector_id); return false; + + success: + MP_VERBOSE(kms, "Selected Encoder %u with CRTC %u\n", + kms->encoder->encoder_id, kms->crtc_id); + return true; } static bool setup_mode(struct kms *kms, int mode_id)