From cc0db37209528493973d4dc5d2f281ad7a3d436d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 2 Jul 2025 15:37:35 +0200 Subject: [PATCH] graphics/fbbootlogd: Use the new graphics api --- graphics/console-draw/src/lib.rs | 33 +++++++++++++++ graphics/fbbootlogd/src/scheme.rs | 70 ++++++++++++++++++++++++++++--- 2 files changed, 97 insertions(+), 6 deletions(-) diff --git a/graphics/console-draw/src/lib.rs b/graphics/console-draw/src/lib.rs index 2cf93db76c..b1551d9c79 100644 --- a/graphics/console-draw/src/lib.rs +++ b/graphics/console-draw/src/lib.rs @@ -226,4 +226,37 @@ impl TextScreen { damage } + + pub fn resize(&mut self, old_map: &mut DisplayMap, new_map: &mut DisplayMap) { + // FIXME fold row when target is narrower and maybe unfold when it is wider + fn copy_row( + old_map: &mut DisplayMap, + new_map: &mut DisplayMap, + from_row: usize, + to_row: usize, + ) { + for x in 0..cmp::min(old_map.width, new_map.width) { + let old_idx = from_row * old_map.width + x; + let new_idx = to_row * new_map.width + x; + unsafe { + (*new_map.offscreen)[new_idx] = (*old_map.offscreen)[old_idx]; + } + } + } + + if new_map.height >= old_map.height { + for row in 0..old_map.height { + copy_row(old_map, new_map, row, row); + } + } else { + let deleted_rows = (old_map.height - new_map.height).div_ceil(16); + for row in 0..new_map.height { + if row + (deleted_rows + 1) * 16 >= old_map.height { + break; + } + copy_row(old_map, new_map, row + deleted_rows * 16, row); + } + self.console.state.y = self.console.state.y.saturating_sub(deleted_rows); + } + } } diff --git a/graphics/fbbootlogd/src/scheme.rs b/graphics/fbbootlogd/src/scheme.rs index 17166c43af..647999fb3b 100644 --- a/graphics/fbbootlogd/src/scheme.rs +++ b/graphics/fbbootlogd/src/scheme.rs @@ -1,12 +1,15 @@ use std::collections::VecDeque; +use std::ptr; -use graphics_ipc::v1::V1GraphicsHandle; +use console_draw::TextScreen; +use graphics_ipc::v2::V2GraphicsHandle; use inputd::ConsumerHandle; use redox_scheme::Scheme; use syscall::{Error, Result, EINVAL, ENOENT}; pub struct DisplayMap { - display_handle: V1GraphicsHandle, + display_handle: V2GraphicsHandle, + fb: usize, inner: graphics_ipc::v1::DisplayMap, } @@ -30,18 +33,24 @@ impl FbbootlogScheme { } pub fn handle_handoff(&mut self) { - let new_display_handle = match self.input_handle.open_display() { - Ok(display) => V1GraphicsHandle::from_file(display).unwrap(), + let new_display_handle = match self.input_handle.open_display_v2() { + Ok(display) => V2GraphicsHandle::from_file(display).unwrap(), Err(err) => { eprintln!("fbbootlogd: No display present yet: {err}"); return; } }; - match new_display_handle.map_display() { + let (width, height) = new_display_handle.display_size(0).unwrap(); + let fb = new_display_handle + .create_dumb_framebuffer(width, height) + .unwrap(); + + match new_display_handle.map_dumb_framebuffer(fb, width, height) { Ok(display_map) => { self.display_map = Some(DisplayMap { display_handle: new_display_handle, + fb, inner: display_map, }); @@ -52,6 +61,53 @@ impl FbbootlogScheme { } } } + + fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) { + let (width, height) = match map.display_handle.display_size(0) { + Ok((width, height)) => (width, height), + Err(err) => { + eprintln!("fbbootlogd: failed to get display size: {}", err); + (map.inner.width() as u32, map.inner.height() as u32) + } + }; + + if width as usize != map.inner.width() || height as usize != map.inner.height() { + match map.display_handle.create_dumb_framebuffer(width, height) { + Ok(fb) => match map.display_handle.map_dumb_framebuffer(fb, width, height) { + Ok(mut new_map) => { + let count = new_map.ptr().len(); + unsafe { + ptr::write_bytes(new_map.ptr_mut() as *mut u32, 0, count); + } + + text_screen.resize( + &mut console_draw::DisplayMap { + offscreen: map.inner.ptr_mut(), + width: map.inner.width(), + height: map.inner.height(), + }, + &mut console_draw::DisplayMap { + offscreen: new_map.ptr_mut(), + width: new_map.width(), + height: new_map.height(), + }, + ); + + map.fb = fb; + map.inner = new_map; + + eprintln!("fbbootlogd: mapped display"); + } + Err(err) => { + eprintln!("fbbootlogd: failed to open display: {}", err); + } + }, + Err(err) => { + eprintln!("fbbootlogd: failed to create framebuffer: {}", err); + } + } + } + } } impl Scheme for FbbootlogScheme { @@ -91,6 +147,8 @@ impl Scheme for FbbootlogScheme { fn write(&mut self, _id: usize, buf: &[u8], _offset: u64, _fcntl_flags: u32) -> Result { if let Some(map) = &mut self.display_map { + Self::handle_resize(map, &mut self.text_screen); + let damage = self.text_screen.write( &mut console_draw::DisplayMap { offscreen: map.inner.ptr_mut(), @@ -102,7 +160,7 @@ impl Scheme for FbbootlogScheme { ); if let Some(map) = &self.display_map { - map.display_handle.sync_rect(damage).unwrap(); + map.display_handle.update_plane(0, map.fb, damage).unwrap(); } }