From 700d657e25ea7d1ef7fa3a9af89368ff97904abf Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Sat, 21 Mar 2020 22:26:59 -0500 Subject: [PATCH] Faster clear screen --- src/vga.rs | 10 ++++++---- src/writers/graphics_640x480x16.rs | 18 +++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/vga.rs b/src/vga.rs index 44e6420..6e47adc 100644 --- a/src/vga.rs +++ b/src/vga.rs @@ -90,13 +90,15 @@ bitflags! { /// Represents the plane masks of the `SequencerIndex::PlaneMask` register. pub struct PlaneMask: u8 { /// Represents `Plane0` of vga memory. - const PLANE0 = 0b00000001; + const PLANE0 = 0b0000_0001; /// Represents `Plane1` of vga memory. - const PLANE1 = 0b00000010; + const PLANE1 = 0b0000_0010; /// Represents `Plane2` of vga memory. - const PLANE2 = 0b00000100; + const PLANE2 = 0b0000_0100; /// Represents `Plane3` of vga memory. - const PLANE3 = 0b00001000; + const PLANE3 = 0b0000_1000; + /// Represents a combination of all the plane masks. + const ALL_PLANES = Self::PLANE0.bits() | Self::PLANE1.bits() | Self::PLANE2.bits() | Self::PLANE3.bits(); } } diff --git a/src/writers/graphics_640x480x16.rs b/src/writers/graphics_640x480x16.rs index 8914011..59c9a1c 100644 --- a/src/writers/graphics_640x480x16.rs +++ b/src/writers/graphics_640x480x16.rs @@ -1,12 +1,13 @@ use crate::{ colors::{Color16Bit, DEFAULT_PALETTE}, - vga::{Vga, VideoMode, VGA}, + vga::{PlaneMask, Vga, VideoMode, VGA}, }; use core::convert::TryInto; use spinning_top::SpinlockGuard; const WIDTH: usize = 640; const HEIGHT: usize = 480; +const ALL_PLANES_SCREEN_SIZE: usize = (WIDTH * HEIGHT) / 4; /// A basic interface for interacting with vga graphics mode 640x480x16 /// @@ -33,20 +34,19 @@ impl Graphics640x480x16 { /// Clears the screen by setting all pixels to `Color16Bit::Black`. pub fn clear_screen(&self) { - // TODO: Clear the screen by using 4-plane mode instead of slow `set_pixel`. - for x in 0..WIDTH { - for y in 0..HEIGHT { - self.set_pixel(x, y, Color16Bit::Black); + let (mut vga, frame_buffer) = self.get_frame_buffer(); + vga.set_plane_mask(PlaneMask::ALL_PLANES); + for offset in 0..ALL_PLANES_SCREEN_SIZE { + unsafe { + frame_buffer + .add(offset) + .write_volatile(Color16Bit::Black as u8); } } } /// Sets the given pixel at `(x, y)` to the given `color`. - /// - /// Panics if `x >= 640` or `y >= 480`. pub fn set_pixel(&self, x: usize, y: usize, color: Color16Bit) { - assert!(x < WIDTH, "x >= {}", WIDTH); - assert!(y < HEIGHT, "y >= {}", HEIGHT); let (mut vga, frame_buffer) = self.get_frame_buffer(); let offset = x / 8 + (WIDTH / 8) * y;