Merge Display into GraphicScreen
This commit is contained in:
+2
-99
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user