vesad: use framebuffer stride
This commit is contained in:
+8
-17
@@ -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
@@ -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
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user