loop: drive render loop by client commits + input

This commit is contained in:
Victoria Brekenfeld 2022-01-28 18:54:25 +01:00
parent ca32139131
commit 56e72b4fef
5 changed files with 50 additions and 16 deletions

View file

@ -9,3 +9,9 @@ pub struct KmsState {}
pub fn init_backend(event_loop: &mut EventLoop<State>, state: &mut State) -> Result<()> { pub fn init_backend(event_loop: &mut EventLoop<State>, state: &mut State) -> Result<()> {
unimplemented!() unimplemented!()
} }
impl KmsState {
pub fn schedule_render(&mut self, output: &Output) {
unimplemented!();
}
}

View file

@ -104,6 +104,7 @@ impl X11State {
{ {
slog_scope::error!("Error rendering: {}", err); slog_scope::error!("Error rendering: {}", err);
} }
surface.pending = false;
} }
}) })
.with_context(|| "Failed to add output to event loop")?; .with_context(|| "Failed to add output to event loop")?;
@ -113,6 +114,7 @@ impl X11State {
surface, surface,
output: output.clone(), output: output.clone(),
render: ping.clone(), render: ping.clone(),
pending: true,
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
fps: Fps::default(), fps: Fps::default(),
_global, _global,
@ -122,6 +124,15 @@ impl X11State {
ping.ping(); ping.ping();
Ok(output) Ok(output)
} }
pub fn schedule_render(&mut self, output: &Output) {
if let Some(surface) = self.surfaces.iter_mut().find(|s| s.output == *output) {
if !surface.pending {
surface.pending = true;
surface.render.ping();
}
}
}
} }
pub struct Surface { pub struct Surface {
@ -129,6 +140,7 @@ pub struct Surface {
surface: X11Surface, surface: X11Surface,
output: Output, output: Output,
render: ping::Ping, render: ping::Ping,
pending: bool,
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
fps: Fps, fps: Fps,
_global: GlobalDrop<WlOutput>, _global: GlobalDrop<WlOutput>,
@ -274,19 +286,8 @@ pub fn init_backend(event_loop: &mut EventLoop<State>, state: &mut State) -> Res
} }
} }
X11Event::PresentCompleted { window_id } | X11Event::Refresh { window_id } => {
if let Some(surface) = state
.backend
.x11()
.surfaces
.iter_mut()
.find(|s| s.window.id() == window_id)
{
surface.render.ping();
}
}
X11Event::Input(event) => state.process_x11_event(event), X11Event::Input(event) => state.process_x11_event(event),
_ => {},
}) })
.map_err(|_| anyhow::anyhow!("Failed to insert X11 Backend into event loop"))?; .map_err(|_| anyhow::anyhow!("Failed to insert X11 Backend into event loop"))?;
@ -345,5 +346,9 @@ impl State {
}; };
self.common.process_input_event(event); self.common.process_input_event(event);
// TODO actually figure out the output
for output in self.common.spaces.outputs() {
self.backend.schedule_render(output);
}
} }
} }

View file

@ -27,7 +27,7 @@ fn main() -> Result<()> {
// init wayland // init wayland
let display = init_wayland_display(&mut event_loop)?; let display = init_wayland_display(&mut event_loop)?;
// init state // init state
let mut state = state::State::new(display); let mut state = state::State::new(display, event_loop.handle());
// init backend // init backend
backend::init_backend_auto(&mut event_loop, &mut state)?; backend::init_backend_auto(&mut event_loop, &mut state)?;

View file

@ -334,6 +334,13 @@ fn check_grab_preconditions(
} }
fn commit(surface: &WlSurface, state: &mut State) { fn commit(surface: &WlSurface, state: &mut State) {
// TODO figure out which output the surface is on.
for output in state.common.spaces.outputs() {//.cloned().collect::<Vec<_>>().into_iter() {
state.backend.schedule_render(output);
// let space = state.common.spaces.active_space(output);
// get output for surface
}
let state = &mut state.common; let state = &mut state.common;
if let Some(toplevel) = state.pending_toplevels.iter().find(|toplevel| { if let Some(toplevel) = state.pending_toplevels.iter().find(|toplevel| {

View file

@ -5,10 +5,13 @@ use crate::{
shell::{init_shell, workspaces::Workspaces, ShellStates}, shell::{init_shell, workspaces::Workspaces, ShellStates},
}; };
use smithay::{ use smithay::{
reexports::wayland_server::Display, reexports::{
calloop::LoopHandle,
wayland_server::Display,
},
wayland::{ wayland::{
data_device::{default_action_chooser, init_data_device}, data_device::{default_action_chooser, init_data_device},
output::xdg::init_xdg_output_manager, output::{xdg::init_xdg_output_manager, Output},
seat::Seat, seat::Seat,
shell::xdg::ToplevelSurface, shell::xdg::ToplevelSurface,
shm::init_shm_global, shm::init_shm_global,
@ -26,6 +29,7 @@ pub struct State {
pub struct Common { pub struct Common {
pub display: Rc<RefCell<Display>>, pub display: Rc<RefCell<Display>>,
pub event_loop_handle: LoopHandle<'static, State>,
pub spaces: Workspaces, pub spaces: Workspaces,
pub shell: ShellStates, pub shell: ShellStates,
@ -87,10 +91,21 @@ impl BackendData {
_ => unreachable!("Called winit in non winit backend"), _ => unreachable!("Called winit in non winit backend"),
} }
} }
pub fn schedule_render(&mut self, output: &Output) {
match self {
BackendData::Winit(_) => {}, // We cannot do this on the winit backend.
// Winit has a very strict render-loop and skipping frames breaks atleast the wayland winit-backend.
// Swapping with damage (which should be empty on these frames) is likely good enough anyway.
BackendData::X11(ref mut state) => state.schedule_render(output),
BackendData::Kms(ref mut state) => state.schedule_render(output),
_ => unreachable!("No backend was initialized"),
}
}
} }
impl State { impl State {
pub fn new(mut display: Display) -> State { pub fn new(mut display: Display, handle: LoopHandle<'static, State>) -> State {
init_shm_global(&mut display, vec![], None); init_shm_global(&mut display, vec![], None);
init_xdg_output_manager(&mut display, None); init_xdg_output_manager(&mut display, None);
let shell_handles = init_shell(&mut display); let shell_handles = init_shell(&mut display);
@ -105,6 +120,7 @@ impl State {
State { State {
common: Common { common: Common {
display: Rc::new(RefCell::new(display)), display: Rc::new(RefCell::new(display)),
event_loop_handle: handle,
spaces: Workspaces::new(), spaces: Workspaces::new(),
shell: shell_handles, shell: shell_handles,