Properly double buffering

This commit is contained in:
2025-05-21 15:50:52 -07:00
parent 5b8475f1a3
commit 64fe7ec941
9 changed files with 203 additions and 125 deletions

View File

@@ -1,4 +1,4 @@
use crate::wayland::shm::ShmPool;
use crate::wayland::{shm::ShmPool, wl_shm::wl_buffer};
use super::drawable::{Drawable, color_blend};
// x and y are center of circle
@@ -16,24 +16,34 @@ impl Circle {
}
impl Drawable for Circle {
fn draw(&self, shm_pool: &mut ShmPool) {
fn update(&mut self) {
self.x += 1;
}
fn draw(&self, buffer: &wl_buffer, shm_pool: &mut ShmPool) {
for l_row in 1..self.radius {
let inner_diff = (((self.radius-1).pow(2) - l_row.pow(2)) as f64).sqrt();
let outer_diff = ((self.radius.pow(2) - l_row.pow(2)) as f64).sqrt();
let row: Vec<u32> = vec![self.color; 2*(inner_diff.floor() as usize)];
shm_pool.write(&row, (self.y-l_row)*shm_pool.width + self.x - inner_diff.floor() as usize);
shm_pool.write(&row, (self.y+l_row-1)*shm_pool.width + self.x - inner_diff.floor() as usize);
shm_pool.write(&row, (self.y-l_row)*buffer.width + self.x - inner_diff.floor() as usize + buffer.offset);
shm_pool.write(&row, (self.y+l_row-1)*buffer.width + self.x - inner_diff.floor() as usize + buffer.offset);
for l_col in (inner_diff.floor() as usize+1)..(outer_diff.ceil() as usize) {
let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt();
let offset = (self.y-l_row)*shm_pool.width + self.x - l_col;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize);
let offset = (self.y-l_row)*shm_pool.width + self.x + l_col-1;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize);
let offset = (self.y+l_row-1)*shm_pool.width + self.x - l_col;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize);
let offset = (self.y+l_row-1)*shm_pool.width + self.x + l_col-1;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize);
let offset = (self.y-l_row)*buffer.width + self.x - l_col + buffer.offset;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset);
let offset = (self.y-l_row)*buffer.width + self.x + l_col-1 + buffer.offset;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset);
let offset = (self.y+l_row-1)*buffer.width + self.x - l_col + buffer.offset;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset);
let offset = (self.y+l_row-1)*buffer.width + self.x + l_col-1 + buffer.offset;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset);
}
}
}
}
impl Into<Box<dyn Drawable>> for Circle {
fn into(self) -> Box<dyn Drawable> {
Box::new(self)
}
}

View File

@@ -1,10 +1,12 @@
use crate::wayland::shm::ShmPool;
use crate::wayland::{shm::ShmPool, wl_shm::wl_buffer};
pub fn color_blend(col1: u32, col2: u32, diff: f64) -> u32 {
// TODO: Account for alpha channel
let a1 = (col1 & 0xff000000) >> 24;
let r1 = (col1 & 0x00ff0000) >> 16;
let g1 = (col1 & 0x0000ff00) >> 8;
let b1 = col1 & 0x000000ff;
let a2 = (col2 & 0xff000000) >> 24;
let r2 = (col2 & 0x00ff0000) >> 16;
let g2 = (col2 & 0x0000ff00) >> 8;
let b2 = col2 & 0x000000ff;
@@ -26,6 +28,7 @@ pub fn color_blend(col1: u32, col2: u32, diff: f64) -> u32 {
return 0xff000000 + (r3 << 16) + (g3 << 8) + b3;
}
pub trait Drawable {
fn draw(&self, shm_pool: &mut ShmPool);
pub trait Drawable : Send {
fn update(&mut self);
fn draw(&self, buffer: &wl_buffer, shm_pool: &mut ShmPool);
}

View File

@@ -1,7 +1,6 @@
use crate::wayland::shm::ShmPool;
use crate::wayland::{shm::ShmPool, wl_shm::wl_buffer};
use super::drawable::{Drawable, color_blend};
// x and y and topleft corner of rect
pub struct Rectangle {
x: usize,
@@ -19,27 +18,37 @@ impl Rectangle {
}
impl Drawable for Rectangle {
fn draw(&self, shm_pool: &mut ShmPool) {
fn update(&mut self) {
// self.x += 1;
}
fn draw(&self, buffer: &wl_buffer, shm_pool: &mut ShmPool) {
for g_row in self.y+self.radius..self.y+self.height-self.radius+1 {
shm_pool.write(&vec![self.color; self.width], g_row*shm_pool.width+self.x);
shm_pool.write(&vec![self.color; self.width], g_row*buffer.width as usize+self.x + buffer.offset);
}
for l_row in 1..self.radius {
let inner_diff = (((self.radius-1).pow(2) - l_row.pow(2)) as f64).sqrt();
let outer_diff = ((self.radius.pow(2) - l_row.pow(2)) as f64).sqrt();
shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.radius-l_row)*shm_pool.width + self.x + self.radius - inner_diff.floor() as usize-1);
shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.height-self.radius+l_row)*shm_pool.width + self.x + self.radius - inner_diff.floor() as usize-1);
shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.radius-l_row)*buffer.width as usize + self.x + self.radius - inner_diff.floor() as usize-1 + buffer.offset);
shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.height-self.radius+l_row)*buffer.width as usize + self.x + self.radius - inner_diff.floor() as usize-1 + buffer.offset);
for l_col in inner_diff.floor() as usize+1..outer_diff.ceil() as usize {
// TODO: handle error from read_pixel
let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt();
let offset = (self.y+self.radius-l_row)*shm_pool.width + self.x + self.radius - l_col - 1;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize);
let offset = (self.y+self.radius-l_row)*shm_pool.width + self.x + self.width - self.radius + l_col;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize);
let offset = (self.y+self.height-self.radius+l_row)*shm_pool.width + self.x + self.radius - l_col - 1;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize);
let offset = (self.y+self.height-self.radius+l_row)*shm_pool.width + self.x + self.width - self.radius + l_col;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize);
let offset = (self.y+self.radius-l_row)*buffer.width as usize + self.x + self.radius - l_col - 1 + buffer.offset;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset);
let offset = (self.y+self.radius-l_row)*buffer.width as usize + self.x + self.width - self.radius + l_col + buffer.offset;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset);
let offset = (self.y+self.height-self.radius+l_row)*buffer.width as usize + self.x + self.radius - l_col - 1 + buffer.offset;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset);
let offset = (self.y+self.height-self.radius+l_row)*buffer.width as usize + self.x + self.width - self.radius + l_col + buffer.offset;
shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset).unwrap(), distance.fract()), offset);
}
}
}
}
impl Into<Box<dyn Drawable>> for Rectangle {
fn into(self) -> Box<dyn Drawable> {
Box::new(self)
}
}