Kernel: Implement fast scrolling for TTY

This commit is contained in:
Bananymous 2024-06-28 23:15:03 +03:00
parent 010c2c934b
commit 42237a3bc8
6 changed files with 46 additions and 6 deletions

View File

@ -17,6 +17,10 @@ namespace Kernel
void set_pixel(uint32_t x, uint32_t y, uint32_t rgb);
// positive rows -> empty pixels on bottom
// negative rows -> empty pixels on top
void scroll(int32_t rows, uint32_t rgb);
void sync_pixels_full();
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);

View File

@ -15,6 +15,7 @@ namespace Kernel
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 bool scroll(Color) override;
virtual void clear(Color) override;
virtual void set_cursor_position(uint32_t, uint32_t) override;

View File

@ -31,6 +31,7 @@ namespace Kernel
virtual uint32_t height() const = 0;
virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) = 0;
virtual bool scroll(Color) { return false; }
virtual void clear(Color) = 0;
virtual void set_cursor_position(uint32_t, uint32_t) = 0;

View File

@ -135,6 +135,25 @@ namespace Kernel
video_buffer_u8[(y * m_width + x) * (BANAN_FB_BPP / 8) + 3] = rgb >> 24;
}
void FramebufferDevice::scroll(int32_t rows, uint32_t rgb)
{
if (rows == 0)
return;
rows = BAN::Math::clamp<int32_t>(rows, -m_height, m_height);
const uint32_t abs_rows = BAN::Math::abs(rows);
auto* video_buffer_u8 = reinterpret_cast<uint8_t*>(m_video_buffer->vaddr());
uint8_t* src = (rows < 0) ? video_buffer_u8 : &video_buffer_u8[(abs_rows * m_width) * (BANAN_FB_BPP / 8)];
uint8_t* dst = (rows > 0) ? video_buffer_u8 : &video_buffer_u8[(abs_rows * m_width) * (BANAN_FB_BPP / 8)];
memmove(dst, src, (m_height - abs_rows) * m_width * (BANAN_FB_BPP / 8));
uint32_t start_y = (rows < 0) ? 0 : m_height - abs_rows;
uint32_t stop_y = (rows < 0) ? abs_rows : m_height;
for (uint32_t y = start_y; y < stop_y; y++)
for (uint32_t x = 0; x < m_width; x++)
set_pixel(x, y, rgb);
}
void FramebufferDevice::sync_pixels_full()
{
auto* video_memory_u8 = reinterpret_cast<uint8_t*>(m_video_memory_vaddr);

View File

@ -33,6 +33,13 @@ namespace Kernel
m_framebuffer_device->sync_pixels_rectangle(x, y, font().width(), font().height());
}
bool FramebufferTerminalDriver::scroll(Color color)
{
m_framebuffer_device->scroll(font().height(), color.rgb);
m_framebuffer_device->sync_pixels_full();
return true;
}
void FramebufferTerminalDriver::clear(Color color)
{
for (uint32_t y = 0; y < m_framebuffer_device->height(); y++)

View File

@ -99,8 +99,8 @@ namespace Kernel
render_from_buffer(last_x, last_y);
if (m_show_cursor)
m_terminal_driver->set_cursor_position(x, y);
last_x = m_column = x;
last_y = m_row = y;
last_x = x;
last_y = y;
}
void VirtualTTY::reset_ansi()
@ -410,10 +410,18 @@ namespace Kernel
for (uint32_t x = 0; x < m_width; x++)
m_buffer[(m_height - 1) * m_width + x] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' };
// Render the whole buffer to the screen
for (uint32_t y = 0; y < m_height; y++)
for (uint32_t x = 0; x < m_width; x++)
render_from_buffer(x, y);
// hide cursor during scrolling
bool old_show_cursor = m_show_cursor;
m_show_cursor = false;
set_cursor_position(0, 0);
if (!m_terminal_driver->scroll(m_background))
{
// No fast scrolling, render the whole buffer to the screen
for (uint32_t y = 0; y < m_height; y++)
for (uint32_t x = 0; x < m_width; x++)
render_from_buffer(x, y);
}
m_show_cursor = old_show_cursor;
m_column = 0;
m_row--;