From 9428853ad60e1659ccb5a8061a9f367808589b7e Mon Sep 17 00:00:00 2001 From: Victor Brekenfeld Date: Thu, 22 Nov 2018 10:10:30 +0100 Subject: [PATCH] anvil: fix for drm backend changes --- anvil/Cargo.toml | 5 +- anvil/src/glium_drawer.rs | 28 ++---- anvil/src/udev.rs | 186 ++++++++++++++++++++++---------------- anvil/src/winit.rs | 6 +- 4 files changed, 121 insertions(+), 104 deletions(-) diff --git a/anvil/Cargo.toml b/anvil/Cargo.toml index fec642d..d7deafe 100644 --- a/anvil/Cargo.toml +++ b/anvil/Cargo.toml @@ -23,8 +23,7 @@ features = [ "renderer_glium" ] gl_generator = "0.9" [features] -default = [ "winit", "tty_launch", "udev" ] +default = [ "winit", "udev" ] winit = [ "smithay/backend_winit" ] -tty_launch = [ "smithay/backend_libinput", "smithay/backend_drm" ] -udev = [ "tty_launch", "smithay/backend_udev" ] +udev = [ "smithay/backend_libinput", "smithay/backend_drm", "smithay/backend_udev", "smithay/backend_session" ] logind = [ "smithay/backend_session_logind" ] diff --git a/anvil/src/glium_drawer.rs b/anvil/src/glium_drawer.rs index 135ed5f..d384ac0 100644 --- a/anvil/src/glium_drawer.rs +++ b/anvil/src/glium_drawer.rs @@ -12,19 +12,15 @@ use glium::{ use slog::Logger; use smithay::{ - backend::graphics::{ - egl::{ - error::Result as EGLResult, - wayland::{BufferAccessError, EGLDisplay, EGLImages, EGLWaylandExtensions, Format}, - EGLGraphicsBackend, - }, - glium::GliumGraphicsBackend, + backend::{ + egl::{BufferAccessError, EGLDisplay, EGLImages, Format}, + graphics::{gl::GLGraphicsBackend, glium::GliumGraphicsBackend}, }, wayland::{ compositor::{roles::Role, SubsurfaceRole, TraversalAction}, shm::with_buffer_contents as shm_buffer_contents, }, - wayland_server::{protocol::wl_buffer, Display, Resource}, + wayland_server::{protocol::wl_buffer, Resource}, }; use shaders; @@ -38,7 +34,7 @@ struct Vertex { implement_vertex!(Vertex, position, tex_coords); -pub struct GliumDrawer { +pub struct GliumDrawer { display: GliumGraphicsBackend, vertex_buffer: glium::VertexBuffer, index_buffer: glium::IndexBuffer, @@ -47,13 +43,13 @@ pub struct GliumDrawer { log: Logger, } -impl GliumDrawer { +impl GliumDrawer { pub fn borrow(&self) -> Ref { self.display.borrow() } } -impl> + EGLGraphicsBackend + 'static> GliumDrawer { +impl> + GLGraphicsBackend + 'static> GliumDrawer { pub fn init(backend: T, egl_display: Rc>>, log: Logger) -> GliumDrawer { let display = backend.into(); @@ -97,7 +93,7 @@ impl> + EGLGraphicsBackend + 'static> GliumDrawe } } -impl GliumDrawer { +impl GliumDrawer { pub fn texture_from_buffer(&self, buffer: Resource) -> Result { // try to retrieve the egl contents of this buffer let images = if let Some(display) = &self.egl_display.borrow().as_ref() { @@ -217,12 +213,6 @@ impl GliumDrawer { } } -impl EGLWaylandExtensions for GliumDrawer { - fn bind_wl_display(&self, display: &Display) -> EGLResult { - self.display.bind_wl_display(display) - } -} - pub struct TextureMetadata { pub texture: Texture2d, pub fragment: usize, @@ -231,7 +221,7 @@ pub struct TextureMetadata { images: Option, } -impl GliumDrawer { +impl GliumDrawer { pub fn draw_windows(&self, window_map: &MyWindowMap, compositor_token: MyCompositorToken, log: &Logger) { let mut frame = self.draw(); frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None); diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index a3de2aa..ccbfbef 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -2,41 +2,42 @@ use std::{ cell::RefCell, collections::HashMap, io::Error as IoError, + os::unix::io::{AsRawFd, RawFd}, path::PathBuf, rc::Rc, sync::{ atomic::{AtomicBool, Ordering}, Arc, }, - time::Duration, }; -use glium::Surface; +use glium::Surface as GliumSurface; use slog::Logger; use smithay::{ backend::{ - drm::{DevPath, DrmBackend, DrmDevice, DrmHandler}, - graphics::{ - egl::wayland::{EGLDisplay, EGLWaylandExtensions}, - GraphicsBackend, + drm::{ + dev_t, + egl::{EglDevice, EglSurface}, + gbm::{egl::Gbm as EglGbmBackend, GbmDevice}, + legacy::LegacyDrmDevice, + DevPath, Device, DeviceHandler, Surface, }, + egl::{EGLDisplay, EGLGraphicsBackend}, + graphics::CursorBackend, input::InputBackend, libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface}, session::{ auto::{auto_session_bind, AutoSession}, - Session, SessionNotifier, + OFlag, Session, SessionNotifier, }, - udev::{primary_gpu, udev_backend_bind, SessionFdDrmDevice, UdevBackend, UdevHandler}, + udev::{primary_gpu, udev_backend_bind, UdevBackend, UdevHandler}, }, - drm::{ - control::{ - connector::{Info as ConnectorInfo, State as ConnectorState}, - crtc, - encoder::Info as EncoderInfo, - Device as ControlDevice, ResourceInfo, - }, - result::Error as DrmError, + drm::control::{ + connector::{Info as ConnectorInfo, State as ConnectorState}, + crtc, + encoder::Info as EncoderInfo, + ResourceInfo, }, image::{ImageBuffer, Rgba}, input::Libinput, @@ -54,6 +55,18 @@ use glium_drawer::GliumDrawer; use input_handler::AnvilInputHandler; use shell::{init_shell, MyWindowMap, Roles, SurfaceData}; +pub struct SessionFd(RawFd); +impl AsRawFd for SessionFd { + fn as_raw_fd(&self) -> RawFd { + self.0 + } +} + +type RenderDevice = + EglDevice>, GbmDevice>>; +type RenderSurface = + EglSurface>, GbmDevice>>; + pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger) -> Result<(), ()> { let name = display.add_socket_auto().unwrap().into_string().unwrap(); info!(log, "Listening on wayland socket"; "name" => name.clone()); @@ -88,13 +101,12 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger let primary_gpu = primary_gpu(&context, &seat).unwrap_or_default(); let bytes = include_bytes!("../resources/cursor2.rgba"); - let mut udev_backend = UdevBackend::new( - event_loop.handle(), + let udev_backend = UdevBackend::new( &context, - session.clone(), UdevHandlerImpl { compositor_token, active_egl_context, + session: session.clone(), backends: HashMap::new(), display: display.clone(), primary_gpu, @@ -103,11 +115,10 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(), logger: log.clone(), }, + seat.clone(), log.clone(), ).map_err(|_| ())?; - let udev_session_id = notifier.register(&mut udev_backend); - init_data_device( &mut display.borrow_mut(), |_| {}, @@ -171,13 +182,14 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger session, )); let libinput_event_source = libinput_bind(libinput_backend, event_loop.handle()) - .map_err(|(e, _)| e) + .map_err(|e| -> IoError { e.into() }) .unwrap(); - let session_event_source = auto_session_bind(notifier, &event_loop.handle()) .map_err(|(e, _)| e) .unwrap(); - let udev_event_source = udev_backend_bind(udev_backend).unwrap(); + let udev_event_source = udev_backend_bind(udev_backend, &event_loop.handle()) + .map_err(|e| -> IoError { e.into() }) + .unwrap(); while running.load(Ordering::SeqCst) { if event_loop @@ -192,7 +204,6 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger } let mut notifier = session_event_source.unbind(); - notifier.unregister(udev_session_id); notifier.unregister(libinput_session_id); libinput_event_source.remove(); @@ -204,7 +215,14 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger struct UdevHandlerImpl { compositor_token: CompositorToken, active_egl_context: Rc>>, - backends: HashMap>>>>>, + session: AutoSession, + backends: HashMap< + dev_t, + ( + RenderDevice, + Rc>>>, + ), + >, display: Rc>, primary_gpu: Option, window_map: Rc>, @@ -215,10 +233,11 @@ struct UdevHandlerImpl { impl UdevHandlerImpl { pub fn scan_connectors( - &self, - device: &mut DrmDevice, + device: &mut RenderDevice, egl_display: Rc>>, - ) -> HashMap>> { + pointer_image: &ImageBuffer, Vec>, + logger: &::slog::Logger, + ) -> HashMap> { // Get a set of all modesetting resource handles (excluding planes): let res_handles = device.resource_handles().unwrap(); @@ -226,9 +245,9 @@ impl UdevHandlerImpl { let connector_infos: Vec = res_handles .connectors() .iter() - .map(|conn| ConnectorInfo::load_from_device(device, *conn).unwrap()) + .map(|conn| device.resource_info::(*conn).unwrap()) .filter(|conn| conn.connection_state() == ConnectorState::Connected) - .inspect(|conn| info!(self.logger, "Connected: {:?}", conn.connector_type())) + .inspect(|conn| info!(logger, "Connected: {:?}", conn.connector_type())) .collect(); let mut backends = HashMap::new(); @@ -238,7 +257,7 @@ impl UdevHandlerImpl { let encoder_infos = connector_info .encoders() .iter() - .flat_map(|encoder_handle| EncoderInfo::load_from_device(device, *encoder_handle)) + .flat_map(|encoder_handle| device.resource_info::(*encoder_handle)) .collect::>(); for encoder_info in encoder_infos { for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) { @@ -247,16 +266,16 @@ impl UdevHandlerImpl { // create a backend let renderer = GliumDrawer::init( device - .create_backend(crtc, mode, vec![connector_info.handle()]) + .create_surface(crtc, mode, vec![connector_info.handle()].into_iter()) .unwrap(), egl_display.clone(), - self.logger.clone(), + logger.clone(), ); // create cursor renderer .borrow() - .set_cursor_representation(&self.pointer_image, (2, 2)) + .set_cursor_representation(pointer_image, (2, 2)) .unwrap(); // render first frame @@ -277,64 +296,77 @@ impl UdevHandlerImpl { } } -impl UdevHandler for UdevHandlerImpl { - fn device_added(&mut self, device: &mut DrmDevice) -> Option { - // init hardware acceleration on the primary gpu. - if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu { - *self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display.borrow()).ok(); +impl UdevHandler for UdevHandlerImpl { + fn device_added(&mut self, _device: dev_t, path: PathBuf) { + if let Some(mut device) = self + .session + .open( + &path, + OFlag::O_RDWR | OFlag::O_CLOEXEC | OFlag::O_NOCTTY | OFlag::O_NONBLOCK, + ).ok() + .and_then(|fd| LegacyDrmDevice::new(SessionFd(fd), self.logger.clone()).ok()) + .and_then(|drm| GbmDevice::new(drm, self.logger.clone()).ok()) + .and_then(|gbm| EglDevice::new(gbm, self.logger.clone()).ok()) + { + // init hardware acceleration on the primary gpu. + if path.canonicalize().ok() == self.primary_gpu { + *self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display.borrow()).ok(); + } + + let backends = Rc::new(RefCell::new(UdevHandlerImpl::scan_connectors( + &mut device, + self.active_egl_context.clone(), + &self.pointer_image, + &self.logger, + ))); + + device.set_handler(DrmHandlerImpl { + compositor_token: self.compositor_token, + backends: backends.clone(), + window_map: self.window_map.clone(), + pointer_location: self.pointer_location.clone(), + logger: self.logger.clone(), + }); + + self.backends.insert(device.device_id(), (device, backends)); } - - let backends = Rc::new(RefCell::new( - self.scan_connectors(device, self.active_egl_context.clone()), - )); - self.backends.insert(device.device_id(), backends.clone()); - - Some(DrmHandlerImpl { - compositor_token: self.compositor_token, - backends, - window_map: self.window_map.clone(), - pointer_location: self.pointer_location.clone(), - logger: self.logger.clone(), - }) } - fn device_changed(&mut self, device: &mut DrmDevice) { - //quick and dirt, just re-init all backends - let backends = &self.backends[&device.device_id()]; - *backends.borrow_mut() = self.scan_connectors(device, self.active_egl_context.clone()); + fn device_changed(&mut self, device: dev_t) { + //quick and dirty, just re-init all backends + if let Some((ref mut device, ref backends)) = self.backends.get_mut(&device) { + *backends.borrow_mut() = UdevHandlerImpl::scan_connectors( + device, + self.active_egl_context.clone(), + &self.pointer_image, + &self.logger, + ); + } } - fn device_removed(&mut self, device: &mut DrmDevice) { + fn device_removed(&mut self, device: dev_t) { // drop the backends on this side - self.backends.remove(&device.device_id()); - - // don't use hardware acceleration anymore, if this was the primary gpu - if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu { - *self.active_egl_context.borrow_mut() = None; + if let Some((dev, _)) = self.backends.remove(&device) { + // don't use hardware acceleration anymore, if this was the primary gpu + if dev.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu { + *self.active_egl_context.borrow_mut() = None; + } } } - - fn error(&mut self, error: IoError) { - error!(self.logger, "{:?}", error); - } } pub struct DrmHandlerImpl { compositor_token: CompositorToken, - backends: Rc>>>>, + backends: Rc>>>, window_map: Rc>, pointer_location: Rc>, logger: ::slog::Logger, } -impl DrmHandler for DrmHandlerImpl { - fn ready( - &mut self, - _device: &mut DrmDevice, - crtc: crtc::Handle, - _frame: u32, - _duration: Duration, - ) { +impl DeviceHandler for DrmHandlerImpl { + type Device = RenderDevice; + + fn vblank(&mut self, crtc: crtc::Handle) { if let Some(drawer) = self.backends.borrow().get(&crtc) { { let (x, y) = *self.pointer_location.borrow(); @@ -347,7 +379,7 @@ impl DrmHandler for DrmHandlerImpl { } } - fn error(&mut self, _device: &mut DrmDevice, error: DrmError) { + fn error(&mut self, error: ::Error) { error!(self.logger, "{:?}", error); } } diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index 4d191bd..2c3c2b0 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -5,11 +5,7 @@ use std::{ }; use smithay::{ - backend::{ - graphics::egl::{wayland::EGLWaylandExtensions, EGLGraphicsBackend}, - input::InputBackend, - winit, - }, + backend::{egl::EGLGraphicsBackend, graphics::gl::GLGraphicsBackend, input::InputBackend, winit}, wayland::{ data_device::{default_action_chooser, init_data_device, set_data_device_focus}, output::{Mode, Output, PhysicalProperties},