From 709a23307a03853bd89c778bad8eaec42fcd745c Mon Sep 17 00:00:00 2001 From: lifning <> Date: Sat, 11 Dec 2021 01:38:48 -0800 Subject: [PATCH] fix a couple minor sdl a/v bugs --- .../src/provided/sdl2/audio.rs | 30 +++++++++-------- .../src/provided/sdl2/canvas.rs | 33 ++++++++++++------- .../src/provided/sdl2/opengl.rs | 11 +++++-- 3 files changed, 47 insertions(+), 27 deletions(-) diff --git a/ferretro_components/src/provided/sdl2/audio.rs b/ferretro_components/src/provided/sdl2/audio.rs index 251cefd..96c19bc 100644 --- a/ferretro_components/src/provided/sdl2/audio.rs +++ b/ferretro_components/src/provided/sdl2/audio.rs @@ -69,21 +69,25 @@ impl RetroComponent for SimpleSdl2AudioComponent { } fn post_run(&mut self, _retro: &mut LibretroWrapper) -> ControlFlow { - match Self::make_converter(self.src_freq, self.queue.spec()) { - Ok(converter) => { - if !self.audio_buffer.is_empty() { - let mut samples = std::mem::take(&mut self.audio_buffer); - samples = resample(&converter, samples); - self.audio_buffer = samples; - self.queue.queue(&self.audio_buffer); - self.audio_buffer.clear(); + if self.src_freq != 0.0 { + match Self::make_converter(self.src_freq, self.queue.spec()) { + Ok(converter) => { + if !self.audio_buffer.is_empty() { + let mut samples = std::mem::take(&mut self.audio_buffer); + samples = resample(&converter, samples); + self.audio_buffer = samples; + self.queue.queue(&self.audio_buffer); + self.audio_buffer.clear(); + } + ControlFlow::Continue + } + Err(e) => { + eprintln!("Audio sample rate conversion failed: {:?}", e); + ControlFlow::Break } - ControlFlow::Continue - } - Err(e) => { - eprintln!("Audio sample rate conversion failed: {:?}", e); - ControlFlow::Break } + } else { + ControlFlow::Continue } } } diff --git a/ferretro_components/src/provided/sdl2/canvas.rs b/ferretro_components/src/provided/sdl2/canvas.rs index a0c1d70..0a219a7 100644 --- a/ferretro_components/src/provided/sdl2/canvas.rs +++ b/ferretro_components/src/provided/sdl2/canvas.rs @@ -4,6 +4,7 @@ use std::ffi::CStr; use std::path::Path; use sdl2::Sdl; +use sdl2::pixels::PixelFormatEnum; use sdl2::render::WindowCanvas; use sdl2::video::FullscreenType; @@ -45,19 +46,27 @@ pub(crate) fn sdl2_pixfmt(retro_fmt: PixelFormat) -> sdl2::pixels::PixelFormatEn } pub(crate) fn frame_to_surface<'a>(frame: &'a VideoFrame) -> crate::base::Result> { - let (bytes, pitch) = frame.data_pitch_as_bytes().unwrap(); let (width, height) = frame.dimensions(); - let pixel_format = frame - .pixel_format() - .map(sdl2_pixfmt) - .ok_or("Unknown pixel format")?; - // dirty, but must be &mut for SDL API. - // safe as long as we don't offer a &mut Surface in the public API. - let data = unsafe { - core::slice::from_raw_parts_mut(bytes.as_ptr() as *mut u8, bytes.len()) - }; - sdl2::surface::Surface::from_data(data, width, height, pitch as u32, pixel_format) - .map_err(Into::into) + if let Some((bytes, pitch)) = frame.data_pitch_as_bytes() { + let pixel_format = frame + .pixel_format() + .map(sdl2_pixfmt) + .ok_or("Unknown pixel format")?; + // dirty, but must be &mut for SDL API. + // safe as long as we don't offer a &mut Surface in the public API. + let data = unsafe { + core::slice::from_raw_parts_mut(bytes.as_ptr() as *mut u8, bytes.len()) + }; + sdl2::surface::Surface::from_data(data, width, height, pitch as u32, pixel_format) + .map_err(Into::into) + } else { + let pixel_format = frame + .pixel_format() + .map(sdl2_pixfmt) + .unwrap_or(PixelFormatEnum::ARGB8888); + sdl2::surface::Surface::new(width, height, pixel_format) + .map_err(Into::into) + } } /// Creates a root window in SDL2, then displays each 2D video frame provided by the core diff --git a/ferretro_components/src/provided/sdl2/opengl.rs b/ferretro_components/src/provided/sdl2/opengl.rs index df9efa3..34fd24f 100644 --- a/ferretro_components/src/provided/sdl2/opengl.rs +++ b/ferretro_components/src/provided/sdl2/opengl.rs @@ -5,6 +5,7 @@ use std::os::raw::c_uint; use std::path::Path; use sdl2::Sdl; +use sdl2::rect::Rect; use sdl2::render::WindowCanvas; use sdl2::video::FullscreenType; @@ -100,7 +101,6 @@ impl RetroComponent for SimpleSdl2OpenglComponent { rom.file_stem().unwrap_or_default().to_string_lossy(), ); self.canvas.window_mut().set_title(&title)?; - self.canvas.window_mut().show(); self.set_geometry(&retro.get_system_av_info().geometry); Ok(()) } @@ -108,14 +108,21 @@ impl RetroComponent for SimpleSdl2OpenglComponent { impl RetroCallbacks for SimpleSdl2OpenglComponent { fn video_refresh(&mut self, frame: &VideoFrame) { + self.canvas.window_mut().show(); + let output_size = self.canvas.output_size().unwrap(); match frame { VideoFrame::HardwareRender { .. } => { + if output_size != self.win_size { + let (w, h) = output_size; + // FIXME: this isn't enough - need core to render to texture that we just scale + self.canvas.set_viewport(Rect::new(0, 0, w, h)); + self.win_size = output_size; + } self.canvas.present(); unsafe { (self.glClear)(gl::COLOR_BUFFER_BIT); } } VideoFrame::Duplicate { .. } => {} _ => { - let output_size = self.canvas.output_size().unwrap(); if output_size != self.win_size { self.canvas.clear(); self.win_size = output_size;