Testing performance with different write modes
This commit is contained in:
parent
700d657e25
commit
01d75b971a
|
@ -41,6 +41,12 @@ pub enum Color16Bit {
|
||||||
White = 0xF,
|
White = 0xF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Color16Bit> for u8 {
|
||||||
|
fn from(value: Color16Bit) -> u8 {
|
||||||
|
value as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a color for vga text modes.
|
/// Represents a color for vga text modes.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
|
32
src/vga.rs
32
src/vga.rs
|
@ -1,7 +1,7 @@
|
||||||
//! Provides access to the vga graphics card.
|
//! Provides access to the vga graphics card.
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
colors::PALETTE_SIZE,
|
colors::{Color16Bit, PALETTE_SIZE},
|
||||||
configurations::{
|
configurations::{
|
||||||
VgaConfiguration, MODE_40X25_CONFIGURATION, MODE_40X50_CONFIGURATION,
|
VgaConfiguration, MODE_40X25_CONFIGURATION, MODE_40X50_CONFIGURATION,
|
||||||
MODE_640X480X16_CONFIGURATION, MODE_80X25_CONFIGURATION,
|
MODE_640X480X16_CONFIGURATION, MODE_80X25_CONFIGURATION,
|
||||||
|
@ -89,6 +89,8 @@ impl From<ReadPlane> for u8 {
|
||||||
bitflags! {
|
bitflags! {
|
||||||
/// Represents the plane masks of the `SequencerIndex::PlaneMask` register.
|
/// Represents the plane masks of the `SequencerIndex::PlaneMask` register.
|
||||||
pub struct PlaneMask: u8 {
|
pub struct PlaneMask: u8 {
|
||||||
|
/// Represents none of the plane masks of vga memory.
|
||||||
|
const NONE = 0b0000_0000;
|
||||||
/// Represents `Plane0` of vga memory.
|
/// Represents `Plane0` of vga memory.
|
||||||
const PLANE0 = 0b0000_0001;
|
const PLANE0 = 0b0000_0001;
|
||||||
/// Represents `Plane1` of vga memory.
|
/// Represents `Plane1` of vga memory.
|
||||||
|
@ -97,7 +99,7 @@ bitflags! {
|
||||||
const PLANE2 = 0b0000_0100;
|
const PLANE2 = 0b0000_0100;
|
||||||
/// Represents `Plane3` of vga memory.
|
/// Represents `Plane3` of vga memory.
|
||||||
const PLANE3 = 0b0000_1000;
|
const PLANE3 = 0b0000_1000;
|
||||||
/// Represents a combination of all the plane masks.
|
/// Represents all of the plane masks of vga memory.
|
||||||
const ALL_PLANES = Self::PLANE0.bits() | Self::PLANE1.bits() | Self::PLANE2.bits() | Self::PLANE3.bits();
|
const ALL_PLANES = Self::PLANE0.bits() | Self::PLANE1.bits() | Self::PLANE2.bits() | Self::PLANE3.bits();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,6 +353,32 @@ impl Vga {
|
||||||
.write(GraphicsControllerIndex::ReadPlaneSelect, read_plane);
|
.write(GraphicsControllerIndex::ReadPlaneSelect, read_plane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the value to use for `GraphicsControllerIndex::SetReset`,
|
||||||
|
/// as spcified by `color`.
|
||||||
|
pub fn set_graphics_set_reset(&mut self, color: Color16Bit) {
|
||||||
|
let original_value = self
|
||||||
|
.graphics_controller_registers
|
||||||
|
.read(GraphicsControllerIndex::SetReset)
|
||||||
|
& 0xF0;
|
||||||
|
self.graphics_controller_registers.write(
|
||||||
|
GraphicsControllerIndex::SetReset,
|
||||||
|
original_value | u8::from(color),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets which planes are effected by `GraphicsControllerIndex::SetReset`,
|
||||||
|
/// as specified by `plane_mask`.
|
||||||
|
pub fn set_graphics_enable_set_reset(&mut self, plane_mask: PlaneMask) {
|
||||||
|
let original_value = self
|
||||||
|
.graphics_controller_registers
|
||||||
|
.read(GraphicsControllerIndex::EnableSetReset)
|
||||||
|
& 0xF0;
|
||||||
|
self.graphics_controller_registers.write(
|
||||||
|
GraphicsControllerIndex::EnableSetReset,
|
||||||
|
original_value | u8::from(plane_mask),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn set_registers(&mut self, configuration: &VgaConfiguration) {
|
fn set_registers(&mut self, configuration: &VgaConfiguration) {
|
||||||
let emulation_mode = self.get_emulation_mode();
|
let emulation_mode = self.get_emulation_mode();
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ use crate::{
|
||||||
colors::{Color16Bit, DEFAULT_PALETTE},
|
colors::{Color16Bit, DEFAULT_PALETTE},
|
||||||
vga::{PlaneMask, Vga, VideoMode, VGA},
|
vga::{PlaneMask, Vga, VideoMode, VGA},
|
||||||
};
|
};
|
||||||
use core::convert::TryInto;
|
|
||||||
use spinning_top::SpinlockGuard;
|
use spinning_top::SpinlockGuard;
|
||||||
|
|
||||||
const WIDTH: usize = 640;
|
const WIDTH: usize = 640;
|
||||||
|
@ -36,6 +35,7 @@ impl Graphics640x480x16 {
|
||||||
pub fn clear_screen(&self) {
|
pub fn clear_screen(&self) {
|
||||||
let (mut vga, frame_buffer) = self.get_frame_buffer();
|
let (mut vga, frame_buffer) = self.get_frame_buffer();
|
||||||
vga.set_plane_mask(PlaneMask::ALL_PLANES);
|
vga.set_plane_mask(PlaneMask::ALL_PLANES);
|
||||||
|
vga.set_graphics_enable_set_reset(PlaneMask::NONE);
|
||||||
for offset in 0..ALL_PLANES_SCREEN_SIZE {
|
for offset in 0..ALL_PLANES_SCREEN_SIZE {
|
||||||
unsafe {
|
unsafe {
|
||||||
frame_buffer
|
frame_buffer
|
||||||
|
@ -50,24 +50,20 @@ impl Graphics640x480x16 {
|
||||||
let (mut vga, frame_buffer) = self.get_frame_buffer();
|
let (mut vga, frame_buffer) = self.get_frame_buffer();
|
||||||
let offset = x / 8 + (WIDTH / 8) * y;
|
let offset = x / 8 + (WIDTH / 8) * y;
|
||||||
|
|
||||||
// Store the current value for masking.
|
// Write to all 4 planes
|
||||||
let x = x & 7;
|
vga.set_plane_mask(PlaneMask::ALL_PLANES);
|
||||||
let mask = 0x80 >> (x & 7);
|
|
||||||
let mut plane_mask = 0x01;
|
|
||||||
|
|
||||||
for plane in 0u8..4u8 {
|
// Set the bits we want set/reset to the color
|
||||||
vga.set_read_plane(plane.try_into().unwrap());
|
vga.set_graphics_set_reset(color);
|
||||||
vga.set_plane_mask(plane.try_into().unwrap());
|
|
||||||
let current_value = unsafe { frame_buffer.add(offset).read_volatile() };
|
// Enable set/reset for all planes
|
||||||
let new_value = if plane_mask & color as u8 != 0 {
|
vga.set_graphics_enable_set_reset(PlaneMask::ALL_PLANES);
|
||||||
current_value | mask
|
unsafe {
|
||||||
} else {
|
// In write mode 0, when enable set/reset is turned on, cpu data
|
||||||
current_value & !mask
|
// is replaced with the data from the set/reset register. Since
|
||||||
};
|
// we're using set/reset for all 4 planes, it doesn't matter what value
|
||||||
unsafe {
|
// we write to the memory address.
|
||||||
frame_buffer.add(offset).write_volatile(new_value);
|
frame_buffer.add(offset).write(0x0);
|
||||||
}
|
|
||||||
plane_mask <<= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue