diff --git a/Cargo.toml b/Cargo.toml index b31f128..6b228aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,8 @@ slog-stdlog = "2.0.0-0.2" libloading = "0.4.0" wayland-client = { version = "0.9.9", optional = true } winit = { version = "0.8.2", optional = true } -drm = { version = "=0.2.1", optional = true } -gbm = { version = "=0.2.1", optional = true } +drm = { version = "^0.3.0", optional = true } +gbm = { version = "^0.2.2", optional = true } glium = { version = "0.17.1", optional = true, default-features = false } input = { version = "0.2.0", optional = true } rental = "0.4.11" @@ -37,6 +37,3 @@ backend_winit = ["winit", "wayland-server/dlopen", "wayland-client/dlopen"] backend_drm = ["drm", "gbm"] backend_libinput = ["input"] renderer_glium = ["glium"] - -[replace] -"drm:0.2.1" = { git = "https://github.com/Drakulix/drm-rs", branch = "future" } diff --git a/examples/drm.rs b/examples/drm.rs index 749b171..5f88726 100644 --- a/examples/drm.rs +++ b/examples/drm.rs @@ -16,6 +16,7 @@ mod helpers; use drm::control::{Device as ControlDevice, ResourceInfo}; use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState}; use drm::control::encoder::Info as EncoderInfo; +use drm::result::Error as DrmError; use glium::Surface; use helpers::{init_shell, GliumDrawer, MyWindowMap, Roles, SurfaceData}; use slog::{Drain, Logger}; @@ -27,7 +28,6 @@ use smithay::wayland::shell::ShellState; use smithay::wayland::shm::init_shm_global; use std::cell::RefCell; use std::fs::OpenOptions; -use std::io::Error as IoError; use std::rc::Rc; use std::time::Duration; use wayland_server::{EventLoopHandle, StateToken}; @@ -72,9 +72,9 @@ fn main() { let crtc = encoder_info.current_crtc() // or use the first one that is compatible with the encoder .unwrap_or_else(|| - *res_handles.crtcs() + *res_handles.filter_crtcs(encoder_info.possible_crtcs()) .iter() - .find(|crtc| encoder_info.supports_crtc(**crtc)) + .next() .unwrap()); // Assuming we found a good connector and loaded the info into `connector_info` @@ -186,7 +186,7 @@ impl DrmHandler> for DrmHandlerImpl { } fn error(&mut self, _evlh: &mut EventLoopHandle, _device: &mut DrmDevice>, - error: IoError) { + error: DrmError) { panic!("{:?}", error); } } diff --git a/src/backend/drm/backend.rs b/src/backend/drm/backend.rs index 65b8253..a58bff7 100644 --- a/src/backend/drm/backend.rs +++ b/src/backend/drm/backend.rs @@ -2,9 +2,8 @@ use super::devices; use super::error::*; use backend::graphics::GraphicsBackend; use backend::graphics::egl::{EGLGraphicsBackend, EGLSurface, PixelFormat, SwapBuffersError}; -use drm::buffer::Buffer; +use drm::control::{Device, ResourceInfo}; use drm::control::{connector, crtc, encoder, framebuffer, Mode}; -use drm::control::ResourceInfo; use gbm::{BufferObject, BufferObjectFlags, Format as GbmFormat, Surface as GbmSurface, SurfaceBufferHandle}; use image::{ImageBuffer, Rgba}; use nix::c_void; @@ -211,10 +210,22 @@ impl DrmBackend { .collect::>>()?; // and if any encoder supports the selected crtc + let resource_handles = self.graphics + .head() + .head() + .head() + .resource_handles() + .chain_err(|| { + ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())) + })?; if !encoders .iter() - .any(|encoder| encoder.supports_crtc(self.crtc)) - { + .map(|encoder| encoder.possible_crtcs()) + .all(|crtc_list| { + resource_handles + .filter_crtcs(crtc_list) + .contains(&self.crtc) + }) { bail!(ErrorKind::NoSuitableEncoder(info, self.crtc)); } @@ -440,17 +451,11 @@ impl GraphicsBackend for DrmBackend { if crtc::set_cursor2( self.graphics.head().head().head(), self.crtc, - Buffer::handle(&cursor), - (w, h), + &cursor, (hotspot.0 as i32, hotspot.1 as i32), ).is_err() { - crtc::set_cursor( - self.graphics.head().head().head(), - self.crtc, - Buffer::handle(&cursor), - (w, h), - ).chain_err(|| { + crtc::set_cursor(self.graphics.head().head().head(), self.crtc, &cursor).chain_err(|| { ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())) })?; } @@ -502,7 +507,7 @@ impl EGLGraphicsBackend for DrmBackend { trace!(self.logger, "Queueing Page flip"); // and flip - crtc::page_flip(graphics.context.devices.drm, self.crtc, fb.handle(), &[crtc::PageFlipFlags::PageFlipEvent], self.crtc).map_err(|_| SwapBuffersError::ContextLost) + crtc::page_flip(graphics.context.devices.drm, self.crtc, fb.handle(), &[crtc::PageFlipFlags::PageFlipEvent]).map_err(|_| SwapBuffersError::ContextLost) }) }) } diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index 5b53d81..e838f79 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -80,10 +80,10 @@ //! let crtc = encoder_info.current_crtc() //! // or use the first one that is compatible with the encoder //! .unwrap_or_else(|| -//! *res_handles.crtcs() -//! .iter() -//! .find(|crtc| encoder_info.supports_crtc(**crtc)) -//! .unwrap()); +//! *res_handles.filter_crtcs(encoder_info.possible_crtcs()) +//! .iter() +//! .next() +//! .unwrap()); //! //! // Use first mode (usually the highest resolution) //! let mode = connector_info.modes()[0]; @@ -118,7 +118,7 @@ //! # //! # use drm::control::{Device as ControlDevice, ResourceInfo}; //! # use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState}; -//! use std::io::Error as IoError; +//! use drm::result::Error as DrmError; //! # use std::fs::OpenOptions; //! # use std::time::Duration; //! use smithay::backend::drm::{DrmDevice, DrmBackend, DrmHandler, drm_device_bind}; @@ -167,7 +167,7 @@ //! fn error(&mut self, //! _: &mut EventLoopHandle, //! device: &mut DrmDevice, -//! error: IoError) +//! error: DrmError) //! { //! panic!("DrmDevice errored: {}", error); //! } @@ -186,13 +186,13 @@ use backend::graphics::egl::{EGLContext, GlAttributes, PixelFormatRequirements}; use drm::Device as BasicDevice; use drm::control::{connector, crtc, encoder, Mode, ResourceInfo}; use drm::control::Device as ControlDevice; +use drm::result::Error as DrmError; use gbm::Device as GbmDevice; use nix; use std::borrow::Borrow; use std::collections::HashMap; use std::fs::File; -use std::io::{Error as IoError, Result as IoResult}; -use std::marker::PhantomData; +use std::io::Result as IoResult; use std::os::unix::io::{AsRawFd, RawFd}; use std::rc::Rc; use std::time::Duration; @@ -356,7 +356,7 @@ impl + Borrow + 'static> 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).chain_err(|| ErrorKind::GbmInitFailed) + GbmDevice::new_from_drm(drm).chain_err(|| ErrorKind::GbmInitFailed) })?), |devices| { debug!(log, "Creating egl context from gbm device"); @@ -420,7 +420,15 @@ impl + Borrow + 'static> DrmDevice { .collect::>>()?; // and if any encoder supports the selected crtc - if !encoders.iter().any(|encoder| encoder.supports_crtc(crtc)) { + let resource_handles = self.resource_handles().chain_err(|| { + ErrorKind::DrmDev(format!("{:?}", self.context.head().head())) + })?; + if !encoders + .iter() + .map(|encoder| encoder.possible_crtcs()) + .all(|crtc_list| { + resource_handles.filter_crtcs(crtc_list).contains(&crtc) + }) { bail!(ErrorKind::NoSuitableEncoder(con_info, crtc)) } } @@ -460,7 +468,7 @@ pub trait DrmHandler + 'static> { /// /// The related backends are most likely *not* usable anymore and /// the whole stack has to be recreated. - fn error(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice, error: IoError); + fn error(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice, error: DrmError); } /// Bind a `DrmDevice` to an EventLoop, @@ -487,51 +495,31 @@ where { FdEventSourceImpl { ready: |evlh, id, _, _| { - use std::any::Any; - let &mut (ref mut dev, ref mut handler) = id; - struct PageFlipHandler<'a, 'b, B: Borrow + 'static, H: DrmHandler + 'static> { - handler: &'a mut H, - evlh: &'b mut EventLoopHandle, - _marker: PhantomData, - }; - - impl<'a, 'b, B, H> crtc::PageFlipHandler> for PageFlipHandler<'a, 'b, B, H> - where - B: Borrow + 'static, - H: DrmHandler + 'static, - { - fn handle_event(&mut self, device: &mut DrmDevice, frame: u32, duration: Duration, - userdata: Box) { - let crtc_id: crtc::Handle = *userdata.downcast().unwrap(); - let token = device.backends.get(&crtc_id).cloned(); - if let Some(token) = token { - // we can now unlock the buffer - self.evlh.state().get(&token).borrow().unlock_buffer(); - trace!(device.logger, "Handling event for backend {:?}", crtc_id); - // and then call the user to render the next frame - self.handler - .ready(self.evlh, device, &token, frame, duration); + let events = crtc::receive_events(dev); + match events { + Ok(events) => for event in events { + match event { + crtc::Event::PageFlip(event) => { + let token = dev.backends.get(&event.crtc).cloned(); + if let Some(token) = token { + // we can now unlock the buffer + evlh.state().get(&token).borrow().unlock_buffer(); + trace!(dev.logger, "Handling event for backend {:?}", event.crtc); + // and then call the user to render the next frame + handler.ready(evlh, dev, &token, event.frame, event.duration); + } + } + _ => {} } - } - } - - crtc::handle_event( - dev, - 2, - None::<&mut ()>, - Some(&mut PageFlipHandler { - handler, - evlh, - _marker: PhantomData, - }), - None::<&mut ()>, - ).unwrap(); + }, + Err(err) => return handler.error(evlh, dev, err), + }; }, error: |evlh, id, _, error| { warn!(id.0.logger, "DrmDevice errored: {}", error); - id.1.error(evlh, &mut id.0, error); + id.1.error(evlh, &mut id.0, error.into()); }, } }