mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:47:34 +00:00
Terminal: optimize repaints a bunch.
We track dirty character cells + pending whole-terminal scrolls. This drastically reduces the number of pixels pushed.
This commit is contained in:
parent
e452303c66
commit
d0137f0e96
3 changed files with 35 additions and 7 deletions
|
@ -2,10 +2,13 @@
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
#include <Widgets/Font.h>
|
#include <Widgets/Font.h>
|
||||||
#include <Widgets/Painter.h>
|
#include <Widgets/Painter.h>
|
||||||
|
#include <AK/StdLibExtras.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <gui.h>
|
#include <gui.h>
|
||||||
|
|
||||||
|
#define FAST_SCROLL
|
||||||
|
|
||||||
void Terminal::create_window()
|
void Terminal::create_window()
|
||||||
{
|
{
|
||||||
auto& font = Font::defaultFont();
|
auto& font = Font::defaultFont();
|
||||||
|
@ -278,6 +281,13 @@ void Terminal::scroll_up()
|
||||||
{
|
{
|
||||||
if (m_cursor_row == (rows() - 1)) {
|
if (m_cursor_row == (rows() - 1)) {
|
||||||
memcpy(m_buffer, m_buffer + m_columns, m_columns * (m_rows - 1));
|
memcpy(m_buffer, m_buffer + m_columns, m_columns * (m_rows - 1));
|
||||||
|
#ifdef FAST_SCROLL
|
||||||
|
++m_rows_to_scroll_backing_store;
|
||||||
|
#else
|
||||||
|
for (size_t i = 0; i < m_rows * m_columns; ++i) {
|
||||||
|
m_attributes[i].dirty = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
memset(&m_buffer[(m_rows - 1) * m_columns], ' ', m_columns);
|
memset(&m_buffer[(m_rows - 1) * m_columns], ' ', m_columns);
|
||||||
memcpy(m_attributes, m_attributes + m_columns, m_columns * (m_rows - 1) * sizeof(Attribute));
|
memcpy(m_attributes, m_attributes + m_columns, m_columns * (m_rows - 1) * sizeof(Attribute));
|
||||||
for (size_t i = 0; i < m_columns; ++i)
|
for (size_t i = 0; i < m_columns; ++i)
|
||||||
|
@ -390,14 +400,32 @@ void Terminal::paint()
|
||||||
Rect rect { 0, 0, m_pixel_width, m_pixel_height };
|
Rect rect { 0, 0, m_pixel_width, m_pixel_height };
|
||||||
Font& font = Font::defaultFont();
|
Font& font = Font::defaultFont();
|
||||||
Painter painter(*m_backing);
|
Painter painter(*m_backing);
|
||||||
|
int line_height = Font::defaultFont().glyphHeight() + m_line_spacing;
|
||||||
|
#ifdef FAST_SCROLL
|
||||||
|
if (m_rows_to_scroll_backing_store && m_rows_to_scroll_backing_store < m_rows) {
|
||||||
|
int first_scanline = m_inset;
|
||||||
|
int second_scanline = m_inset + (m_rows_to_scroll_backing_store * line_height);
|
||||||
|
int num_rows_to_memcpy = m_rows - m_rows_to_scroll_backing_store;
|
||||||
|
int scanlines_to_copy = (num_rows_to_memcpy * line_height) - m_line_spacing;
|
||||||
|
fast_dword_copy(
|
||||||
|
m_backing->scanline(first_scanline),
|
||||||
|
m_backing->scanline(second_scanline),
|
||||||
|
scanlines_to_copy * m_pixel_width
|
||||||
|
);
|
||||||
|
}
|
||||||
|
m_rows_to_scroll_backing_store = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (word row = 0; row < m_rows; ++row) {
|
for (word row = 0; row < m_rows; ++row) {
|
||||||
int y = row * (font.glyphHeight() + m_line_spacing);
|
int y = row * line_height;
|
||||||
for (word column = 0; column < m_columns; ++column) {
|
for (word column = 0; column < m_columns; ++column) {
|
||||||
char ch = m_buffer[(row * m_columns) + (column)];
|
|
||||||
auto& attribute = m_attributes[(row * m_columns) + (column)];
|
auto& attribute = m_attributes[(row * m_columns) + (column)];
|
||||||
|
if (!attribute.dirty)
|
||||||
|
continue;
|
||||||
|
attribute.dirty = false;
|
||||||
|
char ch = m_buffer[(row * m_columns) + (column)];
|
||||||
int x = column * font.glyphWidth();
|
int x = column * font.glyphWidth();
|
||||||
Rect glyph_rect { x + m_inset, y + m_inset, font.glyphWidth(), font.glyphHeight() + m_line_spacing };
|
Rect glyph_rect { x + m_inset, y + m_inset, font.glyphWidth(), line_height };
|
||||||
auto glyph_background = ansi_color(attribute.background_color);
|
auto glyph_background = ansi_color(attribute.background_color);
|
||||||
painter.fill_rect(glyph_rect, glyph_background);
|
painter.fill_rect(glyph_rect, glyph_background);
|
||||||
if (ch == ' ')
|
if (ch == ' ')
|
||||||
|
|
|
@ -41,10 +41,12 @@ private:
|
||||||
foreground_color = 7;
|
foreground_color = 7;
|
||||||
background_color = 0;
|
background_color = 0;
|
||||||
bold = false;
|
bold = false;
|
||||||
|
dirty = true;
|
||||||
}
|
}
|
||||||
unsigned foreground_color : 4;
|
unsigned foreground_color : 4;
|
||||||
unsigned background_color : 4;
|
unsigned background_color : 4;
|
||||||
bool bold : 1;
|
bool bold : 1;
|
||||||
|
bool dirty : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
byte* m_buffer { nullptr };
|
byte* m_buffer { nullptr };
|
||||||
|
@ -80,6 +82,7 @@ private:
|
||||||
|
|
||||||
int m_pixel_width { 0 };
|
int m_pixel_width { 0 };
|
||||||
int m_pixel_height { 0 };
|
int m_pixel_height { 0 };
|
||||||
|
int m_rows_to_scroll_backing_store { 0 };
|
||||||
|
|
||||||
int m_inset { 2 };
|
int m_inset { 2 };
|
||||||
int m_line_spacing { 4 };
|
int m_line_spacing { 4 };
|
||||||
|
|
|
@ -61,8 +61,6 @@ int main(int, char**)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbgprintf("ptm_fd = %d\n", ptm_fd);
|
|
||||||
|
|
||||||
make_shell(ptm_fd);
|
make_shell(ptm_fd);
|
||||||
|
|
||||||
int event_fd = open("/dev/gui_events", O_RDONLY | O_NONBLOCK);
|
int event_fd = open("/dev/gui_events", O_RDONLY | O_NONBLOCK);
|
||||||
|
@ -79,9 +77,8 @@ int main(int, char**)
|
||||||
byte buffer[1024];
|
byte buffer[1024];
|
||||||
ssize_t ptm_nread = read(ptm_fd, buffer, sizeof(buffer));
|
ssize_t ptm_nread = read(ptm_fd, buffer, sizeof(buffer));
|
||||||
if (ptm_nread > 0) {
|
if (ptm_nread > 0) {
|
||||||
for (ssize_t i = 0; i < ptm_nread; ++i) {
|
for (ssize_t i = 0; i < ptm_nread; ++i)
|
||||||
terminal.on_char(buffer[i]);
|
terminal.on_char(buffer[i]);
|
||||||
}
|
|
||||||
terminal.paint();
|
terminal.paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue