Skip to content

Commit

Permalink
stop waking up every 1ms for polling and do regular frame scheduling
Browse files Browse the repository at this point in the history
Actually schedule frame callbacks the right way by scheduling the callback to be
completed a frame interval after the current commit, less a couple ms for
processing time.

Also stop processing buffers for sync subsurfaces twice.
  • Loading branch information
nicolasavru committed Mar 6, 2024
1 parent cb6d645 commit c05eb69
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 239 deletions.
55 changes: 18 additions & 37 deletions src/bin/wprsc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
// limitations under the License.

use std::fs;
use std::io::ErrorKind;
use std::path::PathBuf;
use std::time::Duration;

use bpaf::Parser;
use optional_struct::optional_struct;
Expand All @@ -24,7 +22,7 @@ use serde_derive::Deserialize;
use serde_derive::Serialize;
use smithay::reexports::calloop::channel::Event;
use smithay::reexports::calloop::EventLoop;
use smithay_client_toolkit::reexports::client::backend::WaylandError;
use smithay_client_toolkit::reexports::calloop_wayland_source::WaylandSource;
use smithay_client_toolkit::reexports::client::globals::registry_queue_init;
use smithay_client_toolkit::reexports::client::ConnectError;
use smithay_client_toolkit::reexports::client::Connection;
Expand All @@ -33,7 +31,6 @@ use wprs::args;
use wprs::args::Config;
use wprs::args::OptionalConfig;
use wprs::args::SerializableLevel;
use wprs::client::CalloopData;
use wprs::client::ClientOptions;
use wprs::client::WprsClientState;
use wprs::control_server;
Expand Down Expand Up @@ -136,7 +133,7 @@ fn main() -> Result<()> {
_ => anyhow!(e),
})?;

let (globals, mut event_queue) = registry_queue_init(&conn)?;
let (globals, event_queue) = registry_queue_init(&conn)?;

