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");