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
This commit is contained in:
Lily Tsuru 2024-08-05 01:04:21 -04:00
parent 5944c5c1cb
commit de2cfc07ae
4 changed files with 44 additions and 11 deletions

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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) {}

View file

@ -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,
);
}
}