adding plain sdl2 surface component

This commit is contained in:
lifning 2021-10-16 02:26:33 -07:00
parent b735e5f4e5
commit 26ff040136
6 changed files with 209 additions and 0 deletions

View File

@ -0,0 +1,112 @@
use std::cell::RefCell;
use std::os::raw::c_uint;
use std::rc::Rc;
use std::path::PathBuf;
use crate::prelude::*;
use crate::retro::ffi::*;
impl<T: RetroCallbacks> RetroCallbacks for Rc<RefCell<T>> {
fn video_refresh(&mut self, data: &[u8], width: c_uint, height: c_uint, pitch: c_uint) {
RefCell::borrow_mut(self).video_refresh(data, width, height, pitch)
}
fn video_refresh_dupe(&mut self, width: c_uint, height: c_uint, pitch: c_uint) {
RefCell::borrow_mut(self).video_refresh_dupe(width, height, pitch)
}
fn video_refresh_hw(&mut self, width: c_uint, height: c_uint) {
RefCell::borrow_mut(self).video_refresh_hw(width, height)
}
fn audio_sample(&mut self, left: i16, right: i16) {
RefCell::borrow_mut(self).audio_sample(left, right)
}
fn audio_sample_batch(&mut self, stereo_pcm: &[i16]) -> usize {
RefCell::borrow_mut(self).audio_sample_batch(stereo_pcm)
}
fn input_poll(&mut self) {
RefCell::borrow_mut(self).input_poll()
}
fn input_state(&mut self, port: u32, device: InputDeviceId, index: InputIndex) -> i16 {
RefCell::borrow_mut(self).input_state(port, device, index)
}
fn set_rotation(&mut self, rotation: EnvRotation) -> Option<bool> {
RefCell::borrow_mut(self).set_rotation(rotation)
}
fn get_overscan(&mut self) -> Option<bool> {
RefCell::borrow_mut(self).get_overscan()
}
fn set_message(&mut self, message: &Message) -> Option<bool> {
RefCell::borrow_mut(self).set_message(message)
}
fn shutdown(&mut self) -> Option<bool> {
RefCell::borrow_mut(self).shutdown()
}
fn set_performance_level(&mut self, level: c_uint) -> Option<bool> {
RefCell::borrow_mut(self).set_performance_level(level)
}
fn get_system_directory(&mut self) -> Option<PathBuf> {
RefCell::borrow_mut(self).get_system_directory()
}
fn set_pixel_format(&mut self, format: PixelFormat) -> Option<bool> {
RefCell::borrow_mut(self).set_pixel_format(format)
}
fn set_input_descriptors(&mut self, input_descriptors: &Vec<InputDescriptor2>) -> Option<bool> {
RefCell::borrow_mut(self).set_input_descriptors(input_descriptors)
}
fn set_hw_render(&mut self, hw_render_callback: &HwRenderCallback) -> Option<bool> {
RefCell::borrow_mut(self).set_hw_render(hw_render_callback)
}
fn get_variable(&mut self, key: &str) -> Option<String> {
RefCell::borrow_mut(self).get_variable(key)
}
fn set_variables(&mut self, variables: &Vec<Variable2>) -> Option<bool> {
RefCell::borrow_mut(self).set_variables(variables)
}
fn get_variable_update(&mut self) -> Option<bool> {
RefCell::borrow_mut(self).get_variable_update()
}
fn set_support_no_game(&mut self, supports_no_game: bool) -> Option<bool> {
RefCell::borrow_mut(self).set_support_no_game(supports_no_game)
}
fn get_libretro_path(&mut self) -> Option<PathBuf> {
RefCell::borrow_mut(self).get_libretro_path()
}
fn get_input_device_capabilities(&mut self) -> Option<u64> {
RefCell::borrow_mut(self).get_input_device_capabilities()
}
fn get_core_assets_directory(&mut self) -> Option<PathBuf> {
RefCell::borrow_mut(self).get_core_assets_directory()
}
fn get_save_directory(&mut self) -> Option<PathBuf> {
RefCell::borrow_mut(self).get_save_directory()
}
fn set_system_av_info(&mut self, system_av_info: &SystemAvInfo) -> Option<bool> {
RefCell::borrow_mut(self).set_system_av_info(system_av_info)
}
fn set_subsystem_info(&mut self, subsystem_info: &Vec<SubsystemInfo2>) -> Option<bool> {
RefCell::borrow_mut(self).set_subsystem_info(subsystem_info)
}
fn set_controller_info(&mut self, controller_info: &Vec<ControllerDescription2>) -> Option<bool> {
RefCell::borrow_mut(self).set_controller_info(controller_info)
}
fn set_memory_maps(&mut self, memory_map: &MemoryMap) -> Option<bool> {
RefCell::borrow_mut(self).set_memory_maps(memory_map)
}
fn set_geometry(&mut self, game_geometry: &GameGeometry) -> Option<bool> {
RefCell::borrow_mut(self).set_geometry(game_geometry)
}
fn get_username(&mut self) -> Option<String> {
RefCell::borrow_mut(self).get_username()
}
fn get_language(&mut self) -> Option<Language> {
RefCell::borrow_mut(self).get_language()
}
fn hw_get_current_framebuffer(&mut self) -> Option<usize> {
RefCell::borrow_mut(self).hw_get_current_framebuffer()
}
fn hw_get_proc_address(&mut self, sym: &str) -> Option<*const ()> {
RefCell::borrow_mut(self).hw_get_proc_address(sym)
}
// TODO: the rest, dynamically.
// can we proc macro it?
// 's~^\( *\)fn \(.*\)(&mut self\(, \)\?\([^)]*\))\(.*\){$~\1fn \2(\&mut self\3\4)\5{\n\1 RefCell::borrow_mut(self).\2(\4)~'
}

