Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
5.3 kB · 169 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170#[cfg(feature = "gpu_scaling")]pub mod gpu;pub mod palettes;
use std::sync::Arc;
use winit::{dpi::PhysicalSize, event_loop::ActiveEventLoop, window::Window};
use crate::coordinates::WINDOW_SIZE as WINDOW_SIZE16;const WINDOW_SIZE: (usize, usize) = (WINDOW_SIZE16.0 as usize, WINDOW_SIZE16.1 as usize);use palettes::{Palette, RGB8};
#[cfg(not(any(feature = "gpu_scaling", feature = "soft_scaling")))]compile_error!("at least one of gpu_scaling or soft_scaling needs to be active");
#[expect( clippy::large_enum_variant, reason = "this doesn't get moved a lot, so it doesn't matter. If it's not in the enum i also don't box it")]#[cfg(all(feature = "gpu_scaling", feature = "soft_scaling"))]pub enum BothRenderBackend { GPU(GPURenderBackend), Soft(SoftRenderBackend),}
#[cfg(all(feature = "gpu_scaling", feature = "soft_scaling"))]impl BothRenderBackend { pub fn new(window: Arc<Window>, palette: Palette<RGB8>) -> Self { match GPURenderBackend::try_new(window.clone(), palette) { Ok(b) => Self::GPU(b), Err(e) => { eprintln!( "GPU render backend creation failed: {e}.\n\nFalling back to software scaling" ); Self::Soft(SoftRenderBackend::new(window, palette)) } } }
pub fn resize(&mut self, size: PhysicalSize<u32>) { match self { BothRenderBackend::GPU(b) => b.resize(size), BothRenderBackend::Soft(b) => b.resize(size), } }
pub fn render( &mut self, frame_buffer: &[[u8; WINDOW_SIZE.0]; WINDOW_SIZE.1], event_loop: &ActiveEventLoop, ) { match self { BothRenderBackend::GPU(b) => b.render(frame_buffer, event_loop), BothRenderBackend::Soft(b) => b.render(frame_buffer, event_loop), } }
pub fn get_size(&self) -> PhysicalSize<u32> { match self { BothRenderBackend::GPU(b) => b.get_size(), BothRenderBackend::Soft(b) => b.get_size(), } }}
#[cfg(feature = "gpu_scaling")]pub struct GPURenderBackend { backend: gpu::GPUState,}
#[cfg(feature = "gpu_scaling")]impl GPURenderBackend { fn try_new(window: Arc<Window>, palette: Palette<RGB8>) -> Result<Self, String> { let mut backend = smol::block_on(gpu::GPUState::new(window))?; backend.queue_palette_update(palette.into());
Ok(Self { backend }) }
pub fn new(window: Arc<Window>, palette: Palette<RGB8>) -> Self { Self::try_new(window, palette).unwrap() }
pub fn resize(&mut self, size: PhysicalSize<u32>) { self.backend.resize(size); }
pub fn render( &mut self, frame_buffer: &[[u8; WINDOW_SIZE.0]; WINDOW_SIZE.1], event_loop: &ActiveEventLoop, ) { match self.backend.render(frame_buffer) { Ok(_) => {} Err(wgpu::SurfaceError::Lost) => self.backend.reinit_surface(), Err(wgpu::SurfaceError::OutOfMemory) => event_loop.exit(), Err(e) => eprint!("{:?}", e), } }
pub fn get_size(&self) -> PhysicalSize<u32> { self.backend.size() }}
// softscaling is small enough to not have its own file / module#[cfg(feature = "soft_scaling")]pub struct SoftRenderBackend { backend: softbuffer::Surface<Arc<Window>, Arc<Window>>, width: u32, height: u32, palette: Palette<palettes::ZRGB>,}
#[cfg(feature = "soft_scaling")]impl SoftRenderBackend { pub fn new(window: Arc<Window>, palette: Palette<RGB8>) -> Self { let size = window.inner_size(); let context = softbuffer::Context::new(window.clone()).unwrap(); Self { backend: softbuffer::Surface::new(&context, window).unwrap(), width: size.width, height: size.height, palette: palette.into(), } }
pub fn resize(&mut self, size: PhysicalSize<u32>) { self.width = size.width; self.height = size.height; self.backend .resize( std::num::NonZeroU32::new(size.width).unwrap(), std::num::NonZeroU32::new(size.height).unwrap(), ) .unwrap() }
pub fn render( &mut self, frame_buffer: &[[u8; WINDOW_SIZE.0]; WINDOW_SIZE.1], _: &ActiveEventLoop, ) { let mut buffer = self.backend.buffer_mut().unwrap(); assert!(buffer.len() == usize::try_from(self.width * self.height).unwrap()); let x_step = WINDOW_SIZE.0 as f32 / self.width as f32; let y_step = WINDOW_SIZE.1 as f32 / self.height as f32; for (y_idx, row) in buffer .chunks_exact_mut(self.width.try_into().unwrap()) .enumerate() { for (x_idx, pixel) in row.iter_mut().enumerate() { let x_idx = x_idx as f32 * x_step; let y_idx = y_idx as f32 * y_step; *pixel = self .palette .get_raw(frame_buffer[y_idx.floor() as usize][x_idx.floor() as usize]); } } buffer.present().unwrap(); }
pub fn get_size(&self) -> PhysicalSize<u32> { PhysicalSize { width: self.width, height: self.height, } }}