Update to calloop 0.8, DrmDevice as an EventSource
This commit is contained in:
parent
e008360bde
commit
aaa6e625e9
|
@ -12,7 +12,7 @@ members = [ "anvil" ]
|
|||
|
||||
[dependencies]
|
||||
bitflags = "1"
|
||||
calloop = "0.6.2"
|
||||
calloop = {version = "0.8.0" }
|
||||
cgmath = "0.18.0"
|
||||
dbus = { version = "0.9.0", optional = true }
|
||||
drm-fourcc = "^2.1.1"
|
||||
|
@ -35,7 +35,7 @@ wayland-egl = { version = "0.28", optional = true }
|
|||
wayland-protocols = { version = "0.28", features = ["unstable_protocols", "server"], optional = true }
|
||||
wayland-server = { version = "0.28.3", optional = true }
|
||||
wayland-sys = { version = "0.28", optional = true }
|
||||
winit = { version = "0.24.0", optional = true }
|
||||
winit = { version = "0.25.0", optional = true }
|
||||
xkbcommon = "0.4.0"
|
||||
scan_fmt = { version = "0.2", default-features = false }
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use smithay::{
|
|||
},
|
||||
};
|
||||
|
||||
impl AnvilState {
|
||||
impl<Backend> AnvilState<Backend> {
|
||||
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
||||
match event {
|
||||
InputEvent::Keyboard { event, .. } => self.on_keyboard_key::<B>(event),
|
||||
|
|
|
@ -39,14 +39,13 @@ fn main() {
|
|||
o!(),
|
||||
);
|
||||
|
||||
let mut event_loop = EventLoop::<AnvilState>::new().unwrap();
|
||||
let display = Rc::new(RefCell::new(Display::new()));
|
||||
|
||||
let arg = ::std::env::args().nth(1);
|
||||
match arg.as_ref().map(|s| &s[..]) {
|
||||
#[cfg(feature = "winit")]
|
||||
Some("--winit") => {
|
||||
info!(log, "Starting anvil with winit backend");
|
||||
let mut event_loop = EventLoop::try_new().unwrap();
|
||||
let display = Rc::new(RefCell::new(Display::new()));
|
||||
if let Err(()) = winit::run_winit(display, &mut event_loop, log.clone()) {
|
||||
crit!(log, "Failed to initialize winit backend.");
|
||||
}
|
||||
|
@ -54,6 +53,8 @@ fn main() {
|
|||
#[cfg(feature = "udev")]
|
||||
Some("--tty-udev") => {
|
||||
info!(log, "Starting anvil on a tty using udev");
|
||||
let mut event_loop = EventLoop::try_new().unwrap();
|
||||
let display = Rc::new(RefCell::new(Display::new()));
|
||||
if let Err(()) = udev::run_udev(display, &mut event_loop, log.clone()) {
|
||||
crit!(log, "Failed to initialize tty backend.");
|
||||
}
|
||||
|
|
|
@ -9,10 +9,7 @@ use std::{
|
|||
|
||||
use smithay::{
|
||||
reexports::{
|
||||
calloop::{
|
||||
generic::{Fd, Generic},
|
||||
Interest, LoopHandle, Mode, Source,
|
||||
},
|
||||
calloop::{generic::Generic, Interest, LoopHandle, Mode, RegistrationToken},
|
||||
wayland_server::{protocol::wl_surface::WlSurface, Display},
|
||||
},
|
||||
wayland::{
|
||||
|
@ -36,11 +33,12 @@ use crate::udev::MyOutput;
|
|||
#[cfg(feature = "xwayland")]
|
||||
use crate::xwayland::XWm;
|
||||
|
||||
pub struct AnvilState {
|
||||
pub struct AnvilState<Backend> {
|
||||
pub backend: Backend,
|
||||
pub socket_name: String,
|
||||
pub running: Arc<AtomicBool>,
|
||||
pub display: Rc<RefCell<Display>>,
|
||||
pub handle: LoopHandle<AnvilState>,
|
||||
pub handle: LoopHandle<'static, AnvilState<Backend>>,
|
||||
pub ctoken: CompositorToken<crate::shell::Roles>,
|
||||
pub window_map: Rc<RefCell<crate::window_map::WindowMap<crate::shell::Roles>>>,
|
||||
pub dnd_icon: Arc<Mutex<Option<WlSurface>>>,
|
||||
|
@ -56,30 +54,30 @@ pub struct AnvilState {
|
|||
#[cfg(feature = "udev")]
|
||||
pub session: Option<AutoSession>,
|
||||
// things we must keep alive
|
||||
_wayland_event_source: Source<Generic<Fd>>,
|
||||
_wayland_event_source: RegistrationToken,
|
||||
#[cfg(feature = "xwayland")]
|
||||
_xwayland: XWayland<XWm>,
|
||||
_xwayland: XWayland<XWm<Backend>>,
|
||||
}
|
||||
|
||||
impl AnvilState {
|
||||
impl<Backend: Default + 'static> AnvilState<Backend> {
|
||||
pub fn init(
|
||||
display: Rc<RefCell<Display>>,
|
||||
handle: LoopHandle<AnvilState>,
|
||||
handle: LoopHandle<'static, AnvilState<Backend>>,
|
||||
#[cfg(feature = "egl")] egl_reader: Rc<RefCell<Option<EGLBufferReader>>>,
|
||||
#[cfg(feature = "udev")] session: Option<AutoSession>,
|
||||
#[cfg(not(feature = "udev"))] _session: Option<()>,
|
||||
#[cfg(feature = "udev")] output_map: Option<Rc<RefCell<Vec<MyOutput>>>>,
|
||||
#[cfg(not(feature = "udev"))] _output_map: Option<()>,
|
||||
log: slog::Logger,
|
||||
) -> AnvilState {
|
||||
) -> AnvilState<Backend> {
|
||||
// init the wayland connection
|
||||
let _wayland_event_source = handle
|
||||
.insert_source(
|
||||
Generic::from_fd(display.borrow().get_poll_fd(), Interest::Readable, Mode::Level),
|
||||
Generic::from_fd(display.borrow().get_poll_fd(), Interest::READ, Mode::Level),
|
||||
{
|
||||
let display = display.clone();
|
||||
let log = log.clone();
|
||||
move |_, _, state: &mut AnvilState| {
|
||||
move |_, _, state: &mut AnvilState<Backend>| {
|
||||
let mut display = display.borrow_mut();
|
||||
match display.dispatch(std::time::Duration::from_millis(0), state) {
|
||||
Ok(_) => Ok(()),
|
||||
|
@ -176,6 +174,7 @@ impl AnvilState {
|
|||
};
|
||||
|
||||
AnvilState {
|
||||
backend: Default::default(),
|
||||
running: Arc::new(AtomicBool::new(true)),
|
||||
display,
|
||||
handle,
|
||||
|
|
|
@ -16,7 +16,7 @@ use slog::Logger;
|
|||
use smithay::backend::{drm::DevPath, egl::display::EGLBufferReader, udev::primary_gpu};
|
||||
use smithay::{
|
||||
backend::{
|
||||
drm::{device_bind, DeviceHandler, DrmDevice, DrmError, DrmRenderSurface},
|
||||
drm::{DrmDevice, DrmError, DrmEvent, DrmRenderSurface},
|
||||
egl::{EGLContext, EGLDisplay},
|
||||
libinput::{LibinputInputBackend, LibinputSessionInterface},
|
||||
renderer::{
|
||||
|
@ -29,9 +29,8 @@ use smithay::{
|
|||
},
|
||||
reexports::{
|
||||
calloop::{
|
||||
generic::Generic,
|
||||
timer::{Timer, TimerHandle},
|
||||
EventLoop, LoopHandle, Source,
|
||||
Dispatcher, EventLoop, LoopHandle, RegistrationToken,
|
||||
},
|
||||
drm::{
|
||||
self,
|
||||
|
@ -71,9 +70,17 @@ impl AsRawFd for SessionFd {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct UdevData {}
|
||||
|
||||
impl Default for UdevData {
|
||||
fn default() -> UdevData {
|
||||
UdevData {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_udev(
|
||||
display: Rc<RefCell<Display>>,
|
||||
event_loop: &mut EventLoop<AnvilState>,
|
||||
event_loop: &mut EventLoop<'static, AnvilState<UdevData>>,
|
||||
log: Logger,
|
||||
) -> Result<(), ()> {
|
||||
let name = display
|
||||
|
@ -272,10 +279,11 @@ struct BackendData {
|
|||
context: EGLContext,
|
||||
egl: EGLDisplay,
|
||||
gbm: GbmDevice<SessionFd>,
|
||||
event_source: Source<Generic<DrmDevice<SessionFd>>>,
|
||||
registration_token: RegistrationToken,
|
||||
event_dispatcher: Dispatcher<'static, DrmDevice<SessionFd>, AnvilState<UdevData>>,
|
||||
}
|
||||
|
||||
struct UdevHandlerImpl<Data: 'static> {
|
||||
struct UdevHandlerImpl {
|
||||
compositor_token: CompositorToken<Roles>,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
|
||||
|
@ -290,12 +298,12 @@ struct UdevHandlerImpl<Data: 'static> {
|
|||
pointer_image: ImageBuffer<Rgba<u8>, Vec<u8>>,
|
||||
cursor_status: Arc<Mutex<CursorImageStatus>>,
|
||||
dnd_icon: Arc<Mutex<Option<wl_surface::WlSurface>>>,
|
||||
loop_handle: LoopHandle<Data>,
|
||||
loop_handle: LoopHandle<'static, AnvilState<UdevData>>,
|
||||
signaler: Signaler<SessionSignal>,
|
||||
logger: ::slog::Logger,
|
||||
}
|
||||
|
||||
impl<Data: 'static> UdevHandlerImpl<Data> {
|
||||
impl UdevHandlerImpl {
|
||||
pub fn scan_connectors(
|
||||
device: &mut DrmDevice<SessionFd>,
|
||||
gbm: &GbmDevice<SessionFd>,
|
||||
|
@ -392,7 +400,7 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Data: 'static> UdevHandlerImpl<Data> {
|
||||
impl UdevHandlerImpl {
|
||||
fn device_added(&mut self, device_id: dev_t, path: PathBuf) {
|
||||
// Try to open the device
|
||||
if let Some((mut device, gbm)) = self
|
||||
|
@ -465,7 +473,7 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
|||
}
|
||||
};
|
||||
|
||||
let backends = Rc::new(RefCell::new(UdevHandlerImpl::<Data>::scan_connectors(
|
||||
let backends = Rc::new(RefCell::new(UdevHandlerImpl::scan_connectors(
|
||||
&mut device,
|
||||
&gbm,
|
||||
&egl,
|
||||
|
@ -516,15 +524,22 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
|||
SessionSignal::ActivateSession | SessionSignal::ActivateDevice { .. } => listener.activate(),
|
||||
_ => {}
|
||||
});
|
||||
device.set_handler(DrmHandlerImpl {
|
||||
let mut drm_handler = DrmHandlerImpl {
|
||||
renderer,
|
||||
loop_handle: self.loop_handle.clone(),
|
||||
});
|
||||
};
|
||||
|
||||
device.link(self.signaler.clone());
|
||||
let dev_id = device.device_id();
|
||||
let event_source = device_bind(&self.loop_handle, device)
|
||||
.map_err(|e| -> IoError { e.into() })
|
||||
let event_dispatcher = Dispatcher::new(device, move |event, _, _| match event {
|
||||
DrmEvent::VBlank(crtc) => drm_handler.vblank(crtc),
|
||||
DrmEvent::Error(error) => {
|
||||
error!(drm_handler.renderer.logger, "{:?}", error);
|
||||
}
|
||||
});
|
||||
let registration_token = self
|
||||
.loop_handle
|
||||
.register_dispatcher(event_dispatcher.clone())
|
||||
.unwrap();
|
||||
|
||||
trace!(self.logger, "Backends: {:?}", backends.borrow().keys());
|
||||
|
@ -538,7 +553,8 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
|||
dev_id,
|
||||
BackendData {
|
||||
_restart_token: restart_token,
|
||||
event_source,
|
||||
registration_token,
|
||||
event_dispatcher,
|
||||
surfaces: backends,
|
||||
egl,
|
||||
context,
|
||||
|
@ -557,11 +573,11 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
|||
let mut output_map = self.output_map.borrow_mut();
|
||||
let signaler = self.signaler.clone();
|
||||
output_map.retain(|output| output.device_id != device);
|
||||
self.loop_handle
|
||||
.with_source(&backend_data.event_source, |source| {
|
||||
|
||||
let mut source = backend_data.event_dispatcher.as_source_mut();
|
||||
let mut backends = backend_data.surfaces.borrow_mut();
|
||||
*backends = UdevHandlerImpl::<Data>::scan_connectors(
|
||||
&mut source.file,
|
||||
*backends = UdevHandlerImpl::scan_connectors(
|
||||
&mut *source,
|
||||
&backend_data.gbm,
|
||||
&backend_data.egl,
|
||||
&backend_data.context,
|
||||
|
@ -576,7 +592,6 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
|||
// render first frame
|
||||
schedule_initial_render(renderer.clone(), &loop_handle, logger);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,7 +606,8 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
|||
.borrow_mut()
|
||||
.retain(|output| output.device_id != device);
|
||||
|
||||
let _device = self.loop_handle.remove(backend_data.event_source).unwrap();
|
||||
let _device = self.loop_handle.remove(backend_data.registration_token);
|
||||
let _device = backend_data.event_dispatcher.into_source_inner();
|
||||
|
||||
// don't use hardware acceleration anymore, if this was the primary gpu
|
||||
#[cfg(feature = "egl")]
|
||||
|
@ -607,22 +623,18 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
|||
|
||||
pub struct DrmHandlerImpl<Data: 'static> {
|
||||
renderer: Rc<DrmRenderer>,
|
||||
loop_handle: LoopHandle<Data>,
|
||||
loop_handle: LoopHandle<'static, Data>,
|
||||
}
|
||||
|
||||
impl<Data: 'static> DeviceHandler for DrmHandlerImpl<Data> {
|
||||
impl<Data: 'static> DrmHandlerImpl<Data> {
|
||||
fn vblank(&mut self, crtc: crtc::Handle) {
|
||||
self.renderer.clone().render(crtc, None, Some(&self.loop_handle))
|
||||
}
|
||||
|
||||
fn error(&mut self, error: DrmError) {
|
||||
error!(self.renderer.logger, "{:?}", error);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DrmRendererSessionListener<Data: 'static> {
|
||||
renderer: Rc<DrmRenderer>,
|
||||
loop_handle: LoopHandle<Data>,
|
||||
loop_handle: LoopHandle<'static, Data>,
|
||||
}
|
||||
|
||||
impl<Data: 'static> DrmRendererSessionListener<Data> {
|
||||
|
@ -652,7 +664,7 @@ pub struct DrmRenderer {
|
|||
}
|
||||
|
||||
impl DrmRenderer {
|
||||
fn render_all<Data: 'static>(self: Rc<Self>, evt_handle: Option<&LoopHandle<Data>>) {
|
||||
fn render_all<Data: 'static>(self: Rc<Self>, evt_handle: Option<&LoopHandle<'static, Data>>) {
|
||||
for crtc in self.backends.borrow().keys() {
|
||||
self.clone().render(*crtc, None, evt_handle);
|
||||
}
|
||||
|
@ -661,7 +673,7 @@ impl DrmRenderer {
|
|||
self: Rc<Self>,
|
||||
crtc: crtc::Handle,
|
||||
timer: Option<TimerHandle<(std::rc::Weak<DrmRenderer>, crtc::Handle)>>,
|
||||
evt_handle: Option<&LoopHandle<Data>>,
|
||||
evt_handle: Option<&LoopHandle<'static, Data>>,
|
||||
) {
|
||||
if let Some(surface) = self.backends.borrow().get(&crtc) {
|
||||
let result = DrmRenderer::render_surface(
|
||||
|
@ -716,7 +728,7 @@ impl DrmRenderer {
|
|||
renderer.render(
|
||||
crtc,
|
||||
Some(handle.clone()),
|
||||
Option::<&LoopHandle<Data>>::None,
|
||||
Option::<&LoopHandle<'static, Data>>::None,
|
||||
);
|
||||
}
|
||||
})
|
||||
|
@ -846,7 +858,7 @@ impl DrmRenderer {
|
|||
|
||||
fn schedule_initial_render<Data: 'static>(
|
||||
renderer: Rc<RefCell<RenderSurface>>,
|
||||
evt_handle: &LoopHandle<Data>,
|
||||
evt_handle: &LoopHandle<'static, Data>,
|
||||
logger: ::slog::Logger,
|
||||
) {
|
||||
let result = {
|
||||
|
|
|
@ -17,9 +17,17 @@ use slog::Logger;
|
|||
use crate::drawing::*;
|
||||
use crate::state::AnvilState;
|
||||
|
||||
pub struct WinitData;
|
||||
|
||||
impl Default for WinitData {
|
||||
fn default() -> WinitData {
|
||||
WinitData
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_winit(
|
||||
display: Rc<RefCell<Display>>,
|
||||
event_loop: &mut EventLoop<AnvilState>,
|
||||
event_loop: &mut EventLoop<'static, AnvilState<WinitData>>,
|
||||
log: Logger,
|
||||
) -> Result<(), ()> {
|
||||
let (renderer, mut input) = winit::init(log.clone()).map_err(|err| {
|
||||
|
|
|
@ -35,16 +35,16 @@ mod x11rb_event_source;
|
|||
|
||||
/// Implementation of [`smithay::xwayland::XWindowManager`] that is used for starting XWayland.
|
||||
/// After XWayland was started, the actual state is kept in `X11State`.
|
||||
pub struct XWm {
|
||||
handle: LoopHandle<AnvilState>,
|
||||
pub struct XWm<Backend> {
|
||||
handle: LoopHandle<'static, AnvilState<Backend>>,
|
||||
token: CompositorToken<Roles>,
|
||||
window_map: Rc<RefCell<MyWindowMap>>,
|
||||
log: slog::Logger,
|
||||
}
|
||||
|
||||
impl XWm {
|
||||
impl<Backend> XWm<Backend> {
|
||||
pub fn new(
|
||||
handle: LoopHandle<AnvilState>,
|
||||
handle: LoopHandle<'static, AnvilState<Backend>>,
|
||||
token: CompositorToken<Roles>,
|
||||
window_map: Rc<RefCell<MyWindowMap>>,
|
||||
log: slog::Logger,
|
||||
|
@ -58,7 +58,7 @@ impl XWm {
|
|||
}
|
||||
}
|
||||
|
||||
impl XWindowManager for XWm {
|
||||
impl<Backend> XWindowManager for XWm<Backend> {
|
||||
fn xwayland_ready(&mut self, connection: UnixStream, client: Client) {
|
||||
let (wm, source) =
|
||||
X11State::start_wm(connection, self.token, self.window_map.clone(), self.log.clone()).unwrap();
|
||||
|
|
|
@ -21,7 +21,7 @@ pub struct X11Source {
|
|||
impl X11Source {
|
||||
pub fn new(connection: Rc<RustConnection>) -> Self {
|
||||
let fd = Fd(connection.stream().as_raw_fd());
|
||||
let generic = Generic::new(fd, Interest::Readable, Mode::Level);
|
||||
let generic = Generic::new(fd, Interest::READ, Mode::Level);
|
||||
Self { connection, generic }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use slog::Drain;
|
|||
use smithay::{
|
||||
backend::{
|
||||
allocator::{dumb::DumbBuffer, Fourcc, Slot, Swapchain},
|
||||
drm::{device_bind, DeviceHandler, DrmDevice, DrmError, DrmSurface},
|
||||
drm::{DrmDevice, DrmEvent, DrmSurface},
|
||||
},
|
||||
reexports::{
|
||||
calloop::EventLoop,
|
||||
|
@ -16,7 +16,6 @@ use smithay::{
|
|||
};
|
||||
use std::{
|
||||
fs::{File, OpenOptions},
|
||||
io::Error as IoError,
|
||||
os::unix::io::{AsRawFd, RawFd},
|
||||
rc::Rc,
|
||||
sync::Mutex,
|
||||
|
@ -48,7 +47,7 @@ fn main() {
|
|||
file: Rc::new(options.open("/dev/dri/card0").unwrap()),
|
||||
};
|
||||
|
||||
let mut device = DrmDevice::new(fd.clone(), true, log.clone()).unwrap();
|
||||
let device = DrmDevice::new(fd.clone(), true, log.clone()).unwrap();
|
||||
|
||||
// Get a set of all modesetting resource handles (excluding planes):
|
||||
let res_handles = ControlDevice::resource_handles(&device).unwrap();
|
||||
|
@ -111,20 +110,23 @@ fn main() {
|
|||
*first_buffer.userdata() = Some(framebuffer);
|
||||
|
||||
// Get the device as an allocator into the
|
||||
device.set_handler(DrmHandlerImpl {
|
||||
let mut vblank_handler = VBlankHandler {
|
||||
swapchain,
|
||||
current: first_buffer,
|
||||
surface: surface.clone(),
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Register the DrmDevice on the EventLoop
|
||||
*/
|
||||
let mut event_loop = EventLoop::<()>::new().unwrap();
|
||||
let _source = device_bind(&event_loop.handle(), device)
|
||||
.map_err(|err| -> IoError { err.into() })
|
||||
let mut event_loop = EventLoop::<()>::try_new().unwrap();
|
||||
event_loop
|
||||
.handle()
|
||||
.insert_source(device, move |event, _: &mut (), _: &mut ()| match event {
|
||||
DrmEvent::VBlank(crtc) => vblank_handler.vblank(crtc),
|
||||
DrmEvent::Error(e) => panic!("{}", e),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// Start rendering
|
||||
surface
|
||||
.commit([(framebuffer, surface.plane())].iter(), true)
|
||||
|
@ -134,13 +136,13 @@ fn main() {
|
|||
event_loop.run(None, &mut (), |_| {}).unwrap();
|
||||
}
|
||||
|
||||
pub struct DrmHandlerImpl {
|
||||
pub struct VBlankHandler {
|
||||
swapchain: Swapchain<DrmDevice<FdWrapper>, DumbBuffer<FdWrapper>, framebuffer::Handle>,
|
||||
current: Slot<DumbBuffer<FdWrapper>, framebuffer::Handle>,
|
||||
surface: Rc<DrmSurface<FdWrapper>>,
|
||||
}
|
||||
|
||||
impl DeviceHandler for DrmHandlerImpl {
|
||||
impl VBlankHandler {
|
||||
fn vblank(&mut self, _crtc: crtc::Handle) {
|
||||
{
|
||||
// Next buffer
|
||||
|
@ -168,8 +170,4 @@ impl DeviceHandler for DrmHandlerImpl {
|
|||
.page_flip([(fb, self.surface.plane())].iter(), true)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn error(&mut self, error: DrmError) {
|
||||
panic!("{:?}", error);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::cell::RefCell;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{atomic::AtomicBool, Arc};
|
||||
|
||||
use calloop::{generic::Generic, InsertError, LoopHandle, Source};
|
||||
use calloop::{EventSource, Interest, Poll, Readiness, Token};
|
||||
use drm::control::{connector, crtc, Device as ControlDevice, Event, Mode, ResourceHandles};
|
||||
use drm::{ClientCapability, Device as BasicDevice};
|
||||
use nix::libc::dev_t;
|
||||
|
@ -21,7 +20,6 @@ use legacy::LegacyDrmDevice;
|
|||
pub struct DrmDevice<A: AsRawFd + 'static> {
|
||||
pub(super) dev_id: dev_t,
|
||||
pub(crate) internal: Arc<DrmDeviceInternal<A>>,
|
||||
handler: Rc<RefCell<Option<Box<dyn DeviceHandler>>>>,
|
||||
#[cfg(feature = "backend_session")]
|
||||
pub(super) links: RefCell<Vec<crate::signaling::SignalToken>>,
|
||||
has_universal_planes: bool,
|
||||
|
@ -145,7 +143,6 @@ impl<A: AsRawFd + 'static> DrmDevice<A> {
|
|||
Ok(DrmDevice {
|
||||
dev_id,
|
||||
internal,
|
||||
handler: Rc::new(RefCell::new(None)),
|
||||
#[cfg(feature = "backend_session")]
|
||||
links: RefCell::new(Vec::new()),
|
||||
has_universal_planes,
|
||||
|
@ -180,43 +177,6 @@ impl<A: AsRawFd + 'static> DrmDevice<A> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Processes any open events of the underlying file descriptor.
|
||||
///
|
||||
/// You should not call this function manually, but rather use
|
||||
/// [`device_bind`] to register the device
|
||||
/// to an [`EventLoop`](calloop::EventLoop)
|
||||
/// and call this function when the device becomes readable
|
||||
/// to synchronize your rendering to the vblank events of the open crtc's
|
||||
pub fn process_events(&mut self) {
|
||||
match self.receive_events() {
|
||||
Ok(events) => {
|
||||
for event in events {
|
||||
if let Event::PageFlip(event) = event {
|
||||
trace!(self.logger, "Got a page-flip event for crtc ({:?})", event.crtc);
|
||||
if let Some(handler) = self.handler.borrow_mut().as_mut() {
|
||||
handler.vblank(event.crtc);
|
||||
}
|
||||
} else {
|
||||
trace!(
|
||||
self.logger,
|
||||
"Got a non-page-flip event of device '{:?}'.",
|
||||
self.dev_path()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(source) => {
|
||||
if let Some(handler) = self.handler.borrow_mut().as_mut() {
|
||||
handler.error(Error::Access {
|
||||
errmsg: "Error processing drm events",
|
||||
dev: self.dev_path(),
|
||||
source,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns if the underlying implementation uses atomic-modesetting or not.
|
||||
pub fn is_atomic(&self) -> bool {
|
||||
match *self.internal {
|
||||
|
@ -225,19 +185,6 @@ impl<A: AsRawFd + 'static> DrmDevice<A> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Assigns a [`DeviceHandler`] called during event processing.
|
||||
///
|
||||
/// See [`device_bind`] and [`DeviceHandler`]
|
||||
pub fn set_handler(&mut self, handler: impl DeviceHandler + 'static) {
|
||||
let handler = Some(Box::new(handler) as Box<dyn DeviceHandler + 'static>);
|
||||
*self.handler.borrow_mut() = handler;
|
||||
}
|
||||
|
||||
/// Clear a set [`DeviceHandler`](trait.DeviceHandler.html), if any
|
||||
pub fn clear_handler(&mut self) {
|
||||
self.handler.borrow_mut().take();
|
||||
}
|
||||
|
||||
/// Returns a list of crtcs for this device
|
||||
pub fn crtcs(&self) -> &[crtc::Handle] {
|
||||
self.resources.crtcs()
|
||||
|
@ -334,16 +281,6 @@ impl<A: AsRawFd + 'static> DrmDevice<A> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Trait to receive events of a bound [`DrmDevice`]
|
||||
///
|
||||
/// See [`device_bind`]
|
||||
pub trait DeviceHandler {
|
||||
/// A vblank blank event on the provided crtc has happend
|
||||
fn vblank(&mut self, crtc: crtc::Handle);
|
||||
/// An error happend while processing events
|
||||
fn error(&mut self, error: Error);
|
||||
}
|
||||
|
||||
/// Trait representing open devices that *may* return a `Path`
|
||||
pub trait DevPath {
|
||||
/// Returns the path of the open device if possible
|
||||
|
@ -358,25 +295,64 @@ impl<A: AsRawFd> DevPath for A {
|
|||
}
|
||||
}
|
||||
|
||||
/// calloop source associated with a Device
|
||||
pub type DrmSource<A> = Generic<DrmDevice<A>>;
|
||||
/// Events that can be generated by a DrmDevice
|
||||
pub enum DrmEvent {
|
||||
/// A vblank blank event on the provided crtc has happend
|
||||
VBlank(crtc::Handle),
|
||||
/// An error happend while processing events
|
||||
Error(Error),
|
||||
}
|
||||
|
||||
/// Bind a `Device` to an [`EventLoop`](calloop::EventLoop),
|
||||
///
|
||||
/// This will cause it to recieve events and feed them into a previously
|
||||
/// set [`DeviceHandler`](DeviceHandler).
|
||||
pub fn device_bind<A, Data>(
|
||||
handle: &LoopHandle<Data>,
|
||||
device: DrmDevice<A>,
|
||||
) -> ::std::result::Result<Source<DrmSource<A>>, InsertError<DrmSource<A>>>
|
||||
impl<A> EventSource for DrmDevice<A>
|
||||
where
|
||||
A: AsRawFd + 'static,
|
||||
Data: 'static,
|
||||
{
|
||||
let source = Generic::new(device, calloop::Interest::Readable, calloop::Mode::Level);
|
||||
type Event = DrmEvent;
|
||||
type Metadata = ();
|
||||
type Ret = ();
|
||||
|
||||
handle.insert_source(source, |_, source, _| {
|
||||
source.process_events();
|
||||
fn process_events<F>(&mut self, _: Readiness, _: Token, mut callback: F) -> std::io::Result<()>
|
||||
where
|
||||
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
|
||||
{
|
||||
match self.receive_events() {
|
||||
Ok(events) => {
|
||||
for event in events {
|
||||
if let Event::PageFlip(event) = event {
|
||||
trace!(self.logger, "Got a page-flip event for crtc ({:?})", event.crtc);
|
||||
callback(DrmEvent::VBlank(event.crtc), &mut ());
|
||||
} else {
|
||||
trace!(
|
||||
self.logger,
|
||||
"Got a non-page-flip event of device '{:?}'.",
|
||||
self.dev_path()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(source) => {
|
||||
callback(
|
||||
DrmEvent::Error(Error::Access {
|
||||
errmsg: "Error processing drm events",
|
||||
dev: self.dev_path(),
|
||||
source,
|
||||
}),
|
||||
&mut (),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
|
||||
poll.register(self.as_raw_fd(), Interest::READ, calloop::Mode::Level, token)
|
||||
}
|
||||
|
||||
fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
|
||||
poll.reregister(self.as_raw_fd(), Interest::READ, calloop::Mode::Level, token)
|
||||
}
|
||||
|
||||
fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> {
|
||||
poll.unregister(self.as_raw_fd())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ mod render;
|
|||
pub(self) mod session;
|
||||
pub(self) mod surface;
|
||||
|
||||
pub use device::{device_bind, DevPath, DeviceHandler, DrmDevice, DrmSource};
|
||||
pub use device::{DevPath, DrmDevice, DrmEvent};
|
||||
pub use error::Error as DrmError;
|
||||
#[cfg(feature = "backend_gbm")]
|
||||
pub use render::{DrmRenderSurface, Error as DrmRenderError};
|
||||
|
|
|
@ -469,11 +469,11 @@ impl EventSource for LibinputInputBackend {
|
|||
}
|
||||
|
||||
fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
|
||||
poll.register(self.as_raw_fd(), Interest::Readable, Mode::Level, token)
|
||||
poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, token)
|
||||
}
|
||||
|
||||
fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
|
||||
poll.reregister(self.as_raw_fd(), Interest::Readable, Mode::Level, token)
|
||||
poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, token)
|
||||
}
|
||||
|
||||
fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> {
|
||||
|
|
|
@ -76,9 +76,9 @@ impl EventSource for DBusConnection {
|
|||
fn reregister(&mut self, poll: &mut Poll, token: Token) -> io::Result<()> {
|
||||
let new_watch = self.cx.channel().watch();
|
||||
let new_interest = match (new_watch.read, new_watch.write) {
|
||||
(true, true) => Some(Interest::Both),
|
||||
(true, false) => Some(Interest::Readable),
|
||||
(false, true) => Some(Interest::Writable),
|
||||
(true, true) => Some(Interest::BOTH),
|
||||
(true, false) => Some(Interest::READ),
|
||||
(false, true) => Some(Interest::WRITE),
|
||||
(false, false) => None,
|
||||
};
|
||||
if new_watch.fd != self.current_watch.fd {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
//! // process the initial list of devices
|
||||
//! }
|
||||
//!
|
||||
//! # let event_loop = smithay::reexports::calloop::EventLoop::<()>::new().unwrap();
|
||||
//! # let event_loop = smithay::reexports::calloop::EventLoop::<()>::try_new().unwrap();
|
||||
//! # let loop_handle = event_loop.handle();
|
||||
//! // setup the event source for long-term monitoring
|
||||
//! loop_handle.insert_source(udev, |event, _, _dispatch_data| match event {
|
||||
|
@ -182,11 +182,11 @@ impl EventSource for UdevBackend {
|
|||
}
|
||||
|
||||
fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
|
||||
poll.register(self.as_raw_fd(), Interest::Readable, Mode::Level, token)
|
||||
poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, token)
|
||||
}
|
||||
|
||||
fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
|
||||
poll.reregister(self.as_raw_fd(), Interest::Readable, Mode::Level, token)
|
||||
poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, token)
|
||||
}
|
||||
|
||||
fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> {
|
||||
|
|
|
@ -55,7 +55,7 @@ use std::{
|
|||
|
||||
use calloop::{
|
||||
generic::{Fd, Generic},
|
||||
Interest, LoopHandle, Mode, Source,
|
||||
Interest, LoopHandle, Mode, RegistrationToken,
|
||||
};
|
||||
|
||||
use nix::Error as NixError;
|
||||
|
@ -91,7 +91,7 @@ impl<WM: XWindowManager + 'static> XWayland<WM> {
|
|||
/// Start the XWayland server
|
||||
pub fn init<L, T: Any, Data: 'static>(
|
||||
wm: WM,
|
||||
handle: LoopHandle<Data>,
|
||||
handle: LoopHandle<'static, Data>,
|
||||
display: Rc<RefCell<Display>>,
|
||||
data: &mut T,
|
||||
logger: L,
|
||||
|
@ -109,7 +109,7 @@ impl<WM: XWindowManager + 'static> XWayland<WM> {
|
|||
source_maker: Box::new(move |inner, fd| {
|
||||
handle
|
||||
.insert_source(
|
||||
Generic::new(Fd(fd), Interest::Readable, Mode::Level),
|
||||
Generic::new(Fd(fd), Interest::READ, Mode::Level),
|
||||
move |evt, _, _| {
|
||||
debug_assert!(evt.readable);
|
||||
xwayland_ready(&inner);
|
||||
|
@ -136,13 +136,13 @@ impl<WM: XWindowManager> Drop for XWayland<WM> {
|
|||
struct XWaylandInstance {
|
||||
display_lock: X11Lock,
|
||||
wayland_client: Client,
|
||||
startup_handler: Option<Source<Generic<Fd>>>,
|
||||
startup_handler: Option<RegistrationToken>,
|
||||
wm_fd: Option<UnixStream>,
|
||||
started_at: ::std::time::Instant,
|
||||
child_stdout: Option<ChildStdout>,
|
||||
}
|
||||
|
||||
type SourceMaker<WM> = dyn FnMut(Rc<RefCell<Inner<WM>>>, RawFd) -> Result<Source<Generic<Fd>>, ()>;
|
||||
type SourceMaker<WM> = dyn FnMut(Rc<RefCell<Inner<WM>>>, RawFd) -> Result<RegistrationToken, ()>;
|
||||
|
||||
// Inner implementation of the XWayland manager
|
||||
struct Inner<WM: XWindowManager> {
|
||||
|
@ -150,7 +150,7 @@ struct Inner<WM: XWindowManager> {
|
|||
source_maker: Box<SourceMaker<WM>>,
|
||||
wayland_display: Rc<RefCell<Display>>,
|
||||
instance: Option<XWaylandInstance>,
|
||||
kill_source: Box<dyn Fn(Source<Generic<Fd>>)>,
|
||||
kill_source: Box<dyn Fn(RegistrationToken)>,
|
||||
log: ::slog::Logger,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue