diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs index 869b7eb..8c4ab36 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -39,12 +39,11 @@ pub struct FramebufferInfo { #[repr(u32)] #[derive(Debug, Clone, Copy)] -#[allow(non_camel_case_types)] -pub enum ColorFormat { - BGR565 = 16, - RGBA8888 = 32, +pub enum ColorDepth { + ColorDepth16 = 16, + ColorDepth32 = 32, } -use self::ColorFormat::*; +use self::ColorDepth::*; #[repr(C)] union ColorBuffer { @@ -54,16 +53,16 @@ union ColorBuffer { } impl ColorBuffer { - fn new(color_format: ColorFormat, bus_addr: u32, size: u32) -> ColorBuffer { + fn new(color_depth: ColorDepth, bus_addr: u32, size: u32) -> ColorBuffer { unsafe { - match color_format { - BGR565 => ColorBuffer { + match color_depth { + ColorDepth16 => ColorBuffer { buf16: core::slice::from_raw_parts_mut( bus_addr as *mut u16, (size / 2) as usize, ), }, - RGBA8888 => ColorBuffer { + ColorDepth32 => ColorBuffer { buf32: core::slice::from_raw_parts_mut( bus_addr as *mut u32, (size / 4) as usize, @@ -97,7 +96,7 @@ impl ColorBuffer { /// Frambuffer structure pub struct Framebuffer { pub fb_info: FramebufferInfo, - pub color_format: ColorFormat, + pub color_depth: ColorDepth, buf: ColorBuffer, } @@ -105,7 +104,7 @@ impl fmt::Debug for Framebuffer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut f = f.debug_struct("Framebuffer"); f.field("fb_info", &self.fb_info); - f.field("color_format", &self.color_format); + f.field("color_depth", &self.color_depth); f.field("base_addr", unsafe { &self.buf.base_addr }); f.finish() } @@ -127,9 +126,9 @@ impl Framebuffer { }; let info = mailbox::framebuffer_alloc(width, height, depth)?; - let color_format = match info.depth { - 16 => BGR565, - 32 => RGBA8888, + let color_depth = match info.depth { + 16 => ColorDepth16, + 32 => ColorDepth32, _ => Err(format!("unsupported color depth {}", info.depth))?, }; @@ -147,8 +146,8 @@ impl Framebuffer { let paddr = info.bus_addr & !0xC0000000; let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb") as u32; Ok(Framebuffer { - buf: ColorBuffer::new(color_format, vaddr, info.screen_size), - color_format, + buf: ColorBuffer::new(color_depth, vaddr, info.screen_size), + color_depth, fb_info: info, }) } @@ -161,18 +160,18 @@ impl Framebuffer { /// Read pixel at `(x, y)`. #[inline] pub fn read(&self, x: u32, y: u32) -> u32 { - match self.color_format { - BGR565 => self.buf.read16(y * self.fb_info.xres + x) as u32, - RGBA8888 => self.buf.read32(y * self.fb_info.xres + x), + match self.color_depth { + ColorDepth16 => self.buf.read16(y * self.fb_info.xres + x) as u32, + ColorDepth32 => self.buf.read32(y * self.fb_info.xres + x), } } /// Write pixel at `(x, y)`. #[inline] pub fn write(&mut self, x: u32, y: u32, pixel: u32) { - match self.color_format { - BGR565 => self.buf.write16(y * self.fb_info.xres + x, pixel as u16), - RGBA8888 => self.buf.write32(y * self.fb_info.xres + x, pixel), + match self.color_depth { + ColorDepth16 => self.buf.write16(y * self.fb_info.xres + x, pixel as u16), + ColorDepth32 => self.buf.write32(y * self.fb_info.xres + x, pixel), } } diff --git a/kernel/src/arch/aarch64/driver/console/color.rs b/kernel/src/arch/aarch64/driver/console/color.rs new file mode 100644 index 0000000..b5cdfe4 --- /dev/null +++ b/kernel/src/arch/aarch64/driver/console/color.rs @@ -0,0 +1,90 @@ +//! Frambuffer color + +pub trait FramebufferColor { + /// pack as 32-bit integer + fn pack16(&self) -> u16; + + /// pack as 32-bit integer + fn pack32(&self) -> u32; +} + +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct RgbColor(u8, u8, u8); + +#[repr(u8)] +#[allow(dead_code)] +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ConsoleColor { + Black = 0, + Red = 1, + Green = 2, + Yellow = 3, + Blue = 4, + Magenta = 5, + Cyan = 6, + White = 7, + BrightBlack = 60, + BrightRed = 61, + BrightGreen = 62, + BrightYellow = 63, + BrightBlue = 64, + BrightMagenta = 65, + BrightCyan = 66, + BrightWhite = 67, +} +use self::ConsoleColor::*; + +impl From for RgbColor { + /// Convert `ConsoleColor` to `RgbColor`. + /// use `CMD` color scheme. + /// (ref: https://en.wikipedia.org/wiki/ANSI_escape_code) + fn from(color: ConsoleColor) -> Self { + match color { + Black => RgbColor(0, 0, 0), + Red => RgbColor(128, 0, 0), + Green => RgbColor(0, 128, 8), + Yellow => RgbColor(128, 128, 0), + Blue => RgbColor(0, 0, 128), + Magenta => RgbColor(128, 0, 128), + Cyan => RgbColor(0, 128, 128), + White => RgbColor(192, 192, 192), + BrightBlack => RgbColor(128, 128, 128), + BrightRed => RgbColor(255, 0, 0), + BrightGreen => RgbColor(0, 255, 0), + BrightYellow => RgbColor(255, 255, 0), + BrightBlue => RgbColor(0, 0, 255), + BrightMagenta => RgbColor(255, 0, 255), + BrightCyan => RgbColor(0, 255, 255), + BrightWhite => RgbColor(255, 255, 255), + } + } +} + +impl FramebufferColor for RgbColor { + #[inline] + fn pack16(&self) -> u16 { + // BGR565 + ((self.0 as u16 & 0xF8) << 8) | ((self.1 as u16 & 0xFC) << 3) | (self.2 as u16 >> 3) + } + + #[inline] + fn pack32(&self) -> u32 { + // BGRA8888 + // FIXME: qemu and low version RPi use RGBA order for 24/32-bit color depth, + // but RPi3 B+ uses BGRA order for 24/32-bit color depth. + ((self.0 as u32) << 16) | ((self.1 as u32) << 8) | (self.2 as u32) + } +} + +impl FramebufferColor for ConsoleColor { + #[inline] + fn pack16(&self) -> u16 { + RgbColor::from(*self).pack16() + } + + #[inline] + fn pack32(&self) -> u32 { + RgbColor::from(*self).pack32() + } +} diff --git a/kernel/src/arch/aarch64/driver/fonts/font8x16.rs b/kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/fonts/font8x16.rs rename to kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs diff --git a/kernel/src/arch/aarch64/driver/fonts/mod.rs b/kernel/src/arch/aarch64/driver/console/fonts/mod.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/fonts/mod.rs rename to kernel/src/arch/aarch64/driver/console/fonts/mod.rs diff --git a/kernel/src/arch/aarch64/driver/console.rs b/kernel/src/arch/aarch64/driver/console/mod.rs similarity index 77% rename from kernel/src/arch/aarch64/driver/console.rs rename to kernel/src/arch/aarch64/driver/console/mod.rs index 4822e41..89d9135 100644 --- a/kernel/src/arch/aarch64/driver/console.rs +++ b/kernel/src/arch/aarch64/driver/console/mod.rs @@ -1,7 +1,12 @@ //! Framebuffer console display driver for ARM64 -use super::fb::{FramebufferInfo, FRAME_BUFFER}; -use super::fonts::{Font, Font8x16}; +mod color; +mod fonts; + +use self::color::{ConsoleColor, ConsoleColor::*, FramebufferColor}; +use self::fonts::{Font, Font8x16}; + +use super::fb::{ColorDepth::*, FramebufferInfo, FRAME_BUFFER}; use alloc::vec::Vec; use core::fmt; use core::marker::PhantomData; @@ -9,21 +14,28 @@ use lazy_static::lazy_static; use log::*; use spin::Mutex; +#[repr(C)] #[derive(Debug, Clone, Copy, PartialEq)] -struct Color(u8); +struct ColorPair { + foreground: C, + background: C, +} -#[derive(Debug, Clone, Copy, PartialEq)] #[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct ConsoleChar { ascii_char: u8, - color: Color, + color: ColorPair, } impl Default for ConsoleChar { fn default() -> Self { ConsoleChar { ascii_char: b' ', - color: Color(0), + color: ColorPair { + foreground: Black, + background: Black, + }, } } } @@ -47,16 +59,29 @@ impl ConsoleBuffer { } /// Write one character at `(row, col)`. - /// TODO: color fn write(&mut self, row: usize, col: usize, ch: ConsoleChar) { self.buf[row][col] = ch; let off_x = col * F::WIDTH; let off_y = row * F::HEIGHT; if let Some(fb) = FRAME_BUFFER.lock().as_mut() { + let (foreground, background) = match fb.color_depth { + ColorDepth16 => ( + ch.color.foreground.pack16() as u32, + ch.color.background.pack16() as u32, + ), + ColorDepth32 => ( + ch.color.foreground.pack32(), + ch.color.background.pack32(), + ), + }; for y in 0..F::HEIGHT { for x in 0..F::WIDTH { - let pixel = if ch.color.0 != 0 && F::get(ch.ascii_char, x, y) { !0 } else { 0 }; + let pixel = if F::get(ch.ascii_char, x, y) { + foreground + } else { + background + }; fb.write((off_x + x) as u32, (off_y + y) as u32, pixel); } } @@ -70,7 +95,7 @@ impl ConsoleBuffer { /// Insert one blank line at the bottom, and scroll up one line. /// XXX: read framebuffer is toooo slow, do not use `fb.copy()`. - pub fn new_line(&mut self) { + fn new_line(&mut self) { for i in 1..self.num_row { for j in 0..self.num_col { if self.buf[i - 1][j] != self.buf[i][j] { @@ -104,7 +129,7 @@ impl ConsoleBuffer { /// Console structure pub struct Console { /// current color - color: Color, + color: ColorPair, /// cursor row row: usize, /// cursor column @@ -118,7 +143,10 @@ impl Console { let num_row = fb.yres as usize / F::HEIGHT; let num_col = fb.xres as usize / F::WIDTH; Console { - color: Color(1), + color: ColorPair { + foreground: BrightWhite, + background: Black, + }, row: 0, col: 0, buf: ConsoleBuffer::new(num_row, num_col), @@ -134,6 +162,7 @@ impl Console { } } + // TODO: pasre color with ANSI escape sequences fn write_byte(&mut self, byte: u8) { match byte { b'\x7f' => { @@ -164,7 +193,10 @@ impl Console { } pub fn clear(&mut self) { - self.color = Color(1); + self.color = ColorPair { + foreground: BrightWhite, + background: Black, + }; self.row = 0; self.col = 0; self.buf.clear(); diff --git a/kernel/src/arch/aarch64/driver/mod.rs b/kernel/src/arch/aarch64/driver/mod.rs index c7553ff..9c29662 100644 --- a/kernel/src/arch/aarch64/driver/mod.rs +++ b/kernel/src/arch/aarch64/driver/mod.rs @@ -5,8 +5,6 @@ use once::*; pub use self::board::fb; pub use self::board::serial; - -pub mod fonts; pub mod console; /// Initialize ARM64 common drivers diff --git a/kernel/src/arch/aarch64/io.rs b/kernel/src/arch/aarch64/io.rs index cfad9eb..d452fcb 100644 --- a/kernel/src/arch/aarch64/io.rs +++ b/kernel/src/arch/aarch64/io.rs @@ -1,4 +1,4 @@ -//! Serial driver for aarch64. +//! Input/output for aarch64. use super::driver::serial::*; use super::driver::console::CONSOLE;