round out a bit more of camera support
This commit is contained in:
parent
bbee2b95dd
commit
fd2eb03c07
|
@ -1,13 +1,14 @@
|
|||
use core::convert::{TryFrom, TryInto};
|
||||
use core::mem::size_of;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::os::raw::{c_uint};
|
||||
use std::slice::from_raw_parts;
|
||||
|
||||
use super::constants::*;
|
||||
use super::ffi::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum VideoFrame<'a> {
|
||||
XRGB1555 { data: &'a [u16], width: c_uint, height: c_uint, pitch_u16: usize },
|
||||
RGB565 { data: &'a [u16], width: c_uint, height: c_uint, pitch_u16: usize },
|
||||
|
@ -54,6 +55,44 @@ impl<'a> VideoFrame<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Debug for VideoFrame<'a> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
VideoFrame::XRGB1555 { data, width, height, pitch_u16 } => {
|
||||
write!(
|
||||
f,
|
||||
"XRGB1555 {{ data: &[u16; {}], width: {}, height: {}, pitch_u16: {} }}",
|
||||
data.len(), width, height, pitch_u16
|
||||
)
|
||||
}
|
||||
VideoFrame::RGB565 { data, width, height, pitch_u16 } => {
|
||||
write!(
|
||||
f,
|
||||
"RGB565 {{ data: &[u16; {}], width: {}, height: {}, pitch_u16: {} }}",
|
||||
data.len(), width, height, pitch_u16
|
||||
)
|
||||
}
|
||||
VideoFrame::XRGB8888 { data, width, height, pitch_u32 } => {
|
||||
write!(
|
||||
f,
|
||||
"XRGB8888 {{ data: &[u32; {}], width: {}, height: {}, pitch_u32: {} }}",
|
||||
data.len(), width, height, pitch_u32
|
||||
)
|
||||
}
|
||||
VideoFrame::Duplicate { width, height, pitch_u8 } => {
|
||||
write!(
|
||||
f,
|
||||
"Duplicate {{ width: {}, height: {}, pitch_u8: {} }}",
|
||||
width, height, pitch_u8
|
||||
)
|
||||
}
|
||||
VideoFrame::HardwareRender { width, height } => {
|
||||
write!(f, "HardwareRender {{ width: {}, height: {} }}", width, height)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum InputDeviceId {
|
||||
None(c_uint),
|
||||
|
|
|
@ -574,8 +574,8 @@ impl StaticCallbacks {
|
|||
}
|
||||
EnvCmd::GetCameraInterface => {
|
||||
let cc: &mut CameraCallback = Self::from_void(data)?;
|
||||
let gl_tex = (cc.caps & 1 << (CameraBuffer::OpenGLTexture as u64)) != 0;
|
||||
let raw_fb = (cc.caps & 1 << (CameraBuffer::RawFramebuffer as u64)) != 0;
|
||||
let cap_gl_tex = (cc.caps & 1 << (CameraBuffer::OpenGLTexture as u64)) != 0;
|
||||
let cap_raw_fb = (cc.caps & 1 << (CameraBuffer::RawFramebuffer as u64)) != 0;
|
||||
let wrapper = handler.libretro_core();
|
||||
if !(cc.frame_raw_framebuffer as *const ()).is_null() {
|
||||
wrapper.camera_frame_raw_framebuffer_cb.replace(cc.frame_raw_framebuffer);
|
||||
|
@ -591,7 +591,8 @@ impl StaticCallbacks {
|
|||
}
|
||||
cc.start = Self::camera_start;
|
||||
cc.stop = Self::camera_stop;
|
||||
handler.get_camera_interface(cc.width, cc.height, gl_tex, raw_fb)?
|
||||
handler.get_camera_interface(cc.width, cc.height, cap_raw_fb, cap_gl_tex)
|
||||
.unwrap_or(true) // only say false if someone explicitly objected. TODO: is this okay?
|
||||
}
|
||||
EnvCmd::GetLogInterface => unsafe {
|
||||
c_ext_handle_get_log_interface(data as *mut LogCallback)
|
||||
|
|
|
@ -14,7 +14,6 @@ use ferretro_components::provided::{
|
|||
stdlib::*,
|
||||
};
|
||||
use ferretro_components::base::ControlFlow;
|
||||
use ferretro_components::provided::stdlib::{StderrCallTraceComponent, StderrSysInfoLogComponent};
|
||||
|
||||
#[derive(StructOpt)]
|
||||
struct Opt {
|
||||
|
@ -53,7 +52,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
emu.register_component(stderr_log)?;
|
||||
|
||||
if opt.trace_api {
|
||||
emu.register_component(StderrCallTraceComponent { prefix: "{trace} ".to_string() });
|
||||
emu.register_component(StderrCallTraceComponent { prefix: "{trace} ".to_string() })?;
|
||||
}
|
||||
|
||||
// must register before opengl so it can have priority in queries about what N64 plugin to use
|
||||
|
|
|
@ -12,6 +12,7 @@ use std::os::raw::c_uint;
|
|||
use std::path::{PathBuf, Path};
|
||||
use std::io::Read;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::c_void;
|
||||
|
||||
pub struct RetroComponentBase {
|
||||
retro: LibretroWrapper,
|
||||
|
@ -210,6 +211,17 @@ impl RetroComponentBase {
|
|||
ControlFlow::Continue
|
||||
}
|
||||
|
||||
pub fn serialize_buf(&mut self, mut state: impl AsMut<[u8]>) -> Result<()> {
|
||||
let state = state.as_mut();
|
||||
let serialize_size = unsafe { (&self.retro.core_api.retro_serialize_size)() };
|
||||
if state.len() != serialize_size {
|
||||
Err(format!("serialize_size mismatch: {} != {}", state.len(), serialize_size).into())
|
||||
} else {
|
||||
unsafe { (&self.retro.core_api.retro_serialize)(state.as_mut_ptr() as *mut c_void, state.len()) }
|
||||
Ok(()) // FIXME: make retro_serialize return bool in libretro-sys ffi
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unserialize_path(&mut self, state: impl AsRef<Path>) -> Result<()> {
|
||||
let path = state.as_ref();
|
||||
let mut v = Vec::new();
|
||||
|
@ -531,6 +543,30 @@ impl RetroCallbacks for RetroComponentBase {
|
|||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn get_camera_interface(&mut self, width: c_uint, height: c_uint, cap_raw_fb: bool, cap_gl_tex: bool) -> Option<bool> {
|
||||
self.components.iter_mut()
|
||||
.map(|comp| comp.get_camera_interface(width, height, cap_raw_fb, cap_gl_tex))
|
||||
.flatten()
|
||||
.fold(false, |x, y| x || y) // not "any" because we don't short-circuit
|
||||
.into()
|
||||
}
|
||||
|
||||
fn camera_start(&mut self) -> Option<bool> {
|
||||
self.components.iter_mut()
|
||||
.map(|comp| comp.camera_start())
|
||||
.flatten()
|
||||
.fold(true, |x, y| x && y) // not "all" because we don't short-circuit
|
||||
.into()
|
||||
}
|
||||
|
||||
fn camera_stop(&mut self) -> Option<()> {
|
||||
self.components.iter_mut()
|
||||
.map(|comp| comp.camera_stop())
|
||||
.flatten()
|
||||
.fold((), |_, _| {}) // not "all" because we don't short-circuit
|
||||
.into()
|
||||
}
|
||||
|
||||
fn hw_get_current_framebuffer(&mut self) -> Option<usize> {
|
||||
self.components.iter_mut()
|
||||
.map(|comp| comp.hw_get_current_framebuffer())
|
||||
|
|
|
@ -7,5 +7,5 @@ pub mod prelude {
|
|||
pub use ferretro_base::retro::constants::*;
|
||||
pub use ferretro_base::retro::wrapped_types::*;
|
||||
pub use ferretro_base::retro::wrapper::{RetroCallbacks, LibretroWrapper, LibretroWrapperAccess};
|
||||
pub use ferretro_base::retro::ffi::{PixelFormat, GameGeometry, HwContextResetFn, HwRenderCallback, SystemAvInfo, SystemInfo, MemoryMap};
|
||||
pub use ferretro_base::retro::ffi::{PixelFormat, GameGeometry, HwContextResetFn, HwRenderCallback, SystemAvInfo, SystemInfo, MemoryMap, LogLevel};
|
||||
}
|
||||
|
|
|
@ -24,6 +24,16 @@ impl Sdl2SurfaceComponent {
|
|||
pub fn surface(&self) -> &Surface {
|
||||
&self.surface
|
||||
}
|
||||
|
||||
pub fn surface_owned(&self) -> Surface {
|
||||
let mut clone = Surface::new(
|
||||
self.surface.width(),
|
||||
self.surface.height(),
|
||||
self.surface.pixel_format_enum(),
|
||||
).unwrap();
|
||||
self.surface.blit(None, &mut clone, None).unwrap();
|
||||
clone
|
||||
}
|
||||
}
|
||||
|
||||
impl RetroComponent for Sdl2SurfaceComponent {}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
use std::os::raw::c_uint;
|
||||
use crate::base::RetroComponent;
|
||||
use crate::prelude::RetroCallbacks;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CameraInfoComponent {
|
||||
initialized: bool,
|
||||
started: bool,
|
||||
width: c_uint,
|
||||
height: c_uint,
|
||||
cap_raw_fb: bool,
|
||||
cap_gl_tex: bool,
|
||||
}
|
||||
|
||||
impl CameraInfoComponent {
|
||||
pub fn dimensions(&self) -> Option<(c_uint, c_uint)> {
|
||||
if self.initialized {
|
||||
Some((self.width, self.height))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn raw_fb(&self) -> Option<bool> {
|
||||
if self.initialized {
|
||||
Some(self.cap_raw_fb)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gl_tex(&self) -> Option<bool> {
|
||||
if self.initialized {
|
||||
Some(self.cap_gl_tex)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn started(&self) -> bool {
|
||||
self.started
|
||||
}
|
||||
}
|
||||
|
||||
impl RetroComponent for CameraInfoComponent {}
|
||||
|
||||
impl RetroCallbacks for CameraInfoComponent {
|
||||
fn get_camera_interface(&mut self, width: c_uint, height: c_uint, cap_raw_fb: bool, cap_gl_tex: bool) -> Option<bool> {
|
||||
self.initialized = true;
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
self.cap_raw_fb = cap_raw_fb;
|
||||
self.cap_gl_tex = cap_gl_tex;
|
||||
Some(true)
|
||||
}
|
||||
|
||||
fn camera_start(&mut self) -> Option<bool> {
|
||||
self.started = true;
|
||||
Some(true)
|
||||
}
|
||||
|
||||
fn camera_stop(&mut self) -> Option<()> {
|
||||
self.started = false;
|
||||
Some(())
|
||||
}
|
||||
}
|
|
@ -79,7 +79,7 @@ impl RetroCallbacks for StderrCallTraceComponent {
|
|||
eprintln!("{}video_refresh({:?})", self.prefix, frame);
|
||||
}
|
||||
fn audio_samples(&mut self, stereo_pcm: &[i16]) -> usize {
|
||||
eprintln!("{}audio_samples([i16; {}])", self.prefix, stereo_pcm.len());
|
||||
eprintln!("{}audio_samples(&[i16; {}])", self.prefix, stereo_pcm.len());
|
||||
0
|
||||
}
|
||||
fn input_poll(&mut self) {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
//! Generally-useful [RetroComponent](crate::base::RetroComponent)s that have no dependencies
|
||||
//! outside of [std].
|
||||
|
||||
mod camera;
|
||||
mod fps;
|
||||
mod logs;
|
||||
mod paths;
|
||||
|
||||
pub use camera::CameraInfoComponent;
|
||||
pub use fps::SleepFramerateLimitComponent;
|
||||
pub use logs::StderrCallTraceComponent;
|
||||
pub use logs::StderrLogComponent;
|
||||
|
|
Loading…
Reference in New Issue