use rgb::Rgb; use crate::events::{Event, EventBus}; use crate::geometry::*; use crate::lib8::interpolate::Fract8Ops; use crate::power::AsMilliwatts; use crate::task::Task; use crate::time::Periodically; use running_average::RealTimeRunningAverage; use core::fmt::Debug; pub trait HardwarePixel: Send + Sync + Copy + AsMilliwatts + Default + From> + Fract8Ops {} impl HardwarePixel for T where T: Send + Sync + Copy + AsMilliwatts + Default + From> + Fract8Ops {} pub trait PixelView { type Pixel: HardwarePixel; fn next(&mut self) -> Option<(Coordinates, &mut Self::Pixel)>; } pub trait Sample { type Pixel: HardwarePixel; fn sample(&mut self, rect: &Rectangle) -> impl PixelView; } pub trait Shader: Send + Sync { fn draw(&self, surface_coords: &VirtualCoordinates, frame: usize) -> Rgb; } pub trait Surfaces: Send + Sync { type Surface: Surface; type Error: Debug; fn new_surface(&mut self, area: Rectangle) -> Result; fn render_to(&self, output: &mut S, frame: usize); } pub trait Surface: Send + Sync { fn set_shader(&mut self, shader: Box); fn clear_shader(&mut self); fn set_rect(&mut self, rect: Rectangle); fn set_opacity(&mut self, opacity: u8); } pub trait Output: Sample + Send { fn on_event(&mut self, event: &Event); fn blank(&mut self); fn commit(&mut self); } #[derive(Debug)] pub struct Renderer { output: T, surfaces: S, fps: RealTimeRunningAverage, fps_display: Periodically, frame: usize, frame_count: usize } impl Renderer { pub fn new(output: T, surfaces: S) -> Self { Self { output, surfaces: surfaces, fps: RealTimeRunningAverage::default(), fps_display: Periodically::new_every_n_seconds(5), frame: 0, frame_count: 0 } } } impl Task for Renderer { fn name(&self) -> &'static str { "Renderer" } fn on_property_change(&mut self, key: &'static str, value: &crate::events::Variant, _bus: &mut EventBus) { self.output.on_event(&Event::new_property_change(key, value.clone())); } fn on_tick(&mut self, bus: &mut EventBus) { self.output.blank(); self.surfaces.render_to(&mut self.output, self.frame); self.output.commit(); self.frame += 1; self.fps_display.run(|| { self.fps.insert((self.frame - self.frame_count) as u32); self.frame_count = self.frame; let fps = self.fps.measurement(); bus.push(Event::new_property_change("output.fps", fps.rate() as u32)); }); } }