96 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
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<Rgb<u8>> + Fract8Ops {}
 | 
						|
impl<T> HardwarePixel for T where T: Send + Sync + Copy + AsMilliwatts + Default + From<Rgb<u8>> + Fract8Ops {}
 | 
						|
 | 
						|
pub trait PixelView {
 | 
						|
    type Pixel: HardwarePixel;
 | 
						|
    fn next(&mut self) -> Option<(Coordinates<Virtual>, &mut Self::Pixel)>;
 | 
						|
}
 | 
						|
 | 
						|
pub trait Sample {
 | 
						|
    type Pixel: HardwarePixel;
 | 
						|
 | 
						|
    fn sample(&mut self, rect: &Rectangle<Virtual>) -> impl PixelView<Pixel = Self::Pixel>;
 | 
						|
}
 | 
						|
 | 
						|
pub trait Shader: Send + Sync {
 | 
						|
    fn draw(&self, surface_coords: &VirtualCoordinates, frame: usize) -> Rgb<u8>;
 | 
						|
}
 | 
						|
 | 
						|
pub trait Surfaces: Send + Sync {
 | 
						|
    type Surface: Surface;
 | 
						|
    type Error: Debug;
 | 
						|
    fn new_surface(&mut self, area: Rectangle<Virtual>) -> Result<Self::Surface, Self::Error>;
 | 
						|
    fn render_to<S: Sample>(&self, output: &mut S, frame: usize);
 | 
						|
}
 | 
						|
 | 
						|
pub trait Surface: Send + Sync {
 | 
						|
    fn set_shader(&mut self, shader: Box<dyn Shader>);
 | 
						|
    fn clear_shader(&mut self);
 | 
						|
 | 
						|
    fn set_rect(&mut self, rect: Rectangle<Virtual>);
 | 
						|
    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<T: Output, S: Surfaces> {
 | 
						|
    output: T,
 | 
						|
    surfaces: S,
 | 
						|
    fps: RealTimeRunningAverage<u32>,
 | 
						|
    fps_display: Periodically,
 | 
						|
    frame: usize,
 | 
						|
    frame_count: usize
 | 
						|
}
 | 
						|
 | 
						|
impl<T: Output, S: Surfaces> Renderer<T, S> {
 | 
						|
    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<T: Output, S: Surfaces> Task for Renderer<T, S> {
 | 
						|
    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));
 | 
						|
        });
 | 
						|
    }
 | 
						|
} |