Kernel: Add per terminal palette for TerminalDriver

This allows better color approximation on text mode and in future will
allow user to possibly change the palette
This commit is contained in:
2025-04-23 18:44:37 +03:00
parent 4d840a8d9a
commit cc7c1ad30d
9 changed files with 121 additions and 102 deletions

View File

@@ -104,7 +104,7 @@ namespace Debug
{
if (!isprint(ch))
ch = '?';
g_terminal_driver->putchar_at(ch, col, row, TerminalColor::BRIGHT_WHITE, TerminalColor::BLACK);
g_terminal_driver->putchar_at(ch, col, row, TerminalColor::WHITE, TerminalColor::BLACK);
col++;
if (col >= g_terminal_driver->width())
@@ -121,9 +121,9 @@ namespace Debug
{
for (uint32_t i = col; i < g_terminal_driver->width(); i++)
{
g_terminal_driver->putchar_at(' ', i, row, TerminalColor::BRIGHT_WHITE, TerminalColor::BLACK);
g_terminal_driver->putchar_at(' ', i, row, TerminalColor::WHITE, TerminalColor::BLACK);
if (row + 1 < g_terminal_driver->height())
g_terminal_driver->putchar_at(' ', i, row + 1, TerminalColor::BRIGHT_WHITE, TerminalColor::BLACK);
g_terminal_driver->putchar_at(' ', i, row + 1, TerminalColor::WHITE, TerminalColor::BLACK);
}
}
}

View File

@@ -360,7 +360,7 @@ namespace Kernel
[&x, y](char ch)
{
if (x < g_terminal_driver->width() && y < g_terminal_driver->height())
g_terminal_driver->putchar_at(ch, x++, y, TerminalColor::BRIGHT_WHITE, TerminalColor::BLACK);
g_terminal_driver->putchar_at(ch, x++, y, TerminalColor::WHITE, TerminalColor::BLACK);
};
BAN::Formatter::print(proc_putc, "CPU { 2}: { 3}.{3}%", current_id(), load_x1000 / 1000, load_x1000 % 1000);

View File

