From de2cfc07aee555590937f15fdfd6bedb308f39c3 Mon Sep 17 00:00:00 2001 From: modeco80 Date: Mon, 5 Aug 2024 01:04:21 -0400 Subject: [PATCH] make rfb handle disconnected pitch better meh, it works. I really should probably do this in Frontend, but that would be another conversion step. idk --- crates/retro_frontend/src/frontend.rs | 2 +- .../retro_frontend/src/libretro_callbacks.rs | 6 +-- crates/retrovnc/src/main.rs | 6 +-- crates/retrovnc/src/rfb.rs | 41 +++++++++++++++++-- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/crates/retro_frontend/src/frontend.rs b/crates/retro_frontend/src/frontend.rs index 9080dda..ae7147b 100644 --- a/crates/retro_frontend/src/frontend.rs +++ b/crates/retro_frontend/src/frontend.rs @@ -24,7 +24,7 @@ pub(crate) static mut FRONTEND: *mut Frontend = std::ptr::null_mut(); /// Interface for the frontend to call to user code. pub trait FrontendInterface { /// Called when video is updated. - fn video_update(&mut self, slice: &[u32]); + fn video_update(&mut self, slice: &[u32], pitch: u32); /// Called when resize occurs. fn video_resize(&mut self, width: u32, height: u32); diff --git a/crates/retro_frontend/src/libretro_callbacks.rs b/crates/retro_frontend/src/libretro_callbacks.rs index 3aab5ff..c4fb4b9 100644 --- a/crates/retro_frontend/src/libretro_callbacks.rs +++ b/crates/retro_frontend/src/libretro_callbacks.rs @@ -202,7 +202,7 @@ pub(crate) unsafe extern "C" fn video_refresh_callback( .resize((pitch * height as usize) as usize, 0); // some cores are stupid - (*(*FRONTEND).interface).video_resize(pitch as u32, height); + (*(*FRONTEND).interface).video_resize(width, height); } // TODO: Make this convert from weird pitches to native resolution where possible. @@ -217,7 +217,7 @@ pub(crate) unsafe extern "C" fn video_refresh_callback( } } - (*(*FRONTEND).interface).video_update(&(*FRONTEND).converted_pixel_buffer[..]); + (*(*FRONTEND).interface).video_update(&(*FRONTEND).converted_pixel_buffer[..], pitch as u32); } _ => { let pixel_data_slice = std::slice::from_raw_parts( @@ -225,7 +225,7 @@ pub(crate) unsafe extern "C" fn video_refresh_callback( (pitch * height as usize) as usize, ); - (*(*FRONTEND).interface).video_update(&pixel_data_slice); + (*(*FRONTEND).interface).video_update(&pixel_data_slice, pitch as u32); } } } diff --git a/crates/retrovnc/src/main.rs b/crates/retrovnc/src/main.rs index 1b63553..dea6a08 100644 --- a/crates/retrovnc/src/main.rs +++ b/crates/retrovnc/src/main.rs @@ -104,10 +104,10 @@ impl FrontendInterface for App { self.rfb_server.resize(width as u16, height as u16); } - fn video_update(&mut self, slice: &[u32]) { - let framebuffer_size = self.get_frontend().get_size(); + fn video_update(&mut self, slice: &[u32], pitch: u32) { + //let framebuffer_size = self.get_frontend().get_size(); self.rfb_server - .update_buffer(&slice, framebuffer_size.0 as u16, framebuffer_size.1 as u16); + .update_buffer(&slice, pitch); } fn audio_sample(&mut self, _slice: &[i16], _size: usize) {} diff --git a/crates/retrovnc/src/rfb.rs b/crates/retrovnc/src/rfb.rs index 1718736..87c16ca 100644 --- a/crates/retrovnc/src/rfb.rs +++ b/crates/retrovnc/src/rfb.rs @@ -18,6 +18,9 @@ pub struct RfbServer { // This follows the same format as libretro joypad buttons. buttons: [bool; 32], + + width: u16, + height: u16 } impl RfbServer { @@ -53,6 +56,8 @@ impl RfbServer { ptr: NonNull::new_unchecked(screen), framebuffer: Vec::new(), buttons: [false; 32], + width: config.width, + height: config.height }); // Disable the normal libvnc cursor (it's annoying) @@ -76,6 +81,9 @@ impl RfbServer { pub fn resize(&mut self, w: u16, h: u16) { let len = (w as usize) * (h as usize); + self.width = w; + self.height = h; + self.framebuffer.resize(len, 0); unsafe { @@ -91,16 +99,41 @@ impl RfbServer { } } - pub fn update_buffer(&mut self, slice: &[u32], width: u16, height: u16) { - self.framebuffer.copy_from_slice(&slice); + pub fn update_buffer(&mut self, slice: &[u32], pitch: u32) { + + //self.framebuffer.copy_from_slice(&slice); + + let has_disconnected_pitch = pitch != self.width as u32; + + #[cfg(debug)] + if has_disconnected_pitch { + info!("DEBUG: Pitch is not the same as width {}, {}", pitch, self.width); + } + + // copy a line at a time (test) + for y in 0..self.height { + let src_line_off = (y as u32 * pitch) as usize; + let mut dest_line_off = src_line_off; + + // copy only + if has_disconnected_pitch { + dest_line_off = (y * self.width) as usize; + } + + // Create slices repressenting each part + let src_slice = &slice[src_line_off..src_line_off + self.width as usize]; + let dest_slice = &mut self.framebuffer[dest_line_off..dest_line_off + self.width as usize]; + + dest_slice.copy_from_slice(src_slice); + } unsafe { rfb::bindings::rfbMarkRectAsModified( self.ptr.as_ptr(), 0, 0, - width as i32, - height as i32, + self.width as i32, + self.height as i32, ); } }