Skip to content

Commit

Permalink
Merge pull request #221 from LGFae/go-back-to-slot-pool
Browse files Browse the repository at this point in the history
Implement frame callbacks and a new memory pool
  • Loading branch information
LGFae authored Feb 26, 2024
2 parents 0f8d1ac + 9fcc9f9 commit d174d13
Show file tree
Hide file tree
Showing 5 changed files with 332 additions and 131 deletions.
21 changes: 14 additions & 7 deletions daemon/src/animations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ use self::anim_barrier::ArcAnimBarrier;
///The default thread stack size of 2MiB is way too overkill for our purposes
const STACK_SIZE: usize = 1 << 17; //128KiB

pub struct Animator {
pub(super) struct Animator {
anim_barrier: ArcAnimBarrier,
}

impl Animator {
pub fn new() -> Self {
pub(super) fn new() -> Self {
Self {
anim_barrier: ArcAnimBarrier::new(),
}
Expand Down Expand Up @@ -69,7 +69,11 @@ impl Animator {
}
}

pub fn transition(&mut self, bytes: Vec<u8>, wallpapers: Vec<Vec<Arc<Wallpaper>>>) -> Answer {
pub(super) fn transition(
&mut self,
bytes: Vec<u8>,
wallpapers: Vec<Vec<Arc<Wallpaper>>>,
) -> Answer {
match thread::Builder::new()
.stack_size(1 << 15)
.name("transition spawner".to_string())
Expand Down Expand Up @@ -140,8 +144,7 @@ impl Animator {
continue;
}

let (success, buffer) =
wallpapers[i].canvas_change(|canvas| frame.unpack(canvas));
let success = wallpapers[i].canvas_change(|canvas| frame.unpack(canvas));

if !success {
error!("failed to unpack frame, canvas is smaller than expected");
Expand All @@ -150,7 +153,7 @@ impl Animator {
continue;
}

wallpapers[i].draw(&buffer);
wallpapers[i].draw();
i += 1;
}

Expand All @@ -169,7 +172,11 @@ impl Animator {
}
}

pub fn animate(&mut self, bytes: Vec<u8>, wallpapers: Vec<Vec<Arc<Wallpaper>>>) -> Answer {
pub(super) fn animate(
&mut self,
bytes: Vec<u8>,
wallpapers: Vec<Vec<Arc<Wallpaper>>>,
) -> Answer {
let barrier = self.anim_barrier.clone();
match thread::Builder::new()
.stack_size(1 << 15)
Expand Down
30 changes: 15 additions & 15 deletions daemon/src/animations/transitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ macro_rules! change_cols {
};
}

pub struct Transition {
pub(super) struct Transition {
animation_tokens: Vec<AnimationToken>,
wallpapers: Vec<Arc<Wallpaper>>,
dimensions: (u32, u32),
Expand All @@ -59,7 +59,7 @@ pub struct Transition {

/// All transitions return whether or not they completed
impl Transition {
pub fn new(
pub(super) fn new(
wallpapers: Vec<Arc<Wallpaper>>,
dimensions: (u32, u32),
transition: utils::ipc::ArchivedTransition,
Expand Down Expand Up @@ -92,7 +92,7 @@ impl Transition {
}
}

pub fn execute(mut self, new_img: &[u8]) {
pub(super) fn execute(mut self, new_img: &[u8]) {
debug!("Starting transitions");
match self.transition_type {
ArchivedTransitionType::Simple => self.simple(new_img),
Expand Down Expand Up @@ -140,12 +140,12 @@ impl Transition {
while !done {
done = true;
for wallpaper in self.wallpapers.iter_mut() {
let (_, buffer) = wallpaper.canvas_change(|canvas| {
wallpaper.canvas_change(|canvas| {
for (old, new) in canvas.chunks_exact_mut(4).zip(new_img.chunks_exact(3)) {
change_cols!(step, old, new, done);
}
});
wallpaper.draw(&buffer);
wallpaper.draw();
}
self.send_frame(&mut now);
}
Expand All @@ -158,7 +158,7 @@ impl Transition {
let mut now = Instant::now();
while start.elapsed().as_secs_f64() < seq.duration() {
for wallpaper in self.wallpapers.iter_mut() {
let (_, buffer) = wallpaper.canvas_change(|canvas| {
wallpaper.canvas_change(|canvas| {
canvas
.par_chunks_exact_mut(4)
.zip(new_img.par_chunks_exact(3))
Expand All @@ -169,7 +169,7 @@ impl Transition {
}
});
});
wallpaper.draw(&buffer);
wallpaper.draw();
}
self.send_frame(&mut now);
step = seq.now() as f64;
Expand Down Expand Up @@ -227,7 +227,7 @@ impl Transition {

while start.elapsed().as_secs_f64() < seq.duration() {
for wallpaper in self.wallpapers.iter_mut() {
let (_, buffer) = wallpaper.canvas_change(|canvas| {
wallpaper.canvas_change(|canvas| {
canvas
.par_chunks_exact_mut(4)
.zip(new_img.par_chunks_exact(3))
Expand All @@ -240,7 +240,7 @@ impl Transition {
}
});
});
wallpaper.draw(&buffer);
wallpaper.draw();
}
self.send_frame(&mut now);

Expand Down Expand Up @@ -288,7 +288,7 @@ impl Transition {

while start.elapsed().as_secs_f64() < seq.duration() {
for wallpaper in self.wallpapers.iter_mut() {
let (_, buffer) = wallpaper.canvas_change(|canvas| {
wallpaper.canvas_change(|canvas| {
canvas
.par_chunks_exact_mut(4)
.zip(new_img.par_chunks_exact(3))
Expand All @@ -301,7 +301,7 @@ impl Transition {
}
});
});
wallpaper.draw(&buffer);
wallpaper.draw();
}
self.send_frame(&mut now);

Expand Down Expand Up @@ -335,7 +335,7 @@ impl Transition {
let mut now = Instant::now();
while start.elapsed().as_secs_f64() < seq.duration() {
for wallpaper in self.wallpapers.iter_mut() {
let (_, buffer) = wallpaper.canvas_change(|canvas| {
wallpaper.canvas_change(|canvas| {
canvas
.par_chunks_exact_mut(4)
.zip(new_img.par_chunks_exact(3))
Expand All @@ -354,7 +354,7 @@ impl Transition {
}
});
});
wallpaper.draw(&buffer);
wallpaper.draw();
}
self.send_frame(&mut now);

Expand Down Expand Up @@ -386,7 +386,7 @@ impl Transition {
let mut now = Instant::now();
while start.elapsed().as_secs_f64() < seq.duration() {
for wallpaper in self.wallpapers.iter_mut() {
let (_, buffer) = wallpaper.canvas_change(|canvas| {
wallpaper.canvas_change(|canvas| {
canvas
.par_chunks_exact_mut(4)
.zip(new_img.par_chunks_exact(3))
Expand All @@ -405,7 +405,7 @@ impl Transition {
}
});
});
wallpaper.draw(&buffer);
wallpaper.draw();
}
self.send_frame(&mut now);

Expand Down
175 changes: 175 additions & 0 deletions daemon/src/bump_pool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};

use smithay_client_toolkit::shm::{raw::RawPool, Shm};
use wayland_client::{
protocol::{wl_buffer::WlBuffer, wl_shm},
QueueHandle,
};

use crate::Daemon;

#[derive(Debug)]
struct Buffer {
inner: WlBuffer,
released: Arc<AtomicBool>,
}

impl Buffer {
fn new(inner: WlBuffer, released: Arc<AtomicBool>) -> Self {
Self { inner, released }
}
}

impl Drop for Buffer {
fn drop(&mut self) {
self.inner.destroy();
}
}

#[derive(Debug)]
/// A pool implementation that only gives buffers of a fixed size, creating new ones if none of
/// them are freed. It also takes care of copying the previous buffer's content over to the new one
/// for us
pub(crate) struct BumpPool {
pool: RawPool,
buffers: Vec<Buffer>,
width: i32,
height: i32,
last_used_buffer: Option<usize>,
}

impl BumpPool {
/// We assume `width` and `height` have already been multiplied by their scale factor
pub(crate) fn new(width: i32, height: i32, shm: &Shm, qh: &QueueHandle<Daemon>) -> Self {
let len = width as usize * height as usize * 4;
let mut pool = RawPool::new(len, shm).expect("failed to create RawPool");
let released = Arc::new(AtomicBool::new(true));
let buffers = vec![Buffer::new(
pool.create_buffer(
0,
width,
height,
width * 4,
wl_shm::Format::Xrgb8888,
released.clone(),
qh,
),
released,
)];

Self {
pool,
buffers,
width,
height,
last_used_buffer: None,
}
}

#[inline]
fn buffer_len(&self) -> usize {
self.width as usize * self.height as usize * 4
}

#[inline]
fn buffer_offset(&self, buffer_index: usize) -> usize {
self.buffer_len() * buffer_index
}

#[inline]
fn occupied_bytes(&self) -> usize {
self.buffer_offset(self.buffers.len())
}

/// resizes the pool and creates a new WlBuffer at the next free offset
fn grow(&mut self, qh: &QueueHandle<Daemon>) {
//TODO: CHECK IF WE HAVE SIZE
let len = self.buffer_len();
self.pool
.resize(self.occupied_bytes() + len)
.expect("failed to resize RawPool");
let released = Arc::new(AtomicBool::new(true));
let new_buffer_index = self.buffers.len();
self.buffers.push(Buffer::new(
self.pool.create_buffer(
self.buffer_offset(new_buffer_index).try_into().unwrap(),
self.width,
self.height,
self.width * 4,
wl_shm::Format::Xrgb8888,
released.clone(),
qh,
),
released,
));
log::info!(
"BumpPool with: {} buffers. Size: {}Kb",
self.buffers.len(),
self.pool.len() / 1024
);
}

/// Returns a drawable surface. If we can't find a free buffer, we request more memory
///
/// This function automatically handles copying the previous buffer over onto the new one
pub(crate) fn get_drawable(&mut self, qh: &QueueHandle<Daemon>) -> &mut [u8] {
let (i, buf) = match self
.buffers
.iter()
.enumerate()
.find(|(_, b)| b.released.load(Ordering::Acquire))
{
Some((i, buf)) => (i, buf),
None => {
self.grow(qh);
(self.buffers.len() - 1, self.buffers.last().unwrap())
}
};

let len = self.buffer_len();
let offset = self.buffer_offset(i);
buf.released.store(false, Ordering::Release);

if let Some(i) = self.last_used_buffer {
let last_offset = self.buffer_offset(i);
self.pool
.mmap()
.copy_within(last_offset..last_offset + len, offset);
}
self.last_used_buffer = Some(i);

&mut self.pool.mmap()[offset..offset + len]
}

/// gets the last buffer we've drawn to
///
/// This may return None if there was a resize request in-between the last call to get_drawable
#[inline]
pub(crate) fn get_commitable_buffer(&self) -> Option<&WlBuffer> {
self.last_used_buffer.map(|i| &self.buffers[i].inner)
}

/// We assume `width` and `height` have already been multiplied by their scale factor
pub(crate) fn resize(&mut self, width: i32, height: i32, qh: &QueueHandle<Daemon>) {
self.width = width;
self.height = height;
self.last_used_buffer = None;
self.buffers.clear();
let released = Arc::new(AtomicBool::new(true));
self.buffers.push(Buffer::new(
self.pool.create_buffer(
0,
width,
height,
width * 4,
wl_shm::Format::Xrgb8888,
released.clone(),
qh,
),
released,
));
}
}
Loading

0 comments on commit d174d13

Please sign in to comment.