diff --git a/src/buffers.rs b/src/buffers.rs new file mode 100644 index 0000000..0de96d6 --- /dev/null +++ b/src/buffers.rs @@ -0,0 +1,140 @@ +use crate::geometry::*; +use crate::render::{Surface, Shader, Surfaces}; + +use std::fmt::{Debug, Formatter}; +use std::rc::Rc; +use std::cell::RefCell; +use std::io; + +#[cfg(feature="threads")] +use std::sync::{Arc, Mutex}; + +#[derive(Debug)] +pub struct ShaderBinding { + shader: Option>, + rect: Rectangle +} + +#[derive(Clone)] +pub struct BoundSurface { + pub binding: T +} + +impl Debug for BoundSurface>> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("BoundSurface") + .field("shader", &self.binding.borrow().shader) + .finish() + } +} + +pub type SimpleSurface = BoundSurface>>; + +impl Default for BoundSurface>>{ + fn default() -> Self { + Self { + binding: Rc::new(RefCell::new(ShaderBinding { + shader: None, + rect: Rectangle::everything() + })), + } + } +} + +impl Surface for BoundSurface>> { + fn rect(&self) -> Rectangle { + self.binding.borrow().rect.clone() + } + + fn with_shader(&self, mut f: F) { + if let Some(ref shader) = self.binding.borrow().shader { + f(shader.as_ref()); + } + } + + fn set_shader(&mut self, shader: Box) { + self.binding.borrow_mut().shader = Some(shader); + } + + fn clear_shader(&mut self) { + self.binding.borrow_mut().shader = None; + } +} + +#[cfg(feature="threads")] +pub type SharedSurface = BoundSurface>>; + +#[cfg(feature="threads")] +impl Default for BoundSurface>> { + fn default() -> Self { + Self { + binding: Arc::new(Mutex::new(ShaderBinding { + shader: None, + rect: Rectangle::everything() + })), + } + } +} + +#[cfg(feature="threads")] +impl Surface for BoundSurface>> { + fn rect(&self) -> Rectangle { + let r = self.binding.lock().unwrap(); + r.rect.clone() + //self.binding.lock().unwrap().rect.clone() + } + + fn with_shader(&self, mut f: F) { + if let Some(ref shader) = self.binding.lock().unwrap().shader { + f(shader.as_ref()); + } + } + + fn set_shader(&mut self, shader: Box) { + self.binding.lock().unwrap().shader = Some(shader); + } + + fn clear_shader(&mut self) { + self.binding.lock().unwrap().shader = None; + } +} + +#[cfg(feature="threads")] +impl Debug for BoundSurface>> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("BoundSurface") + .field("shader", &self.binding.lock().unwrap().shader) + .finish() + } +} + +#[derive(Clone)] +pub struct SurfacePool { + surfaces: Vec +} + +impl Debug for SurfacePool { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.surfaces.fmt(f) + } +} + +impl SurfacePool { + pub const fn new() -> Self { + Self { + surfaces: Vec::new() + } + } + + pub fn iter(&self) -> std::slice::Iter { + self.surfaces.iter() + } +} + +impl Surfaces for SurfacePool { + fn new_surface(&mut self, _area: &Rectangle) -> Result { + let surface = S::default(); + self.surfaces.push(surface.clone()); + return Ok(surface); + } +} diff --git a/src/main.rs b/src/main.rs index bba86b3..aac5a4a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod geometry; mod platform; mod animations; mod mappings; +mod buffers; use crate::platform::DisplayInit; use crate::render::Surfaces; @@ -25,10 +26,10 @@ use ws2812_esp32_rmt_driver::lib_smart_leds::Ws2812Esp32Rmt as DisplayType; use crate::platform::smart_leds_lib::spi::SPIDisplay as DisplayType; #[cfg(feature="threads")] -use crate::render::SharedSurface as SurfaceType; +use crate::buffers::SharedSurface as SurfaceType; #[cfg(not(feature="threads"))] -use crate::render::SimpleSurface as SurfaceType; +use crate::buffers::SimpleSurface as SurfaceType; use crate::render::Renderer; diff --git a/src/platform/smart_leds_lib.rs b/src/platform/smart_leds_lib.rs index 53a4e5d..189232f 100644 --- a/src/platform/smart_leds_lib.rs +++ b/src/platform/smart_leds_lib.rs @@ -1,7 +1,8 @@ use smart_leds_trait::SmartLedsWrite; use crate::lib8::Rgb8Blend; -use crate::render::{Surface, SurfacePool, Display, Surfaces}; +use crate::render::{Framed, Surface, Display, Surfaces}; +use crate::buffers::SurfacePool; use crate::power::{brightness_for_mw, AsMilliwatts}; use crate::geometry::*; use crate::mappings::*; @@ -96,20 +97,8 @@ T: SmartLedsWrite, S: Surface, T::Color: HardwarePixel, [T::Color; PIXEL_NUM]: Pixbuf, -Rgb: From { - - fn start_frame(&mut self) { - self.pixbuf.blank(); - } - - fn end_frame(&mut self) { - let b = brightness_for_mw(self.pixbuf.as_milliwatts(), 255, self.max_mw); - if let Err(_) = self.target.write(brightness(self.pixbuf.iter().cloned().map(|x| { x.into() }), b)) { - //if let Err(_) = self.target.write(self.pixbuf.iter().cloned()) { - panic!("Could not write frame"); - } - } - +Rgb: From +{ fn render_frame(&mut self) { let surfaces = self.surfaces.take().unwrap(); for surface in surfaces.iter() { @@ -129,6 +118,25 @@ Rgb: From { } } +impl Framed for SmartLedDisplay where +T: SmartLedsWrite, +S: Surface, +T::Color: HardwarePixel, +[T::Color; PIXEL_NUM]: Pixbuf, +Rgb: From { + + fn start_frame(&mut self) { + self.pixbuf.blank(); + } + + fn end_frame(&mut self) { + let b = brightness_for_mw(self.pixbuf.as_milliwatts(), 255, self.max_mw); + if let Err(_) = self.target.write(brightness(self.pixbuf.iter().cloned().map(|x| { x.into() }), b)) { + panic!("Could not write frame"); + } + } +} + #[cfg(feature="rmt")] pub mod rmt { use esp_idf_svc::hal::prelude::Peripherals; diff --git a/src/render.rs b/src/render.rs index d7897e9..8117c98 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,11 +1,6 @@ -use std::rc::Rc; -use std::cell::RefCell; use std::io; use rgb::RGB8; -#[cfg(feature="threads")] -use std::sync::{Arc, Mutex}; - use crate::geometry::*; use crate::task::Task; use crate::time::Periodically; @@ -17,6 +12,10 @@ pub trait Shader: Send + Debug { fn draw(&self, surface_coords: &VirtualCoordinates) -> RGB8; } +pub trait Surfaces: Debug { + fn new_surface(&mut self, area: &Rectangle) -> Result; +} + pub trait Surface: Default + Clone + Debug { fn with_shader(&self, f: F); fn set_shader(&mut self, shader: Box); @@ -25,13 +24,12 @@ pub trait Surface: Default + Clone + Debug { fn rect(&self) -> Rectangle; } -pub trait Surfaces: Debug { - fn new_surface(&mut self, area: &Rectangle) -> Result; -} - -pub trait Display: Surfaces { +pub trait Framed { fn start_frame(&mut self) {} fn end_frame(&mut self) {} +} + +pub trait Display: Surfaces + Framed { fn render_frame(&mut self); } @@ -67,126 +65,3 @@ impl, S: Surface> Task for Renderer { }); } } - -#[derive(Debug)] -pub struct ShaderBinding { - shader: Option>, - rect: Rectangle -} - -#[derive(Clone)] -pub struct BoundSurface { - pub binding: T -} - -impl Debug for BoundSurface>> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("BoundSurface") - .field("shader", &self.binding.borrow().shader) - .finish() - } -} - -pub type SimpleSurface = BoundSurface>>; - -impl Default for BoundSurface>>{ - fn default() -> Self { - Self { - binding: Rc::new(RefCell::new(ShaderBinding { - shader: None, - rect: Rectangle::everything() - })), - } - } -} - -impl Surface for BoundSurface>> { - fn rect(&self) -> Rectangle { - self.binding.borrow().rect.clone() - } - - fn with_shader(&self, mut f: F) { - if let Some(ref shader) = self.binding.borrow().shader { - f(shader.as_ref()); - } - } - - fn set_shader(&mut self, shader: Box) { - self.binding.borrow_mut().shader = Some(shader); - } - - fn clear_shader(&mut self) { - self.binding.borrow_mut().shader = None; - } -} - -#[cfg(feature="threads")] -pub type SharedSurface = BoundSurface>>; - -#[cfg(feature="threads")] -impl Default for BoundSurface>> { - fn default() -> Self { - Self { - binding: Arc::new(Mutex::new(ShaderBinding { - shader: None, - })), - } - } -} - -#[cfg(feature="threads")] -impl Surface for BoundSurface>> { - fn with_shader(&self, mut f: F) { - if let Some(ref shader) = self.binding.lock().unwrap().shader { - f(shader.as_ref()); - } - } - - fn set_shader(&mut self, shader: Box) { - self.binding.lock().unwrap().shader = Some(shader); - } - - fn clear_shader(&mut self) { - self.binding.lock().unwrap().shader = None; - } -} - -#[cfg(feature="threads")] -impl Debug for BoundSurface>> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("BoundSurface") - .field("shader", &self.binding.lock().unwrap().shader) - .finish() - } -} - -#[derive(Clone)] -pub struct SurfacePool { - surfaces: Vec -} - -impl Debug for SurfacePool { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.surfaces.fmt(f) - } -} - -impl SurfacePool { - pub const fn new() -> Self { - Self { - surfaces: Vec::new() - } - } - - pub fn iter(&self) -> std::slice::Iter { - self.surfaces.iter() - } -} - -impl Surfaces for SurfacePool { - fn new_surface(&mut self, _area: &Rectangle) -> Result { - let surface = S::default(); - self.surfaces.push(surface.clone()); - return Ok(surface); - } -}