@@ -3,15 +3,38 @@
namespace Kernel
{
static consteval TerminalDriver::Palette default_palette()
{
TerminalDriver::Palette palette;
palette[ 0] = 0x000000;
palette[ 1] = 0xFF0000;
palette[ 2] = 0x00FF00;
palette[ 3] = 0xFFFF00;
palette[ 4] = 0x0000FF;
palette[ 5] = 0xFF00FF;
palette[ 6] = 0x00FFFF;
palette[ 7] = 0xBFBFBF;
palette[ 8] = 0x3F3F3F;
palette[ 9] = 0xFF7F7F;
palette[10] = 0x7FFF7F;
palette[11] = 0xFFFF7F;
palette[12] = 0x7F7FFF;
palette[13] = 0xFF7FFF;
palette[14] = 0x7FFFFF;
palette[15] = 0xFFFFFF;
return palette;
}
BAN::ErrorOr<BAN::RefPtr<FramebufferTerminalDriver>> FramebufferTerminalDriver::create(BAN::RefPtr<FramebufferDevice> framebuffer_device)
{
auto* driver_ptr = new FramebufferTerminalDriver(framebuffer_device);
auto* driver_ptr = new FramebufferTerminalDriver(framebuffer_device, default_palette());
if (driver_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto driver = BAN::RefPtr<FramebufferTerminalDriver>::adopt(driver_ptr);
TRY(driver->set_font(BAN::move(TRY(LibFont::Font::prefs()))));
driver->set_cursor_position(0, 0);
driver->clear(TerminalColor::BLACK);
driver->clear(driver->m_palette[0]);
return driver;
}
@@ -60,6 +83,9 @@ namespace Kernel
for (uint32_t x = 0; x < m_framebuffer_device->width(); x++)
m_framebuffer_device->set_pixel(x, y, color.rgb);
m_framebuffer_device->sync_pixels_full();
if (m_cursor_shown)
show_cursor(false);
}
void FramebufferTerminalDriver::read_cursor()

View File

@@ -7,36 +7,39 @@
namespace Kernel
{
static constexpr TerminalDriver::Color s_palette[] {
TerminalColor::BLACK,
TerminalColor::BLUE,
TerminalColor::GREEN,
TerminalColor::CYAN,
TerminalColor::RED,
TerminalColor::MAGENTA,
TerminalColor::YELLOW,
TerminalColor::WHITE,
TerminalColor::BRIGHT_BLACK,
TerminalColor::BRIGHT_BLUE,
TerminalColor::BRIGHT_GREEN,
TerminalColor::BRIGHT_CYAN,
TerminalColor::BRIGHT_RED,
TerminalColor::BRIGHT_MAGENTA,
TerminalColor::BRIGHT_YELLOW,
TerminalColor::BRIGHT_WHITE,
};
static consteval TerminalDriver::Palette default_palette()
{
TerminalDriver::Palette palette;
palette[ 0] = 0x000000;
palette[ 1] = 0x0000AA;
palette[ 2] = 0x00AA00;
palette[ 3] = 0x00AAAA;
palette[ 4] = 0xAA0000;
palette[ 5] = 0xAA00AA;
palette[ 6] = 0xAA5500;
palette[ 7] = 0xAAAAAA;
palette[ 8] = 0x555555;
palette[ 9] = 0x5555FF;
palette[10] = 0x55FF55;
palette[11] = 0x55FFFF;
palette[12] = 0xFF5555;
palette[13] = 0xFF55FF;
palette[14] = 0xFFFF55;
palette[15] = 0xFFFFFF;
return palette;
}
static constexpr uint8_t color_to_text_mode_color(TerminalDriver::Color color)
{
uint32_t min_diff = BAN::numeric_limits<uint32_t>::max();
uint8_t closest = 0;
static_assert(sizeof(s_palette) / sizeof(*s_palette) == 16);
static_assert(default_palette().size() == 16);
for (size_t i = 0; i < 16; i++)
{
const auto rdiff = color.red() - s_palette[i].red();
const auto gdiff = color.green() - s_palette[i].green();
const auto bdiff = color.blue() - s_palette[i].blue();
const auto rdiff = color.red() - default_palette()[i].red();
const auto gdiff = color.green() - default_palette()[i].green();
const auto bdiff = color.blue() - default_palette()[i].blue();
const uint32_t diff = rdiff*rdiff + gdiff*gdiff + bdiff*bdiff;
if (diff >= min_diff)
continue;
@@ -56,7 +59,8 @@ namespace Kernel
g_boot_info.framebuffer.address,
g_boot_info.framebuffer.width,
g_boot_info.framebuffer.height,
g_boot_info.framebuffer.pitch
g_boot_info.framebuffer.pitch,
default_palette()
);
if (driver_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
@@ -83,7 +87,7 @@ namespace Kernel
m_vaddr = vaddr + (m_paddr % PAGE_SIZE);
set_cursor_position(0, 0);
clear(TerminalColor::BLACK);
clear(m_palette[0]);
return {};
}
@@ -114,7 +118,7 @@ namespace Kernel
{
for (uint32_t y = 0; y < m_height; y++)
for (uint32_t x = 0; x < m_width; x++)
putchar_at(' ', x, y, TerminalColor::BRIGHT_WHITE, color);
putchar_at(' ', x, y, color, color);
}
void TextModeTerminalDriver::set_cursor_shown(bool shown)

View File

@@ -39,6 +39,9 @@ namespace Kernel
: TTY(0600, 0, 0)
, m_name(MUST(BAN::String::formatted("tty{}", s_next_tty_number++)))
, m_terminal_driver(driver)
, m_palette(driver->palette())
, m_foreground(m_palette[15])
, m_background(m_palette[0])
{
m_width = m_terminal_driver->width();
m_height = m_terminal_driver->height();
@@ -95,10 +98,11 @@ namespace Kernel
void VirtualTTY::reset_ansi()
{
ASSERT(m_write_lock.current_processor_has_lock());
m_ansi_state.index = 0;
m_ansi_state.nums[0] = -1;
m_ansi_state.nums[1] = -1;
m_ansi_state.question = false;
m_ansi_state = {
.nums = { -1, -1, -1, -1, -1 },
.index = 0,
.question = false,
};
m_state = State::Normal;
}
@@ -108,49 +112,29 @@ namespace Kernel
switch (ch)
{
case 0:
m_foreground = TerminalColor::BRIGHT_WHITE;
m_background = TerminalColor::BLACK;
m_foreground = m_palette[15];
m_background = m_palette[0];
m_colors_inverted = false;
break;
case 7: m_colors_inverted = true; break;
case 27: m_colors_inverted = false; break;
case 30: m_foreground = TerminalColor::BLACK; break;
case 31: m_foreground = TerminalColor::RED; break;
case 32: m_foreground = TerminalColor::GREEN; break;
case 33: m_foreground = TerminalColor::YELLOW; break;
case 34: m_foreground = TerminalColor::BLUE; break;
case 35: m_foreground = TerminalColor::MAGENTA; break;
case 36: m_foreground = TerminalColor::CYAN; break;
case 37: m_foreground = TerminalColor::WHITE; break;
case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
m_foreground = m_palette[ch - 30];
break;
case 40: m_background = TerminalColor::BLACK; break;
case 41: m_background = TerminalColor::RED; break;
case 42: m_background = TerminalColor::GREEN; break;
case 43: m_background = TerminalColor::YELLOW; break;
case 44: m_background = TerminalColor::BLUE; break;
case 45: m_background = TerminalColor::MAGENTA; break;
case 46: m_background = TerminalColor::CYAN; break;
case 47: m_background = TerminalColor::WHITE; break;
case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47:
m_background = m_palette[ch - 40];
break;
case 90: m_foreground = TerminalColor::BRIGHT_BLACK; break;
case 91: m_foreground = TerminalColor::BRIGHT_RED; break;
case 92: m_foreground = TerminalColor::BRIGHT_GREEN; break;
case 93: m_foreground = TerminalColor::BRIGHT_YELLOW; break;
case 94: m_foreground = TerminalColor::BRIGHT_BLUE; break;
case 95: m_foreground = TerminalColor::BRIGHT_MAGENTA; break;
case 96: m_foreground = TerminalColor::BRIGHT_CYAN; break;
case 97: m_foreground = TerminalColor::BRIGHT_WHITE; break;
case 90: case 91: case 92: case 93: case 94: case 95: case 96: case 97:
m_foreground = m_palette[ch - 90 + 8];
break;
case 100: m_background = TerminalColor::BRIGHT_BLACK; break;
case 101: m_background = TerminalColor::BRIGHT_RED; break;
case 102: m_background = TerminalColor::BRIGHT_GREEN; break;
case 103: m_background = TerminalColor::BRIGHT_YELLOW; break;
case 104: m_background = TerminalColor::BRIGHT_BLUE; break;
case 105: m_background = TerminalColor::BRIGHT_MAGENTA; break;
case 106: m_background = TerminalColor::BRIGHT_CYAN; break;
case 107: m_background = TerminalColor::BRIGHT_WHITE; break;
case 100: case 101: case 102: case 103: case 104: case 105: case 106: case 107:
m_background = m_palette[ch - 100 + 8];
break;
}
}