anvil: fix for drm backend changes

This commit is contained in:
Victor Brekenfeld 2018-11-22 10:10:30 +01:00
parent db495ce4dc
commit 9428853ad6
4 changed files with 121 additions and 104 deletions

View File

@ -23,8 +23,7 @@ features = [ "renderer_glium" ]
gl_generator = "0.9" gl_generator = "0.9"
[features] [features]
default = [ "winit", "tty_launch", "udev" ] default = [ "winit", "udev" ]
winit = [ "smithay/backend_winit" ] winit = [ "smithay/backend_winit" ]
tty_launch = [ "smithay/backend_libinput", "smithay/backend_drm" ] udev = [ "smithay/backend_libinput", "smithay/backend_drm", "smithay/backend_udev", "smithay/backend_session" ]
udev = [ "tty_launch", "smithay/backend_udev" ]
logind = [ "smithay/backend_session_logind" ] logind = [ "smithay/backend_session_logind" ]

View File

@ -12,19 +12,15 @@ use glium::{
use slog::Logger; use slog::Logger;
use smithay::{ use smithay::{
backend::graphics::{ backend::{
egl::{ egl::{BufferAccessError, EGLDisplay, EGLImages, Format},
error::Result as EGLResult, graphics::{gl::GLGraphicsBackend, glium::GliumGraphicsBackend},
wayland::{BufferAccessError, EGLDisplay, EGLImages, EGLWaylandExtensions, Format},
EGLGraphicsBackend,
},
glium::GliumGraphicsBackend,
}, },
wayland::{ wayland::{
compositor::{roles::Role, SubsurfaceRole, TraversalAction}, compositor::{roles::Role, SubsurfaceRole, TraversalAction},
shm::with_buffer_contents as shm_buffer_contents, shm::with_buffer_contents as shm_buffer_contents,
}, },
wayland_server::{protocol::wl_buffer, Display, Resource}, wayland_server::{protocol::wl_buffer, Resource},
}; };
use shaders; use shaders;
@ -38,7 +34,7 @@ struct Vertex {
implement_vertex!(Vertex, position, tex_coords); implement_vertex!(Vertex, position, tex_coords);
pub struct GliumDrawer<F: EGLGraphicsBackend + 'static> { pub struct GliumDrawer<F: GLGraphicsBackend + 'static> {
display: GliumGraphicsBackend<F>, display: GliumGraphicsBackend<F>,
vertex_buffer: glium::VertexBuffer<Vertex>, vertex_buffer: glium::VertexBuffer<Vertex>,
index_buffer: glium::IndexBuffer<u16>, index_buffer: glium::IndexBuffer<u16>,
@ -47,13 +43,13 @@ pub struct GliumDrawer<F: EGLGraphicsBackend + 'static> {
log: Logger, log: Logger,
} }
impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> { impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
pub fn borrow(&self) -> Ref<F> { pub fn borrow(&self) -> Ref<F> {
self.display.borrow() self.display.borrow()
} }
} }
impl<T: Into<GliumGraphicsBackend<T>> + EGLGraphicsBackend + 'static> GliumDrawer<T> { impl<T: Into<GliumGraphicsBackend<T>> + GLGraphicsBackend + 'static> GliumDrawer<T> {
pub fn init(backend: T, egl_display: Rc<RefCell<Option<EGLDisplay>>>, log: Logger) -> GliumDrawer<T> { pub fn init(backend: T, egl_display: Rc<RefCell<Option<EGLDisplay>>>, log: Logger) -> GliumDrawer<T> {
let display = backend.into(); let display = backend.into();
@ -97,7 +93,7 @@ impl<T: Into<GliumGraphicsBackend<T>> + EGLGraphicsBackend + 'static> GliumDrawe
} }
} }
impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> { impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
pub fn texture_from_buffer(&self, buffer: Resource<wl_buffer::WlBuffer>) -> Result<TextureMetadata, ()> { pub fn texture_from_buffer(&self, buffer: Resource<wl_buffer::WlBuffer>) -> Result<TextureMetadata, ()> {
// try to retrieve the egl contents of this buffer // try to retrieve the egl contents of this buffer
let images = if let Some(display) = &self.egl_display.borrow().as_ref() { let images = if let Some(display) = &self.egl_display.borrow().as_ref() {
@ -217,12 +213,6 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
} }
} }
impl<G: EGLWaylandExtensions + EGLGraphicsBackend + 'static> EGLWaylandExtensions for GliumDrawer<G> {
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
self.display.bind_wl_display(display)
}
}
pub struct TextureMetadata { pub struct TextureMetadata {
pub texture: Texture2d, pub texture: Texture2d,
pub fragment: usize, pub fragment: usize,
@ -231,7 +221,7 @@ pub struct TextureMetadata {
images: Option<EGLImages>, images: Option<EGLImages>,
} }
impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> { impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
pub fn draw_windows(&self, window_map: &MyWindowMap, compositor_token: MyCompositorToken, log: &Logger) { pub fn draw_windows(&self, window_map: &MyWindowMap, compositor_token: MyCompositorToken, log: &Logger) {
let mut frame = self.draw(); let mut frame = self.draw();
frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None); frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);

View File

@ -2,41 +2,42 @@ use std::{
cell::RefCell, cell::RefCell,
collections::HashMap, collections::HashMap,
io::Error as IoError, io::Error as IoError,
os::unix::io::{AsRawFd, RawFd},
path::PathBuf, path::PathBuf,
rc::Rc, rc::Rc,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
Arc, Arc,
}, },
time::Duration,
}; };
use glium::Surface; use glium::Surface as GliumSurface;
use slog::Logger; use slog::Logger;
use smithay::{ use smithay::{
backend::{ backend::{
drm::{DevPath, DrmBackend, DrmDevice, DrmHandler}, drm::{
graphics::{ dev_t,
egl::wayland::{EGLDisplay, EGLWaylandExtensions}, egl::{EglDevice, EglSurface},
GraphicsBackend, gbm::{egl::Gbm as EglGbmBackend, GbmDevice},
legacy::LegacyDrmDevice,
DevPath, Device, DeviceHandler, Surface,
}, },
egl::{EGLDisplay, EGLGraphicsBackend},
graphics::CursorBackend,
input::InputBackend, input::InputBackend,
libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface}, libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface},
session::{ session::{
auto::{auto_session_bind, AutoSession}, 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::{ drm::control::{
control::{ connector::{Info as ConnectorInfo, State as ConnectorState},
connector::{Info as ConnectorInfo, State as ConnectorState}, crtc,
crtc, encoder::Info as EncoderInfo,
encoder::Info as EncoderInfo, ResourceInfo,
Device as ControlDevice, ResourceInfo,
},
result::Error as DrmError,
}, },
image::{ImageBuffer, Rgba}, image::{ImageBuffer, Rgba},
input::Libinput, input::Libinput,
@ -54,6 +55,18 @@ use glium_drawer::GliumDrawer;
use input_handler::AnvilInputHandler; use input_handler::AnvilInputHandler;
use shell::{init_shell, MyWindowMap, Roles, SurfaceData}; 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<EglGbmBackend<LegacyDrmDevice<SessionFd>>, GbmDevice<LegacyDrmDevice<SessionFd>>>;
type RenderSurface =
EglSurface<EglGbmBackend<LegacyDrmDevice<SessionFd>>, GbmDevice<LegacyDrmDevice<SessionFd>>>;
pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger) -> Result<(), ()> { pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger) -> Result<(), ()> {
let name = display.add_socket_auto().unwrap().into_string().unwrap(); let name = display.add_socket_auto().unwrap().into_string().unwrap();
info!(log, "Listening on wayland socket"; "name" => name.clone()); 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 primary_gpu = primary_gpu(&context, &seat).unwrap_or_default();
let bytes = include_bytes!("../resources/cursor2.rgba"); let bytes = include_bytes!("../resources/cursor2.rgba");
let mut udev_backend = UdevBackend::new( let udev_backend = UdevBackend::new(
event_loop.handle(),
&context, &context,
session.clone(),
UdevHandlerImpl { UdevHandlerImpl {
compositor_token, compositor_token,
active_egl_context, active_egl_context,
session: session.clone(),
backends: HashMap::new(), backends: HashMap::new(),
display: display.clone(), display: display.clone(),
primary_gpu, 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(), pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
logger: log.clone(), logger: log.clone(),
}, },
seat.clone(),
log.clone(), log.clone(),
).map_err(|_| ())?; ).map_err(|_| ())?;
let udev_session_id = notifier.register(&mut udev_backend);
init_data_device( init_data_device(
&mut display.borrow_mut(), &mut display.borrow_mut(),
|_| {}, |_| {},
@ -171,13 +182,14 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
session, session,
)); ));
let libinput_event_source = libinput_bind(libinput_backend, event_loop.handle()) let libinput_event_source = libinput_bind(libinput_backend, event_loop.handle())
.map_err(|(e, _)| e) .map_err(|e| -> IoError { e.into() })
.unwrap(); .unwrap();
let session_event_source = auto_session_bind(notifier, &event_loop.handle()) let session_event_source = auto_session_bind(notifier, &event_loop.handle())
.map_err(|(e, _)| e) .map_err(|(e, _)| e)
.unwrap(); .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) { while running.load(Ordering::SeqCst) {
if event_loop 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(); let mut notifier = session_event_source.unbind();
notifier.unregister(udev_session_id);
notifier.unregister(libinput_session_id); notifier.unregister(libinput_session_id);
libinput_event_source.remove(); libinput_event_source.remove();
@ -204,7 +215,14 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
struct UdevHandlerImpl { struct UdevHandlerImpl {
compositor_token: CompositorToken<SurfaceData, Roles>, compositor_token: CompositorToken<SurfaceData, Roles>,
active_egl_context: Rc<RefCell<Option<EGLDisplay>>>, active_egl_context: Rc<RefCell<Option<EGLDisplay>>>,
backends: HashMap<u64, Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>>>>>, session: AutoSession,
backends: HashMap<
dev_t,
(
RenderDevice,
Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<RenderSurface>>>>,
),
>,
display: Rc<RefCell<Display>>, display: Rc<RefCell<Display>>,
primary_gpu: Option<PathBuf>, primary_gpu: Option<PathBuf>,
window_map: Rc<RefCell<MyWindowMap>>, window_map: Rc<RefCell<MyWindowMap>>,
@ -215,10 +233,11 @@ struct UdevHandlerImpl {
impl UdevHandlerImpl { impl UdevHandlerImpl {
pub fn scan_connectors( pub fn scan_connectors(
&self, device: &mut RenderDevice,
device: &mut DrmDevice<SessionFdDrmDevice>,
egl_display: Rc<RefCell<Option<EGLDisplay>>>, egl_display: Rc<RefCell<Option<EGLDisplay>>>,
) -> HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>> { pointer_image: &ImageBuffer<Rgba<u8>, Vec<u8>>,
logger: &::slog::Logger,
) -> HashMap<crtc::Handle, GliumDrawer<RenderSurface>> {
// Get a set of all modesetting resource handles (excluding planes): // Get a set of all modesetting resource handles (excluding planes):
let res_handles = device.resource_handles().unwrap(); let res_handles = device.resource_handles().unwrap();
@ -226,9 +245,9 @@ impl UdevHandlerImpl {
let connector_infos: Vec<ConnectorInfo> = res_handles let connector_infos: Vec<ConnectorInfo> = res_handles
.connectors() .connectors()
.iter() .iter()
.map(|conn| ConnectorInfo::load_from_device(device, *conn).unwrap()) .map(|conn| device.resource_info::<ConnectorInfo>(*conn).unwrap())
.filter(|conn| conn.connection_state() == ConnectorState::Connected) .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(); .collect();
let mut backends = HashMap::new(); let mut backends = HashMap::new();
@ -238,7 +257,7 @@ impl UdevHandlerImpl {
let encoder_infos = connector_info let encoder_infos = connector_info
.encoders() .encoders()
.iter() .iter()
.flat_map(|encoder_handle| EncoderInfo::load_from_device(device, *encoder_handle)) .flat_map(|encoder_handle| device.resource_info::<EncoderInfo>(*encoder_handle))
.collect::<Vec<EncoderInfo>>(); .collect::<Vec<EncoderInfo>>();
for encoder_info in encoder_infos { for encoder_info in encoder_infos {
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) { for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
@ -247,16 +266,16 @@ impl UdevHandlerImpl {
// create a backend // create a backend
let renderer = GliumDrawer::init( let renderer = GliumDrawer::init(
device device
.create_backend(crtc, mode, vec![connector_info.handle()]) .create_surface(crtc, mode, vec![connector_info.handle()].into_iter())
.unwrap(), .unwrap(),
egl_display.clone(), egl_display.clone(),
self.logger.clone(), logger.clone(),
); );
// create cursor // create cursor
renderer renderer
.borrow() .borrow()
.set_cursor_representation(&self.pointer_image, (2, 2)) .set_cursor_representation(pointer_image, (2, 2))
.unwrap(); .unwrap();
// render first frame // render first frame
@ -277,64 +296,77 @@ impl UdevHandlerImpl {
} }
} }
impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl { impl UdevHandler for UdevHandlerImpl {
fn device_added(&mut self, device: &mut DrmDevice<SessionFdDrmDevice>) -> Option<DrmHandlerImpl> { fn device_added(&mut self, _device: dev_t, path: PathBuf) {
// init hardware acceleration on the primary gpu. if let Some(mut device) = self
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu { .session
*self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display.borrow()).ok(); .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<SessionFdDrmDevice>) { fn device_changed(&mut self, device: dev_t) {
//quick and dirt, just re-init all backends //quick and dirty, just re-init all backends
let backends = &self.backends[&device.device_id()]; if let Some((ref mut device, ref backends)) = self.backends.get_mut(&device) {
*backends.borrow_mut() = self.scan_connectors(device, self.active_egl_context.clone()); *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<SessionFdDrmDevice>) { fn device_removed(&mut self, device: dev_t) {
// drop the backends on this side // drop the backends on this side
self.backends.remove(&device.device_id()); if let Some((dev, _)) = self.backends.remove(&device) {
// don't use hardware acceleration anymore, if this was the primary gpu
// 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 {
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu { *self.active_egl_context.borrow_mut() = None;
*self.active_egl_context.borrow_mut() = None; }
} }
} }
fn error(&mut self, error: IoError) {
error!(self.logger, "{:?}", error);
}
} }
pub struct DrmHandlerImpl { pub struct DrmHandlerImpl {
compositor_token: CompositorToken<SurfaceData, Roles>, compositor_token: CompositorToken<SurfaceData, Roles>,
backends: Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>>>>, backends: Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<RenderSurface>>>>,
window_map: Rc<RefCell<MyWindowMap>>, window_map: Rc<RefCell<MyWindowMap>>,
pointer_location: Rc<RefCell<(f64, f64)>>, pointer_location: Rc<RefCell<(f64, f64)>>,
logger: ::slog::Logger, logger: ::slog::Logger,
} }
impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl { impl DeviceHandler for DrmHandlerImpl {
fn ready( type Device = RenderDevice;
&mut self,
_device: &mut DrmDevice<SessionFdDrmDevice>, fn vblank(&mut self, crtc: crtc::Handle) {
crtc: crtc::Handle,
_frame: u32,
_duration: Duration,
) {
if let Some(drawer) = self.backends.borrow().get(&crtc) { if let Some(drawer) = self.backends.borrow().get(&crtc) {
{ {
let (x, y) = *self.pointer_location.borrow(); let (x, y) = *self.pointer_location.borrow();
@ -347,7 +379,7 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
} }
} }
fn error(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, error: DrmError) { fn error(&mut self, error: <RenderSurface as Surface>::Error) {
error!(self.logger, "{:?}", error); error!(self.logger, "{:?}", error);
} }
} }

View File

@ -5,11 +5,7 @@ use std::{
}; };
use smithay::{ use smithay::{
backend::{ backend::{egl::EGLGraphicsBackend, graphics::gl::GLGraphicsBackend, input::InputBackend, winit},
graphics::egl::{wayland::EGLWaylandExtensions, EGLGraphicsBackend},
input::InputBackend,
winit,
},
wayland::{ wayland::{
data_device::{default_action_chooser, init_data_device, set_data_device_focus}, data_device::{default_action_chooser, init_data_device, set_data_device_focus},
output::{Mode, Output, PhysicalProperties}, output::{Mode, Output, PhysicalProperties},