scale framebuffer in place

This commit is contained in:
Alex Janka 2023-03-09 11:52:24 +11:00
parent 66f7518bb0
commit 52fe997e28
2 changed files with 37 additions and 12 deletions

View file

@ -8,7 +8,7 @@ use baseview::{
}; };
use gb_emu_lib::{ use gb_emu_lib::{
connect::{JoypadButtons, JoypadState, Renderer, HEIGHT, WIDTH}, connect::{JoypadButtons, JoypadState, Renderer, HEIGHT, WIDTH},
util::scale_buffer, util::scale_buffer_in_place,
}; };
use keyboard_types::{Code, KeyState}; use keyboard_types::{Code, KeyState};
use nih_plug::prelude::*; use nih_plug::prelude::*;
@ -74,6 +74,7 @@ impl Editor for Emulator {
pub struct EmulatorWindow { pub struct EmulatorWindow {
pix: Pixels, pix: Pixels,
scale: usize, scale: usize,
scaled_buf: Vec<[u8; 4]>,
frame_receiver: Arc<FrameReceiver>, frame_receiver: Arc<FrameReceiver>,
joypad_sender: Arc<JoypadSender>, joypad_sender: Arc<JoypadSender>,
} }
@ -86,20 +87,22 @@ impl EmulatorWindow {
) -> Self { ) -> Self {
let info = WindowInfo::from_logical_size(Size::new(WIDTH as f64, HEIGHT as f64), 1.); 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 { Self {
pix, pix,
scale, scale,
scaled_buf,
frame_receiver, frame_receiver,
joypad_sender, 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 physical_size = info.physical_size();
let scale = (physical_size.width as usize / WIDTH).min(physical_size.height as usize / HEIGHT); 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( pixels::Pixels::new(
physical_size.width, physical_size.width,
@ -108,21 +111,24 @@ fn init_pixbuf(info: WindowInfo, window: &mut Window) -> (Pixels, usize) {
) )
.unwrap(), .unwrap(),
scale, scale,
scaled_buf,
) )
} }
impl WindowHandler for EmulatorWindow { impl WindowHandler for EmulatorWindow {
fn on_frame(&mut self, _window: &mut Window) { 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(ref mut receiver) = *self.frame_receiver.lock().expect("failed to lock mutex") {
if let Some(buf) = receiver.try_iter().last() { if let Some(ref buf) = receiver.try_iter().last() {
let scaled_buf = if self.scale != 1 { if self.scale != 1 {
scale_buffer(&buf, WIDTH, HEIGHT, self.scale) scale_buffer_in_place(buf, &mut self.scaled_buf, WIDTH, HEIGHT, self.scale);
} else { }
buf for (pixel, source) in self
}; .pix
for (pixel, source) in self.pix.get_frame_mut().chunks_exact_mut(4).zip(scaled_buf) .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(); self.pix.render().unwrap();
} }
@ -132,7 +138,7 @@ impl WindowHandler for EmulatorWindow {
fn on_event(&mut self, window: &mut Window, event: baseview::Event) -> EventStatus { fn on_event(&mut self, window: &mut Window, event: baseview::Event) -> EventStatus {
match event { match event {
Event::Window(WindowEvent::Resized(info)) => { 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 EventStatus::Captured
} }
Event::Keyboard(event) => { Event::Keyboard(event) => {

View file

@ -143,3 +143,22 @@ pub fn scale_buffer<T: From<Colour> + Copy>(
} }
v v
} }
pub fn scale_buffer_in_place<T: From<Colour> + 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];
}
}
}
}
}