summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2025-04-26 02:43:15 +0200
committerMitya Selivanov <automainint@guattari.tech>2025-04-26 02:43:15 +0200
commit22d045066fdcd8a27e76102102d966cf46abd422 (patch)
treeb9d4a3c1d611b207424efef1919b83d439e0a99b
parent72b9fc8c1515c12600513fd9759f9b9034825726 (diff)
downloadreduced_system_layer-22d045066fdcd8a27e76102102d966cf46abd422.zip
LCD text rendering perf
-rw-r--r--graphics.c200
1 files changed, 151 insertions, 49 deletions
diff --git a/graphics.c b/graphics.c
index a63f622..d9ff10f 100644
--- a/graphics.c
+++ b/graphics.c
@@ -1027,6 +1027,111 @@ enum {
LCD_Len = sizeof(_lcd_bits) / sizeof(*_lcd_bits),
};
+u8 _lcd_widths[LCD_Len] = {
+ 1, 3, 5, 5, 5, 4, 1, 2, 2, 6, 5, 2, 5, 1, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 1, 2, 3, 5, 3, 3, 5, 4, 4, 4, 4, 4, 4,
+ 4, 4, 3, 3, 4, 3, 5, 5, 4, 4, 4, 4, 4, 5, 4, 5, 5, 5, 5,
+ 4, 2, 3, 2, 5, 6, 2, 4, 4, 4, 4, 4, 3, 4, 4, 3, 2, 3, 2,
+ 5, 4, 4, 4, 4, 3, 4, 3, 4, 5, 5, 5, 5, 4, 3, 1, 3, 6,
+};
+
+u64 _lcd_kerning[LCD_Len * 2] = {
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xbffffffff3ff83ffull, 0x3bfffcd6ull,
+ 0x7ff7ffffffffffffull, 0x3fffffffull,
+ 0x7f7ffffbbbff4b5ull, 0xff3ffffull,
+ 0x77f7ffffbfbfffbdull, 0x1ff7ffffull,
+ 0x57d7ffffb7b7e9a5ull, 0x1bd2ff9full,
+ 0xbffffffff3ff83ffull, 0x3bfffcd6ull,
+ 0xdfffffffe7ffe9f7ull, 0x3bfabf82ull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0x2d77fcfffbff96ffull, 0x2fffffffull,
+ 0x26f7feff9bba96bdull, 0xe77ffffull,
+ 0x57d7ffffb7b7e9a5ull, 0x1bd2ff9full,
+ 0x26f7feff9bba96bdull, 0xe77ffffull,
+ 0x57d7ffffb7b7e9a5ull, 0x1bd2ff9full,
+ 0xbffffffff3ff83ffull, 0x3bfffcd6ull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0x57d7ffffb7b7e9a5ull, 0x1bd2ff9full,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xbffffffffbff97ffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0x7ff7ffffffffffffull, 0x3fffffffull,
+ 0x7ff7ffffffffffffull, 0x3fffffffull,
+ 0xfffffffff7ffebffull, 0x3bffffdfull,
+ 0x2ff7fffffbfff6ffull, 0x2fffffffull,
+ 0x26f7feff9bba96bdull, 0xe77ffffull,
+ 0xbffffffffbff97ffull, 0x3fffffffull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xdffffffff7ffe9f7ull, 0x3bfaff9full,
+ 0x9fffffffe1df81f3ull, 0x3bfabc82ull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xdffffffff7ffe9f7ull, 0x3bfaff9full,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xdffffffffffffdf7ull, 0x3ffbffffull,
+ 0x57d7ffffb7b7e9a5ull, 0x1bd2ff9full,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xbffffffffbff97ffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0x27f7ffffbbbff6bdull, 0xff7ffffull,
+ 0x9fffffffe1df81f3ull, 0x3bfabc82ull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xbffffffffbff97ffull, 0x3fffffffull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xdffffffffffffdf7ull, 0x3ffbffffull,
+ 0xbffffffff3ff83ffull, 0x3bfffcd6ull,
+ 0xfffffffff7ffebffull, 0x3bffffdfull,
+ 0xdfffffffe7ffe9f7ull, 0x3bfabf82ull,
+ 0x57d7ffffb7b7e9a5ull, 0x1bd2ff9full,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0x2d77fcfffbff96ffull, 0x2fffffffull,
+ 0x5782bdbba7b7e9a5ull, 0x1b82b782ull,
+ 0xbffffffff3ff83ffull, 0x3bfffcd6ull,
+ 0x2ff7fffffbfff6ffull, 0x2fffffffull,
+ 0x27f7ffffbbbff6bdull, 0xff7ffffull,
+ 0x2ff7fffffbfff6ffull, 0x2fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0x2ff7fefffbff96ffull, 0x2fffffffull,
+ 0xbffffffffbff97ffull, 0x3fffffffull,
+ 0x7ff7ffffffffffffull, 0x3fffffffull,
+ 0x57f7ffffbfbffdb5ull, 0x1ff3ffffull,
+ 0x57d7ffffb7b7e9a5ull, 0x1bd2ff9full,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0x57d7ffffb7b7e9a5ull, 0x1bd2ff9full,
+ 0x7ff7ffffffffffffull, 0x3fffffffull,
+ 0x7ff7ffffffffffffull, 0x3fffffffull,
+ 0x2ff7fffffbfff6ffull, 0x2fffffffull,
+ 0x2ff7fefffbff96ffull, 0x2fffffffull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xbffffffff3ff83ffull, 0x3bfffcd6ull,
+ 0x7f7ffffbbbff4b5ull, 0xff3ffffull,
+ 0xbffffffff3ff83ffull, 0x3bfffcd6ull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xbffffffffbff97ffull, 0x3fffffffull,
+ 0xbffffffffbfff7ffull, 0x3fffffffull,
+ 0xfffffffff7ffebffull, 0x3bffffdfull,
+ 0xbffffffff3ff83ffull, 0x3bfffcd6ull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0xdfffffffe7ffe9f7ull, 0x3bfabf82ull,
+ 0xffffffffffffffffull, 0x3fffffffull,
+ 0x26f7feff9bba96bdull, 0xe77ffffull,
+ 0x9fffffffe1df81f3ull, 0x3bfabc82ull,
+};
+
static u64 lcd_column_convolved_(c32 c, i64 column_index) {
if (column_index < 0 || column_index >= LCD_Width)
return 0;
@@ -1057,37 +1162,30 @@ static b8 lcd_column_empty_(c32 c, i64 column_index) {
}
static i64 lcd_char_width_(c32 c) {
- // FIXME, PERF: Pre-calculate dimensions.
-
i64 index = c - LCD_First;
if (index < -1)
return 0;
if (index < 0 || index >= LCD_Len)
return LCD_Space;
- i64 width = 0;
- for (; width < LCD_Width; ++width)
- if (lcd_column_empty_(c, width) && lcd_column_empty_(c, width + 1))
- break;
- return width;
+ return _lcd_widths[index];
}
static i64 lcd_spacing_(i64 num_chars, c32 *text, i64 index) {
- // FIXME, PERF: Pre-calculate kerning.
-
if (text == NULL)
return 0;
-
if (index < 0 || index + 1 >= num_chars)
return 0;
- u64 a = lcd_column_convolved_(text[index], lcd_char_width_(text[index]) - 1);
- u64 b = lcd_column_convolved_(text[index + 1], 0);
+ i64 a = text[index] - LCD_First;
+ i64 b = text[index + 1] - LCD_First;
- if (!!(a & b))
- return 1;
+ if (a < 0 || a >= LCD_Len || b < 0 || b >= LCD_Len)
+ return 0;
- return 0;
+ if (b < 64)
+ return !!(_lcd_kerning[a * 2] & (1ull << b ));
+ return !!(_lcd_kerning[a * 2 + 1] & (1ull << (b - 64)));
}
static i64 lcd_cursor_(i64 num_chars, c32 *text) {
@@ -1195,24 +1293,28 @@ static void lcd_draw_text_(Pixel_Buffer dst, vec4_f32 color, f64 x0, f64 y0, f64
if (w >= EPSILON && index >= 0 && index < LCD_Len) {
i64 i0 = (i64) floor(x + 0.5);
- i64 i1 = (i64) floor(x + w - 0.5);
+ i64 i1 = (i64) floor(x + w + 0.5);
i64 j0 = (i64) floor(y + 0.5);
- i64 j1 = (i64) floor(y + h - 0.5);
+ i64 j1 = (i64) floor(y + h + 0.5);
- if (i0 < 0) i0 = 0;
- if (i1 >= dst.width) i1 = dst.width - 1;
- if (j0 < 0) j0 = 0;
- if (j1 >= dst.height) j1 = dst.height - 1;
+ i64 i00 = i0;
+ i64 j00 = j0;
- f64 w_inv = 1. / w;
- f64 h_inv = 1. / h;
+ if (i0 < 0) i0 = 0;
+ if (i1 > dst.width) i1 = dst.width;
+ if (j0 < 0) j0 = 0;
+ if (j1 > dst.height) j1 = dst.height;
- // FIXME, PERF: Use integer arithmetic.
+ u32 w_inv = (u32) floor(0x10000 / w + 0.5);
+ u32 h_inv = (u32) floor(0x10000 / h + 0.5);
- for (i64 j = j0; j <= j1; ++j) {
- i64 row = (i64) floor(((j - y + 0.5) * LCD_Height) * h_inv);
- for (i64 i = i0; i <= i1; ++i) {
- i64 column = (i64) floor(((i - x + 0.5) * num_cols) * w_inv);
+ u32 w_half = w_inv / 2;
+ u32 h_half = h_inv / 2;
+
+ for (i64 j = j0; j < j1; ++j) {
+ u32 row = (((j - j00) * LCD_Height) * h_inv + h_half) >> 16;
+ for (i64 i = i0; i < i1; ++i) {
+ u32 column = (((i - i00) * num_cols) * w_inv + w_half) >> 16;
if ((_lcd_bits[index] & (1ull << (row * 8 + column))) != 0)
put_pixel_(dst.pixels + j * dst.stride + i, color);
@@ -2736,15 +2838,15 @@ TEST("text letter A") {
// printf("\n");
b8 expect_bits[100] = {
- 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
@@ -2795,13 +2897,13 @@ TEST("text letter z") {
b8 expect_bits[100] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
@@ -2853,13 +2955,13 @@ TEST("text digits 42") {
b8 expect_bits[100] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 1, 0, 0, 1, 1, 1, 1,
- 1, 0, 0, 1, 0, 0, 1, 1, 1, 1,
- 1, 0, 0, 1, 0, 0, 0, 0, 0, 1,
- 1, 1, 1, 1, 0, 0, 0, 1, 1, 0,
- 1, 1, 1, 1, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 1, 0, 0, 1, 0, 0, 0,
- 0, 0, 0, 1, 0, 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 1, 0, 0, 1, 1, 1, 1,
+ 1, 1, 0, 1, 0, 0, 0, 0, 0, 1,
+ 1, 1, 0, 1, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};