vesad: use framebuffer stride

This commit is contained in:
Jeremy Soller
2022-09-16 13:28:04 -06:00
parent 14be75f29f
commit cbcf133518
6 changed files with 110 additions and 73 deletions
+8 -17
View File
@@ -24,7 +24,6 @@ static FONT_ITALIC: &'static [u8] = include_bytes!("../res/DejaVuSansMono-Obliqu
pub struct Display {
pub width: usize,
pub height: usize,
pub onscreen: &'static mut [u32],
pub offscreen: &'static mut [u32],
#[cfg(feature="rusttype")]
pub font: Font<'static>,
@@ -38,7 +37,7 @@ pub struct Display {
impl Display {
#[cfg(not(feature="rusttype"))]
pub fn new(width: usize, height: usize, onscreen: usize) -> Display {
pub fn new(width: usize, height: usize) -> Display {
let size = width * height;
let offscreen = unsafe {
@@ -50,13 +49,12 @@ impl Display {
Display {
width: width,
height: height,
onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
}
}
#[cfg(feature="rusttype")]
pub fn new(width: usize, height: usize, onscreen: usize) -> Display {
pub fn new(width: usize, height: usize) -> Display {
let size = width * height;
let offscreen = unsafe {
Global
@@ -67,7 +65,6 @@ impl Display {
Display {
width: width,
height: height,
onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) },
font: FontCollection::from_bytes(FONT).into_font().unwrap(),
font_bold: FontCollection::from_bytes(FONT_BOLD).into_font().unwrap(),
@@ -124,9 +121,6 @@ impl Display {
self.width = width;
self.height = height;
let onscreen = self.onscreen.as_mut_ptr();
self.onscreen = unsafe { slice::from_raw_parts_mut(onscreen, size) };
unsafe { Global.deallocate(NonNull::new_unchecked(self.offscreen.as_mut_ptr() as *mut u8), Layout::from_size_align_unchecked(self.offscreen.len() * 4, 4096)) };
self.offscreen = unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) };
} else {
@@ -268,7 +262,7 @@ impl Display {
}
/// Copy from offscreen to onscreen
pub fn sync(&mut self, x: usize, y: usize, w: usize, h: usize) {
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);
@@ -276,13 +270,10 @@ impl Display {
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 = self.onscreen.as_mut_ptr() as usize;
let mut onscreen_ptr = onscreen.as_mut_ptr() as usize;
let stride = self.width * 4;
let offset = y * stride + start_x * 4;
offscreen_ptr += offset;
onscreen_ptr += offset;
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 {
@@ -293,8 +284,8 @@ impl Display {
len
);
}
offscreen_ptr += stride;
onscreen_ptr += stride;
offscreen_ptr += self.width * 4;
onscreen_ptr += stride * 4;
rows -= 1;
}
}
+10 -11
View File
@@ -7,7 +7,7 @@ use std::{env, process, ptr};
use std::fs::File;
use std::io::{Read, Write};
use std::os::unix::io::{RawFd, FromRawFd};
use syscall::{physmap, physunmap, Packet, SchemeMut, EVENT_READ, PHYSMAP_WRITE, PHYSMAP_WRITE_COMBINE};
use syscall::{Packet, SchemeMut, EVENT_READ};
use crate::scheme::{DisplayScheme, HandleKind};
@@ -43,24 +43,23 @@ fn main() {
.expect("FRAMEBUFFER_ADDR not set"),
16
).expect("failed to parse FRAMEBUFFER_ADDR");
let stride = usize::from_str_radix(
&env::var("FRAMEBUFFER_STRIDE")
.expect("FRAMEBUFFER_STRIDE not set"),
16
).expect("failed to parse FRAMEBUFFER_STRIDE");
println!("vesad: {}x{} at 0x{:X}", width, height, physbaseptr);
println!("vesad: {}x{} stride {} at 0x{:X}", width, height, stride, physbaseptr);
if physbaseptr == 0 {
return;
}
redox_daemon::Daemon::new(|daemon| inner(daemon, width, height, physbaseptr, &spec)).expect("failed to create daemon");
redox_daemon::Daemon::new(|daemon| inner(daemon, width, height, physbaseptr, stride, &spec)).expect("failed to create daemon");
}
fn inner(daemon: redox_daemon::Daemon, width: usize, height: usize, physbaseptr: usize, spec: &[bool]) -> ! {
fn inner(daemon: redox_daemon::Daemon, width: usize, height: usize, physbaseptr: usize, stride: usize, spec: &[bool]) -> ! {
let mut socket = File::create(":display").expect("vesad: failed to create display scheme");
let size = width * height;
//TODO: Remap on resize
let largest_size = 8 * 1024 * 1024;
let onscreen = unsafe { physmap(physbaseptr, largest_size * 4, PHYSMAP_WRITE | PHYSMAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") };
unsafe { ptr::write_bytes(onscreen as *mut u32, 0, size); }
let mut scheme = DisplayScheme::new(width, height, onscreen, &spec);
let mut scheme = DisplayScheme::new(width, height, physbaseptr, stride, &spec);
syscall::setrens(0, 0).expect("vesad: failed to enter null namespace");
+79 -21
View File
@@ -1,8 +1,8 @@
use std::collections::BTreeMap;
use std::{mem, slice, str};
use std::{mem, ptr, slice, str};
use orbclient::{Event, EventOption};
use syscall::{Error, EventFlags, EACCES, EBADF, EINVAL, ENOENT, Map, OldMap, O_NONBLOCK, Result, SchemeMut};
use syscall::{Error, EventFlags, EACCES, EBADF, EINVAL, ENOENT, Map, OldMap, O_NONBLOCK, physmap, physunmap, PHYSMAP_WRITE, PHYSMAP_WRITE_COMBINE, Result, SchemeMut};
use crate::display::Display;
use crate::screen::{Screen, GraphicScreen, TextScreen};
@@ -24,6 +24,9 @@ pub struct Handle {
pub struct DisplayScheme {
width: usize,
height: usize,
physbaseptr: usize,
onscreen: &'static mut [u32],
stride: usize,
active: usize,
pub screens: BTreeMap<usize, Box<dyn Screen>>,
next_id: usize,
@@ -31,24 +34,42 @@ pub struct DisplayScheme {
}
impl DisplayScheme {
pub fn new(width: usize, height: usize, onscreen: usize, spec: &[bool]) -> DisplayScheme {
pub fn new(width: usize, height: usize, physbaseptr: usize, stride: usize, spec: &[bool]) -> DisplayScheme {
let onscreen = unsafe {
let size = stride * height;
let onscreen_ptr = physmap(
physbaseptr,
size * 4,
PHYSMAP_WRITE | PHYSMAP_WRITE_COMBINE
).expect("vesad: failed to map framebuffer") as *mut u32;
ptr::write_bytes(onscreen_ptr, 0, size);
slice::from_raw_parts_mut(
onscreen_ptr,
size
)
};
let mut screens: BTreeMap<usize, Box<dyn Screen>> = BTreeMap::new();
let mut screen_i = 1;
for &screen_type in spec.iter() {
if screen_type {
screens.insert(screen_i, Box::new(GraphicScreen::new(Display::new(width, height, onscreen))));
screens.insert(screen_i, Box::new(GraphicScreen::new(Display::new(width, height))));
} else {
screens.insert(screen_i, Box::new(TextScreen::new(Display::new(width, height, onscreen))));
screens.insert(screen_i, Box::new(TextScreen::new(Display::new(width, height))));
}
screen_i += 1;
}
DisplayScheme {
width: width,
height: height,
width,
height,
physbaseptr,
onscreen,
stride,
active: 1,
screens: screens,
screens,
next_id: 0,
handles: BTreeMap::new(),
}
@@ -69,6 +90,44 @@ impl DisplayScheme {
Some(0)
}
fn resize(&mut self, width: usize, height: usize, stride: usize) {
println!("Resizing to {}, {} stride {}", width, height, stride);
// Unmap old onscreen
unsafe {
physunmap(self.onscreen.as_mut_ptr() as usize).expect("vesad: failed to unmap framebuffer");
}
// Map new onscreen
self.onscreen = unsafe {
let size = stride * height;
let onscreen_ptr = physmap(
self.physbaseptr,
size * 4,
PHYSMAP_WRITE | PHYSMAP_WRITE_COMBINE
).expect("vesad: failed to map framebuffer") as *mut u32;
ptr::write_bytes(onscreen_ptr, 0, size);
slice::from_raw_parts_mut(
onscreen_ptr,
size
)
};
// Update size
self.width = width;
self.height = height;
self.stride = stride;
// Resize screens
for (screen_i, screen) in self.screens.iter_mut() {
screen.resize(width, height);
if *screen_i == self.active {
screen.redraw(self.onscreen, self.stride);
}
}
}
}
impl SchemeMut for DisplayScheme {
@@ -195,7 +254,7 @@ impl SchemeMut for DisplayScheme {
if let HandleKind::Screen(screen_i) = handle.kind {
if let Some(screen) = self.screens.get_mut(&screen_i) {
if screen_i == self.active {
screen.sync();
screen.sync(self.onscreen, self.stride);
}
return Ok(0);
}
@@ -224,7 +283,7 @@ impl SchemeMut for DisplayScheme {
let new_active = (buf[0] - 0xF4) as usize + 1;
if let Some(screen) = self.screens.get_mut(&new_active) {
self.active = new_active;
screen.redraw();
screen.redraw(self.onscreen, self.stride);
}
Ok(1)
} else {
@@ -246,15 +305,10 @@ impl SchemeMut for DisplayScheme {
_ => ()
},
EventOption::Resize(resize_event) => {
println!("Resizing to {}, {}", resize_event.width, resize_event.height);
self.width = resize_event.width as usize;
self.height = resize_event.height as usize;
for (screen_i, screen) in self.screens.iter_mut() {
screen.resize(resize_event.width as usize, resize_event.height as usize);
if *screen_i == self.active {
screen.redraw();
}
}
let width = resize_event.width as usize;
let height = resize_event.height as usize;
let stride = width; //TODO: get stride somehow
self.resize(width, height, stride);
},
_ => ()
};
@@ -262,7 +316,7 @@ impl SchemeMut for DisplayScheme {
if let Some(new_active) = new_active_opt {
if let Some(screen) = self.screens.get_mut(&new_active) {
self.active = new_active;
screen.redraw();
screen.redraw(self.onscreen, self.stride);
}
} else {
if let Some(screen) = self.screens.get_mut(&self.active) {
@@ -274,7 +328,11 @@ impl SchemeMut for DisplayScheme {
Ok(events.len() * mem::size_of::<Event>())
},
HandleKind::Screen(screen_i) => if let Some(screen) = self.screens.get_mut(&screen_i) {
screen.write(buf, screen_i == self.active)
let count = screen.write(buf)?;
if screen_i == self.active {
screen.sync(self.onscreen, self.stride);
}
Ok(count)
} else {
Err(Error::new(EBADF))
}
+5 -12
View File
@@ -75,7 +75,7 @@ impl Screen for GraphicScreen {
}
}
fn write(&mut self, buf: &[u8], sync: bool) -> Result<usize> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let size = cmp::max(0, cmp::min(self.display.offscreen.len() as isize - self.seek as isize, (buf.len()/4) as isize)) as usize;
if size > 0 {
@@ -85,13 +85,6 @@ impl Screen for GraphicScreen {
self.display.offscreen.as_mut_ptr().offset(self.seek as isize) as *mut u8,
size * 4
);
if sync {
ptr::copy(
buf.as_ptr(),
self.display.onscreen.as_mut_ptr().offset(self.seek as isize) as *mut u8,
size * 4
);
}
}
}
@@ -111,13 +104,13 @@ impl Screen for GraphicScreen {
Ok(self.seek * 4)
}
fn sync(&mut self) {
self.redraw();
fn sync(&mut self, onscreen: &mut [u32], stride: usize) {
self.redraw(onscreen, stride);
}
fn redraw(&mut self) {
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);
self.display.sync(0, 0, width, height, onscreen, stride);
}
}
+3 -3
View File
@@ -22,11 +22,11 @@ pub trait Screen {
fn can_read(&self) -> Option<usize>;
fn write(&mut self, buf: &[u8], sync: bool) -> Result<usize>;
fn write(&mut self, buf: &[u8]) -> Result<usize>;
fn seek(&mut self, pos: isize, whence: usize) -> Result<usize>;
fn sync(&mut self);
fn sync(&mut self, onscreen: &mut [u32], stride: usize);
fn redraw(&mut self);
fn redraw(&mut self, onscreen: &mut [u32], stride: usize);
}
+5 -9
View File
@@ -132,7 +132,7 @@ impl Screen for TextScreen {
}
}
fn write(&mut self, buf: &[u8], sync: bool) -> Result<usize> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
if self.console.state.cursor && self.console.state.x < self.console.state.w && self.console.state.y < self.console.state.h {
let x = self.console.state.x;
let y = self.console.state.y;
@@ -202,10 +202,6 @@ impl Screen for TextScreen {
self.changed.insert(y);
}
if sync {
self.sync();
}
Ok(buf.len())
}
@@ -213,18 +209,18 @@ impl Screen for TextScreen {
Ok(0)
}
fn sync(&mut self) {
fn sync(&mut self, onscreen: &mut [u32], stride: usize) {
let width = self.display.width;
for change in self.changed.iter() {
self.display.sync(0, change * 16, width, 16);
self.display.sync(0, change * 16, width, 16, onscreen, stride);
}
self.changed.clear();
}
fn redraw(&mut self) {
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);
self.display.sync(0, 0, width, height, onscreen, stride);
self.changed.clear();
}
}