View File

@ -8,3 +8,5 @@ pub mod prelude {
pub use crate::retro::wrapper::{RetroCallbacks, LibretroWrapper, LibretroWrapperAccess};
pub use crate::retro::ffi::{PixelFormat, GameGeometry, HwContextResetFn, HwRenderCallback, SystemAvInfo, SystemInfo};
}
mod dynamic_borrow;

View File

@ -0,0 +1,33 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::path::Path;
use crate::base::ControlFlow;
use crate::base::RetroComponent;
use crate::base::Result;
use ferretro_base::prelude::*;
impl<T> RetroComponent for Rc<RefCell<T>> where
T: RetroComponent,
Rc<RefCell<T>>: RetroCallbacks,
{
fn pre_init(&mut self, retro: &mut LibretroWrapper) -> Result<()> {
RefCell::try_borrow_mut(self)?.pre_init(retro)
}
fn post_init(&mut self, retro: &mut LibretroWrapper) -> Result<()> {
RefCell::try_borrow_mut(self)?.post_init(retro)
}
fn pre_load_game(&mut self, retro: &mut LibretroWrapper, rom: &Path) -> Result<()> {
RefCell::try_borrow_mut(self)?.pre_load_game(retro, rom)
}
fn post_load_game(&mut self, retro: &mut LibretroWrapper, rom: &Path) -> Result<()> {
RefCell::try_borrow_mut(self)?.post_load_game(retro, rom)
}
fn pre_run(&mut self, retro: &mut LibretroWrapper) -> ControlFlow {
RefCell::borrow_mut(self).pre_run(retro)
}
fn post_run(&mut self, retro: &mut LibretroWrapper) -> ControlFlow {
RefCell::borrow_mut(self).post_run(retro)
}
}

View File

@ -8,3 +8,5 @@ pub mod prelude {
pub use ferretro_base::retro::wrapper::{RetroCallbacks, LibretroWrapper, LibretroWrapperAccess};
pub use ferretro_base::retro::ffi::{PixelFormat, GameGeometry, HwContextResetFn, HwRenderCallback, SystemAvInfo, SystemInfo, MemoryMap};
}
mod dynamic_borrow;

View File

@ -2,8 +2,10 @@ mod canvas;
mod audio;
mod gamepad;
mod opengl;
mod surface;
pub use canvas::SimpleSdl2CanvasComponent;
pub use opengl::SimpleSdl2OpenglComponent;
pub use audio::SimpleSdl2AudioComponent;
pub use gamepad::SimpleSdl2GamepadComponent;
pub use surface::Sdl2SurfaceComponent;

View File

@ -0,0 +1,58 @@
use crate::prelude::*;
use sdl2::surface::Surface;
pub struct Sdl2SurfaceComponent {
surface: Surface<'static>,
pixel_format: sdl2::pixels::PixelFormatEnum,
}
impl Sdl2SurfaceComponent {
pub fn new(retro: &LibretroWrapper) -> Result<Self, Box<dyn std::error::Error>> {
let geometry = retro.get_system_av_info().geometry;
let pixel_format = sdl2::pixels::PixelFormatEnum::ARGB1555;
let surface = Surface::new(
geometry.base_width,
geometry.base_height,
pixel_format,
)?;
Ok(Sdl2SurfaceComponent {
surface,
pixel_format,
})
}
pub fn surface(&self) -> &Surface {
&self.surface
}
}
impl RetroComponent for Sdl2SurfaceComponent {}
impl RetroCallbacks for Sdl2SurfaceComponent {
fn video_refresh(&mut self, data: &[u8], width: u32, height: u32, pitch: u32) {
let data = unsafe {
core::slice::from_raw_parts_mut(data.as_ptr() as *mut u8, data.len())
};
if let Ok(surf) = Surface::from_data(data, width, height, pitch, self.pixel_format) {
self.surface = surf;
}
}
fn set_pixel_format(&mut self, pix_fmt: PixelFormat) -> Option<bool> {
self.pixel_format = match pix_fmt {
PixelFormat::ARGB1555 => sdl2::pixels::PixelFormatEnum::RGB555,
PixelFormat::ARGB8888 => sdl2::pixels::PixelFormatEnum::ARGB8888,
PixelFormat::RGB565 => sdl2::pixels::PixelFormatEnum::RGB565,
};
Some(true)
}
fn get_variable(&mut self, key: &str) -> Option<String> {
match key {
"parallel-n64-gfxplugin" => Some("angrylion".to_string()),
_ => None,
}
}
}