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.
This commit is contained in:
Bananymous 2023-11-22 21:57:17 +02:00
parent b88a7e0c6b
commit fd18071975
5 changed files with 99 additions and 9 deletions

View File

@ -64,6 +64,7 @@ set(KERNEL_SOURCES
kernel/Storage/StorageDevice.cpp kernel/Storage/StorageDevice.cpp
kernel/Syscall.cpp kernel/Syscall.cpp
kernel/Syscall.S kernel/Syscall.S
kernel/Terminal/FramebufferTerminal.cpp
kernel/Terminal/Serial.cpp kernel/Terminal/Serial.cpp
kernel/Terminal/TTY.cpp kernel/Terminal/TTY.cpp
kernel/Terminal/VesaTerminalDriver.cpp kernel/Terminal/VesaTerminalDriver.cpp

View File

@ -0,0 +1,32 @@
#pragma once
#include <kernel/Device/FramebufferDevice.h>
#include <kernel/Terminal/TerminalDriver.h>
namespace Kernel
{
class FramebufferTerminalDriver final : public TerminalDriver
{
public:
static FramebufferTerminalDriver* create(BAN::RefPtr<FramebufferDevice>);
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<FramebufferDevice> framebuffer_device)
: m_framebuffer_device(framebuffer_device)
{ }
private:
BAN::RefPtr<FramebufferDevice> m_framebuffer_device;
static constexpr Color s_cursor_color = TerminalColor::BRIGHT_WHITE;
};
}

View File

@ -23,10 +23,6 @@ namespace Kernel
MUST(s_instance->TmpFileSystem::initialize(0755, 0, 0)); MUST(s_instance->TmpFileSystem::initialize(0755, 0, 0));
s_instance->add_device(MUST(NullDevice::create(0666, 0, 0))); s_instance->add_device(MUST(NullDevice::create(0666, 0, 0)));
s_instance->add_device(MUST(ZeroDevice::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() DevFileSystem& DevFileSystem::get()

View File

@ -0,0 +1,58 @@
#include <kernel/Terminal/FramebufferTerminal.h>
namespace Kernel
{
FramebufferTerminalDriver* FramebufferTerminalDriver::create(BAN::RefPtr<FramebufferDevice> 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);
}
}

View File

@ -2,6 +2,7 @@
#include <kernel/Arch.h> #include <kernel/Arch.h>
#include <kernel/BootInfo.h> #include <kernel/BootInfo.h>
#include <kernel/Debug.h> #include <kernel/Debug.h>
#include <kernel/Device/FramebufferDevice.h>
#include <kernel/FS/DevFS/FileSystem.h> #include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/ProcFS/FileSystem.h> #include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h> #include <kernel/FS/VirtualFileSystem.h>
@ -20,7 +21,7 @@
#include <kernel/Syscall.h> #include <kernel/Syscall.h>
#include <kernel/Terminal/Serial.h> #include <kernel/Terminal/Serial.h>
#include <kernel/Terminal/VirtualTTY.h> #include <kernel/Terminal/VirtualTTY.h>
#include <kernel/Terminal/VesaTerminalDriver.h> #include <kernel/Terminal/FramebufferTerminal.h>
#include <kernel/Timer/Timer.h> #include <kernel/Timer/Timer.h>
struct ParsedCommandLine struct ParsedCommandLine
@ -108,10 +109,6 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
PageTable::initialize(); PageTable::initialize();
dprintln("PageTable initialized"); dprintln("PageTable initialized");
g_terminal_driver = VesaTerminalDriver::create();
if (g_terminal_driver)
dprintln("VESA initialized");
Heap::initialize(); Heap::initialize();
dprintln("Heap initialzed"); dprintln("Heap initialzed");
@ -130,6 +127,12 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
DevFileSystem::initialize(); DevFileSystem::initialize();
dprintln("devfs initialized"); 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(); ProcFileSystem::initialize();
dprintln("procfs initialized"); dprintln("procfs initialized");