From 5c591cf475bd5c6a100c20ee566831a3eeb73e3d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 13 Jan 2024 19:32:24 +0100 Subject: [PATCH] Merge Display into GraphicScreen --- vesad/src/display.rs | 101 +------------------------------- vesad/src/scheme.rs | 5 +- vesad/src/screen/graphic.rs | 114 +++++++++++++++++++++++++++++------- vesad/src/screen/text.rs | 8 +-- 4 files changed, 101 insertions(+), 127 deletions(-) diff --git a/vesad/src/display.rs b/vesad/src/display.rs index 6a6e29ee64..f746c5ac14 100644 --- a/vesad/src/display.rs +++ b/vesad/src/display.rs @@ -1,5 +1,5 @@ use std::alloc::{self, Layout}; -use std::{cmp, ptr}; +use std::ptr; use std::ptr::NonNull; pub struct OffscreenBuffer { @@ -14,7 +14,7 @@ impl OffscreenBuffer { } #[inline] - fn new(len: usize) -> Self { + pub fn new(len: usize) -> Self { let layout = Self::layout(len); let ptr = unsafe { alloc::alloc_zeroed(layout) }; let ptr = ptr::slice_from_raw_parts_mut(ptr.cast(), len); @@ -39,100 +39,3 @@ impl std::ops::DerefMut for OffscreenBuffer { unsafe { self.ptr.as_mut() } } } - -/// A display -pub struct Display { - pub width: usize, - pub height: usize, - pub offscreen: OffscreenBuffer, -} - -impl Display { - pub fn new(width: usize, height: usize) -> Display { - let size = width * height; - let offscreen = OffscreenBuffer::new(size); - Display { - width, - height, - offscreen, - } - } - - pub fn resize(&mut self, width: usize, height: usize) { - if width != self.width || height != self.height { - println!("Resize display to {}, {}", width, height); - - let size = width * height; - let mut offscreen = OffscreenBuffer::new(size); - - { - let mut old_ptr = self.offscreen.as_ptr(); - let mut new_ptr = offscreen.as_mut_ptr(); - - for _y in 0..cmp::min(height, self.height) { - unsafe { - ptr::copy( - old_ptr as *const u8, - new_ptr as *mut u8, - cmp::min(width, self.width) * 4 - ); - if width > self.width { - ptr::write_bytes( - new_ptr.offset(self.width as isize), - 0, - width - self.width - ); - } - old_ptr = old_ptr.offset(self.width as isize); - new_ptr = new_ptr.offset(width as isize); - } - } - - if height > self.height { - for _y in self.height..height { - unsafe { - ptr::write_bytes(new_ptr, 0, width); - new_ptr = new_ptr.offset(width as isize); - } - } - } - } - - self.width = width; - self.height = height; - - self.offscreen = offscreen; - } else { - println!("Display is already {}, {}", width, height); - } - } - - /// Copy from offscreen to onscreen - pub fn sync(&mut self, x: usize, y: usize, w: usize, h: usize, onscreen: &mut [u32], stride: usize) { - let start_y = cmp::min(self.height, y); - let end_y = cmp::min(self.height, y + h); - - let start_x = cmp::min(self.width, x); - let len = (cmp::min(self.width, x + w) - start_x) * 4; - - let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize; - let mut onscreen_ptr = onscreen.as_mut_ptr() as usize; - - offscreen_ptr += (y * self.width + start_x) * 4; - onscreen_ptr += (y * stride + start_x) * 4; - - let mut rows = end_y - start_y; - while rows > 0 { - unsafe { - ptr::copy( - offscreen_ptr as *const u8, - onscreen_ptr as *mut u8, - len - ); - } - offscreen_ptr += self.width * 4; - onscreen_ptr += stride * 4; - rows -= 1; - } - } -} diff --git a/vesad/src/scheme.rs b/vesad/src/scheme.rs index 37ce23d111..9cce63e627 100644 --- a/vesad/src/scheme.rs +++ b/vesad/src/scheme.rs @@ -4,7 +4,6 @@ use std::{mem, ptr, slice, str}; use syscall::{Error, EventFlags, EBADF, EINVAL, ENOENT, O_NONBLOCK, Result, SchemeMut, PAGE_SIZE, MapFlags}; use crate::{ - display::Display, framebuffer::FrameBuffer, screen::{Screen, GraphicScreen, TextScreen}, }; @@ -57,7 +56,7 @@ impl DisplayScheme { let mut screens = BTreeMap::>::new(); for fb_i in 0..framebuffers.len() { let fb = &framebuffers[fb_i]; - let graphic_screen = GraphicScreen::new(Display::new(fb.width, fb.height)); + let graphic_screen = GraphicScreen::new(fb.width, fb.height); screens.insert(ScreenIndex(fb_i), if vt_type { Box::new(graphic_screen) } else { @@ -311,7 +310,7 @@ impl SchemeMut for DisplayScheme { for (screen_i, screen) in screens.iter_mut() { match mode { VtMode::Graphic => { - *screen = Box::new(GraphicScreen::new(Display::new(screen.width(), screen.height()))); + *screen = Box::new(GraphicScreen::new(screen.width(), screen.height())); } VtMode::Default => { diff --git a/vesad/src/screen/graphic.rs b/vesad/src/screen/graphic.rs index 506d4e4a0e..7dbacae73e 100644 --- a/vesad/src/screen/graphic.rs +++ b/vesad/src/screen/graphic.rs @@ -1,11 +1,11 @@ use std::collections::VecDeque; use std::convert::TryInto; -use std::{mem, slice}; +use std::{mem, slice, cmp, ptr}; use orbclient::{Event, ResizeEvent}; use syscall::error::*; -use crate::display::Display; +use crate::display::OffscreenBuffer; use crate::screen::Screen; // Keep synced with orbital @@ -19,15 +19,19 @@ pub struct SyncRect { } pub struct GraphicScreen { - pub display: Display, + pub width: usize, + pub height: usize, + pub offscreen: OffscreenBuffer, pub input: VecDeque, pub sync_rects: Vec, } impl GraphicScreen { - pub fn new(display: Display) -> GraphicScreen { + pub fn new(width: usize, height: usize) -> GraphicScreen { GraphicScreen { - display, + width, + height, + offscreen: OffscreenBuffer::new(width * height), input: VecDeque::new(), sync_rects: Vec::new(), } @@ -36,16 +40,61 @@ impl GraphicScreen { impl Screen for GraphicScreen { fn width(&self) -> usize { - self.display.width + self.width } fn height(&self) -> usize { - self.display.height + self.height } fn resize(&mut self, width: usize, height: usize) { //TODO: Fix issue with mapped screens - self.display.resize(width, height); + + if width != self.width || height != self.height { + println!("Resize display to {}, {}", width, height); + + let size = width * height; + let mut offscreen = OffscreenBuffer::new(size); + + let mut old_ptr = self.offscreen.as_ptr(); + let mut new_ptr = offscreen.as_mut_ptr(); + + for _y in 0..cmp::min(height, self.height) { + unsafe { + ptr::copy( + old_ptr as *const u8, + new_ptr as *mut u8, + cmp::min(width, self.width) * 4 + ); + if width > self.width { + ptr::write_bytes( + new_ptr.offset(self.width as isize), + 0, + width - self.width + ); + } + old_ptr = old_ptr.offset(self.width as isize); + new_ptr = new_ptr.offset(width as isize); + } + } + + if height > self.height { + for _y in self.height..height { + unsafe { + ptr::write_bytes(new_ptr, 0, width); + new_ptr = new_ptr.offset(width as isize); + } + } + } + + self.width = width; + self.height = height; + + self.offscreen = offscreen; + } else { + println!("Display is already {}, {}", width, height); + }; + self.input.push_back(ResizeEvent { width: width as u32, height: height as u32, @@ -53,8 +102,8 @@ impl Screen for GraphicScreen { } fn map(&self, offset: usize, size: usize) -> Result { - if offset + size <= self.display.offscreen.len() * 4 { - Ok(self.display.offscreen.as_ptr() as usize + offset) + if offset + size <= self.offscreen.len() * 4 { + Ok(self.offscreen.as_ptr() as usize + offset) } else { Err(Error::new(EINVAL)) } @@ -104,20 +153,43 @@ impl Screen for GraphicScreen { fn sync(&mut self, onscreen: &mut [u32], stride: usize) { for sync_rect in self.sync_rects.drain(..) { - self.display.sync( - sync_rect.x.try_into().unwrap_or(0), - sync_rect.y.try_into().unwrap_or(0), - sync_rect.w.try_into().unwrap_or(0), - sync_rect.h.try_into().unwrap_or(0), - onscreen, - stride, - ); + let x = sync_rect.x.try_into().unwrap_or(0); + let y = sync_rect.y.try_into().unwrap_or(0); + let w = sync_rect.w.try_into().unwrap_or(0); + let h = sync_rect.h.try_into().unwrap_or(0); + + let start_y = cmp::min(self.height, y); + let end_y = cmp::min(self.height, y + h); + + let start_x = cmp::min(self.width, x); + let len = (cmp::min(self.width, x + w) - start_x) * 4; + + let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize; + let mut onscreen_ptr = onscreen.as_mut_ptr() as usize; + + offscreen_ptr += (y * self.width + start_x) * 4; + onscreen_ptr += (y * stride + start_x) * 4; + + let mut rows = end_y - start_y; + while rows > 0 { + unsafe { + ptr::copy( + offscreen_ptr as *const u8, + onscreen_ptr as *mut u8, + len + ); + } + offscreen_ptr += self.width * 4; + onscreen_ptr += stride * 4; + rows -= 1; + }; } } fn redraw(&mut self, onscreen: &mut [u32], stride: usize) { - let width = self.display.width; - let height = self.display.height; - self.display.sync(0, 0, width, height, onscreen, stride); + let width = self.width.try_into().unwrap(); + let height = self.height.try_into().unwrap(); + self.sync_rects.push(SyncRect { x: 0, y: 0, w: width, h: height }); + self.sync(onscreen, stride); } } diff --git a/vesad/src/screen/text.rs b/vesad/src/screen/text.rs index fd7647e77d..d4952d09b4 100644 --- a/vesad/src/screen/text.rs +++ b/vesad/src/screen/text.rs @@ -39,7 +39,7 @@ impl TextScreen { let start_x = cmp::min(screen.width(), x); let len = cmp::min(screen.width(), x + w) - start_x; - let mut offscreen_ptr = screen.display.offscreen.as_mut_ptr() as usize; + let mut offscreen_ptr = screen.offscreen.as_mut_ptr() as usize; let stride = screen.width() * 4; @@ -66,7 +66,7 @@ impl TextScreen { let start_x = cmp::min(screen.width(), x); let len = cmp::min(screen.width(), x + w) - start_x; - let mut offscreen_ptr = screen.display.offscreen.as_mut_ptr() as usize; + let mut offscreen_ptr = screen.offscreen.as_mut_ptr() as usize; let stride = screen.width() * 4; @@ -93,7 +93,7 @@ impl TextScreen { /// Draw a character fn char(screen: &mut GraphicScreen, x: usize, y: usize, character: char, color: u32, _bold: bool, _italic: bool) { if x + 8 <= screen.width() && y + 16 <= screen.height() { - let mut dst = screen.display.offscreen.as_mut_ptr() as usize + (y * screen.width() + x) * 4; + let mut dst = screen.offscreen.as_mut_ptr() as usize + (y * screen.width() + x) * 4; let font_i = 16 * (character as usize); if font_i + 16 <= FONT.len() { @@ -245,7 +245,7 @@ impl Screen for TextScreen { ransid::Event::ScreenBuffer { .. } => (), ransid::Event::Move {from_x, from_y, to_x, to_y, w, h } => { let width = screen.width(); - let pixels = &mut screen.display.offscreen; + let pixels = &mut screen.offscreen; for raw_y in 0..h { let y = if from_y > to_y {