kms: Corrently resume when switching back VTs
This commit is contained in:
parent
e5cd473a3a
commit
81374ed282
2 changed files with 86 additions and 35 deletions
|
|
@ -35,7 +35,7 @@ use smithay::{
|
||||||
nix::{fcntl::OFlag, sys::stat::dev_t},
|
nix::{fcntl::OFlag, sys::stat::dev_t},
|
||||||
wayland_server::protocol::wl_output,
|
wayland_server::protocol::wl_output,
|
||||||
},
|
},
|
||||||
utils::signaling::{Linkable, Signaler},
|
utils::signaling::{Linkable, Signaler, SignalToken},
|
||||||
wayland::output::{Mode as OutputMode, Output, PhysicalProperties},
|
wayland::output::{Mode as OutputMode, Output, PhysicalProperties},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -59,7 +59,8 @@ pub struct KmsState {
|
||||||
primary: DrmNode,
|
primary: DrmNode,
|
||||||
session: AutoSession,
|
session: AutoSession,
|
||||||
signaler: Signaler<Signal>,
|
signaler: Signaler<Signal>,
|
||||||
tokens: Vec<RegistrationToken>,
|
_restart_token: SignalToken,
|
||||||
|
_tokens: Vec<RegistrationToken>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
|
|
@ -87,7 +88,7 @@ pub struct Surface {
|
||||||
fps: Fps,
|
fps: Fps,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_backend(event_loop: &mut EventLoop<State>, state: &mut State) -> Result<()> {
|
pub fn init_backend(event_loop: &mut EventLoop<'static, State>, state: &mut State) -> Result<()> {
|
||||||
let (session, notifier) = AutoSession::new(None).context("Failed to acquire session")?;
|
let (session, notifier) = AutoSession::new(None).context("Failed to acquire session")?;
|
||||||
let signaler = notifier.signaler();
|
let signaler = notifier.signaler();
|
||||||
|
|
||||||
|
|
@ -147,51 +148,94 @@ pub fn init_backend(event_loop: &mut EventLoop<State>, state: &mut State) -> Res
|
||||||
};
|
};
|
||||||
slog_scope::info!("Using {} as primary gpu for rendering", primary);
|
slog_scope::info!("Using {} as primary gpu for rendering", primary);
|
||||||
|
|
||||||
|
let udev_dispatcher = Dispatcher::new(udev_backend, move |event, _, state: &mut State| {
|
||||||
|
match match event {
|
||||||
|
UdevEvent::Added { device_id, path } => state
|
||||||
|
.device_added(device_id, path)
|
||||||
|
.with_context(|| format!("Failed to add drm device: {}", device_id)),
|
||||||
|
UdevEvent::Changed { device_id } => state
|
||||||
|
.device_changed(device_id)
|
||||||
|
.with_context(|| format!("Failed to update drm device: {}", device_id)),
|
||||||
|
UdevEvent::Removed { device_id } => state
|
||||||
|
.device_removed(device_id)
|
||||||
|
.with_context(|| format!("Failed to remove drm device: {}", device_id)),
|
||||||
|
} {
|
||||||
|
Ok(()) => {
|
||||||
|
slog_scope::debug!("Successfully handled udev event")
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
slog_scope::error!("Error while handling udev event: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let udev_event_source = event_loop
|
||||||
|
.handle()
|
||||||
|
.register_dispatcher(udev_dispatcher.clone())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let handle = event_loop.handle();
|
||||||
|
let dispatcher = udev_dispatcher.clone();
|
||||||
|
let _restart_token = signaler.register(move |signal| {
|
||||||
|
if let Signal::ActivateSession = signal {
|
||||||
|
let dispatcher = dispatcher.clone();
|
||||||
|
handle.insert_idle(move |state| {
|
||||||
|
for (dev, path) in dispatcher.as_source_ref().device_list() {
|
||||||
|
let drm_node = match DrmNode::from_dev_id(dev) {
|
||||||
|
Ok(node) => node,
|
||||||
|
Err(err) => {
|
||||||
|
slog_scope::error!("Failed to read drm device {}: {}", path.display(), err);
|
||||||
|
continue
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if state.backend.kms().devices.contains_key(&drm_node) {
|
||||||
|
if let Err(err) = state.device_changed(dev) {
|
||||||
|
slog_scope::error!("Failed to update drm device {}: {}", path.display(), err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Err(err) = state.device_added(dev, path.into()) {
|
||||||
|
slog_scope::error!("Failed to add drm device {}: {}", path.display(), err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.common
|
||||||
|
.output_conf
|
||||||
|
.update(&mut *state.common.display.borrow_mut());
|
||||||
|
|
||||||
|
state.common.config.read_outputs(state.common.output_conf.outputs(), &mut state.backend, &mut state.common.shell);
|
||||||
|
state.common.shell.refresh_outputs();
|
||||||
|
state.common.config.write_outputs(state.common.output_conf.outputs());
|
||||||
|
|
||||||
|
for output in state.common.shell.outputs() {
|
||||||
|
state.backend.kms().schedule_render(output);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
state.backend = BackendData::Kms(KmsState {
|
state.backend = BackendData::Kms(KmsState {
|
||||||
api,
|
api,
|
||||||
tokens: vec![libinput_event_source, session_event_source],
|
_tokens: vec![libinput_event_source, session_event_source, udev_event_source],
|
||||||
primary,
|
primary,
|
||||||
session,
|
session,
|
||||||
signaler,
|
signaler,
|
||||||
|
_restart_token,
|
||||||
devices: HashMap::new(),
|
devices: HashMap::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
for (dev, path) in udev_backend.device_list() {
|
for (dev, path) in udev_dispatcher.as_source_ref().device_list() {
|
||||||
state
|
state
|
||||||
.device_added(dev, path.into())
|
.device_added(dev, path.into())
|
||||||
.with_context(|| format!("Failed to add drm device: {}", path.display()))?;
|
.with_context(|| format!("Failed to add drm device: {}", path.display()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let udev_event_source = event_loop
|
|
||||||
.handle()
|
|
||||||
.insert_source(udev_backend, move |event, _, state| {
|
|
||||||
match match event {
|
|
||||||
UdevEvent::Added { device_id, path } => state
|
|
||||||
.device_added(device_id, path)
|
|
||||||
.with_context(|| format!("Failed to add drm device: {}", device_id)),
|
|
||||||
UdevEvent::Changed { device_id } => state
|
|
||||||
.device_changed(device_id)
|
|
||||||
.with_context(|| format!("Failed to update drm device: {}", device_id)),
|
|
||||||
UdevEvent::Removed { device_id } => state
|
|
||||||
.device_removed(device_id)
|
|
||||||
.with_context(|| format!("Failed to remove drm device: {}", device_id)),
|
|
||||||
} {
|
|
||||||
Ok(()) => {
|
|
||||||
slog_scope::debug!("Successfully handled udev event")
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
slog_scope::error!("Error while handling udev event: {}", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
state.backend.kms().tokens.push(udev_event_source);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
fn device_added(&mut self, dev: dev_t, path: PathBuf) -> Result<()> {
|
fn device_added(&mut self, dev: dev_t, path: PathBuf) -> Result<()> {
|
||||||
|
if !self.backend.kms().session.is_active() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let fd = SessionFd::new(
|
let fd = SessionFd::new(
|
||||||
self.backend
|
self.backend
|
||||||
.kms()
|
.kms()
|
||||||
|
|
@ -335,6 +379,10 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_changed(&mut self, dev: dev_t) -> Result<()> {
|
fn device_changed(&mut self, dev: dev_t) -> Result<()> {
|
||||||
|
if !self.backend.kms().session.is_active() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let drm_node = DrmNode::from_dev_id(dev)?;
|
let drm_node = DrmNode::from_dev_id(dev)?;
|
||||||
let mut outputs_removed = Vec::new();
|
let mut outputs_removed = Vec::new();
|
||||||
let mut outputs_added = Vec::new();
|
let mut outputs_added = Vec::new();
|
||||||
|
|
@ -404,9 +452,12 @@ impl State {
|
||||||
self.common
|
self.common
|
||||||
.output_conf
|
.output_conf
|
||||||
.update(&mut *self.common.display.borrow_mut());
|
.update(&mut *self.common.display.borrow_mut());
|
||||||
self.common.config.read_outputs(self.common.output_conf.outputs(), &mut self.backend, &mut self.common.shell);
|
|
||||||
self.common.shell.refresh_outputs();
|
if self.backend.kms().session.is_active() {
|
||||||
self.common.config.write_outputs(self.common.output_conf.outputs());
|
self.common.config.read_outputs(self.common.output_conf.outputs(), &mut self.backend, &mut self.common.shell);
|
||||||
|
self.common.shell.refresh_outputs();
|
||||||
|
self.common.config.write_outputs(self.common.output_conf.outputs());
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ pub mod x11;
|
||||||
// TODO
|
// TODO
|
||||||
// pub mod wayland; // tbd in smithay
|
// pub mod wayland; // tbd in smithay
|
||||||
|
|
||||||
pub fn init_backend_auto(event_loop: &mut EventLoop<State>, state: &mut State) -> Result<()> {
|
pub fn init_backend_auto(event_loop: &mut EventLoop<'static, State>, state: &mut State) -> Result<()> {
|
||||||
match std::env::var("COSMIC_BACKEND") {
|
match std::env::var("COSMIC_BACKEND") {
|
||||||
Ok(x) if x == "x11" => x11::init_backend(event_loop, state),
|
Ok(x) if x == "x11" => x11::init_backend(event_loop, state),
|
||||||
Ok(x) if x == "winit" => winit::init_backend(event_loop, state),
|
Ok(x) if x == "winit" => winit::init_backend(event_loop, state),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue