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"
[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" ]

View File

@ -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<F: EGLGraphicsBackend + 'static> {
pub struct GliumDrawer<F: GLGraphicsBackend + 'static> {
display: GliumGraphicsBackend<F>,
vertex_buffer: glium::VertexBuffer<Vertex>,
index_buffer: glium::IndexBuffer<u16>,
@ -47,13 +43,13 @@ pub struct GliumDrawer<F: EGLGraphicsBackend + 'static> {
log: Logger,
}
impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
pub fn borrow(&self) -> Ref<F> {
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> {
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, ()> {
// 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<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 texture: Texture2d,
pub fragment: usize,
@ -231,7 +221,7 @@ pub struct TextureMetadata {
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) {
let mut frame = self.draw();
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,
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<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<(), ()> {
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<SurfaceData, Roles>,
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>>,
primary_gpu: Option<PathBuf>,
window_map: Rc<RefCell<MyWindowMap>>,
@ -215,10 +233,11 @@ struct UdevHandlerImpl {
impl UdevHandlerImpl {
pub fn scan_connectors(
&self,
device: &mut DrmDevice<SessionFdDrmDevice>,
device: &mut RenderDevice,
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):
let res_handles = device.resource_handles().unwrap();
@ -226,9 +245,9 @@ impl UdevHandlerImpl {
let connector_infos: Vec<ConnectorInfo> = res_handles
.connectors()
.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)
.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::<EncoderInfo>(*encoder_handle))
.collect::<Vec<EncoderInfo>>();
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<DrmHandlerImpl> for UdevHandlerImpl {
fn device_added(&mut self, device: &mut DrmDevice<SessionFdDrmDevice>) -> Option<DrmHandlerImpl> {
// 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<SessionFdDrmDevice>) {
//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<SessionFdDrmDevice>) {
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<SurfaceData, Roles>,
backends: Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>>>>,
backends: Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<RenderSurface>>>>,
window_map: Rc<RefCell<MyWindowMap>>,
pointer_location: Rc<RefCell<(f64, f64)>>,
logger: ::slog::Logger,
}
impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
fn ready(
&mut self,
_device: &mut DrmDevice<SessionFdDrmDevice>,
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<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);
}
}

View File

@ -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},