From 291affc992beba3ff84e6635c2a21bb760a34212 Mon Sep 17 00:00:00 2001 From: Victoria Fischer Date: Sat, 16 Nov 2024 11:49:10 +0100 Subject: [PATCH] mappings: first implementation of surface mapping and pixel selection engine --- src/main.rs | 1 + src/mappings.rs | 259 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 src/mappings.rs diff --git a/src/main.rs b/src/main.rs index caee73a..55f0810 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ mod time; mod geometry; mod platform; mod animations; +mod mappings; use crate::platform::DisplayInit; use crate::render::Surfaces; diff --git a/src/mappings.rs b/src/mappings.rs new file mode 100644 index 0000000..6386126 --- /dev/null +++ b/src/mappings.rs @@ -0,0 +1,259 @@ +use crate::geometry::*; + +use crate::lib8::scale8; + +use std::cmp::max; +use std::fmt::{Formatter, Debug}; + +pub trait CoordinateView: Debug { + fn next(&mut self) -> Option<(VirtualCoordinates, PhysicalCoordinates)>; +} + +pub trait PixelMapping> { + fn select(&self, rect: &Rectangle) -> impl CoordinateView; +} + +#[derive(Debug)] +struct LinearCoordView { + rect: Rectangle, + idx: u8, +} + +impl CoordinateView for LinearCoordView { + fn next(&mut self) -> Option<(VirtualCoordinates, PhysicalCoordinates)> { + if self.idx == self.rect.bottom_right.x { + None + } else { + let virt = VirtualCoordinates::new(self.idx, 0); + let phys = PhysicalCoordinates::new(self.idx as usize, 0); + self.idx += 1; + return Some((virt, phys)) + } + } +} + +pub struct LinearPixelMapping { +} + +impl LinearPixelMapping { + pub fn new() -> Self { + Self {} + } +} + +impl PixelMapping for LinearPixelMapping { + fn select(&self, rect: &Rectangle) -> impl CoordinateView { + LinearCoordView { + rect: rect.clone(), + idx: 0, + } + } +} + +#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stride { + pub length: u8, + pub x: u8, + pub y: u8, + pub reverse: bool, + pub physical_idx: usize +} + +#[derive(Debug)] +pub struct StrideMapping { + pub strides: [Stride; STRIDE_NUM], + pub stride_count: usize, + pixel_count: usize, + top: u8, + left: u8, + height: u8, + width: u8 +} + +impl StrideMapping { + pub fn new() -> Self { + /*let stride_json = vec!( + (0, 0, 17), + (1, 0, 17), + (2, 0, 17), + (3, 0, 17), + (4, 0, 16), + (5, 0, 17), + (6, 0, 17), + (7, 0, 17), + (8, 0, 17), + (9, 0, 17), + (10, 0, 17), + (11, 0, 17), + (12, 0, 18), + (13, 0, 17), + (14, 0, 18), + (15, 0, 17), + (16, 0, 17), + (17, 0, 17) + );*/ + let stride_json = vec!( + (0, 0, 16, false), + (1, 0, 16, true), + (2, 0, 16, false), + (3, 0, 16, true), + (4, 0, 16, false), + (5, 0, 16, true), + (6, 0, 16, false), + (7, 0, 16, true), + (8, 0, 16, false), + (9, 0, 16, true), + (10, 0, 16, false), + (11, 0, 16, true), + (12, 0, 16, false), + (13, 0, 16, true), + (14, 0, 16, false), + (15, 0, 16, true), + ); + let mut strides = [Stride::default(); STRIDE_NUM]; + let stride_count = stride_json.len(); + let mut physical_idx = 0; + let mut height = 0; + let mut width = 0; + for stride_idx in 0..stride_count { + let json_data = stride_json[stride_idx]; + let x = json_data.0; + let y = json_data.1; + let length = json_data.2; + let reverse = json_data.3; + strides[stride_idx] = Stride { + length, + x, + y, + reverse, + physical_idx + }; + physical_idx += length as usize; + width = max(width, stride_idx + x as usize); + height = max(height, length as usize + y as usize) + } + let top = 0; + let left = 0; + + log::info!("strides={:?}", strides); + + Self { + strides, + stride_count, + pixel_count: physical_idx, + top, + left, + height: height as u8, + width: width as u8 + } + } +} + +impl PixelMapping for StrideMapping { + fn select(&self, rect: &Rectangle) -> impl CoordinateView { + let ret = StrideView::new(self, rect); + //log::info!("select={:?}", ret); + return ret; + } +} + +#[derive(Debug)] +struct StrideSpace {} +impl CoordinateSpace for StrideSpace {} + +type StrideCoords = Coordinates; + +struct StrideView<'a> { + map: &'a StrideMapping, + rect: Rectangle, + span_start: u8, + span_end: u8, + offset_start: u8, + offset_end: u8, + virt_step_width: u8, + virt_step_height: u8, + cur_pixel: StrideCoords +} + +impl<'a> Debug for StrideView<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("StrideView") + .field("rect", &self.rect) + .field("span", &(self.span_start, self.span_end)) + .field("offset", &(self.offset_start, self.offset_end)) + .field("step", &(self.virt_step_width, self.virt_step_height)) + .field("cur", &self.cur_pixel).finish() + } +} + +impl<'a> StrideView<'a> { + fn new(map: &'a StrideMapping, rect: &Rectangle) -> Self { + let span_start = scale8(rect.top_left.x, map.width); + let span_end = scale8(rect.bottom_right.x, map.width); + let offset_start = scale8(rect.top_left.y, map.height); + let offset_end = scale8(rect.bottom_right.y, map.height); + let virt_step_width = u8::MAX / std::cmp::max(1, span_end - span_start); + let virt_step_height = u8::MAX / std::cmp::max(1, offset_end - offset_start); + return Self { + map, + rect: rect.clone(), + span_start, + span_end, + offset_start, + offset_end, + virt_step_width, + virt_step_height, + cur_pixel: StrideCoords::new(span_start, offset_start) + }; + } +} + +impl<'a> CoordinateView for StrideView<'a> { + fn next(&mut self) -> Option<(VirtualCoordinates, PhysicalCoordinates)> { + let mut search_idx = self.cur_pixel.x; + let mut next_offset = self.cur_pixel.y + 1; + //log::info!("view={:?}", self); + + while search_idx <= self.span_end { + let cur = &self.map.strides[search_idx as usize]; + + if next_offset < self.offset_start || next_offset < cur.y { + search_idx += 1; + continue; + } + + if next_offset > cur.y + cur.length || next_offset > self.offset_end { + search_idx += 1; + if search_idx <= self.span_end { + next_offset = self.map.strides[search_idx as usize].y; + continue + } else { + //log::info!("search end"); + return None; + } + } + + self.cur_pixel = StrideCoords::new(search_idx, next_offset); + let virt = VirtualCoordinates::new( + (self.cur_pixel.x * self.virt_step_width).try_into().unwrap(), + ((self.cur_pixel.y - cur.y) * self.virt_step_height).try_into().unwrap() + ); + let stride_pos = StrideCoords::new(self.cur_pixel.x.try_into().unwrap(), (self.cur_pixel.y - cur.y).try_into().unwrap()); + + let span = &self.map.strides[stride_pos.x as usize]; + //log::info!("span={:?} stride={:?} cur={:?}", span, stride_pos, self.cur_pixel); + let phys_idx = if span.reverse { + span.physical_idx + (span.length - 1 - stride_pos.y) as usize + } else { + span.physical_idx + stride_pos.y as usize + }; + let phys = PhysicalCoordinates::new(phys_idx, 0); + //log::info!("virt={:?} phys={:?}", virt, phys); + return Some((virt, phys)); + } + + //log::info!("end"); + + return None; + } +}