From cc7c1ad30da158b3b2df9b13cd9e59697677c5f8 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 23 Apr 2025 18:44:37 +0300 Subject: [PATCH] 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 --- .../kernel/Terminal/FramebufferTerminal.h | 9 +-- .../include/kernel/Terminal/TerminalDriver.h | 38 ++++++------ .../kernel/Terminal/TextModeTerminal.h | 7 ++- kernel/include/kernel/Terminal/VirtualTTY.h | 17 ++++-- kernel/kernel/Debug.cpp | 6 +- kernel/kernel/Processor.cpp | 2 +- .../kernel/Terminal/FramebufferTerminal.cpp | 30 +++++++++- kernel/kernel/Terminal/TextModeTerminal.cpp | 54 +++++++++-------- kernel/kernel/Terminal/VirtualTTY.cpp | 60 +++++++------------ 9 files changed, 121 insertions(+), 102 deletions(-) diff --git a/kernel/include/kernel/Terminal/FramebufferTerminal.h b/kernel/include/kernel/Terminal/FramebufferTerminal.h index 30120028..fda9da3a 100644 --- a/kernel/include/kernel/Terminal/FramebufferTerminal.h +++ b/kernel/include/kernel/Terminal/FramebufferTerminal.h @@ -27,9 +27,10 @@ namespace Kernel const LibFont::Font& font() const override { return m_font; }; private: - FramebufferTerminalDriver(BAN::RefPtr framebuffer_device) - : m_framebuffer_device(framebuffer_device) - { } + FramebufferTerminalDriver(BAN::RefPtr framebuffer_device, const Palette& palette) + : TerminalDriver(palette) + , m_framebuffer_device(framebuffer_device) + {} void read_cursor(); void show_cursor(bool use_data); @@ -42,7 +43,7 @@ namespace Kernel uint32_t m_cursor_y { 0 }; bool m_cursor_shown { true }; BAN::Vector m_cursor_data; - static constexpr Color m_cursor_color = TerminalColor::BRIGHT_WHITE; + static constexpr Color m_cursor_color = TerminalColor::WHITE; }; } diff --git a/kernel/include/kernel/Terminal/TerminalDriver.h b/kernel/include/kernel/Terminal/TerminalDriver.h index 3a5fb0bf..6eb964df 100644 --- a/kernel/include/kernel/Terminal/TerminalDriver.h +++ b/kernel/include/kernel/Terminal/TerminalDriver.h @@ -12,20 +12,28 @@ namespace Kernel public: struct Color { + constexpr Color() + : rgb(0) + { } constexpr Color(uint32_t rgb) : rgb(rgb) { } constexpr Color(uint8_t r, uint8_t g, uint8_t b) : rgb(((uint32_t)r << 16) | ((uint32_t)g << 8) | b) { } - uint8_t red() const { return (rgb >> 0x10) & 0xFF; } - uint8_t green() const { return (rgb >> 0x08) & 0xFF; } - uint8_t blue() const { return (rgb >> 0x00) & 0xFF; } + constexpr uint8_t red() const { return (rgb >> 0x10) & 0xFF; } + constexpr uint8_t green() const { return (rgb >> 0x08) & 0xFF; } + constexpr uint8_t blue() const { return (rgb >> 0x00) & 0xFF; } uint32_t rgb; }; + using Palette = BAN::Array; + public: static BAN::ErrorOr initialize_from_boot_info(); + TerminalDriver(const Palette& palette) + : m_palette(palette) + {} virtual ~TerminalDriver() {} virtual uint32_t width() const = 0; virtual uint32_t height() const = 0; @@ -40,29 +48,19 @@ namespace Kernel virtual bool has_font() const { return false; } virtual BAN::ErrorOr set_font(LibFont::Font&&) { return BAN::Error::from_errno(EINVAL); } virtual const LibFont::Font& font() const { ASSERT_NOT_REACHED(); } + + const Palette& palette() const { return m_palette; } + + protected: + Palette m_palette; }; extern BAN::RefPtr g_terminal_driver; namespace TerminalColor { - static constexpr TerminalDriver::Color BLACK = 0x000000; - static constexpr TerminalDriver::Color RED = 0xFF0000; - static constexpr TerminalDriver::Color GREEN = 0x00FF00; - static constexpr TerminalDriver::Color YELLOW = 0xFFFF00; - static constexpr TerminalDriver::Color BLUE = 0x0000FF; - static constexpr TerminalDriver::Color MAGENTA = 0xFF00FF; - static constexpr TerminalDriver::Color CYAN = 0x00FFFF; - static constexpr TerminalDriver::Color WHITE = 0xBFBFBF; - - static constexpr TerminalDriver::Color BRIGHT_BLACK = 0x3F3F3F; - static constexpr TerminalDriver::Color BRIGHT_RED = 0xFF7F7F; - static constexpr TerminalDriver::Color BRIGHT_GREEN = 0x7FFF7F; - static constexpr TerminalDriver::Color BRIGHT_YELLOW = 0xFFFF7F; - static constexpr TerminalDriver::Color BRIGHT_BLUE = 0x7F7FFF; - static constexpr TerminalDriver::Color BRIGHT_MAGENTA = 0xFF7FFF; - static constexpr TerminalDriver::Color BRIGHT_CYAN = 0x7FFFFF; - static constexpr TerminalDriver::Color BRIGHT_WHITE = 0xFFFFFF; + constexpr TerminalDriver::Color BLACK = 0x000000; + constexpr TerminalDriver::Color WHITE = 0xFFFFFF; } } diff --git a/kernel/include/kernel/Terminal/TextModeTerminal.h b/kernel/include/kernel/Terminal/TextModeTerminal.h index 0dcf88fb..e2971938 100644 --- a/kernel/include/kernel/Terminal/TextModeTerminal.h +++ b/kernel/include/kernel/Terminal/TextModeTerminal.h @@ -21,8 +21,9 @@ namespace Kernel void set_cursor_position(uint32_t, uint32_t) override; private: - TextModeTerminalDriver(paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch) - : m_paddr(paddr) + TextModeTerminalDriver(paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, const Palette& palette) + : TerminalDriver(palette) + , m_paddr(paddr) , m_width(width) , m_height(height) , m_pitch(pitch) @@ -36,7 +37,7 @@ namespace Kernel const uint32_t m_height; const uint32_t m_pitch; vaddr_t m_vaddr { 0 }; - static constexpr Color s_cursor_color = TerminalColor::BRIGHT_WHITE; + static constexpr Color s_cursor_color = TerminalColor::WHITE; }; } diff --git a/kernel/include/kernel/Terminal/VirtualTTY.h b/kernel/include/kernel/Terminal/VirtualTTY.h index 99c10901..d1cd0f35 100644 --- a/kernel/include/kernel/Terminal/VirtualTTY.h +++ b/kernel/include/kernel/Terminal/VirtualTTY.h @@ -11,6 +11,9 @@ namespace Kernel class VirtualTTY : public TTY { + public: + using Palette = TerminalDriver::Palette; + public: static BAN::ErrorOr> create(BAN::RefPtr); @@ -60,14 +63,16 @@ namespace Kernel struct Cell { - TerminalDriver::Color foreground { TerminalColor::BRIGHT_WHITE }; - TerminalDriver::Color background { TerminalColor::BLACK }; + TerminalDriver::Color foreground; + TerminalDriver::Color background; uint32_t codepoint { ' ' }; }; private: BAN::String m_name; + BAN::RefPtr m_terminal_driver; + State m_state { State::Normal }; AnsiState m_ansi_state { }; UTF8State m_utf8_state { }; @@ -84,11 +89,11 @@ namespace Kernel uint32_t m_column { 0 }; Cell* m_buffer { nullptr }; - TerminalDriver::Color m_foreground { TerminalColor::BRIGHT_WHITE }; - TerminalDriver::Color m_background { TerminalColor::BLACK }; - bool m_colors_inverted { false }; + const Palette& m_palette; - BAN::RefPtr m_terminal_driver; + TerminalDriver::Color m_foreground; + TerminalDriver::Color m_background; + bool m_colors_inverted { false }; }; } diff --git a/kernel/kernel/Debug.cpp b/kernel/kernel/Debug.cpp index 1eb0a58c..c9034df2 100644 --- a/kernel/kernel/Debug.cpp +++ b/kernel/kernel/Debug.cpp @@ -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); } } } diff --git a/kernel/kernel/Processor.cpp b/kernel/kernel/Processor.cpp index ae6dc1a4..9dd0bbce 100644 --- a/kernel/kernel/Processor.cpp +++ b/kernel/kernel/Processor.cpp @@ -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); diff --git a/kernel/kernel/Terminal/FramebufferTerminal.cpp b/kernel/kernel/Terminal/FramebufferTerminal.cpp index d573dc80..25ae047a 100644 --- a/kernel/kernel/Terminal/FramebufferTerminal.cpp +++ b/kernel/kernel/Terminal/FramebufferTerminal.cpp @@ -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> FramebufferTerminalDriver::create(BAN::RefPtr 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::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() diff --git a/kernel/kernel/Terminal/TextModeTerminal.cpp b/kernel/kernel/Terminal/TextModeTerminal.cpp index 63d30665..a5830215 100644 --- a/kernel/kernel/Terminal/TextModeTerminal.cpp +++ b/kernel/kernel/Terminal/TextModeTerminal.cpp @@ -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::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) diff --git a/kernel/kernel/Terminal/VirtualTTY.cpp b/kernel/kernel/Terminal/VirtualTTY.cpp index 8ebd5f1f..5aa6b9a5 100644 --- a/kernel/kernel/Terminal/VirtualTTY.cpp +++ b/kernel/kernel/Terminal/VirtualTTY.cpp @@ -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; } }