drm: Check for valid encoder

This commit is contained in:
Drakulix 2017-09-15 15:52:00 +02:00
parent 660080c45d
commit ab77a87725
3 changed files with 27 additions and 2 deletions

View File

@ -42,4 +42,4 @@ renderer_glium = ["glium"]
"wayland-server:0.9.9" = { git = "https://github.com/Drakulix/wayland-rs", branch = "raw_handler_access"} "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-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"} "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" }

View File

@ -154,6 +154,8 @@ impl error::Error for ModeError {
pub enum CrtcError { pub enum CrtcError {
/// Selected crtc is already in use by another `DrmBackend` /// Selected crtc is already in use by another `DrmBackend`
AlreadyInUse, AlreadyInUse,
/// For the selected crtc no encoder exists that supports all connectors
NoSuitableEncoder,
} }
impl fmt::Display for CrtcError { impl fmt::Display for CrtcError {
@ -170,6 +172,7 @@ impl error::Error for CrtcError {
fn description(&self) -> &str { fn description(&self) -> &str {
match self { match self {
&CrtcError::AlreadyInUse => "Crtc is already in use by another DrmBackend", &CrtcError::AlreadyInUse => "Crtc is already in use by another DrmBackend",
&CrtcError::NoSuitableEncoder => "Crtc has no supported encoder that can drive all connectors",
} }
} }

View File

@ -142,7 +142,7 @@
use backend::graphics::egl::{EGLContext, GlAttributes, PixelFormatRequirements}; use backend::graphics::egl::{EGLContext, GlAttributes, PixelFormatRequirements};
use drm::Device as BasicDevice; 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 drm::control::Device as ControlDevice;
use gbm::Device as GbmDevice; use gbm::Device as GbmDevice;
@ -353,6 +353,8 @@ impl<H: DrmHandler + 'static> DrmDevice<H> {
where where
I: Into<Vec<connector::Handle>>, I: Into<Vec<connector::Handle>>,
{ {
use std::collections::hash_set::HashSet;
for backend in self.backends.iter() { for backend in self.backends.iter() {
if let Some(backend) = backend.upgrade() { if let Some(backend) = backend.upgrade() {
if backend.borrow().is_crtc(crtc) { if backend.borrow().is_crtc(crtc) {
@ -361,6 +363,26 @@ impl<H: DrmHandler + 'static> DrmDevice<H> {
} }
} }
// 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::<HashSet<encoder::Handle>>();
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::<HashSet<encoder::Handle>>();
// and update the list of supported encoders for this combination
set = set.intersection(&conn_set).cloned().collect::<HashSet<encoder::Handle>>();
}
// check if there is any encoder left that can be connected to the crtc
let encoders: Vec<encoder::Info> = set.iter().map(|handle| encoder::Info::load_from_device(self.context.head().head(), *handle).map_err(DrmError::from)).collect::<Result<Vec<encoder::Info>, 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 own_id = self.backends.len();
let logger = self.logger let logger = self.logger
.new(o!("id" => format!("{}", own_id), "crtc" => format!("{:?}", crtc))); .new(o!("id" => format!("{}", own_id), "crtc" => format!("{:?}", crtc)));