From fa6742fb5ff115dd32318c050b1b5364a20c18a1 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Mon, 18 Sep 2017 16:58:20 +0200 Subject: [PATCH] The glory of error-chain --- Cargo.toml | 1 + src/backend/drm/backend.rs | 252 +++++++++++++++++++++++------------- src/backend/drm/error.rs | 207 ++++++----------------------- src/backend/drm/mod.rs | 39 +++--- src/backend/graphics/egl.rs | 212 +++++++++++++++--------------- src/backend/winit.rs | 85 ++++++------ src/lib.rs | 5 + 7 files changed, 380 insertions(+), 421 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 98050f5..ce826fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ clippy = { version = "*", optional = true } rental = "0.4.11" wayland-protocols = { version = "0.10.1", features = ["unstable_protocols", "server"] } image = "0.15.0" +error-chain = "0.11.0" [build-dependencies] gl_generator = "0.5" diff --git a/src/backend/drm/backend.rs b/src/backend/drm/backend.rs index 50789dc..6d0dedb 100644 --- a/src/backend/drm/backend.rs +++ b/src/backend/drm/backend.rs @@ -1,5 +1,5 @@ -use super::{CrtcError, DrmError, ModeError}; use super::devices; +use super::error::*; use backend::graphics::GraphicsBackend; use backend::graphics::egl::{EGLGraphicsBackend, EGLSurface, PixelFormat, SwapBuffersError}; use drm::buffer::Buffer; @@ -94,7 +94,7 @@ pub(crate) struct DrmBackendInternal { impl DrmBackendInternal { pub(crate) fn new(context: Rc, crtc: crtc::Handle, mode: Mode, connectors: I, own_id: usize, logger: L) - -> Result + -> Result where I: Into>, L: Into>, @@ -107,11 +107,12 @@ impl DrmBackendInternal { // check the connectors, if they suite the mode for connector in connectors.iter() { - if !connector::Info::load_from_device(context.head().head(), *connector)? + if !connector::Info::load_from_device(context.head().head(), *connector) + .chain_err(|| ErrorKind::DrmDev(format!("{:?}", context.head().head())))? .modes() .contains(&mode) { - return Err(DrmError::Mode(ModeError::ModeNotSuitable)); + bail!(ErrorKind::ModeNotSuitable(mode)) } } @@ -122,23 +123,31 @@ impl DrmBackendInternal { Ok(GbmTypes { cursor: { // Create an unused cursor buffer (we don't want an Option here) - context.devices.gbm.create_buffer_object( - 1, - 1, - GbmFormat::ARGB8888, - &[BufferObjectFlags::Cursor, BufferObjectFlags::Write], - )? + context + .devices + .gbm + .create_buffer_object( + 1, + 1, + GbmFormat::ARGB8888, + &[BufferObjectFlags::Cursor, BufferObjectFlags::Write], + ) + .chain_err(|| ErrorKind::GbmInitFailed)? }, surface: Surface::try_new( { debug!(log, "Creating GbmSurface"); // create a gbm surface - Box::new(context.devices.gbm.create_surface( - w as u32, - h as u32, - GbmFormat::XRGB8888, - &[BufferObjectFlags::Scanout, BufferObjectFlags::Rendering], - )?) + Box::new(context + .devices + .gbm + .create_surface( + w as u32, + h as u32, + GbmFormat::XRGB8888, + &[BufferObjectFlags::Scanout, BufferObjectFlags::Rendering], + ) + .chain_err(|| ErrorKind::GbmInitFailed)?) }, |surface| { // create an egl surface from the gbm one @@ -147,15 +156,24 @@ impl DrmBackendInternal { // make it active for the first `crtc::set` // (which is needed before the first page_flip) - unsafe { egl_surface.make_current()? }; - egl_surface.swap_buffers()?; + unsafe { + egl_surface + .make_current() + .chain_err(|| ErrorKind::FailedToSwap)? + }; + egl_surface + .swap_buffers() + .chain_err(|| ErrorKind::FailedToSwap)?; // init the first screen // (must be done before calling page_flip for the first time) - let mut front_bo = surface.lock_front_buffer()?; + let mut front_bo = surface + .lock_front_buffer() + .chain_err(|| ErrorKind::FailedToSwap)?; debug!(log, "FrontBuffer color format: {:?}", front_bo.format()); // we need a framebuffer per front buffer - let fb = framebuffer::create(context.devices.drm, &*front_bo)?; + let fb = framebuffer::create(context.devices.drm, &*front_bo) + .chain_err(|| ErrorKind::DrmDev(format!("{:?}", context.devices.drm)))?; debug!(log, "Initialize screen"); crtc::set( @@ -165,6 +183,8 @@ impl DrmBackendInternal { &connectors, (0, 0), Some(mode), + ).chain_err( + || ErrorKind::DrmDev(format!("{:?}", context.devices.drm)), )?; front_bo.set_userdata(fb); @@ -176,7 +196,7 @@ impl DrmBackendInternal { }, }) }, - ).map_err(DrmError::from)?, + ).map_err(Error::from)?, }) })?, crtc, @@ -216,10 +236,15 @@ impl DrmBackend { /// # Errors /// /// Errors if the new connector does not support the currently set `Mode` - pub fn add_connector(&mut self, connector: connector::Handle) -> Result<(), DrmError> { + pub fn add_connector(&mut self, connector: connector::Handle) -> Result<()> { let info = connector::Info::load_from_device(self.0.borrow().graphics.head().head().head(), connector) - .map_err(|err| ModeError::FailedToLoad(err))?; + .chain_err(|| { + ErrorKind::DrmDev(format!( + "{:?}", + self.0.borrow().graphics.head().head().head() + )) + })?; // check if the connector can handle the current mode let mut internal = self.0.borrow_mut(); @@ -229,16 +254,21 @@ impl DrmBackend { .iter() .map(|encoder| { encoder::Info::load_from_device(self.0.borrow().graphics.head().head().head(), *encoder) - .map_err(DrmError::from) + .chain_err(|| { + ErrorKind::DrmDev(format!( + "{:?}", + self.0.borrow().graphics.head().head().head() + )) + }) }) - .collect::, DrmError>>()?; + .collect::>>()?; // and if any encoder supports the selected crtc if !encoders .iter() .any(|encoder| encoder.supports_crtc(self.0.borrow().crtc)) { - return Err(DrmError::Crtc(CrtcError::NoSuitableEncoder)); + bail!(ErrorKind::NoSuitableEncoder(info, self.0.borrow().crtc)); } info!( @@ -249,7 +279,7 @@ impl DrmBackend { internal.connectors.push(connector); Ok(()) } else { - Err(DrmError::Mode(ModeError::ModeNotSuitable)) + bail!(ErrorKind::ModeNotSuitable(self.0.borrow().mode)) } } @@ -270,7 +300,7 @@ impl DrmBackend { info.connector_type() ); } else { - info!(self.0.borrow().logger, "Removeing unknown connector"); + info!(self.0.borrow().logger, "Removing unknown connector"); } self.0.borrow_mut().connectors.retain(|x| *x != connector); @@ -283,14 +313,20 @@ impl DrmBackend { /// This will fail if not all set connectors support the new `Mode`. /// Several internal resources will need to be recreated to fit the new `Mode`. /// Other errors might occur. - pub fn use_mode(&mut self, mode: Mode) -> Result<(), DrmError> { + pub fn use_mode(&mut self, mode: Mode) -> Result<()> { // check the connectors for connector in self.0.borrow().connectors.iter() { - if !connector::Info::load_from_device(self.0.borrow().graphics.head().head().head(), *connector)? + if !connector::Info::load_from_device(self.0.borrow().graphics.head().head().head(), *connector) + .chain_err(|| { + ErrorKind::DrmDev(format!( + "{:?}", + self.0.borrow().graphics.head().head().head() + )) + })? .modes() .contains(&mode) { - return Err(DrmError::Mode(ModeError::ModeNotSuitable)); + bail!(ErrorKind::ModeNotSuitable(mode)); } } @@ -303,61 +339,76 @@ impl DrmBackend { let (w, h) = mode.size(); - internal - .graphics - .rent_all_mut(|graphics| -> Result<(), DrmError> { - // Recreate the surface and the related resources to match the new - // resolution. - debug!(logger, "Reinitializing surface for new mode: {}:{}", w, h); - graphics.gbm.surface = Surface::try_new( - { - // create a new gbm surface - debug!(logger, "Creating GbmSurface"); - Box::new(graphics.context.devices.gbm.create_surface( + internal.graphics.rent_all_mut(|graphics| -> Result<()> { + // Recreate the surface and the related resources to match the new + // resolution. + debug!(logger, "Reinitializing surface for new mode: {}:{}", w, h); + graphics.gbm.surface = Surface::try_new( + { + // create a new gbm surface + debug!(logger, "Creating GbmSurface"); + Box::new(graphics + .context + .devices + .gbm + .create_surface( w as u32, h as u32, GbmFormat::XRGB8888, &[BufferObjectFlags::Scanout, BufferObjectFlags::Rendering], - )?) - }, - |surface| { - // create an egl surface from the gbm one - debug!(logger, "Creating EGLSurface"); - let egl_surface = graphics.context.egl.create_surface(&surface)?; + ) + .chain_err(|| ErrorKind::GbmInitFailed)?) + }, + |surface| { + // create an egl surface from the gbm one + debug!(logger, "Creating EGLSurface"); + let egl_surface = graphics.context.egl.create_surface(&surface)?; - // make it active for the first `crtc::set` - // (which is needed before the first page_flip) - unsafe { egl_surface.make_current()? }; - egl_surface.swap_buffers()?; + // make it active for the first `crtc::set` + // (which is needed before the first page_flip) + unsafe { + egl_surface + .make_current() + .chain_err(|| ErrorKind::FailedToSwap)? + }; + egl_surface + .swap_buffers() + .chain_err(|| ErrorKind::FailedToSwap)?; - let mut front_bo = surface.lock_front_buffer()?; - debug!(logger, "FrontBuffer color format: {:?}", front_bo.format()); - // we need a framebuffer per front_buffer - let fb = framebuffer::create(graphics.context.devices.drm, &*front_bo)?; + let mut front_bo = surface + .lock_front_buffer() + .chain_err(|| ErrorKind::FailedToSwap)?; + debug!(logger, "FrontBuffer color format: {:?}", front_bo.format()); + // we need a framebuffer per front_buffer + let fb = framebuffer::create(graphics.context.devices.drm, &*front_bo).chain_err(|| { + ErrorKind::DrmDev(format!("{:?}", graphics.context.devices.drm)) + })?; - debug!(logger, "Initialize screen"); - crtc::set( - graphics.context.devices.drm, - crtc, - fb.handle(), - &connectors, - (0, 0), - Some(mode), - )?; - front_bo.set_userdata(fb); + debug!(logger, "Initialize screen"); + crtc::set( + graphics.context.devices.drm, + crtc, + fb.handle(), + &connectors, + (0, 0), + Some(mode), + ).chain_err(|| { + ErrorKind::DrmDev(format!("{:?}", graphics.context.devices.drm)) + })?; + front_bo.set_userdata(fb); - Ok(EGL { - surface: egl_surface, - buffers: GbmBuffers { - front_buffer: Cell::new(front_bo), - next_buffer: Cell::new(None), - }, - }) - }, - )?; + Ok(EGL { + surface: egl_surface, + buffers: GbmBuffers { + front_buffer: Cell::new(front_bo), + next_buffer: Cell::new(None), + }, + }) + }, + )?; - Ok(()) - })?; + Ok(()) + })?; info!(logger, "Setting new mode: {:?}", mode.name()); internal.mode = mode; @@ -375,34 +426,46 @@ impl DrmBackend { impl GraphicsBackend for DrmBackend { type CursorFormat = ImageBuffer, Vec>; - type Error = DrmError; + type Error = Error; - fn set_cursor_position(&self, x: u32, y: u32) -> Result<(), DrmError> { + fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> { trace!(self.0.borrow().logger, "Move the cursor to {},{}", x, y); crtc::move_cursor( self.0.borrow().graphics.head().head().head(), self.0.borrow().crtc, (x as i32, y as i32), - ).map_err(DrmError::from) + ).chain_err(|| { + ErrorKind::DrmDev(format!( + "{:?}", + self.0.borrow().graphics.head().head().head() + )) + }) } fn set_cursor_representation(&self, buffer: ImageBuffer, Vec>, hotspot: (u32, u32)) - -> Result<(), DrmError> { + -> Result<()> { let (w, h) = buffer.dimensions(); debug!(self.0.borrow().logger, "Importing cursor"); /// import the cursor into a buffer we can render self.0 .borrow_mut() .graphics - .rent_all_mut(|graphics| -> Result<(), DrmError> { + .rent_all_mut(|graphics| -> Result<()> { graphics.gbm.cursor = { - let mut cursor = graphics.context.devices.gbm.create_buffer_object( - w, - h, - GbmFormat::ARGB8888, - &[BufferObjectFlags::Cursor, BufferObjectFlags::Write], - )?; - cursor.write(&*buffer.into_raw())?; + let mut cursor = graphics + .context + .devices + .gbm + .create_buffer_object( + w, + h, + GbmFormat::ARGB8888, + &[BufferObjectFlags::Cursor, BufferObjectFlags::Write], + ) + .chain_err(|| ErrorKind::GbmInitFailed)?; + cursor + .write(&*buffer.into_raw()) + .chain_err(|| ErrorKind::GbmInitFailed)?; cursor }; Ok(()) @@ -429,7 +492,12 @@ impl GraphicsBackend for DrmBackend { .graphics .rent(|gbm| Buffer::handle(&gbm.cursor)), (w, h), - ).map_err(DrmError::from) + ).chain_err(|| { + ErrorKind::DrmDev(format!( + "{:?}", + self.0.borrow().graphics.head().head().head() + )) + }) } else { Ok(()) } @@ -437,7 +505,7 @@ impl GraphicsBackend for DrmBackend { } impl EGLGraphicsBackend for DrmBackend { - fn swap_buffers(&self) -> Result<(), SwapBuffersError> { + fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> { self.0.borrow().graphics.rent_all(|graphics| { // We cannot call lock_front_buffer anymore without releasing the previous buffer, which will happen when the page flip is done if graphics.gbm.surface.rent(|egl| { @@ -503,7 +571,7 @@ impl EGLGraphicsBackend for DrmBackend { .rent(|context| context.is_current()) } - unsafe fn make_current(&self) -> Result<(), SwapBuffersError> { + unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> { self.0 .borrow() .graphics diff --git a/src/backend/drm/error.rs b/src/backend/drm/error.rs index f652c5a..00cd73c 100644 --- a/src/backend/drm/error.rs +++ b/src/backend/drm/error.rs @@ -1,110 +1,52 @@ -use backend::graphics::egl::{CreationError, SwapBuffersError}; -use drm::result::Error as DrmError; -use gbm::FrontBufferError; +//! +//! Errors thrown by the `DrmDevice` and `DrmBackend` +//! + +use backend::graphics::egl; +use drm::control::{connector, crtc, Mode}; use rental::TryNewError; -use std::error::{self, Error as ErrorTrait}; -use std::fmt; -use std::io::Error as IoError; +error_chain! { + errors { + #[doc = "The `DrmDevice` encountered an access error"] + DrmDev(dev: String) { + description("The drm device encountered an access error"), + display("The drm device ({:?}) encountered an access error", dev), + } -/// Error summing up error types related to all underlying libraries -/// involved in creating the a `DrmDevice`/`DrmBackend` -#[derive(Debug)] -pub enum Error { - /// The `DrmDevice` has encountered an error on an ioctl - Drm(DrmError), - /// The `EGLContext` could not be created - EGLCreation(CreationError), - /// Swapping Buffers via EGL was not possible - EGLSwap(SwapBuffersError), - /// Locking the front buffer of the underlying `GbmSurface` failed - Gbm(FrontBufferError), - /// A generic IO-Error happened accessing the underlying devices - Io(IoError), - /// Selected an invalid Mode - Mode(ModeError), - /// Error related to the selected crtc - Crtc(CrtcError), -} + #[doc = "Creation of gbm resource failed"] + GbmInitFailed { + description("Creation of gbm resource failed"), + display("Creation of gbm resource failed"), + } -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "DrmBackend error: {}", - match self { - &Error::Drm(ref x) => x as &error::Error, - &Error::EGLCreation(ref x) => x as &error::Error, - &Error::EGLSwap(ref x) => x as &error::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, - } - ) - } -} + #[doc = "Swapping front buffers failed"] + FailedToSwap { + description("Swapping front buffers failed"), + display("Swapping front buffers failed"), + } -impl error::Error for Error { - fn description(&self) -> &str { - "DrmBackend error" - } + #[doc = "mode is not compatible with all given connectors"] + ModeNotSuitable(mode: Mode) { + description("Mode is not compatible with all given connectors"), + display("Mode ({:?}) is not compatible with all given connectors", mode), + } - fn cause(&self) -> Option<&error::Error> { - match self { - &Error::Drm(ref x) => Some(x as &error::Error), - &Error::EGLCreation(ref x) => Some(x as &error::Error), - &Error::EGLSwap(ref x) => Some(x as &error::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), + #[doc = "The given crtc is already in use by another backend"] + CrtcAlreadyInUse(crtc: crtc::Handle) { + description("The given crtc is already in use by another backend"), + display("The given crtc ({:?}) is already in use by another backend", crtc), + } + + #[doc = "No encoder was found for a given connector on the set crtc"] + NoSuitableEncoder(connector: connector::Info, crtc: crtc::Handle) { + description("No encoder found for given connector on set crtc"), + display("No encoder found for the given connector '{:?}' on the set crtc ({:?})", connector.connector_type(), crtc), } } -} -impl From for Error { - fn from(err: DrmError) -> Error { - Error::Drm(err) - } -} - -impl From for Error { - fn from(err: CreationError) -> Error { - Error::EGLCreation(err) - } -} - -impl From for Error { - fn from(err: SwapBuffersError) -> Error { - Error::EGLSwap(err) - } -} - -impl From for Error { - fn from(err: FrontBufferError) -> Error { - Error::Gbm(err) - } -} - -impl From for Error { - fn from(err: IoError) -> Error { - Error::Io(err) - } -} - -impl From for Error { - fn from(err: ModeError) -> Error { - match err { - err @ ModeError::ModeNotSuitable => Error::Mode(err), - ModeError::FailedToLoad(err) => Error::Drm(err), - } - } -} - -impl From for Error { - fn from(err: CrtcError) -> Error { - Error::Crtc(err) + links { + EGL(egl::Error, egl::ErrorKind) #[doc = "EGL error"]; } } @@ -113,72 +55,3 @@ impl From> for Error { err.0 } } - -/// Error when trying to select an invalid mode -#[derive(Debug)] -pub enum ModeError { - /// `Mode` is not compatible with all given connectors - ModeNotSuitable, - /// Failed to load `Mode` information - FailedToLoad(DrmError), -} - -impl fmt::Display for ModeError { - 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 ModeError { - fn description(&self) -> &str { - match self { - &ModeError::ModeNotSuitable => "Mode does not match all attached connectors", - &ModeError::FailedToLoad(_) => "Failed to load mode information from device", - } - } - - fn cause(&self) -> Option<&error::Error> { - match self { - &ModeError::FailedToLoad(ref err) => Some(err as &error::Error), - _ => None, - } - } -} - -/// Errors related to the selected crtc -#[derive(Debug)] -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 { - 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", - &CrtcError::NoSuitableEncoder => "Crtc has no supported encoder that can drive all connectors", - } - } - - fn cause(&self) -> Option<&error::Error> { - match self { - _ => None, - } - } -} diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index a72134f..9281b70 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -205,11 +205,11 @@ use wayland_server::EventLoopHandle; use wayland_server::sources::{FdEventSourceHandler, FdInterest}; mod backend; -mod error; +pub mod error; pub use self::backend::{DrmBackend, Id}; use self::backend::DrmBackendInternal; -pub use self::error::{CrtcError, Error as DrmError, ModeError}; +use self::error::*; /// Internal struct as required by the drm crate #[derive(Debug)] @@ -275,7 +275,7 @@ impl DrmDevice { /// # Safety /// The file descriptor might not be valid and needs to be owned by smithay, /// make sure not to share it. Otherwise undefined behavior might occur. - pub unsafe fn new_from_fd(fd: RawFd, logger: L) -> Result + pub unsafe fn new_from_fd(fd: RawFd, logger: L) -> Result where L: Into>, { @@ -299,8 +299,7 @@ impl DrmDevice { /// # Safety /// The file descriptor might not be valid and needs to be owned by smithay, /// make sure not to share it. Otherwise undefined behavior might occur. - pub unsafe fn new_from_fd_with_gl_attr(fd: RawFd, attributes: GlAttributes, logger: L) - -> Result + pub unsafe fn new_from_fd_with_gl_attr(fd: RawFd, attributes: GlAttributes, logger: L) -> Result where L: Into>, { @@ -311,7 +310,7 @@ impl DrmDevice { /// /// Returns an error if the file is no valid drm node or context creation was not /// successful. - pub fn new_from_file(file: File, logger: L) -> Result + pub fn new_from_file(file: File, logger: L) -> Result where L: Into>, { @@ -331,15 +330,14 @@ impl DrmDevice { /// /// Returns an error if the file is no valid drm node or context creation was not /// successful. - pub fn new_from_file_with_gl_attr(file: File, attributes: GlAttributes, logger: L) - -> Result + pub fn new_from_file_with_gl_attr(file: File, attributes: GlAttributes, logger: L) -> Result where L: Into>, { DrmDevice::new(DrmDev::new_from_file(file), attributes, logger) } - fn new(drm: DrmDev, attributes: GlAttributes, logger: L) -> Result + fn new(drm: DrmDev, attributes: GlAttributes, logger: L) -> Result where L: Into>, { @@ -365,7 +363,7 @@ impl DrmDevice { context: Rc::new(Context::try_new( Box::new(Devices::try_new(Box::new(drm), |drm| { debug!(log, "Creating gbm device"); - GbmDevice::new_from_drm::>(drm).map_err(DrmError::from) + GbmDevice::new_from_drm::>(drm).chain_err(|| ErrorKind::GbmInitFailed) })?), |devices| { debug!(log, "Creating egl context from gbm device"); @@ -379,7 +377,7 @@ impl DrmDevice { ..Default::default() }, log.clone(), - ).map_err(DrmError::from) + ).map_err(Error::from) }, )?), backends: Vec::new(), @@ -393,15 +391,14 @@ impl DrmDevice { /// /// Errors if initialization fails or the mode is not available on all given /// connectors. - pub fn create_backend(&mut self, crtc: crtc::Handle, mode: Mode, connectors: I) - -> Result + pub fn create_backend(&mut self, crtc: crtc::Handle, mode: Mode, connectors: I) -> Result 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)); + bail!(ErrorKind::CrtcAlreadyInUse(crtc)) } } } @@ -411,21 +408,25 @@ impl DrmDevice { // check if we have an encoder for every connector for connector in connectors.iter() { - let con_info = connector::Info::load_from_device(self.context.head().head(), *connector)?; + let con_info = connector::Info::load_from_device(self.context.head().head(), *connector) + .chain_err(|| { + ErrorKind::DrmDev(format!("{:?}", self.context.head().head())) + })?; // then check for every connector which encoders it does support let encoders = con_info .encoders() .iter() .map(|encoder| { - encoder::Info::load_from_device(self.context.head().head(), *encoder) - .map_err(DrmError::from) + encoder::Info::load_from_device(self.context.head().head(), *encoder).chain_err(|| { + ErrorKind::DrmDev(format!("{:?}", self.context.head().head())) + }) }) - .collect::, DrmError>>()?; + .collect::>>()?; // and if any encoder supports the selected crtc if !encoders.iter().any(|encoder| encoder.supports_crtc(crtc)) { - return Err(DrmError::Crtc(CrtcError::NoSuitableEncoder)); + bail!(ErrorKind::NoSuitableEncoder(con_info, crtc)) } } diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index d08c8e4..7c32f43 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -10,11 +10,11 @@ use super::GraphicsBackend; use gbm::{AsRaw, Device as GbmDevice, Surface as GbmSurface}; use libloading::Library; use nix::{c_int, c_void}; +use rental::TryNewError; use slog; -use std::error::{self, Error}; +use std::error; use std::ffi::{CStr, CString}; use std::fmt; -use std::io; use std::marker::PhantomData; use std::mem; use std::ops::{Deref, DerefMut}; @@ -74,7 +74,7 @@ pub enum NativeSurfacePtr { } /// Enumerates all supported backends -#[derive(Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum NativeType { /// X11 window & surface X11, @@ -82,66 +82,77 @@ pub enum NativeType { Wayland, /// Gbm surface Gbm, + /// Unknown + Unknown, } -/// Error that can happen while creating an `EGLContext` or `EGLSurface` -#[derive(Debug)] -pub enum CreationError { - /// I/O error from the underlying system - IoError(io::Error), - /// Operating System error - OsError(String), - /// The requested OpenGl version is not supported by the graphics system - OpenGlVersionNotSupported, - /// There is no pixel format available that fulfills all requirements - NoAvailablePixelFormat, - /// Surface creation from an unsupport combination - /// - /// E.g creating a surface from an X11 window on a context created from a wayland display - NonMatchingSurfaceType, - /// Context creation is not supported on this system - NotSupported, -} +error_chain! { + errors { + #[doc = "The requested OpenGL version is not supported"] + OpenGlVersionNotSupported(version: (u8, u8)) { + description("The requested OpenGL version is not supported."), + display("The requested OpenGL version {:?} is not supported.", version), + } -impl From for CreationError { - fn from(err: io::Error) -> Self { - CreationError::IoError(err) + #[doc = "The EGL implementation does not support creating OpenGL ES contexts"] + OpenGlesNotSupported { + description("The EGL implementation does not support creating OpenGL ES contexts") + } + + #[doc = "No available pixel format matched the criteria"] + NoAvailablePixelFormat { + description("No available pixel format matched the criteria.") + } + + #[doc = "Surface type does not match the context type"] + NonMatchingSurfaceType(context: NativeType, surface: NativeType) { + description("Surface type does not match the context type."), + display("Surface type '{:?}' does not match the context type '{:?}'.", surface, context), + } + + #[doc = "Context creation is not supported on the current window system"] + NotSupported { + description("Context creation is not supported on the current window system.") + } + + #[doc = "Loading libEGL failed"] + LoadingEGLFailed { + description("Loading libEGL failed"), + } + + #[doc = "EGL was unable to optain a valid EGL Display"] + DisplayNotSupported { + description("EGL was unable to optain a valid EGL Display") + } + + #[doc = "eglInitialize returned an error"] + InitFailed { + description("Failed to initialize EGL") + } + + #[doc = "Failed to configure the EGL context"] + ConfigFailed { + description("Failed to configure the EGL context") + } + + #[doc = "Context creation failed as one or more requirements could not be met. Try removing some gl attributes or pixel format requirements"] + CreationFailed { + description("Context creation failed as one or more requirements could not be met. Try removing some gl attributes or pixel format requirements") + } + + #[doc = "eglCreateWindowSurface failed"] + SurfaceCreationFailed { + description("Failed to create a new EGLSurface") + } + + #[doc = "The reason of failure could not be determined"] + Unknown(err_no: u32) } } -impl fmt::Display for CreationError { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - formatter.write_str(self.description())?; - if let Some(err) = error::Error::cause(self) { - write!(formatter, ": {}", err)?; - } - Ok(()) - } -} - -impl error::Error for CreationError { - fn description(&self) -> &str { - match *self { - CreationError::IoError(ref err) => err.description(), - CreationError::OsError(ref text) => text, - CreationError::OpenGlVersionNotSupported => { - "The requested OpenGL version is not \ - supported." - } - CreationError::NoAvailablePixelFormat => { - "Couldn't find any pixel format that matches \ - the criterias." - } - CreationError::NonMatchingSurfaceType => "Surface type does not match the context type.", - CreationError::NotSupported => "Context creation is not supported on the current window system", - } - } - - fn cause(&self) -> Option<&error::Error> { - match *self { - CreationError::IoError(ref err) => Some(err), - _ => None, - } +impl From> for Error { + fn from(err: TryNewError) -> Error { + err.0 } } @@ -155,20 +166,22 @@ pub unsafe trait NativeSurface { type Keep: 'static; /// Return a surface for the given type if possible - fn surface(&self, backend: NativeType) -> Result<(NativeSurfacePtr, Self::Keep), CreationError>; + fn surface(&self, backend: NativeType) -> Result<(NativeSurfacePtr, Self::Keep)>; } #[cfg(feature = "backend_winit")] unsafe impl NativeSurface for WinitWindow { type Keep = Option; - fn surface(&self, backend_type: NativeType) - -> Result<(NativeSurfacePtr, Option), CreationError> { + fn surface(&self, backend_type: NativeType) -> Result<(NativeSurfacePtr, Option)> { match backend_type { NativeType::X11 => if let Some(window) = self.get_xlib_window() { Ok((NativeSurfacePtr::X11(window), None)) } else { - return Err(CreationError::NonMatchingSurfaceType); + bail!(ErrorKind::NonMatchingSurfaceType( + NativeType::Wayland, + NativeType::X11 + )); }, NativeType::Wayland => if let Some(surface) = self.get_wayland_surface() { let (w, h) = self.get_inner_size().unwrap(); @@ -179,9 +192,12 @@ unsafe impl NativeSurface for WinitWindow { Some(egl_surface), )) } else { - return Err(CreationError::NonMatchingSurfaceType); + bail!(ErrorKind::NonMatchingSurfaceType( + NativeType::X11, + NativeType::Wayland + )); }, - _ => Err(CreationError::NonMatchingSurfaceType), + x => bail!(ErrorKind::NonMatchingSurfaceType(NativeType::Unknown, x)), } } } @@ -190,18 +206,18 @@ unsafe impl NativeSurface for WinitWindow { unsafe impl<'a, T: 'static> NativeSurface for GbmSurface<'a, T> { type Keep = (); - fn surface(&self, backend: NativeType) -> Result<(NativeSurfacePtr, Self::Keep), CreationError> { + fn surface(&self, backend: NativeType) -> Result<(NativeSurfacePtr, Self::Keep)> { match backend { NativeType::Gbm => Ok((NativeSurfacePtr::Gbm(self.as_raw() as *const _), ())), - _ => Err(CreationError::NonMatchingSurfaceType), + x => bail!(ErrorKind::NonMatchingSurfaceType(NativeType::Gbm, x)), } } } unsafe impl NativeSurface for () { type Keep = (); - fn surface(&self, _backend: NativeType) -> Result<(NativeSurfacePtr, ()), CreationError> { - Err(CreationError::NotSupported) + fn surface(&self, _backend: NativeType) -> Result<(NativeSurfacePtr, ())> { + bail!(ErrorKind::NotSupported) } } @@ -225,7 +241,7 @@ impl<'a> EGLContext<'a, ()> { #[cfg(feature = "backend_winit")] pub fn new_from_winit(window: &'a WinitWindow, attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L) - -> Result, CreationError> + -> Result> where L: Into>, { @@ -242,7 +258,7 @@ impl<'a> EGLContext<'a, ()> { NativeDisplayPtr::Wayland(display) } else { error!(log, "Window is backed by an unsupported graphics framework"); - return Err(CreationError::NotSupported); + bail!(ErrorKind::NotSupported) }, attributes, reqs, @@ -255,7 +271,7 @@ impl<'a> EGLContext<'a, ()> { #[cfg(feature = "backend_drm")] pub fn new_from_gbm(gbm: &'a GbmDevice<'a>, attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L) - -> Result>, CreationError> + -> Result>> where L: Into>, { @@ -275,7 +291,7 @@ impl<'a> EGLContext<'a, ()> { impl<'a, T: NativeSurface> EGLContext<'a, T> { unsafe fn new(native: NativeDisplayPtr, mut attributes: GlAttributes, reqs: PixelFormatRequirements, log: ::slog::Logger) - -> Result, CreationError> + -> Result> where T: NativeSurface, { @@ -297,12 +313,12 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { } } } - Some((1, _)) => { + Some((1, x)) => { error!( log, "OpenGLES 1.* is not supported by the EGL renderer backend" ); - return Err(CreationError::OpenGlVersionNotSupported); + bail!(ErrorKind::OpenGlVersionNotSupported((1, x))); } Some(version) => { error!( @@ -310,12 +326,12 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { "OpenGLES {:?} is unknown and not supported by the EGL renderer backend", version ); - return Err(CreationError::OpenGlVersionNotSupported); + bail!(ErrorKind::OpenGlVersionNotSupported(version)); } }; trace!(log, "Loading libEGL"); - let lib = Library::new("libEGL.so.1")?; + let lib = Library::new("libEGL.so.1").chain_err(|| ErrorKind::LoadingEGLFailed)?; let egl = ffi::egl::Egl::load_with(|sym| { let name = CString::new(sym).unwrap(); let symbol = lib.get::<*mut c_void>(name.as_bytes()); @@ -418,6 +434,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { if display == ffi::egl::NO_DISPLAY { error!(log, "EGL Display is not valid"); + bail!(ErrorKind::DisplayNotSupported); } let egl_version = { @@ -425,7 +442,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { let mut minor: ffi::egl::types::EGLint = mem::uninitialized(); if egl.Initialize(display, &mut major, &mut minor) == 0 { - return Err(CreationError::OsError(String::from("eglInitialize failed"))); + bail!(ErrorKind::InitFailed); } info!(log, "EGL Initialized"); @@ -451,7 +468,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { log, "OpenGLES not supported by the underlying EGL implementation" ); - return Err(CreationError::OpenGlVersionNotSupported); + bail!(ErrorKind::OpenGlesNotSupported); } let descriptor = { @@ -477,7 +494,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { log, "OpenglES 3.* is not supported on EGL Versions lower then 1.3" ); - return Err(CreationError::NoAvailablePixelFormat); + bail!(ErrorKind::NoAvailablePixelFormat); } trace!(log, "Setting RENDERABLE_TYPE to OPENGL_ES3"); out.push(ffi::egl::RENDERABLE_TYPE as c_int); @@ -492,7 +509,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { log, "OpenglES 2.* is not supported on EGL Versions lower then 1.3" ); - return Err(CreationError::NoAvailablePixelFormat); + bail!(ErrorKind::NoAvailablePixelFormat); } trace!(log, "Setting RENDERABLE_TYPE to OPENGL_ES2"); out.push(ffi::egl::RENDERABLE_TYPE as c_int); @@ -561,7 +578,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { if reqs.stereoscopy { error!(log, "Stereoscopy is currently unsupported (sorry!)"); - return Err(CreationError::NoAvailablePixelFormat); + bail!(ErrorKind::NoAvailablePixelFormat); } out.push(ffi::egl::NONE as c_int); @@ -579,13 +596,11 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { &mut num_configs, ) == 0 { - return Err(CreationError::OsError( - String::from("eglChooseConfig failed"), - )); + bail!(ErrorKind::ConfigFailed); } if num_configs == 0 { error!(log, "No matching color format found"); - return Err(CreationError::NoAvailablePixelFormat); + bail!(ErrorKind::NoAvailablePixelFormat); } // analyzing each config @@ -596,7 +611,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { let res = $egl.GetConfigAttrib($display, $config, $attr as ffi::egl::types::EGLint, &mut value); if res == 0 { - return Err(CreationError::OsError(String::from("eglGetConfigAttrib failed"))); + bail!(ErrorKind::ConfigFailed); } value } @@ -654,14 +669,8 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { if context.is_null() { match egl.GetError() as u32 { - ffi::egl::BAD_ATTRIBUTE => { - error!( - log, - "Context creation failed as one or more requirements could not be met. Try removing some gl attributes or pixel format requirements" - ); - return Err(CreationError::OpenGlVersionNotSupported); - } - e => panic!("eglCreateContext failed: 0x{:x}", e), + ffi::egl::BAD_ATTRIBUTE => bail!(ErrorKind::CreationFailed), + err_no => bail!(ErrorKind::Unknown(err_no)), } } debug!(log, "EGL context successfully created"); @@ -709,7 +718,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { } /// Creates a surface bound to the given egl context for rendering - pub fn create_surface<'b>(&'a self, native: &'b T) -> Result, CreationError> { + pub fn create_surface<'b>(&'a self, native: &'b T) -> Result> { trace!(self.logger, "Creating EGL window surface..."); let (surface, keep) = native.surface(self.backend_type)?; @@ -728,9 +737,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { }; if egl_surface.is_null() { - return Err(CreationError::OsError( - String::from("eglCreateWindowSurface failed"), - )); + bail!(ErrorKind::SurfaceCreationFailed); } debug!(self.logger, "EGL surface successfully created"); @@ -801,7 +808,7 @@ impl<'a, 'b, T: NativeSurface> DerefMut for EGLSurface<'a, 'b, T> { impl<'context, 'surface, T: NativeSurface> EGLSurface<'context, 'surface, T> { /// Swaps buffers at the end of a frame. - pub fn swap_buffers(&self) -> Result<(), SwapBuffersError> { + pub fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> { let ret = unsafe { self.context .egl @@ -824,7 +831,7 @@ impl<'context, 'surface, T: NativeSurface> EGLSurface<'context, 'surface, T> { /// /// This function is marked unsafe, because the context cannot be made current /// on multiple threads. - pub unsafe fn make_current(&self) -> Result<(), SwapBuffersError> { + pub unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> { let ret = self.context.egl.MakeCurrent( self.context.display as *const _, self.surface as *const _, @@ -879,7 +886,8 @@ pub enum SwapBuffersError { } impl fmt::Display for SwapBuffersError { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> { + use std::error::Error; write!(formatter, "{}", self.description()) } } @@ -983,7 +991,7 @@ pub struct PixelFormat { /// and can be used to render upon pub trait EGLGraphicsBackend: GraphicsBackend { /// Swaps buffers at the end of a frame. - fn swap_buffers(&self) -> Result<(), SwapBuffersError>; + fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError>; /// Returns the address of an OpenGL function. /// @@ -1006,7 +1014,7 @@ pub trait EGLGraphicsBackend: GraphicsBackend { /// /// This function is marked unsafe, because the context cannot be made current /// on multiple threads. - unsafe fn make_current(&self) -> Result<(), SwapBuffersError>; + unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError>; /// Returns the pixel format of the main framebuffer of the context. fn get_pixel_format(&self) -> PixelFormat; diff --git a/src/backend/winit.rs b/src/backend/winit.rs index f1828be..04d262f 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -2,21 +2,20 @@ use backend::{SeatInternal, TouchSlotInternal}; use backend::graphics::GraphicsBackend; -use backend::graphics::egl::{CreationError, EGLContext, EGLGraphicsBackend, GlAttributes, PixelFormat, +use backend::graphics::egl::{self, EGLContext, EGLGraphicsBackend, GlAttributes, PixelFormat, PixelFormatRequirements, SwapBuffersError}; use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot, TouchUpEvent, UnusedEvent}; use nix::c_void; - +use rental::TryNewError; use std::cmp; -use std::error::Error; +use std::error; use std::fmt; use std::rc::Rc; -use winit::{CreationError as WinitCreationError, ElementState, Event, EventsLoop, KeyboardInput, - MouseButton as WinitMouseButton, MouseCursor, MouseScrollDelta, Touch, TouchPhase, - WindowBuilder, WindowEvent}; +use winit::{ElementState, Event, EventsLoop, KeyboardInput, MouseButton as WinitMouseButton, MouseCursor, + MouseScrollDelta, Touch, TouchPhase, WindowBuilder, WindowEvent}; rental! { mod rental { @@ -40,6 +39,24 @@ rental! { use self::rental::{Window, EGL}; +error_chain! { + errors { + #[doc = "Failed to initialize a window"] + InitFailed { + description("Failed to initialize a window") + } + } + + links { + EGL(egl::Error, egl::ErrorKind) #[doc = "EGL error"]; + } +} + +impl From> for Error { + fn from(err: TryNewError) -> Error { + err.0 + } +} /// Window with an active EGL Context created by `winit`. Implements the /// `EGLGraphicsBackend` graphics backend trait pub struct WinitGraphicsBackend { @@ -64,7 +81,7 @@ pub struct WinitInputBackend { /// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend` /// graphics backend trait and a corresponding `WinitInputBackend`, which implements /// the `InputBackend` trait -pub fn init(logger: L) -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> +pub fn init(logger: L) -> Result<(WinitGraphicsBackend, WinitInputBackend)> where L: Into>, { @@ -81,7 +98,7 @@ where /// graphics backend trait, from a given `WindowBuilder` struct and a corresponding /// `WinitInputBackend`, which implements the `InputBackend` trait pub fn init_from_builder(builder: WindowBuilder, logger: L) - -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> + -> Result<(WinitGraphicsBackend, WinitInputBackend)> where L: Into>, { @@ -101,9 +118,8 @@ where /// graphics backend trait, from a given `WindowBuilder` struct, as well as given /// `GlAttributes` for further customization of the rendering pipeline and a /// corresponding `WinitInputBackend`, which implements the `InputBackend` trait. -pub fn init_from_builder_with_gl_attr( - builder: WindowBuilder, attributes: GlAttributes, logger: L) - -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> +pub fn init_from_builder_with_gl_attr(builder: WindowBuilder, attributes: GlAttributes, logger: L) + -> Result<(WinitGraphicsBackend, WinitInputBackend)> where L: Into>, { @@ -111,11 +127,13 @@ where info!(log, "Initializing a winit backend"); let events_loop = EventsLoop::new(); - let winit_window = builder.build(&events_loop)?; + let winit_window = builder + .build(&events_loop) + .chain_err(|| ErrorKind::InitFailed)?; debug!(log, "Window created"); - let window = match Window::try_new(Box::new(winit_window), |window| { - match EGL::try_new( + let window = Rc::new(Window::try_new(Box::new(winit_window), |window| { + EGL::try_new( Box::new(match EGLContext::new_from_winit( &*window, attributes, @@ -128,20 +146,12 @@ where log.clone(), ) { Ok(context) => context, - Err(err) => { - error!(log, "EGLContext creation failed:\n {}", err); - return Err(err); - } + Err(err) => bail!(err), }), |context| context.create_surface(window), - ) { - Ok(x) => Ok(x), - Err(::rental::TryNewError(err, _)) => return Err(err), - } - }) { - Ok(x) => Rc::new(x), - Err(::rental::TryNewError(err, _)) => return Err(err), - }; + ).map_err(egl::Error::from) + .map_err(Error::from) + })?); Ok(( WinitGraphicsBackend { @@ -172,12 +182,13 @@ impl GraphicsBackend for WinitGraphicsBackend { type CursorFormat = MouseCursor; type Error = (); - fn set_cursor_position(&self, x: u32, y: u32) -> Result<(), ()> { + fn set_cursor_position(&self, x: u32, y: u32) -> ::std::result::Result<(), ()> { debug!(self.logger, "Setting cursor position to {:?}", (x, y)); self.window.head().set_cursor_position(x as i32, y as i32) } - fn set_cursor_representation(&self, cursor: Self::CursorFormat, _hotspot: (u32, u32)) -> Result<(), ()> { + fn set_cursor_representation(&self, cursor: Self::CursorFormat, _hotspot: (u32, u32)) + -> ::std::result::Result<(), ()> { // Cannot log this one, as `CursorFormat` is not `Debug` and should not be debug!(self.logger, "Changing cursor representation"); self.window.head().set_cursor(cursor); @@ -186,7 +197,7 @@ impl GraphicsBackend for WinitGraphicsBackend { } impl EGLGraphicsBackend for WinitGraphicsBackend { - fn swap_buffers(&self) -> Result<(), SwapBuffersError> { + fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> { trace!(self.logger, "Swapping buffers"); self.window .rent(|egl| egl.rent(|surface| surface.swap_buffers())) @@ -208,7 +219,7 @@ impl EGLGraphicsBackend for WinitGraphicsBackend { self.window.rent(|egl| egl.head().is_current()) } - unsafe fn make_current(&self) -> Result<(), SwapBuffersError> { + unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> { debug!(self.logger, "Setting EGL context to be the current context"); self.window .rent(|egl| egl.rent(|surface| surface.make_current())) @@ -228,7 +239,7 @@ pub enum WinitInputError { WindowClosed, } -impl Error for WinitInputError { +impl error::Error for WinitInputError { fn description(&self) -> &str { match *self { WinitInputError::WindowClosed => "Glutin Window was closed", @@ -238,6 +249,7 @@ impl Error for WinitInputError { impl fmt::Display for WinitInputError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use std::error::Error; write!(f, "{}", self.description()) } } @@ -576,7 +588,7 @@ impl InputBackend for WinitInputBackend { /// /// The linked `WinitGraphicsBackend` will error with a lost Context and should /// not be used anymore as well. - fn dispatch_new_events(&mut self) -> Result<(), WinitInputError> { + fn dispatch_new_events(&mut self) -> ::std::result::Result<(), WinitInputError> { let mut closed = false; { @@ -831,12 +843,3 @@ impl From for MouseButtonState { } } } - -impl From for CreationError { - fn from(error: WinitCreationError) -> Self { - match error { - WinitCreationError::OsError(x) => CreationError::OsError(x), - WinitCreationError::NotSupported => CreationError::NotSupported, - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 76050ec..2598c77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", plugin(clippy))] +// `error_chain!` can recurse deeply +#![recursion_limit = "1024"] extern crate image; extern crate nix; @@ -36,6 +38,9 @@ extern crate glium; extern crate slog; extern crate slog_stdlog; +#[macro_use] +extern crate error_chain; + pub mod backend; pub mod compositor; pub mod shm;