From 52fe997e286d84d4496748cb1002bc19b25e32b5 Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Thu, 9 Mar 2023 11:52:24 +1100 Subject: [PATCH] scale framebuffer in place --- gb-vst/src/ui.rs | 30 ++++++++++++++++++------------ lib/src/util.rs | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/gb-vst/src/ui.rs b/gb-vst/src/ui.rs index f00f6b7..9be2fc0 100644 --- a/gb-vst/src/ui.rs +++ b/gb-vst/src/ui.rs @@ -8,7 +8,7 @@ use baseview::{ }; use gb_emu_lib::{ connect::{JoypadButtons, JoypadState, Renderer, HEIGHT, WIDTH}, - util::scale_buffer, + util::scale_buffer_in_place, }; use keyboard_types::{Code, KeyState}; use nih_plug::prelude::*; @@ -74,6 +74,7 @@ impl Editor for Emulator { pub struct EmulatorWindow { pix: Pixels, scale: usize, + scaled_buf: Vec<[u8; 4]>, frame_receiver: Arc, joypad_sender: Arc, } @@ -86,20 +87,22 @@ impl EmulatorWindow { ) -> Self { let info = WindowInfo::from_logical_size(Size::new(WIDTH as f64, HEIGHT as f64), 1.); - let (pix, scale) = init_pixbuf(info, window); + let (pix, scale, scaled_buf) = init_pixbuf(info, window); Self { pix, scale, + scaled_buf, frame_receiver, joypad_sender, } } } -fn init_pixbuf(info: WindowInfo, window: &mut Window) -> (Pixels, usize) { +fn init_pixbuf(info: WindowInfo, window: &mut Window) -> (Pixels, usize, Vec<[u8; 4]>) { let physical_size = info.physical_size(); let scale = (physical_size.width as usize / WIDTH).min(physical_size.height as usize / HEIGHT); + let scaled_buf = vec![[0, 0, 0, 0xFF]; WIDTH * scale * HEIGHT * scale]; ( pixels::Pixels::new( physical_size.width, @@ -108,21 +111,24 @@ fn init_pixbuf(info: WindowInfo, window: &mut Window) -> (Pixels, usize) { ) .unwrap(), scale, + scaled_buf, ) } impl WindowHandler for EmulatorWindow { fn on_frame(&mut self, _window: &mut Window) { if let Some(ref mut receiver) = *self.frame_receiver.lock().expect("failed to lock mutex") { - if let Some(buf) = receiver.try_iter().last() { - let scaled_buf = if self.scale != 1 { - scale_buffer(&buf, WIDTH, HEIGHT, self.scale) - } else { - buf - }; - for (pixel, source) in self.pix.get_frame_mut().chunks_exact_mut(4).zip(scaled_buf) + if let Some(ref buf) = receiver.try_iter().last() { + if self.scale != 1 { + scale_buffer_in_place(buf, &mut self.scaled_buf, WIDTH, HEIGHT, self.scale); + } + for (pixel, source) in self + .pix + .get_frame_mut() + .chunks_exact_mut(4) + .zip(&self.scaled_buf) { - pixel.copy_from_slice(&source); + pixel.copy_from_slice(source); } self.pix.render().unwrap(); } @@ -132,7 +138,7 @@ impl WindowHandler for EmulatorWindow { fn on_event(&mut self, window: &mut Window, event: baseview::Event) -> EventStatus { match event { Event::Window(WindowEvent::Resized(info)) => { - (self.pix, self.scale) = init_pixbuf(info, window); + (self.pix, self.scale, self.scaled_buf) = init_pixbuf(info, window); EventStatus::Captured } Event::Keyboard(event) => { diff --git a/lib/src/util.rs b/lib/src/util.rs index eeda7bc..318df82 100644 --- a/lib/src/util.rs +++ b/lib/src/util.rs @@ -143,3 +143,22 @@ pub fn scale_buffer + Copy>( } v } + +pub fn scale_buffer_in_place + Copy>( + buffer: &[T], + target: &mut [T], + width: usize, + height: usize, + factor: usize, +) { + for y in 0..height { + for y_2 in 0..factor { + for x in 0..width { + for x_2 in 0..factor { + target[(((y * factor) + y_2) * (width * factor)) + (x * factor) + x_2] = + buffer[(y * width) + x]; + } + } + } + } +}