From fd18071975a47fe469be4c80d03a375779e3691c Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 22 Nov 2023 21:57:17 +0200 Subject: [PATCH] Kernel: Implement TerminalDriver for Framebuffer device Use this new FramebufferTerminalDriver for terminal instead of the old VesaTerminalDriver. Only drawback with this is that framebuffer device can only be intialized after DevFS is initialized. --- kernel/CMakeLists.txt | 1 + .../kernel/Terminal/FramebufferTerminal.h | 32 ++++++++++ kernel/kernel/FS/DevFS/FileSystem.cpp | 4 -- .../kernel/Terminal/FramebufferTerminal.cpp | 58 +++++++++++++++++++ kernel/kernel/kernel.cpp | 13 +++-- 5 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 kernel/include/kernel/Terminal/FramebufferTerminal.h create mode 100644 kernel/kernel/Terminal/FramebufferTerminal.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index cbf01af573..5b86f3a589 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -64,6 +64,7 @@ set(KERNEL_SOURCES kernel/Storage/StorageDevice.cpp kernel/Syscall.cpp kernel/Syscall.S + kernel/Terminal/FramebufferTerminal.cpp kernel/Terminal/Serial.cpp kernel/Terminal/TTY.cpp kernel/Terminal/VesaTerminalDriver.cpp diff --git a/kernel/include/kernel/Terminal/FramebufferTerminal.h b/kernel/include/kernel/Terminal/FramebufferTerminal.h new file mode 100644 index 0000000000..299912d35c --- /dev/null +++ b/kernel/include/kernel/Terminal/FramebufferTerminal.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +namespace Kernel +{ + + class FramebufferTerminalDriver final : public TerminalDriver + { + public: + static FramebufferTerminalDriver* create(BAN::RefPtr); + + virtual uint32_t width() const override { return m_framebuffer_device->width() / font().width(); } + virtual uint32_t height() const override { return m_framebuffer_device->height() / font().height(); } + + virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) override; + virtual void clear(Color) override; + + virtual void set_cursor_position(uint32_t, uint32_t) override; + + private: + FramebufferTerminalDriver(BAN::RefPtr framebuffer_device) + : m_framebuffer_device(framebuffer_device) + { } + + private: + BAN::RefPtr m_framebuffer_device; + static constexpr Color s_cursor_color = TerminalColor::BRIGHT_WHITE; + }; + +} diff --git a/kernel/kernel/FS/DevFS/FileSystem.cpp b/kernel/kernel/FS/DevFS/FileSystem.cpp index de6da04ef8..e3c85b4a02 100644 --- a/kernel/kernel/FS/DevFS/FileSystem.cpp +++ b/kernel/kernel/FS/DevFS/FileSystem.cpp @@ -23,10 +23,6 @@ namespace Kernel MUST(s_instance->TmpFileSystem::initialize(0755, 0, 0)); s_instance->add_device(MUST(NullDevice::create(0666, 0, 0))); s_instance->add_device(MUST(ZeroDevice::create(0666, 0, 0))); - - auto fbdev_or_error = FramebufferDevice::create_from_boot_framebuffer(); - if (!fbdev_or_error.is_error()) - s_instance->add_device(fbdev_or_error.release_value()); } DevFileSystem& DevFileSystem::get() diff --git a/kernel/kernel/Terminal/FramebufferTerminal.cpp b/kernel/kernel/Terminal/FramebufferTerminal.cpp new file mode 100644 index 0000000000..db10f46f75 --- /dev/null +++ b/kernel/kernel/Terminal/FramebufferTerminal.cpp @@ -0,0 +1,58 @@ +#include + +namespace Kernel +{ + + FramebufferTerminalDriver* FramebufferTerminalDriver::create(BAN::RefPtr framebuffer_device) + { + auto* driver = new FramebufferTerminalDriver(framebuffer_device); + if (driver == nullptr) + return nullptr; + driver->set_cursor_position(0, 0); + driver->clear(TerminalColor::BLACK); + return driver; + } + + void FramebufferTerminalDriver::putchar_at(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg) + { + const uint8_t* glyph = font().has_glyph(ch) ? font().glyph(ch) : font().glyph('?'); + + x *= font().width(); + y *= font().height(); + + for (uint32_t dy = 0; dy < font().height() && y + dy < m_framebuffer_device->height(); dy++) + { + for (uint32_t dx = 0; dx < font().width() && x + dx < m_framebuffer_device->width(); dx++) + { + const uint8_t bitmask = 1 << (font().width() - dx - 1); + const auto color = glyph[dy * font().pitch()] & bitmask ? fg : bg; + m_framebuffer_device->set_pixel(x + dx, y + dy, color.rgb); + } + } + + m_framebuffer_device->sync_pixels_rectangle(x, y, font().width(), font().height()); + } + + void FramebufferTerminalDriver::clear(Color color) + { + for (uint32_t y = 0; y < m_framebuffer_device->height(); y++) + 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(); + } + + void FramebufferTerminalDriver::set_cursor_position(uint32_t x, uint32_t y) + { + const uint32_t cursor_h = font().height() / 8; + const uint32_t cursor_top = font().height() * 13 / 16; + + x *= font().width(); + y *= font().height(); + + for (uint32_t dy = 0; dy < cursor_h; dy++) + for (uint32_t dx = 0; dx < font().width(); dx++) + m_framebuffer_device->set_pixel(x + dx, y + cursor_top + dy, s_cursor_color.rgb); + m_framebuffer_device->sync_pixels_rectangle(x, y + cursor_top, font().width(), cursor_h); + } + +} diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 047712de14..c7193fcad9 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -20,7 +21,7 @@ #include #include #include -#include +#include #include struct ParsedCommandLine @@ -108,10 +109,6 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info) PageTable::initialize(); dprintln("PageTable initialized"); - g_terminal_driver = VesaTerminalDriver::create(); - if (g_terminal_driver) - dprintln("VESA initialized"); - Heap::initialize(); dprintln("Heap initialzed"); @@ -130,6 +127,12 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info) DevFileSystem::initialize(); dprintln("devfs initialized"); + auto framebuffer_device = FramebufferDevice::create_from_boot_framebuffer(); + if (!framebuffer_device.is_error()) + g_terminal_driver = FramebufferTerminalDriver::create(framebuffer_device.value()); + if (g_terminal_driver) + dprintln("Framebuffer terminal initialized"); + ProcFileSystem::initialize(); dprintln("procfs initialized");