Basic lines and rectangles and pixels
This commit is contained in:
parent
041dd736f1
commit
812e6ceb2a
|
@ -1,5 +1,5 @@
|
||||||
use super::pci::{find_pci_device, PciDevice, PciHeader};
|
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};
|
use x86_64::{instructions::port::Port, PhysAddr, VirtAddr};
|
||||||
|
|
||||||
const BOCHS_ID: u32 = 0x1111_1234;
|
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_LFB_ENABLED: u16 = 0x40;
|
||||||
const VBE_DISPI_BPP_32: u16 = 0x20;
|
const VBE_DISPI_BPP_32: u16 = 0x20;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, Default)]
|
||||||
pub struct Resolution {
|
pub struct Resolution {
|
||||||
width: u16,
|
width: usize,
|
||||||
height: u16,
|
height: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resolution {
|
impl Resolution {
|
||||||
pub fn new(width: u16, height: u16) -> Resolution {
|
pub fn new(width: usize, height: usize) -> Resolution {
|
||||||
Resolution { width, height }
|
Resolution { width, height }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct Capabilities {
|
|
||||||
width: u16,
|
|
||||||
height: u16,
|
|
||||||
bpp: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BochsDevice {
|
pub struct BochsDevice {
|
||||||
index_port: Port<u16>,
|
index_port: Port<u16>,
|
||||||
|
@ -43,6 +36,7 @@ pub struct BochsDevice {
|
||||||
pci_device: PciDevice,
|
pci_device: PciDevice,
|
||||||
physical_address: PhysAddr,
|
physical_address: PhysAddr,
|
||||||
virtual_address: VirtAddr,
|
virtual_address: VirtAddr,
|
||||||
|
current_resolution: Resolution,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BochsDevice {
|
impl BochsDevice {
|
||||||
|
@ -61,6 +55,7 @@ impl BochsDevice {
|
||||||
data_port,
|
data_port,
|
||||||
physical_address,
|
physical_address,
|
||||||
virtual_address,
|
virtual_address,
|
||||||
|
current_resolution: Resolution::default(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -79,7 +74,7 @@ impl BochsDevice {
|
||||||
self.virtual_address = virtual_address;
|
self.virtual_address = virtual_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn capabilities(&mut self) -> Capabilities {
|
pub fn capabilities(&mut self) -> Resolution {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Save original value of VBE_DISPI_INDEX_ENABLE
|
// Save original value of VBE_DISPI_INDEX_ENABLE
|
||||||
self.index_port.write(VBE_DISPI_INDEX_ENABLE);
|
self.index_port.write(VBE_DISPI_INDEX_ENABLE);
|
||||||
|
@ -88,21 +83,51 @@ impl BochsDevice {
|
||||||
|
|
||||||
// Read max width
|
// Read max width
|
||||||
self.index_port.write(VBE_DISPI_INDEX_XRES);
|
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
|
// Read max height
|
||||||
self.index_port.write(VBE_DISPI_INDEX_YRES);
|
self.index_port.write(VBE_DISPI_INDEX_YRES);
|
||||||
let height = self.data_port.read();
|
let height = self.data_port.read() as usize;
|
||||||
|
|
||||||
// Read max bpp
|
|
||||||
self.index_port.write(VBE_DISPI_INDEX_BPP);
|
|
||||||
let bpp = self.data_port.read();
|
|
||||||
|
|
||||||
// Restore original VBE_DISPI_INDEX_ENABLE
|
// Restore original VBE_DISPI_INDEX_ENABLE
|
||||||
self.index_port.write(VBE_DISPI_INDEX_ENABLE);
|
self.index_port.write(VBE_DISPI_INDEX_ENABLE);
|
||||||
self.data_port.write(original_value);
|
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_height(resolution.height);
|
||||||
self.set_bpp();
|
self.set_bpp();
|
||||||
self.enable_display();
|
self.enable_display();
|
||||||
|
self.current_resolution = resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_width(&mut self) -> u16 {
|
pub fn get_width(&mut self) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.index_port.write(VBE_DISPI_INDEX_XRES);
|
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 {
|
unsafe {
|
||||||
self.index_port.write(VBE_DISPI_INDEX_YRES);
|
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 {
|
unsafe {
|
||||||
self.index_port.write(VBE_DISPI_INDEX_XRES);
|
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 {
|
unsafe {
|
||||||
self.index_port.write(VBE_DISPI_INDEX_YRES);
|
self.index_port.write(VBE_DISPI_INDEX_YRES);
|
||||||
self.data_port.write(height);
|
self.data_port.write(height as u16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,25 @@ use octant::Octant;
|
||||||
/// A point in 2D space.
|
/// A point in 2D space.
|
||||||
pub type Point<T> = (T, T);
|
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 {
|
pub(crate) trait SignedNum: Signed + Ord + Copy + NumCast + NumAssignOps {
|
||||||
fn cast<T: NumCast>(value: T) -> Self {
|
fn cast<T: NumCast>(value: T) -> Self {
|
||||||
NumCast::from(value).unwrap()
|
NumCast::from(value).unwrap()
|
||||||
|
|
Loading…
Reference in a new issue