diff --git a/graphics/fbcond/src/display.rs b/graphics/fbcond/src/display.rs index d38d99981e..46785796df 100644 --- a/graphics/fbcond/src/display.rs +++ b/graphics/fbcond/src/display.rs @@ -1,15 +1,14 @@ use inputd::{ConsumerHandle, Damage}; use libredox::flag; -use std::mem; -use std::sync::mpsc::{self, Sender}; -use std::sync::{Arc, Mutex}; -use std::{fs::File, io, os::unix::io::AsRawFd, slice}; +use std::fs::File; +use std::os::unix::io::AsRawFd; +use std::{io, mem, ptr, slice}; fn display_fd_map( width: usize, height: usize, display_file: &mut File, -) -> syscall::Result { +) -> syscall::Result<*mut [u32]> { unsafe { let display_ptr = libredox::call::mmap(libredox::call::MmapArgs { fd: display_file.as_raw_fd() as usize, @@ -19,12 +18,10 @@ fn display_fd_map( flags: flag::MAP_SHARED, addr: core::ptr::null_mut(), })?; - let display_slice = slice::from_raw_parts_mut(display_ptr as *mut u32, width * height); - Ok(DisplayMap { - offscreen: display_slice, - width, - height, - }) + Ok(ptr::slice_from_raw_parts_mut( + display_ptr as *mut u32, + width * height, + )) } } @@ -32,118 +29,51 @@ unsafe fn display_fd_unmap(image: *mut [u32]) { let _ = libredox::call::munmap(image as *mut (), image.len()); } -pub struct DisplayMap { +pub struct Display { + pub input_handle: ConsumerHandle, + pub display_file: File, pub offscreen: *mut [u32], pub width: usize, pub height: usize, } -unsafe impl Send for DisplayMap {} -unsafe impl Sync for DisplayMap {} - -impl Drop for DisplayMap { - fn drop(&mut self) { - unsafe { - display_fd_unmap(self.offscreen); - } - } -} - -enum DisplayCommand { - Resize { width: usize, height: usize }, - ReopenForHandoff, - SyncRects(Vec), -} - -pub struct Display { - pub input_handle: Arc, - cmd_tx: Sender, - pub map: Arc>, -} - impl Display { pub fn open_vt(vt: usize) -> io::Result { - let input_handle = Arc::new(ConsumerHandle::for_vt(vt)?); + let input_handle = ConsumerHandle::for_vt(vt)?; let (mut display_file, width, height) = Self::open_display(&input_handle)?; - let map = Arc::new(Mutex::new( - display_fd_map(width, height, &mut display_file) - .unwrap_or_else(|e| panic!("failed to map display for VT #{vt}: {e}")), - )); - - let (cmd_tx, cmd_rx) = mpsc::channel(); - - let input_handle_clone = input_handle.clone(); - let map_clone = map.clone(); - std::thread::spawn(move || { - while let Ok(cmd) = cmd_rx.recv() { - match cmd { - DisplayCommand::Resize { width, height } => { - match display_fd_map(width, height, &mut display_file) { - Ok(ok) => { - *map_clone.lock().unwrap() = ok; - } - Err(err) => { - eprintln!( - "failed to resize display to {}x{}: {}", - width, height, err - ); - } - } - } - DisplayCommand::ReopenForHandoff => { - eprintln!("fbcond: Performing handoff"); - - let (mut new_display_file, width, height) = - Self::open_display(&input_handle_clone).unwrap(); - - eprintln!("fbcond: Opened new display for VT #{vt}"); - - match display_fd_map(width, height, &mut new_display_file) { - Ok(ok) => { - *map_clone.lock().unwrap() = ok; - display_file = new_display_file; - - eprintln!("fbcond: Mapped new display for VT #{vt}"); - } - Err(err) => { - eprintln!( - "failed to resize display to {}x{}: {}", - width, height, err - ); - } - } - } - DisplayCommand::SyncRects(sync_rects) => unsafe { - libredox::call::write( - display_file.as_raw_fd() as usize, - slice::from_raw_parts( - sync_rects.as_ptr() as *const u8, - sync_rects.len() * mem::size_of::(), - ), - ) - .unwrap(); - }, - } - } - }); + let offscreen = display_fd_map(width, height, &mut display_file) + .unwrap_or_else(|e| panic!("failed to map display for VT #{vt}: {e}")); Ok(Self { input_handle, - cmd_tx, - map, + display_file, + offscreen, + width, + height, }) } /// Re-open the display after a handoff. - /// - /// Once re-opening is finished, you must call [`resize`] to map the new framebuffer. - /// - /// Warning: This must be called in a background thread to avoid a deadlock when the - /// graphics driver (indirectly) writes logs to fbcond. pub fn reopen_for_handoff(&mut self) { - self.cmd_tx.send(DisplayCommand::ReopenForHandoff).unwrap(); + eprintln!("fbcond: Performing handoff"); + + let (mut new_display_file, width, height) = Self::open_display(&self.input_handle).unwrap(); + + eprintln!("fbcond: Opened new display"); + + match display_fd_map(width, height, &mut new_display_file) { + Ok(offscreen) => { + self.offscreen = offscreen; + self.display_file = new_display_file; + + eprintln!("fbcond: Mapped new display"); + } + Err(err) => { + eprintln!("failed to resize display to {}x{}: {}", width, height, err); + } + } } fn open_display(input_handle: &ConsumerHandle) -> io::Result<(File, usize, usize)> { @@ -175,14 +105,34 @@ impl Display { } pub fn resize(&mut self, width: usize, height: usize) { - self.cmd_tx - .send(DisplayCommand::Resize { width, height }) - .unwrap(); + match display_fd_map(width, height, &mut self.display_file) { + Ok(offscreen) => { + self.offscreen = offscreen; + } + Err(err) => { + eprintln!("failed to resize display to {}x{}: {}", width, height, err); + } + } } pub fn sync_rects(&mut self, sync_rects: Vec) { - self.cmd_tx - .send(DisplayCommand::SyncRects(sync_rects)) + unsafe { + libredox::call::write( + self.display_file.as_raw_fd() as usize, + slice::from_raw_parts( + sync_rects.as_ptr() as *const u8, + sync_rects.len() * mem::size_of::(), + ), + ) .unwrap(); + } + } +} + +impl Drop for Display { + fn drop(&mut self) { + unsafe { + display_fd_unmap(self.offscreen); + } } } diff --git a/graphics/fbcond/src/text.rs b/graphics/fbcond/src/text.rs index 696adf0ba2..e01dab8ae6 100644 --- a/graphics/fbcond/src/text.rs +++ b/graphics/fbcond/src/text.rs @@ -128,17 +128,15 @@ impl TextScreen { } pub fn write(&mut self, buf: &[u8]) -> Result { - let map = self.display.map.lock().unwrap(); let damage = self.inner.write( &mut console_draw::DisplayMap { - offscreen: map.offscreen, - width: map.width, - height: map.height, + offscreen: self.display.offscreen, + width: self.display.width, + height: self.display.height, }, buf, &mut self.input, ); - drop(map); self.display.sync_rects(damage);