diff --git a/graphics/vesad/src/framebuffer.rs b/graphics/vesad/src/framebuffer.rs index a3ca0ba769..5e1da0d04b 100644 --- a/graphics/vesad/src/framebuffer.rs +++ b/graphics/vesad/src/framebuffer.rs @@ -1,6 +1,9 @@ -use std::{ptr, slice}; +use std::ptr; + +use syscall::PAGE_SIZE; pub struct FrameBuffer { + pub onscreen: *mut [u32], pub phys: usize, pub width: usize, pub height: usize, @@ -8,8 +11,25 @@ pub struct FrameBuffer { } impl FrameBuffer { - pub fn new(phys: usize, width: usize, height: usize, stride: usize) -> Self { + pub unsafe fn new(phys: usize, width: usize, height: usize, stride: usize) -> Self { + let size = stride * height; + let virt = common::physmap( + phys, + size * 4, + common::Prot { + read: true, + write: true, + }, + common::MemoryType::WriteCombining, + ) + .expect("vesad: failed to map framebuffer") as *mut u32; + //TODO: should we clear the framebuffer here? + ptr::write_bytes(virt, 0, size); + + let onscreen = ptr::slice_from_raw_parts_mut(virt, size); + Self { + onscreen, phys, width, height, @@ -17,7 +37,7 @@ impl FrameBuffer { } } - pub fn parse(var: &str) -> Option { + pub unsafe fn parse(var: &str) -> Option { fn parse_number(part: &str) -> Option { let (start, radix) = if part.starts_with("0x") { (2, 16) @@ -41,20 +61,35 @@ impl FrameBuffer { Some(Self::new(phys, width, height, stride)) } - pub unsafe fn map(&mut self) -> syscall::Result<&'static mut [u32]> { - let size = self.stride * self.height; - let virt = common::physmap( - self.phys, - size * 4, - common::Prot { - read: true, - write: true, - }, - common::MemoryType::WriteCombining, - )? as *mut u32; - //TODO: should we clear the framebuffer here? - ptr::write_bytes(virt, 0, size); + pub unsafe fn resize(&mut self, width: usize, height: usize, stride: usize) { + // Unmap old onscreen + unsafe { + let slice = self.onscreen; + libredox::call::munmap(slice.cast(), (slice.len() * 4).next_multiple_of(PAGE_SIZE)) + .expect("vesad: failed to unmap framebuffer"); + } - Ok(slice::from_raw_parts_mut(virt, size)) + // Map new onscreen + self.onscreen = unsafe { + let size = stride * height; + let onscreen_ptr = common::physmap( + self.phys, + size * 4, + common::Prot { + read: true, + write: true, + }, + common::MemoryType::WriteCombining, + ) + .expect("vesad: failed to map framebuffer") as *mut u32; + ptr::write_bytes(onscreen_ptr, 0, size); + + ptr::slice_from_raw_parts_mut(onscreen_ptr, size) + }; + + // Update size + self.width = width; + self.height = height; + self.stride = stride; } } diff --git a/graphics/vesad/src/main.rs b/graphics/vesad/src/main.rs index 54e257ebd5..bb2bcc6985 100644 --- a/graphics/vesad/src/main.rs +++ b/graphics/vesad/src/main.rs @@ -54,12 +54,12 @@ fn main() { return; } - let mut framebuffers = vec![FrameBuffer::new(phys, width, height, stride)]; + let mut framebuffers = vec![unsafe { FrameBuffer::new(phys, width, height, stride) }]; //TODO: ideal maximum number of outputs? for i in 1..1024 { match env::var(&format!("FRAMEBUFFER{}", i)) { - Ok(var) => match FrameBuffer::parse(&var) { + Ok(var) => match unsafe { FrameBuffer::parse(&var) } { Some(fb) => { println!( "vesad: framebuffer {}: {}x{} stride {} at 0x{:X}", diff --git a/graphics/vesad/src/scheme.rs b/graphics/vesad/src/scheme.rs index 1db03b05f9..c5221f95c3 100644 --- a/graphics/vesad/src/scheme.rs +++ b/graphics/vesad/src/scheme.rs @@ -1,9 +1,7 @@ use std::collections::BTreeMap; -use std::{mem, ptr, slice, str}; +use std::str; -use syscall::{ - Error, EventFlags, MapFlags, Result, SchemeMut, EBADF, EINVAL, ENOENT, O_NONBLOCK, PAGE_SIZE, -}; +use syscall::{Error, EventFlags, MapFlags, Result, SchemeMut, EBADF, EINVAL, ENOENT, O_NONBLOCK}; use crate::{framebuffer::FrameBuffer, screen::GraphicScreen}; @@ -43,7 +41,7 @@ impl DisplayScheme { let mut onscreens = Vec::new(); for fb in framebuffers.iter_mut() { - onscreens.push(unsafe { fb.map().expect("vesad: failed to map framebuffer") }); + onscreens.push(unsafe { &mut *fb.onscreen }); } let mut vts = BTreeMap::>::new(); @@ -96,39 +94,11 @@ impl DisplayScheme { fb_i, width, height, stride ); - // Unmap old onscreen unsafe { - let slice = mem::take(&mut self.onscreens[fb_i]); - libredox::call::munmap( - slice.as_mut_ptr().cast(), - (slice.len() * 4).next_multiple_of(PAGE_SIZE), - ) - .expect("vesad: failed to unmap framebuffer"); + self.framebuffers[fb_i].resize(width, height, stride); + self.onscreens[fb_i] = &mut *self.framebuffers[fb_i].onscreen; } - // Map new onscreen - self.onscreens[fb_i] = unsafe { - let size = stride * height; - let onscreen_ptr = common::physmap( - self.framebuffers[fb_i].phys, - size * 4, - common::Prot { - read: true, - write: true, - }, - common::MemoryType::WriteCombining, - ) - .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.framebuffers[fb_i].width = width; - self.framebuffers[fb_i].height = height; - self.framebuffers[fb_i].stride = stride; - // Resize screens for (vt_i, screens) in self.vts.iter_mut() { for (screen_i, screen) in screens.iter_mut() {