aarch64/fb: add foreground & background color

master
equation314 6 years ago
parent 9dda78d2e3
commit 6c717905d7

@ -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),
}
}

@ -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<ConsoleColor> 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()
}
}

@ -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<C: FramebufferColor> {
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<ConsoleColor>,
}
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<F: Font> ConsoleBuffer<F> {
}
/// 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<F: Font> ConsoleBuffer<F> {
/// 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<F: Font> ConsoleBuffer<F> {
/// Console structure
pub struct Console<F: Font> {
/// current color
color: Color,
color: ColorPair<ConsoleColor>,
/// cursor row
row: usize,
/// cursor column
@ -118,7 +143,10 @@ impl<F: Font> Console<F> {
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<F: Font> Console<F> {
}
}
// TODO: pasre color with ANSI escape sequences
fn write_byte(&mut self, byte: u8) {
match byte {
b'\x7f' => {
@ -164,7 +193,10 @@ impl<F: Font> Console<F> {
}
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();

@ -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

@ -1,4 +1,4 @@
//! Serial driver for aarch64.
//! Input/output for aarch64.
use super::driver::serial::*;
use super::driver::console::CONSOLE;

Loading…
Cancel
Save