From ab77a8772517371873fee2a1d33c0d6c238a248b Mon Sep 17 00:00:00 2001 From: Drakulix Date: Fri, 15 Sep 2017 15:52:00 +0200 Subject: [PATCH] drm: Check for valid encoder --- Cargo.toml | 2 +- src/backend/drm/error.rs | 3 +++ src/backend/drm/mod.rs | 24 +++++++++++++++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 699d88d..98050f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,4 +42,4 @@ renderer_glium = ["glium"] "wayland-server:0.9.9" = { git = "https://github.com/Drakulix/wayland-rs", branch = "raw_handler_access"} "wayland-protocols:0.9.9" = { git = "https://github.com/Drakulix/wayland-rs", branch = "raw_handler_access"} "wayland-client:0.9.9" = { git = "https://github.com/Drakulix/wayland-rs", branch = "raw_handler_access"} -"drm:0.2.1" = { git = "https://github.com/Drakulix/drm-rs", branch = "fix/userdata" } +"drm:0.2.1" = { git = "https://github.com/Drakulix/drm-rs", branch = "future" } diff --git a/src/backend/drm/error.rs b/src/backend/drm/error.rs index 01f7d2c..f652c5a 100644 --- a/src/backend/drm/error.rs +++ b/src/backend/drm/error.rs @@ -154,6 +154,8 @@ impl error::Error for ModeError { pub enum CrtcError { /// Selected crtc is already in use by another `DrmBackend` AlreadyInUse, + /// For the selected crtc no encoder exists that supports all connectors + NoSuitableEncoder, } impl fmt::Display for CrtcError { @@ -170,6 +172,7 @@ impl error::Error for CrtcError { fn description(&self) -> &str { match self { &CrtcError::AlreadyInUse => "Crtc is already in use by another DrmBackend", + &CrtcError::NoSuitableEncoder => "Crtc has no supported encoder that can drive all connectors", } } diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index f2a3a82..9075859 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -142,7 +142,7 @@ use backend::graphics::egl::{EGLContext, GlAttributes, PixelFormatRequirements}; use drm::Device as BasicDevice; -use drm::control::{connector, crtc, Mode}; +use drm::control::{connector, crtc, encoder, Mode, ResourceInfo}; use drm::control::Device as ControlDevice; use gbm::Device as GbmDevice; @@ -353,6 +353,8 @@ impl DrmDevice { where I: Into>, { + use std::collections::hash_set::HashSet; + for backend in self.backends.iter() { if let Some(backend) = backend.upgrade() { if backend.borrow().is_crtc(crtc) { @@ -361,6 +363,26 @@ impl DrmDevice { } } + // check if the given connectors and crtc match + let connectors = connectors.into(); + // get all encoders supported by this device + let mut set = self.context.head().head().resource_handles()?.encoders().iter().cloned().collect::>(); + for connector in connectors.iter() { + let info = connector::Info::load_from_device(self.context.head().head(), *connector)?; + // then check for every connector which encoders it does support + let conn_set = info.encoders().iter().cloned().collect::>(); + // and update the list of supported encoders for this combination + set = set.intersection(&conn_set).cloned().collect::>(); + } + + // check if there is any encoder left that can be connected to the crtc + let encoders: Vec = set.iter().map(|handle| encoder::Info::load_from_device(self.context.head().head(), *handle).map_err(DrmError::from)).collect::, DrmError>>()?; + if !encoders.iter().any(|enc| enc.supports_crtc(crtc)) { + return Err(DrmError::Crtc(CrtcError::NoSuitableEncoder)); + } + + // configuration is valid, the kernel will figure out the rest + let own_id = self.backends.len(); let logger = self.logger .new(o!("id" => format!("{}", own_id), "crtc" => format!("{:?}", crtc)));