Basic lines and rectangles and pixels

This commit is contained in:
Ryan Kennedy 2020-04-13 02:50:02 -05:00
parent 041dd736f1
commit 812e6ceb2a
2 changed files with 73 additions and 28 deletions

View file

@ -1,5 +1,5 @@
use super::pci::{find_pci_device, PciDevice, PciHeader};
use crate::writers::GraphicsWriter;
use crate::drawing::{Bresenham, Point, Rectangle};
use x86_64::{instructions::port::Port, PhysAddr, VirtAddr};
const BOCHS_ID: u32 = 0x1111_1234;
@ -17,25 +17,18 @@ const VBE_DISPI_GETCAPS: u16 = 0x02;
const VBE_DISPI_LFB_ENABLED: u16 = 0x40;
const VBE_DISPI_BPP_32: u16 = 0x20;
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, Default)]
pub struct Resolution {
width: u16,
height: u16,
width: usize,
height: usize,
}
impl Resolution {
pub fn new(width: u16, height: u16) -> Resolution {
pub fn new(width: usize, height: usize) -> Resolution {
Resolution { width, height }
}
}
#[derive(Debug, Copy, Clone)]
pub struct Capabilities {
width: u16,
height: u16,
bpp: u16,
}
#[derive(Debug)]
pub struct BochsDevice {
index_port: Port<u16>,
@ -43,6 +36,7 @@ pub struct BochsDevice {
pci_device: PciDevice,
physical_address: PhysAddr,
virtual_address: VirtAddr,
current_resolution: Resolution,
}
impl BochsDevice {
@ -61,6 +55,7 @@ impl BochsDevice {
data_port,
physical_address,
virtual_address,
current_resolution: Resolution::default(),
})
} else {
None
@ -79,7 +74,7 @@ impl BochsDevice {
self.virtual_address = virtual_address;
}
pub fn capabilities(&mut self) -> Capabilities {
pub fn capabilities(&mut self) -> Resolution {
unsafe {
// Save original value of VBE_DISPI_INDEX_ENABLE
self.index_port.write(VBE_DISPI_INDEX_ENABLE);
@ -88,21 +83,51 @@ impl BochsDevice {
// Read max width
self.index_port.write(VBE_DISPI_INDEX_XRES);
let width = self.data_port.read();
let width = self.data_port.read() as usize;
// Read max height
self.index_port.write(VBE_DISPI_INDEX_YRES);
let height = self.data_port.read();
// Read max bpp
self.index_port.write(VBE_DISPI_INDEX_BPP);
let bpp = self.data_port.read();
let height = self.data_port.read() as usize;
// Restore original VBE_DISPI_INDEX_ENABLE
self.index_port.write(VBE_DISPI_INDEX_ENABLE);
self.data_port.write(original_value);
Capabilities { width, height, bpp }
Resolution { width, height }
}
}
pub fn clear_screen(&self, color: u32) {
let screen_size = self.current_resolution.width * self.current_resolution.height;
let frame_buffer = self.virtual_address.as_mut_ptr::<u32>();
for offset in 0..screen_size {
unsafe {
frame_buffer.add(offset).write_volatile(color);
}
}
}
pub fn draw_line(&self, start: Point<isize>, end: Point<isize>, color: u32) {
for (x, y) in Bresenham::new(start, end) {
self.set_pixel(x as usize, y as usize, color);
}
}
pub fn fill_rectangle(&self, rectangle: &Rectangle, color: u32) {
for y in rectangle.top..rectangle.bottom {
for x in rectangle.left..rectangle.right {
self.set_pixel(x, y, color);
}
}
}
pub fn set_pixel(&self, x: usize, y: usize, color: u32) {
let offset = (y * self.current_resolution.width) + x;
unsafe {
self.virtual_address
.as_mut_ptr::<u32>()
.add(offset)
.write_volatile(color);
}
}
@ -133,33 +158,34 @@ impl BochsDevice {
self.set_height(resolution.height);
self.set_bpp();
self.enable_display();
self.current_resolution = resolution;
}
pub fn get_width(&mut self) -> u16 {
pub fn get_width(&mut self) -> usize {
unsafe {
self.index_port.write(VBE_DISPI_INDEX_XRES);
self.data_port.read()
self.data_port.read() as usize
}
}
pub fn get_height(&mut self) -> u16 {
pub fn get_height(&mut self) -> usize {
unsafe {
self.index_port.write(VBE_DISPI_INDEX_YRES);
self.data_port.read()
self.data_port.read() as usize
}
}
fn set_width(&mut self, width: u16) {
fn set_width(&mut self, width: usize) {
unsafe {
self.index_port.write(VBE_DISPI_INDEX_XRES);
self.data_port.write(width);
self.data_port.write(width as u16);
}
}
fn set_height(&mut self, height: u16) {
fn set_height(&mut self, height: usize) {
unsafe {
self.index_port.write(VBE_DISPI_INDEX_YRES);
self.data_port.write(height);
self.data_port.write(height as u16);
}
}

View file

@ -11,6 +11,25 @@ use octant::Octant;
/// A point in 2D space.
pub type Point<T> = (T, T);
#[derive(Debug, Copy, Clone)]
pub struct Rectangle {
pub left: usize,
pub top: usize,
pub right: usize,
pub bottom: usize,
}
impl Rectangle {
pub fn new(left: usize, top: usize, right: usize, bottom: usize) -> Rectangle {
Rectangle {
left,
top,
right,
bottom,
}
}
}
pub(crate) trait SignedNum: Signed + Ord + Copy + NumCast + NumAssignOps {
fn cast<T: NumCast>(value: T) -> Self {
NumCast::from(value).unwrap()