use std::sync::{Arc, Mutex}; use crate::host::traits::{WindowUpdater, BlitableSurface}; pub const MASK_COLOUR: u32 = 0xFFFFFFFF; #[derive(Clone)] pub struct Frame { pub width: u32, pub height: u32, pub bitmap: Vec, } impl Frame { pub fn new(width: u32, height: u32) -> Self { Self { width, height, bitmap: vec![0; (width * height) as usize] } } pub fn new_shared(width: u32, height: u32) -> Arc> { Arc::new(Mutex::new(Frame::new(width, height))) } pub fn new_updater(frame: Arc>) -> Box { Box::new(FrameUpdateWrapper(frame)) } } impl BlitableSurface for Frame { fn set_size(&mut self, width: u32, height: u32) { self.width = width; self.height = height; self.bitmap.resize((width * height) as usize, 0); } fn set_pixel(&mut self, pos_x: u32, pos_y: u32, pixel: u32) { match pixel { MASK_COLOUR => { }, value if pos_x < self.width && pos_y < self.height => { self.bitmap[(pos_x + (pos_y * self.width)) as usize] = value; }, _ => { }, } } fn blit>(&mut self, pos_x: u32, pos_y: u32, mut bitmap: B, width: u32, height: u32) { for y in pos_y..(pos_y + height) { for x in pos_x..(pos_x + width) { match bitmap.next().unwrap() { MASK_COLOUR => { }, value if x < self.width && y < self.height => { self.bitmap[(x + (y * self.width)) as usize] = value; }, _ => { }, } } } } fn clear(&mut self, value: u32) { let value = if value == MASK_COLOUR { 0 } else { value }; for i in 0..((self.width as usize) * (self.height as usize)) { self.bitmap[i] = value; } } } pub struct FrameUpdateWrapper(Arc>); impl WindowUpdater for FrameUpdateWrapper { fn get_size(&mut self) -> (u32, u32) { match self.0.lock() { Ok(frame) => (frame.width, frame.height), _ => (0, 0), } } fn update_frame(&mut self, width: u32, _height: u32, bitmap: &mut [u32]) { if let Ok(frame) = self.0.lock() { for y in 0..frame.height { for x in 0..frame.width { bitmap[(x + (y * width)) as usize] = frame.bitmap[(x + (y * frame.width)) as usize]; } } } } } #[derive(Clone)] pub struct FrameSwapper { pub current: Arc>, pub previous: Arc>, } impl FrameSwapper { pub fn new(width: u32, height: u32) -> FrameSwapper { FrameSwapper { current: Arc::new(Mutex::new(Frame::new(width, height))), previous: Arc::new(Mutex::new(Frame::new(width, height))), } } pub fn to_boxed(swapper: FrameSwapper) -> Box { Box::new(swapper) } pub fn swap(&mut self) { std::mem::swap(&mut self.current.lock().unwrap().bitmap, &mut self.previous.lock().unwrap().bitmap); } pub fn set_size(&mut self, width: u32, height: u32) { self.previous.lock().unwrap().set_size(width, height); self.current.lock().unwrap().set_size(width, height); } } impl WindowUpdater for FrameSwapper { fn get_size(&mut self) -> (u32, u32) { if let Ok(frame) = self.current.lock() { (frame.width, frame.height) } else { (0, 0) } } fn update_frame(&mut self, width: u32, _height: u32, bitmap: &mut [u32]) { if let Ok(frame) = self.previous.lock() { for y in 0..frame.height { for x in 0..frame.width { bitmap[(x + (y * width)) as usize] = frame.bitmap[(x + (y * frame.width)) as usize]; } } } } }