diff --git a/src/backend/drm/backend.rs b/src/backend/drm/backend.rs index ef16315..57cc563 100644 --- a/src/backend/drm/backend.rs +++ b/src/backend/drm/backend.rs @@ -196,6 +196,10 @@ impl DrmBackendInternal { }) }); } + + pub(crate) fn is_crtc(&self, crtc: crtc::Handle) -> bool { + crtc == self.crtc + } } impl DrmBackend { diff --git a/src/backend/drm/error.rs b/src/backend/drm/error.rs index c689ee2..5e05e5c 100644 --- a/src/backend/drm/error.rs +++ b/src/backend/drm/error.rs @@ -23,6 +23,8 @@ pub enum Error { Io(IoError), /// Selected an invalid Mode Mode(ModeError), + /// Error related to the selected crtc + Crtc(CrtcError), } impl fmt::Display for Error { @@ -37,6 +39,7 @@ impl fmt::Display for Error { &Error::Gbm(ref x) => x as &error::Error, &Error::Io(ref x) => x as &error::Error, &Error::Mode(ref x) => x as &error::Error, + &Error::Crtc(ref x) => x as &error::Error, } ) } @@ -55,6 +58,7 @@ impl error::Error for Error { &Error::Gbm(ref x) => Some(x as &error::Error), &Error::Io(ref x) => Some(x as &error::Error), &Error::Mode(ref x) => Some(x as &error::Error), + &Error::Crtc(ref x) => Some(x as &error::Error), } } } @@ -98,6 +102,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: CrtcError) -> Error { + Error::Crtc(err) + } +} + impl From> for Error { fn from(err: TryNewError) -> Error { err.0 @@ -138,3 +148,34 @@ impl error::Error for ModeError { } } } + +/// Errors related to the selected crtc +#[derive(Debug)] +pub enum CrtcError { + /// Selected crtc is already in use by another `DrmBackend` + AlreadyInUse +} + +impl fmt::Display for CrtcError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.description())?; + if let Some(cause) = self.cause() { + write!(f, "\tCause: {}", cause)?; + } + Ok(()) + } +} + +impl error::Error for CrtcError { + fn description(&self) -> &str { + match self { + &CrtcError::AlreadyInUse => "Crtc is already in use by another DrmBackend", + } + } + + fn cause(&self) -> Option<&error::Error> { + match self { + _ => None, + } + } +} diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index e11bc65..19bfd09 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -164,7 +164,7 @@ mod error; pub use self::backend::{DrmBackend, Id}; use self::backend::DrmBackendInternal; -pub use self::error::{Error as DrmError, ModeError}; +pub use self::error::{Error as DrmError, ModeError, CrtcError}; /// Internal struct as required by the drm crate #[derive(Debug)] @@ -349,12 +349,18 @@ impl DrmDevice { where I: Into>, { + for backend in self.backends.iter() { + if let Some(backend) = backend.upgrade() { + if backend.borrow().is_crtc(crtc) { + return Err(DrmError::Crtc(CrtcError::AlreadyInUse)); + } + } + } + let logger = self.logger .new(o!("drm" => "backend", "crtc" => format!("{:?}", crtc))); let own_id = self.backends.len(); - // TODO: Make sure we do not initialize the same crtc multiple times - // (check weak pointers and return an error otherwise) let backend = Rc::new(RefCell::new(DrmBackendInternal::new( self.context.clone(), crtc,