WIP: VBox resize
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
use syscall::io::{Io, Pio};
|
||||
|
||||
const BGA_INDEX_XRES: u16 = 1;
|
||||
const BGA_INDEX_YRES: u16 = 2;
|
||||
const BGA_INDEX_BPP: u16 = 3;
|
||||
const BGA_INDEX_ENABLE: u16 = 4;
|
||||
|
||||
pub struct Bga {
|
||||
index: Pio<u16>,
|
||||
data: Pio<u16>,
|
||||
}
|
||||
|
||||
impl Bga {
|
||||
pub fn new() -> Bga {
|
||||
Bga {
|
||||
index: Pio::new(0x1CE),
|
||||
data: Pio::new(0x1CF),
|
||||
}
|
||||
}
|
||||
|
||||
fn read(&mut self, index: u16) -> u16 {
|
||||
self.index.write(index);
|
||||
self.data.read()
|
||||
}
|
||||
|
||||
fn write(&mut self, index: u16, data: u16) {
|
||||
self.index.write(index);
|
||||
self.data.write(data);
|
||||
}
|
||||
|
||||
pub fn width(&mut self) -> u16 {
|
||||
self.read(BGA_INDEX_XRES)
|
||||
}
|
||||
|
||||
pub fn height(&mut self) -> u16 {
|
||||
self.read(BGA_INDEX_YRES)
|
||||
}
|
||||
|
||||
pub fn set_size(&mut self, width: u16, height: u16) {
|
||||
self.write(BGA_INDEX_ENABLE, 0);
|
||||
self.write(BGA_INDEX_XRES, width);
|
||||
self.write(BGA_INDEX_YRES, height);
|
||||
self.write(BGA_INDEX_BPP, 32);
|
||||
self.write(BGA_INDEX_ENABLE, 0x41);
|
||||
}
|
||||
}
|
||||
+21
-3
@@ -13,6 +13,10 @@ use syscall::flag::MAP_WRITE;
|
||||
use syscall::io::{Dma, Io, Mmio, Pio};
|
||||
use syscall::iopl;
|
||||
|
||||
use bga::Bga;
|
||||
|
||||
mod bga;
|
||||
|
||||
const VBOX_REQUEST_HEADER_VERSION: u32 = 0x10001;
|
||||
const VBOX_VMMDEV_VERSION: u32 = 0x00010003;
|
||||
|
||||
@@ -234,6 +238,7 @@ fn main() {
|
||||
|
||||
let mut event_queue = EventQueue::<()>::new().expect("vboxd: failed to create event queue");
|
||||
|
||||
let mut bga = Bga::new();
|
||||
let get_mouse = VboxGetMouse::new().expect("vboxd: failed to map GetMouse");
|
||||
let display_change = VboxDisplayChange::new().expect("vboxd: failed to map DisplayChange");
|
||||
let ack_events = VboxAckEvents::new().expect("vboxd: failed to map AckEvents");
|
||||
@@ -247,14 +252,27 @@ fn main() {
|
||||
|
||||
if host_events & VBOX_EVENT_DISPLAY == VBOX_EVENT_DISPLAY {
|
||||
port.write(display_change.physical() as u32);
|
||||
println!("Display {}, {}", display_change.xres.read(), display_change.yres.read());
|
||||
if let Some(ref mut display) = display_opt {
|
||||
let new_width = display_change.xres.read();
|
||||
let new_height = display_change.yres.read();
|
||||
if width != new_width || height != new_height {
|
||||
width = new_width;
|
||||
height = new_height;
|
||||
println!("Display {}, {}", width, height);
|
||||
bga.set_size(width as u16, height as u16);
|
||||
let _ = display.write(&orbclient::ResizeEvent {
|
||||
width: width,
|
||||
height: height,
|
||||
}.to_event());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if host_events & VBOX_EVENT_MOUSE == VBOX_EVENT_MOUSE {
|
||||
port.write(get_mouse.physical() as u32);
|
||||
let x = get_mouse.x.read() * width / 0x10000;
|
||||
let y = get_mouse.y.read() * height / 0x10000;
|
||||
if let Some(ref mut display) = display_opt {
|
||||
let x = get_mouse.x.read() * width / 0x10000;
|
||||
let y = get_mouse.y.read() * height / 0x10000;
|
||||
let _ = display.write(&orbclient::MouseEvent {
|
||||
x: x as i32,
|
||||
y: y as i32,
|
||||
|
||||
@@ -68,6 +68,36 @@ impl Display {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, width: usize, height: usize) {
|
||||
println!("Resize display to {}, {}", width, height);
|
||||
|
||||
let size = width * height;
|
||||
let offscreen = unsafe { heap::allocate(size * 4, 4096) };
|
||||
|
||||
{
|
||||
let mut old_ptr = self.offscreen.as_ptr();
|
||||
let mut new_ptr = offscreen as *mut u32;
|
||||
for _y in 0..cmp::min(height, self.height) {
|
||||
unsafe {
|
||||
fast_copy(new_ptr as *mut u8, old_ptr as *const u8, cmp::min(width, self.width) * 4);
|
||||
old_ptr = old_ptr.offset(self.width as isize);
|
||||
new_ptr = new_ptr.offset(width as isize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
|
||||
let onscreen = self.onscreen.as_mut_ptr();
|
||||
self.onscreen = unsafe { slice::from_raw_parts_mut(onscreen, size) };
|
||||
|
||||
unsafe { heap::deallocate(self.offscreen.as_mut_ptr() as *mut u8, self.offscreen.len() * 4, 4096) };
|
||||
self.offscreen = unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) };
|
||||
|
||||
self.sync(0, 0, width, height);
|
||||
}
|
||||
|
||||
/// Draw a rectangle
|
||||
pub fn rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) {
|
||||
let start_y = cmp::min(self.height - 1, y);
|
||||
@@ -244,3 +274,9 @@ impl Display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Display {
|
||||
fn drop(&mut self) {
|
||||
unsafe { heap::deallocate(self.offscreen.as_mut_ptr() as *mut u8, self.offscreen.len() * 4, 4096) };
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -55,8 +55,9 @@ fn main() {
|
||||
let mut socket = File::create(":display").expect("vesad: failed to create display scheme");
|
||||
|
||||
let size = width * height;
|
||||
|
||||
let onscreen = unsafe { physmap(physbaseptr, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") };
|
||||
//TODO: Remap on resize
|
||||
let largest_size = 8 * 1024 * 1024;
|
||||
let onscreen = unsafe { physmap(physbaseptr, largest_size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") };
|
||||
unsafe { fast_set64(onscreen as *mut u64, 0, size/2) };
|
||||
|
||||
let mut scheme = DisplayScheme::new(width, height, onscreen, &spec);
|
||||
|
||||
+15
-9
@@ -142,21 +142,27 @@ impl SchemeMut for DisplayScheme {
|
||||
let events = unsafe { slice::from_raw_parts(buf.as_ptr() as *const Event, buf.len()/mem::size_of::<Event>()) };
|
||||
|
||||
for event in events.iter() {
|
||||
let new_active_opt = if let EventOption::Key(key_event) = event.to_option() {
|
||||
match key_event.scancode {
|
||||
let mut new_active_opt = None;
|
||||
match event.to_option() {
|
||||
EventOption::Key(key_event) => match key_event.scancode {
|
||||
f @ 0x3B ... 0x44 => { // F1 through F10
|
||||
Some((f - 0x3A) as usize)
|
||||
new_active_opt = Some((f - 0x3A) as usize);
|
||||
},
|
||||
0x57 => { // F11
|
||||
Some(11)
|
||||
new_active_opt = Some(11);
|
||||
},
|
||||
0x58 => { // F12
|
||||
Some(12)
|
||||
new_active_opt = Some(12);
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
_ => ()
|
||||
},
|
||||
EventOption::Resize(resize_event) => {
|
||||
println!("Resizing to {}, {}", resize_event.width, resize_event.height);
|
||||
for (_screen_id, screen) in self.screens.iter_mut() {
|
||||
screen.resize(resize_event.width as usize, resize_event.height as usize);
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
};
|
||||
|
||||
if let Some(new_active) = new_active_opt {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::{cmp, mem, slice};
|
||||
|
||||
use orbclient::Event;
|
||||
use orbclient::{Event, ResizeEvent};
|
||||
use syscall::error::*;
|
||||
use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END};
|
||||
|
||||
@@ -36,6 +36,15 @@ impl Screen for GraphicScreen {
|
||||
self.display.height
|
||||
}
|
||||
|
||||
fn resize(&mut self, width: usize, height: usize) {
|
||||
//TODO: Fix issue with mapped screens
|
||||
self.display.resize(width, height);
|
||||
self.input.push_back(ResizeEvent {
|
||||
width: width as u32,
|
||||
height: height as u32,
|
||||
}.to_event());
|
||||
}
|
||||
|
||||
fn event(&mut self, flags: usize) -> Result<usize> {
|
||||
self.requested = flags;
|
||||
Ok(0)
|
||||
|
||||
@@ -12,6 +12,8 @@ pub trait Screen {
|
||||
|
||||
fn height(&self) -> usize;
|
||||
|
||||
fn resize(&mut self, width: usize, height: usize);
|
||||
|
||||
fn event(&mut self, flags: usize) -> Result<usize>;
|
||||
|
||||
fn map(&self, offset: usize, size: usize) -> Result<usize>;
|
||||
|
||||
@@ -43,6 +43,10 @@ impl Screen for TextScreen {
|
||||
self.console.h
|
||||
}
|
||||
|
||||
fn resize(&mut self, width: usize, height: usize) {
|
||||
self.display.resize(width, height);
|
||||
}
|
||||
|
||||
fn event(&mut self, flags: usize) -> Result<usize> {
|
||||
self.requested = flags;
|
||||
Ok(0)
|
||||
|
||||
Reference in New Issue
Block a user