fs::create_dir_all(config.socket.parent().location(loc!())?).location(loc!())?;
let mut serializer = Serializer::new_client(&config.socket).with_context(loc!(), || {
Expand All @@ -154,17 +151,22 @@ fn main() -> Result<()> {
let options = ClientOptions {
title_prefix: config.title_prefix,
};
let mut loop_data = CalloopData {
state: WprsClientState::new(event_queue.handle(), globals, conn, serializer, options)
.location(loc!())?,
};
let mut state = WprsClientState::new(
event_queue.handle(),
globals,
conn.clone(),
serializer,
options,
)
.location(loc!())?;

let mut event_loop = EventLoop::try_new()?;

event_loop.handle().insert_source(
reader,
|event, _metadata, loop_data: &mut CalloopData| {
|event, _metadata, state: &mut WprsClientState| {
match event {
Event::Msg(msg) => loop_data.state.handle_request(msg),
Event::Msg(msg) => state.handle_request(msg),
Event::Closed => {
unreachable!("serialization::client_loop terminates the process when the server disconnects.");
},
Expand All @@ -173,7 +175,7 @@ fn main() -> Result<()> {
).unwrap();

{
let capabilities = loop_data.state.capabilities.clone();
let capabilities = state.capabilities.clone();
control_server::start(config.control_socket, move |input: &str| {
Ok(match input {
// TODO: make the input use json when we have more commands
Expand All @@ -187,32 +189,11 @@ fn main() -> Result<()> {
.location(loc!())?;
}

event_loop
.run(Duration::from_millis(1), &mut loop_data, move |loop_data| {
// WouldBlock means that the compositor can't keep up with our messages.
// Seems rare, so we will retry again on next loop.

match event_queue.flush() {
Ok(_) => {},
Err(WaylandError::Io(err)) if err.kind() == ErrorKind::WouldBlock => {
warn!("{err:?}");
},
_ => {
panic!("Error writing to wayland connection.");
},
};

match event_queue.prepare_read().unwrap().read() {
Ok(_) => {
event_queue.dispatch_pending(&mut loop_data.state).unwrap();
},
Err(WaylandError::Io(err)) if err.kind() == ErrorKind::WouldBlock => {},
_ => {
panic!("Error reading from wayland connection.");
},
};
})
WaylandSource::new(conn, event_queue)
.insert(event_loop.handle())
.location(loc!())?;

event_loop.run(None, &mut state, |_| {}).location(loc!())?;

Ok(())
}
82 changes: 28 additions & 54 deletions src/bin/wprsd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ use serde_derive::Deserialize;
use serde_derive::Serialize;
use smithay::reexports::calloop::channel::Event;
use smithay::reexports::calloop::generic::Generic;
use smithay::reexports::calloop::timer::TimeoutAction;
use smithay::reexports::calloop::timer::Timer;
use smithay::reexports::calloop::EventLoop;
use smithay::reexports::calloop::Interest;
use smithay::reexports::calloop::Mode;
Expand Down Expand Up @@ -173,26 +171,20 @@ impl OptionalConfig<WprsdConfig> for OptionalWprsdConfig {
}
}

pub struct CalloopData {
pub state: WprsServerState,
pub display: Display<WprsServerState>,
}

fn init_wayland_listener(
wayland_display: &str,
loop_data: &mut CalloopData,
event_loop: &EventLoop<CalloopData>,
mut display: Display<WprsServerState>,
state: &mut WprsServerState,
event_loop: &EventLoop<WprsServerState>,
) -> Result<()> {
let listening_socket = ListeningSocketSource::with_name(wayland_display).location(loc!())?;
let writer = loop_data.state.serializer.writer().into_inner();
let writer = state.serializer.writer().into_inner();
let mut dh = display.handle();

event_loop
.handle()
.insert_source(listening_socket, move |stream, _, loop_data| {
loop_data
.display
.handle()
.insert_client(stream, Arc::new(ClientState::new(writer.clone())))
.insert_source(listening_socket, move |stream, _, _| {
dh.insert_client(stream, Arc::new(ClientState::new(writer.clone())))
.unwrap();
})
.location(loc!())?;
Expand All @@ -201,20 +193,12 @@ fn init_wayland_listener(
.handle()
.insert_source(
Generic::new(
loop_data
.display
.backend()
.poll_fd()
.try_clone_to_owned()
.unwrap(),
display.backend().poll_fd().try_clone_to_owned().unwrap(),
Interest::READ,
Mode::Level,
),
|_, _, loop_data| {
loop_data
.display
.dispatch_clients(&mut loop_data.state)
.unwrap();
move |_, _, state| {
display.dispatch_clients(state).unwrap();
Ok(PostAction::Continue)
},
)
Expand Down Expand Up @@ -263,17 +247,19 @@ pub fn main() -> Result<()> {
let mut event_loop = EventLoop::try_new().location(loc!())?;
let display: Display<WprsServerState> = Display::new().location(loc!())?;

let mut loop_data = CalloopData {
state: WprsServerState::new(
display.handle(),
serializer,
config.enable_xwayland,
config.kde_server_side_decorations,
),
display,
};
let frame_interval = Duration::from_secs_f64(1.0 / (config.framerate as f64));

let mut state = WprsServerState::new(
display.handle(),
event_loop.handle(),
serializer,
config.enable_xwayland,
frame_interval,
config.kde_server_side_decorations,
);

init_wayland_listener(&config.wayland_display, &mut loop_data, &event_loop).location(loc!())?;
init_wayland_listener(&config.wayland_display, display, &mut state, &event_loop)
.location(loc!())?;

if config.enable_xwayland {
start_xwayland_xdg_shell(
Expand All @@ -285,38 +271,26 @@ pub fn main() -> Result<()> {
}

// TODO: do this in WprsServerState::new;
let _keyboard = loop_data
.state
let _keyboard = state
.seat
.add_keyboard(Default::default(), 200, 200)
.location(loc!())?;
let _pointer = loop_data.state.seat.add_pointer();
let _pointer = state.seat.add_pointer();

event_loop
.handle()
.insert_source(reader, |event, _metadata, loop_data| {
.insert_source(reader, |event, _metadata, state| {
match event {
Event::Msg(msg) => loop_data.state.handle_event(msg),
Event::Msg(msg) => state.handle_event(msg),
Event::Closed => {
unreachable!("reader is an in-memory channel whose write end has the same lifetime as serializer: the lifetime of the program.")
},
}
}).unwrap();

let frame_interval = Duration::from_secs_f64(1.0 / (config.framerate as f64));
event_loop
.handle()
.insert_source(Timer::immediate(), move |_, _, loop_data| {
if loop_data.state.serializer.other_end_connected() {
loop_data.state.send_callbacks(frame_interval);
}
TimeoutAction::ToDuration(Duration::from_millis(1))
})
.unwrap();

event_loop
.run(Duration::from_millis(1), &mut loop_data, move |loop_data| {
loop_data.display.flush_clients().unwrap();
.run(None, &mut state, move |state| {
state.dh.flush_clients().unwrap();
})
.location(loc!())?;

Expand Down
84 changes: 26 additions & 58 deletions src/bin/xwayland-xdg-shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
// limitations under the License.

use std::ffi::OsString;
use std::io::ErrorKind;
use std::path::PathBuf;
use std::time::Duration;

use bpaf::Parser;
use optional_struct::optional_struct;
Expand All @@ -29,7 +27,7 @@ use smithay::reexports::calloop::Mode;
use smithay::reexports::calloop::PostAction;
use smithay::reexports::wayland_server::Display;
use smithay::wayland::socket::ListeningSocketSource;
use smithay_client_toolkit::reexports::client::backend::WaylandError;
use smithay_client_toolkit::reexports::calloop_wayland_source::WaylandSource;
use smithay_client_toolkit::reexports::client::globals::registry_queue_init;
use smithay_client_toolkit::reexports::client::Connection;
use tracing::Level;
Expand All @@ -40,7 +38,6 @@ use wprs::args::SerializableLevel;
use wprs::prelude::*;
use wprs::utils;
use wprs::xwayland_xdg_shell::compositor::DecorationBehavior;
use wprs::xwayland_xdg_shell::CalloopData;
use wprs::xwayland_xdg_shell::WprsState;

#[optional_struct]
Expand Down Expand Up @@ -141,8 +138,8 @@ impl OptionalConfig<XwaylandXdgShellConfig> for OptionalXwaylandXdgShellConfig {

fn init_wayland_listener(
wayland_display: &str,
display: &mut Display<WprsState>,
event_loop: &EventLoop<CalloopData>,
mut display: Display<WprsState>,
event_loop: &EventLoop<WprsState>,
) -> Result<OsString> {
let listening_socket = ListeningSocketSource::with_name(wayland_display).location(loc!())?;
let socket_name = listening_socket.socket_name().to_os_string();
Expand All @@ -155,11 +152,8 @@ fn init_wayland_listener(
Interest::READ,
Mode::Level,
),
|_, _, loop_data| {
loop_data
.display
.dispatch_clients(&mut loop_data.state)
.unwrap();
move |_, _, state| {
display.dispatch_clients(state).unwrap();
Ok(PostAction::Continue)
},
)
Expand All @@ -184,38 +178,32 @@ pub fn main() -> Result<()> {
let display: Display<WprsState> = Display::new().location(loc!())?;

let conn = Connection::connect_to_env().location(loc!())?;
let (globals, mut event_queue) = registry_queue_init(&conn).location(loc!())?;
let (globals, event_queue) = registry_queue_init(&conn).location(loc!())?;

let mut state = WprsState::new(
display.handle(),
&globals,
event_queue.handle(),
conn.clone(),
event_loop.handle(),
config.decoration_behavior,
)
.location(loc!())?;

let mut loop_data = CalloopData {
state: WprsState::new(
display.handle(),
&globals,
event_queue.handle(),
conn,
event_loop.handle(),
config.decoration_behavior,
)
.location(loc!())?,
display,
globals,
};
init_wayland_listener(&config.wayland_display, display, &event_loop).location(loc!())?;

init_wayland_listener(&config.wayland_display, &mut loop_data.display, &event_loop)
.location(loc!())?;

let seat = &mut loop_data.state.compositor_state.seat;
let seat = &mut state.compositor_state.seat;
// TODO: do this in WprsState::new;
let _keyboard = seat
.add_keyboard(Default::default(), 200, 200)
.location(loc!())?;
let _pointer = seat.add_pointer();

loop_data
.state
state
.compositor_state
.xwayland
.start(
loop_data.state.event_loop_handle.clone(),
state.event_loop_handle.clone(),
config.display,
vec![(
"WAYLAND_DEBUG",
Expand All @@ -230,33 +218,13 @@ pub fn main() -> Result<()> {
)
.context(loc!(), "Error starting Xwayland.")?;

event_loop
.run(Duration::from_millis(1), &mut loop_data, move |loop_data| {
// WouldBlock means that the compositor can't keep up with our messages.
// Seems rare, so we will retry again on next loop.

match event_queue.flush() {
Ok(_) => {},
Err(WaylandError::Io(err)) if err.kind() == ErrorKind::WouldBlock => {
warn!("{err:?}");
},
_ => {
panic!("Error writing to wayland connection.");
},
};

match event_queue.prepare_read().unwrap().read() {
Ok(_) => {
event_queue.dispatch_pending(&mut loop_data.state).unwrap();
},
Err(WaylandError::Io(err)) if err.kind() == ErrorKind::WouldBlock => {},
_ => {
panic!("Error reading from wayland connection.");
},
};
WaylandSource::new(conn, event_queue)
.insert(event_loop.handle())
.location(loc!())?;

// compositor stuff
loop_data.display.flush_clients().unwrap();
event_loop
.run(None, &mut state, move |state| {
state.dh.flush_clients().unwrap();
})
.context(loc!(), "Error starting event loop.")?;
Ok(())
Expand Down
Loading

0 comments on commit c05eb69

Please sign in to comment.