Skip to content

Commit

Permalink
use just one request for animated images
Browse files Browse the repository at this point in the history
We had separated them a long time ago in order to send them in a
pipeline. However, that turned out to have the issue of the animation
not starting as soon as possible after the transition was finished, so
we began sending both one after the other in two messages.

That is rather wasteful, so this commit merges everything together in
one big request.
  • Loading branch information
LGFae committed May 3, 2024
1 parent e251de3 commit 07e8a73
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 306 deletions.
86 changes: 33 additions & 53 deletions daemon/src/animations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use log::error;
use std::{
sync::Arc,
thread::{self, Scope},
time::Duration,
};

use utils::{
Expand Down Expand Up @@ -38,7 +37,8 @@ impl Animator {
transition: &'b ipc::Transition,
img: &'b [u8],
path: &'b String,
mut wallpapers: Vec<Arc<Wallpaper>>,
dim: (u32, u32),
wallpapers: &'b mut Vec<Arc<Wallpaper>>,
) where
'a: 'b,
{
Expand All @@ -52,19 +52,15 @@ impl Animator {
for w in wallpapers.iter_mut() {
w.set_img_info(BgImg::Img(path.to_string()));
}
let dimensions = wallpapers[0].get_dimensions();
let expected_len = dimensions.0 as usize
* dimensions.1 as usize
* crate::pixel_format().channels() as usize;

if img.len() == expected_len {
Transition::new(wallpapers, dimensions, transition).execute(img);
} else {
error!(
"image is of wrong size! Image len: {}, expected len: {expected_len}",
img.len(),
);

let expect = wallpapers[0].get_dimensions();
if dim != expect {
wallpapers.clear();
error!("image has wrong dimensions! Expect {expect:?}, actual {dim:?}");
return;
}

Transition::new(wallpapers, dim, transition).execute(img);
})
{
error!("failed to spawn 'transition' thread: {}", e);
Expand All @@ -75,18 +71,34 @@ impl Animator {
&mut self,
transition: ipc::Transition,
imgs: Box<[Img]>,
wallpapers: Vec<Vec<Arc<Wallpaper>>>,
animations: Option<Box<[Animation]>>,
mut wallpapers: Vec<Vec<Arc<Wallpaper>>>,
) -> Answer {
match thread::Builder::new()
let barrier = self.anim_barrier.clone();
let spawn_result = thread::Builder::new()
.stack_size(1 << 15)
.name("transition spawner".to_string())
.name("animation spawner".to_string())
.spawn(move || {
thread::scope(|s| {
for (Img { img, path }, wallpapers) in imgs.iter().zip(wallpapers) {
Self::spawn_transition_thread(s, &transition, img, path, wallpapers);
for (Img { img, path, dim, .. }, wallpapers) in
imgs.iter().zip(wallpapers.iter_mut())
{
Self::spawn_transition_thread(s, &transition, img, path, *dim, wallpapers);
}
});
}) {
drop(imgs);
#[allow(clippy::drop_non_drop)]
drop(transition);
if let Some(animations) = animations {
thread::scope(|s| {
for (animation, wallpapers) in animations.iter().zip(wallpapers) {
let barrier = barrier.clone();
Self::spawn_animation_thread(s, animation, wallpapers, barrier);
}
});
}
});
match spawn_result {
Ok(_) => Answer::Ok,
Err(e) => Answer::Err(e.to_string()),
}
Expand All @@ -105,7 +117,7 @@ impl Animator {
.stack_size(STACK_SIZE) //the default of 2MB is way too overkill for this
.spawn_scoped(scope, move || {
/* We only need to animate if we have > 1 frame */
if animation.animation.len() <= 1 {
if animation.animation.len() <= 1 || wallpapers.is_empty() {
return;
}
log::debug!("Starting animation");
Expand All @@ -115,16 +127,6 @@ impl Animator {
.map(|w| w.create_animation_token())
.collect();

for (wallpaper, token) in wallpapers.iter().zip(&tokens) {
loop {
if !wallpaper.has_animation_id(token) || token.is_transition_done() {
break;
}
let duration: Duration = animation.animation[0].1;
std::thread::sleep(duration / 2);
}
}

let mut now = std::time::Instant::now();

let mut decompressor = Decompressor::new();
Expand Down Expand Up @@ -172,26 +174,4 @@ impl Animator {
error!("failed to spawn 'animation' thread: {}", e);
}
}

pub(super) fn animate(
&mut self,
animations: Box<[Animation]>,
wallpapers: Vec<Vec<Arc<Wallpaper>>>,
) -> Answer {
let barrier = self.anim_barrier.clone();
match thread::Builder::new()
.stack_size(1 << 15)
.name("animation spawner".to_string())
.spawn(move || {
thread::scope(|s| {
for (animation, wallpapers) in animations.iter().zip(wallpapers) {
let barrier = barrier.clone();
Self::spawn_animation_thread(s, animation, wallpapers, barrier);
}
});
}) {
Ok(_) => Answer::Ok,
Err(e) => Answer::Err(e.to_string()),
}
}
}
11 changes: 4 additions & 7 deletions daemon/src/animations/transitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use keyframe::{
functions::BezierCurve, keyframes, mint::Vector2, num_traits::Pow, AnimationSequence,
};

pub(super) struct Transition {
pub(super) struct Transition<'a> {
animation_tokens: Vec<AnimationToken>,
wallpapers: Vec<Arc<Wallpaper>>,
wallpapers: &'a mut Vec<Arc<Wallpaper>>,
dimensions: (u32, u32),
transition_type: TransitionType,
duration: f32,
Expand All @@ -30,9 +30,9 @@ pub(super) struct Transition {
}

/// All transitions return whether or not they completed
impl Transition {
impl<'a> Transition<'a> {
pub(super) fn new(
wallpapers: Vec<Arc<Wallpaper>>,
wallpapers: &'a mut Vec<Arc<Wallpaper>>,
dimensions: (u32, u32),
transition: &utils::ipc::Transition,
) -> Self {
Expand Down Expand Up @@ -76,9 +76,6 @@ impl Transition {
TransitionType::Fade => self.fade(new_img),
};
debug!("Transitions finished");
for (wallpaper, token) in self.wallpapers.iter().zip(self.animation_tokens) {
token.set_transition_done(wallpaper);
}
}

fn updt_wallpapers(&mut self, now: &mut Instant) {
Expand Down
17 changes: 4 additions & 13 deletions daemon/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ use wayland_client::{
};

use utils::ipc::{
connect_to_socket, get_socket_path, read_socket, AnimationRequest, Answer, BgInfo,
ImageRequest, PixelFormat, Request, Scale,
connect_to_socket, get_socket_path, read_socket, Answer, BgInfo, ImageRequest, PixelFormat,
Request, Scale,
};

use animations::Animator;
Expand Down Expand Up @@ -371,16 +371,6 @@ impl Daemon {
};
let request = Request::receive(bytes);
let answer = match request {
Request::Animation(AnimationRequest {
animations,
outputs,
}) => {
let mut wallpapers = Vec::new();
for names in outputs.iter() {
wallpapers.push(self.find_wallpapers_by_names(names));
}
self.animator.animate(animations, wallpapers)
}
Request::Clear(clear) => {
let wallpapers = self.find_wallpapers_by_names(&clear.outputs);
let color = clear.color;
Expand Down Expand Up @@ -415,6 +405,7 @@ impl Daemon {
transition,
imgs,
outputs,
animations,
}) => {
let mut used_wallpapers = Vec::new();
for names in outputs.iter() {
Expand All @@ -424,7 +415,7 @@ impl Daemon {
}
used_wallpapers.push(wallpapers);
}
self.animator.transition(transition, imgs, used_wallpapers)
self.animator.transition(transition, imgs, animations, used_wallpapers)
}
};
if let Err(e) = answer.send(&stream) {
Expand Down
18 changes: 1 addition & 17 deletions daemon/src/wallpaper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,6 @@ struct AnimationState {
#[derive(Debug)]
pub(super) struct AnimationToken {
id: usize,
transition_done: Arc<AtomicBool>,
}

impl AnimationToken {
pub(super) fn is_transition_done(&self) -> bool {
self.transition_done.load(Ordering::Acquire)
}

pub(super) fn set_transition_done(&self, wallpaper: &Wallpaper) {
if wallpaper.has_animation_id(self) {
self.transition_done.store(true, Ordering::Release);
}
}
}

struct FrameCallbackHandler {
Expand Down Expand Up @@ -381,10 +368,7 @@ impl Wallpaper {
#[inline]
pub(super) fn create_animation_token(&self) -> AnimationToken {
let id = self.animation_state.id.load(Ordering::Acquire);
AnimationToken {
id,
transition_done: Arc::clone(&self.animation_state.transition_finished),
}
AnimationToken { id }
}

#[inline]
Expand Down
Loading

0 comments on commit 07e8a73

Please sign in to comment.