Merge Display into GraphicScreen

This commit is contained in:
bjorn3
2024-01-13 19:32:24 +01:00
parent 24d1f95de3
commit 5c591cf475
4 changed files with 101 additions and 127 deletions
+2 -99
View File
@@ -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;
}
}
}
+2 -3
View File
@@ -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::<ScreenIndex, Box<dyn Screen>>::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 => {
+93 -21
View File
@@ -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<Event>,
pub sync_rects: Vec<SyncRect>,
}
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<usize> {
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);
}
}
+4 -4
View File
@@ -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 {