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..4d4d26b 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,40 @@ 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; + + //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, ); } }