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"
version = "0.3.3"
dependencies = [
"bytemuck",
"clap",
"cpal",
"ctrlc",

View file

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