This commit is contained in:
Alex Janka 2023-09-28 15:43:55 +10:00
parent a925944010
commit 14046462d8
3 changed files with 40 additions and 47 deletions

1
Cargo.lock generated
View file

@ -1103,6 +1103,7 @@ dependencies = [
name = "gb-emu" name = "gb-emu"
version = "0.3.3" version = "0.3.3"
dependencies = [ dependencies = [
"bytemuck",
"clap", "clap",
"cpal", "cpal",
"ctrlc", "ctrlc",

View file

@ -14,8 +14,11 @@ gilrs = "0.10"
cpal = "0.15" cpal = "0.15"
futures = "0.3" futures = "0.3"
ctrlc = "3.2.5" ctrlc = "3.2.5"
nokhwa = { version = "0.10.3", features = ["input-avfoundation"], optional = true } nokhwa = { version = "0.10.3", features = [
"input-avfoundation",
], optional = true }
send_wrapper = { version = "0.6.0", optional = true } send_wrapper = { version = "0.6.0", optional = true }
winit = "0.28" winit = "0.28"
winit_input_helper = "0.14" winit_input_helper = "0.14"
pixels = "0.12" pixels = "0.12"
bytemuck = "1.13"

View file

@ -3,10 +3,7 @@ use std::{
sync::{mpsc::Sender, Arc, Mutex}, sync::{mpsc::Sender, Arc, Mutex},
}; };
use gb_emu_lib::{ use gb_emu_lib::connect::{EmulatorMessage, JoypadState, Renderer};
connect::{EmulatorMessage, JoypadState, Renderer},
util::scale_buffer_in_place,
};
use gilrs::{ use gilrs::{
ff::{BaseEffect, BaseEffectType, EffectBuilder, Replay, Ticks}, ff::{BaseEffect, BaseEffectType, EffectBuilder, Replay, Ticks},
Button, Gilrs, Button, Gilrs,
@ -23,17 +20,16 @@ use winit_input_helper::WinitInputHelper;
pub struct WindowInfo { pub struct WindowInfo {
id: WindowId, id: WindowId,
data: Arc<WindowData>, data: Arc<Mutex<WindowData>>,
} }
pub struct WindowData { pub struct WindowData {
scaled_buf: Mutex<Vec<[u8; 4]>>, pixels: Pixels,
pixels: Mutex<Pixels>,
} }
pub struct WindowManager { pub struct WindowManager {
event_loop: EventLoop<()>, event_loop: EventLoop<()>,
windows: HashMap<WindowId, Arc<WindowData>>, windows: HashMap<WindowId, Arc<Mutex<WindowData>>>,
input: Arc<Mutex<WinitInputHelper>>, input: Arc<Mutex<WinitInputHelper>>,
sender: Sender<EmulatorMessage>, sender: Sender<EmulatorMessage>,
} }
@ -78,13 +74,8 @@ impl WindowManager {
} }
Event::RedrawRequested(window_id) => { Event::RedrawRequested(window_id) => {
if let Some(w) = self.windows.get(&window_id) { if let Some(w) = self.windows.get(&window_id) {
if let Ok(scaled_buf) = w.scaled_buf.lock() && let Ok(mut pixels) = w.pixels.lock() { if let Ok(data) = w.lock() {
for (pixel, source) in data.pixels.render().unwrap();
pixels.frame_mut().chunks_exact_mut(4).zip(scaled_buf.iter())
{
pixel.copy_from_slice(source);
}
pixels.render().unwrap();
} }
} }
} }
@ -97,7 +88,7 @@ impl WindowManager {
pub struct WindowRenderer { pub struct WindowRenderer {
window: Window, window: Window,
input: Arc<Mutex<WinitInputHelper>>, input: Arc<Mutex<WinitInputHelper>>,
data: Arc<WindowData>, data: Arc<Mutex<WindowData>>,
width: usize, width: usize,
height: usize, height: usize,
factor: usize, factor: usize,
@ -124,21 +115,12 @@ impl WindowRenderer {
let pixels = { let pixels = {
let window_size = window.inner_size(); let window_size = window.inner_size();
let surface_texture = let width = window_size.width / (real_factor as u32);
SurfaceTexture::new(window_size.width, window_size.height, &window); let height = window_size.height / (real_factor as u32);
pixels::PixelsBuilder::new(window_size.width, window_size.height, surface_texture) new_pixels(width, height, real_factor as u32, &window)
.request_adapter_options(pixels::wgpu::RequestAdapterOptionsBase {
power_preference: pixels::wgpu::PowerPreference::HighPerformance,
..pixels::wgpu::RequestAdapterOptionsBase::default()
})
.build()
.unwrap()
}; };
let data = Arc::new(WindowData { let data = Arc::new(Mutex::new(WindowData { pixels }));
scaled_buf: Mutex::new(Vec::new()),
pixels: Mutex::new(pixels),
});
let info = WindowInfo { let info = WindowInfo {
id: window.id(), id: window.id(),
data: data.clone(), data: data.clone(),
@ -172,28 +154,23 @@ impl Renderer<[u8; 4]> for WindowRenderer {
let h = (height * self.real_factor) as u32; let h = (height * self.real_factor) as u32;
self.window.set_inner_size(PhysicalSize::new(w, h)); self.window.set_inner_size(PhysicalSize::new(w, h));
if let Ok(mut scaled_buf) = self.data.scaled_buf.lock() && let Ok(mut pixels) = self.data.pixels.lock() {
*pixels = {
let window_size = self.window.inner_size();
let surface_texture =
SurfaceTexture::new(window_size.width, window_size.height, &self.window);
Pixels::new(window_size.width, window_size.height, surface_texture).unwrap()
};
scaled_buf.resize((w * h) as usize, [0; 4]); if let Ok(mut data) = self.data.lock() {
data.pixels = new_pixels(
width as u32,
height as u32,
self.real_factor as u32,
&self.window,
);
} }
self.window.request_redraw(); self.window.request_redraw();
} }
fn display(&mut self, buffer: &[[u8; 4]]) { fn display(&mut self, buffer: &[[u8; 4]]) {
if let Ok(mut scaled_buf) = self.data.scaled_buf.lock() { if let Ok(mut data) = self.data.lock() {
scale_buffer_in_place( data.pixels
buffer, .frame_mut()
&mut scaled_buf, .copy_from_slice(bytemuck::cast_slice(buffer));
self.width,
self.height,
self.real_factor,
);
} }
self.window.request_redraw(); self.window.request_redraw();
} }
@ -281,3 +258,15 @@ impl Renderer<[u8; 4]> for WindowRenderer {
} }
} }
} }
fn new_pixels(width: u32, height: u32, scaling: u32, window: &Window) -> Pixels {
let surface_texture: SurfaceTexture<'_, Window> =
SurfaceTexture::new(width * scaling, height * scaling, window);
pixels::PixelsBuilder::new(width, height, surface_texture)
.request_adapter_options(pixels::wgpu::RequestAdapterOptionsBase {
power_preference: pixels::wgpu::PowerPreference::HighPerformance,
..pixels::wgpu::RequestAdapterOptionsBase::default()
})
.build()
.unwrap()
}