Wake the event loop when wallpaper decoding completes
This commit is contained in:
1 parent
6dd132a4a5
commit
b469929847
4 files changed
+49
-12
No files matched your search
@@ -90,12 +90,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
event_loop.handle().insert_source(
|
||||
Timer::from_duration(Duration::from_millis(150)),
|
||||
move |_, _, state: &mut Ferese| {
|
||||
// Decoders finish on a worker even when an idle DRM output has no
|
||||
// pending frame. Wake rendering once, never continuously for wallpaper.
|
||||
if state.wallpaper.poll() {
|
||||
state.backdrop_generation = state.backdrop_generation.wrapping_add(1);
|
||||
backends::direct::render_all(state);
|
||||
}
|
||||
if let Some(result) = monitor
|
||||
.as_mut()
|
||||
.and_then(|monitor| monitor.poll(std::time::Instant::now()))
|
||||
@@ -124,9 +118,15 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
},
|
||||
)?;
|
||||
let result = event_loop.run(None, &mut state, |state| {
|
||||
// The decoder wakes the loop after publishing its result, including
|
||||
// when no output has a pending frame.
|
||||
let wallpaper_changed = state.wallpaper.poll();
|
||||
if wallpaper_changed {
|
||||
state.backdrop_generation = state.backdrop_generation.wrapping_add(1);
|
||||
}
|
||||
// All input/Wayland callbacks have returned, releasing seat locks.
|
||||
// Coalesce cursor changes and redraw here, never inside cursor_image.
|
||||
if std::mem::take(&mut state.cursor_redraw_pending) {
|
||||
if std::mem::take(&mut state.cursor_redraw_pending) || wallpaper_changed {
|
||||
backends::direct::render_all(state);
|
||||
}
|
||||
// Registry/sync/configure replies must not depend on a submitted
|
||||
|
||||
@@ -602,7 +602,10 @@ impl Ferese {
|
||||
resize_transactions: HashMap::new(),
|
||||
resize_snapshots: HashMap::new(),
|
||||
nested_backend: None,
|
||||
wallpaper: crate::wallpaper::WallpaperState::new(config.wallpaper),
|
||||
wallpaper: crate::wallpaper::WallpaperState::with_wakeup(
|
||||
config.wallpaper,
|
||||
Some(event_loop.get_signal()),
|
||||
),
|
||||
maximized_windows: HashSet::new(),
|
||||
maximized_column_widths: HashMap::new(),
|
||||
window_stack: crate::stacking::WindowStack::default(),
|
||||
|
||||
@@ -67,15 +67,25 @@ pub(crate) struct WallpaperState {
|
||||
pixels: Option<image::RgbaImage>,
|
||||
textures: HashMap<ErasedContextId, WallpaperTexture>,
|
||||
upload_retries: HashMap<ErasedContextId, Instant>,
|
||||
wakeup: Option<smithay::reexports::calloop::LoopSignal>,
|
||||
}
|
||||
|
||||
impl WallpaperState {
|
||||
#[cfg(test)]
|
||||
pub fn new(config: WallpaperConfig) -> Self {
|
||||
Self::with_wakeup(config, None)
|
||||
}
|
||||
|
||||
pub fn with_wakeup(
|
||||
config: WallpaperConfig,
|
||||
wakeup: Option<smithay::reexports::calloop::LoopSignal>,
|
||||
) -> Self {
|
||||
let retained = config.clone();
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
let owned = config.path.as_ref().is_some_and(|path| path.is_file());
|
||||
if owned {
|
||||
let path = config.path.unwrap();
|
||||
let wakeup = wakeup.clone();
|
||||
std::thread::spawn(move || {
|
||||
let load = || -> Result<image::RgbaImage, String> {
|
||||
let (width, height) =
|
||||
@@ -88,6 +98,9 @@ impl WallpaperState {
|
||||
.map_err(|e| e.to_string())
|
||||
};
|
||||
let _ = sender.send(load());
|
||||
if let Some(wakeup) = wakeup {
|
||||
wakeup.wakeup();
|
||||
}
|
||||
});
|
||||
}
|
||||
Self {
|
||||
@@ -100,6 +113,7 @@ impl WallpaperState {
|
||||
pixels: None,
|
||||
textures: HashMap::new(),
|
||||
upload_retries: HashMap::new(),
|
||||
wakeup,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +140,7 @@ impl WallpaperState {
|
||||
tracing::warn!("new wallpaper is unavailable; retaining previous image");
|
||||
return;
|
||||
}
|
||||
let mut replacement = Self::new(config);
|
||||
let mut replacement = Self::with_wakeup(config, self.wakeup.clone());
|
||||
self.config = replacement.config;
|
||||
self.mode = replacement.mode;
|
||||
self.owned = replacement.owned;
|
||||
@@ -296,6 +310,29 @@ fn image_geometry(
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn decoder_wakes_an_idle_event_loop() {
|
||||
use smithay::reexports::calloop::{EventLoop, timer::Timer};
|
||||
let mut event_loop = EventLoop::<WallpaperState>::try_new().unwrap();
|
||||
event_loop
|
||||
.handle()
|
||||
.insert_source(Timer::from_duration(Duration::from_secs(5)), |_, _, _| {
|
||||
panic!("wallpaper decoder failed to wake the idle event loop");
|
||||
})
|
||||
.unwrap();
|
||||
let signal = event_loop.get_signal();
|
||||
let mut state =
|
||||
WallpaperState::with_wakeup(WallpaperConfig::default(), Some(signal.clone()));
|
||||
event_loop
|
||||
.run(None, &mut state, |state| {
|
||||
if state.poll() {
|
||||
assert!(state.pixels.is_some());
|
||||
signal.stop();
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failed_uploads_back_off_per_context_and_reset_for_new_pixels() {
|
||||
use smithay::backend::renderer::ContextId;
|
||||
|
||||
@@ -1068,9 +1068,6 @@ fn output_elements(
|
||||
);
|
||||
return elements;
|
||||
}
|
||||
if state.wallpaper.poll() {
|
||||
state.backdrop_generation = state.backdrop_generation.wrapping_add(1);
|
||||
}
|
||||
let Some(output_geometry) = state.space.output_geometry(output) else {
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user