From 9289a829be63e690604459af8e4f16eadfece1c3 Mon Sep 17 00:00:00 2001 From: Victoria Fischer Date: Fri, 29 Nov 2024 10:57:33 +0100 Subject: [PATCH] mappings: split coord mapping from pixel mapping --- src/mappings.rs | 75 +++++++--------------------------- src/platform/smart_leds_lib.rs | 65 +++++++++++++++++++---------- src/render.rs | 18 ++++++++ 3 files changed, 77 insertions(+), 81 deletions(-) diff --git a/src/mappings.rs b/src/mappings.rs index 28b689a..0b61836 100644 --- a/src/mappings.rs +++ b/src/mappings.rs @@ -4,55 +4,16 @@ use crate::lib8::interpolate::scale8; use std::cmp::{max, min}; use std::fmt::{Formatter, Debug}; -use ansi_term::Color; -use rgb::Rgb; -pub trait CoordinateView: Debug { +pub trait CoordinateView<'a>: Debug { type Space: CoordinateSpace; fn next(&mut self) -> Option<(Coordinates, Coordinates)>; } -pub trait PixelMapping { +pub trait Select<'a> { type Space: CoordinateSpace; - fn select(&self, rect: &Rectangle) -> impl CoordinateView; - fn to_idx(&self, coords: &Coordinates) -> usize; -} - -pub trait DisplayDump { - fn dump(&self, map: &T); -} - -impl DisplayDump for [Rgb; PIXEL_NUM] { - fn dump(&self, _map: &LinearPixelMapping) { - for ref pixel in self { - print!("{}", Color::RGB(pixel.r, pixel.g, pixel.b).paint("█")); - } - println!(); - } -} - -impl DisplayDump for [Rgb; PIXEL_NUM] { - fn dump(&self, map: &StrideMapping) { - for y in 0..map.stride_count { - let stride = &map.strides[y]; - for x in 0..stride.length { - let idx = if stride.reverse { - stride.physical_idx + stride.length as usize - x as usize - } else { - stride.physical_idx + x as usize - }; - if idx >= self.len() { - println!(); - println!("frame!!!"); - return; - } - let pixel = &self[idx]; - print!("{}", Color::RGB(pixel.r, pixel.g, pixel.b).paint("█")); - } - println!(); - } - println!("frame!!!"); - } + type View: CoordinateView<'a>; + fn select(&'a self, rect: &Rectangle) -> Self::View; } #[derive(Debug)] @@ -68,7 +29,7 @@ impl CoordinateSpace for LinearSpace { pub type LinearCoords = Coordinates; -impl CoordinateView for LinearCoordView { +impl<'a> CoordinateView<'a> for LinearCoordView { type Space = LinearSpace; fn next(&mut self) -> Option<(VirtualCoordinates, LinearCoords)> { if self.idx as u8 == self.rect.bottom_right.x { @@ -94,18 +55,15 @@ impl LinearPixelMapping { } } -impl PixelMapping for LinearPixelMapping { +impl<'a> Select<'a> for LinearPixelMapping { type Space = LinearSpace; - fn select(&self, rect: &Rectangle) -> impl CoordinateView { + type View = LinearCoordView; + fn select(&'a self, rect: &Rectangle) -> Self::View { LinearCoordView { rect: rect.clone(), idx: 0, } } - - fn to_idx(&self, coords: &Coordinates) -> usize { - coords.x - } } #[derive(Default, Clone, Copy, Debug, PartialEq, Eq)] @@ -190,7 +148,7 @@ impl StrideMapping { let mut strides = [Stride::default(); STRIDE_NUM]; let stride_count = stride_json.len(); let mut physical_idx = 0; - let mut size: Option> = None;//Rectangle::new(Coordinates::new(usize::MAX, usize::MAX), Coordinates::new(0, 0)); + let mut size: Option> = None; for stride_idx in 0..stride_count { let json_data = stride_json[stride_idx]; let x = json_data.0; @@ -237,15 +195,12 @@ impl StrideMapping { } } -impl PixelMapping for StrideMapping { +impl<'a> Select<'a> for StrideMapping { type Space = StrideSpace; - fn select(&self, rect: &Rectangle) -> impl CoordinateView { + type View = StrideView<'a>; + fn select(&'a self, rect: &Rectangle) -> Self::View { StrideView::new(self, rect) } - - fn to_idx(&self, coords: &Coordinates) -> usize { - self.strides[coords.x as usize].pixel_idx_for_offset(coords.y) - } } #[derive(Debug, Clone, Copy)] @@ -255,8 +210,8 @@ impl CoordinateSpace for StrideSpace { } pub type StrideCoords = Coordinates; -struct StrideView<'a> { - map: &'a StrideMapping, +pub struct StrideView<'a> { + pub map: &'a StrideMapping, range: Rectangle, cur: StrideCoords, step_size: VirtualCoordinates @@ -310,7 +265,7 @@ impl<'a> StrideView<'a> { } } -impl<'a> CoordinateView for StrideView<'a> { +impl<'a> CoordinateView<'a> for StrideView<'a> { type Space = StrideSpace; fn next(&mut self) -> Option<(VirtualCoordinates, StrideCoords)> { // Keep scanning until we reach the far right of the range diff --git a/src/platform/smart_leds_lib.rs b/src/platform/smart_leds_lib.rs index 189a55d..6063b1a 100644 --- a/src/platform/smart_leds_lib.rs +++ b/src/platform/smart_leds_lib.rs @@ -1,8 +1,7 @@ use smart_leds_trait::SmartLedsWrite; -use crate::lib8::Rgb8Blend; use crate::lib8::interpolate::Fract8Ops; -use crate::render::{Surface, Display, Surfaces}; +use crate::render::{Display, HardwarePixel, PixelView, Sample, Surface, Surfaces}; use crate::buffers::SurfacePool; use crate::power::{brightness_for_mw, AsMilliwatts}; use crate::geometry::*; @@ -10,13 +9,8 @@ use crate::mappings::*; use std::fmt::{Debug, Formatter}; use std::io; - -use rgb::Rgb; use std::ops::IndexMut; -pub trait HardwarePixel: Send + Sync + Rgb8Blend + Copy + AsMilliwatts + Default + From> + Fract8Ops {} -impl HardwarePixel for T where T: Send + Sync + Rgb8Blend + Copy + AsMilliwatts + Default + From> + Fract8Ops {} - pub trait Pixbuf: AsMilliwatts + IndexMut { type Pixel: HardwarePixel; fn new() -> Self; @@ -24,6 +18,38 @@ pub trait Pixbuf: AsMilliwatts + IndexMut { fn iter_with_brightness(&self, brightness: u8) -> impl Iterator + Send; } +struct StrideSampler<'a, P: Pixbuf> { + pixbuf: &'a mut P, + selection: StrideView<'a> +} + +impl<'a, P: Pixbuf> PixelView for StrideSampler<'a, P> { + type Pixel = P::Pixel; + fn next(&mut self) -> Option<(Coordinates, &mut Self::Pixel)> { + if let Some((virt, coords)) = self.selection.next() { + let idx = self.selection.map.strides[coords.x as usize].pixel_idx_for_offset(coords.y); + Some((virt, &mut self.pixbuf[idx])) + } else { + None + } + } +} + +struct StrideOutput { + pixbuf: P, + stride_map: StrideMapping +} + +impl Sample for StrideOutput

{ + type Pixel = P::Pixel; + fn sample(&mut self, rect: &Rectangle) -> impl PixelView { + StrideSampler { + pixbuf: &mut self.pixbuf, + selection: self.stride_map.select(rect) + } + } +} + impl Pixbuf for [T; PIXEL_NUM] { type Pixel = T; fn new() -> Self { @@ -41,9 +67,8 @@ impl Pixbuf for [T; PIXEL_NUM] { struct SmartLedDisplay> { surfaces : Option>, - pixmap: StrideMapping, + output: StrideOutput

, target: T, - pixbuf: P, max_mw: u32, frame: usize } @@ -51,7 +76,7 @@ struct SmartLedDisplay> { impl> Debug for SmartLedDisplay { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { f.debug_struct("SmartLedDisplay") - .field("total_mw", &self.pixbuf.as_milliwatts()) + .field("total_mw", &self.output.pixbuf.as_milliwatts()) .field("surfaces", &self.surfaces) .finish() } @@ -60,11 +85,10 @@ impl> Debug for SmartLedDi impl> SmartLedDisplay { fn new(target: T, max_mw: u32, pixmap: StrideMapping, pixbuf: P) -> Self { SmartLedDisplay { - pixbuf, + output: StrideOutput { pixbuf: pixbuf, stride_map: pixmap }, surfaces: Some(SurfacePool::new()), target, max_mw, - pixmap, frame: 0 } } @@ -88,20 +112,19 @@ T: FastWrite, S: Surface, P: Pixbuf { fn start_frame(&mut self) { - self.pixbuf.blank(); + self.output.pixbuf.blank(); } fn render_frame(&mut self) { let surfaces = self.surfaces.take().unwrap(); for surface in surfaces.iter() { - let rect = surface.rect().clone(); - let mut sel = self.pixmap.select(&rect); + let rect = surface.rect(); let opacity = surface.opacity(); if opacity > 0 { + let mut sample = self.output.sample(&rect); surface.with_shader(|shader| { - while let Some((virt_coords, phys_coords)) = sel.next() { - let idx = self.pixmap.to_idx(&phys_coords); - self.pixbuf[idx] = self.pixbuf[idx].blend8(shader.draw(&virt_coords, self.frame).into(), opacity); + while let Some((virt_coords, pixel)) = sample.next() { + *pixel = pixel.blend8(shader.draw(&virt_coords, self.frame).into(), opacity); } }) } @@ -110,10 +133,10 @@ P: Pixbuf { } fn end_frame(&mut self) { - let b = brightness_for_mw(self.pixbuf.as_milliwatts(), 255, self.max_mw); - if let Err(_) = self.target.fast_write(self.pixbuf.iter_with_brightness(b)) { + let b = brightness_for_mw(self.output.pixbuf.as_milliwatts(), 255, self.max_mw); + if self.target.fast_write(self.output.pixbuf.iter_with_brightness(b)).is_err() { panic!("Could not write frame!"); - } + }; self.frame += 1; } } diff --git a/src/render.rs b/src/render.rs index 5ebb2fe..df2b565 100644 --- a/src/render.rs +++ b/src/render.rs @@ -2,12 +2,30 @@ use std::io; use rgb::Rgb; use crate::geometry::*; +use crate::lib8::Rgb8Blend; +use crate::lib8::interpolate::Fract8Ops; +use crate::power::AsMilliwatts; use crate::task::Task; use crate::time::Periodically; use running_average::RealTimeRunningAverage; use std::marker::PhantomData; use std::fmt::Debug; +pub trait HardwarePixel: Send + Sync + Rgb8Blend + Copy + AsMilliwatts + Default + From> + Fract8Ops {} +impl HardwarePixel for T where T: Send + Sync + Rgb8Blend + 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 + Debug { fn draw(&self, surface_coords: &VirtualCoordinates, frame: usize) -> Rgb; }