diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2025-04-26 02:43:15 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2025-04-26 02:43:15 +0200 |
commit | 22d045066fdcd8a27e76102102d966cf46abd422 (patch) | |
tree | b9d4a3c1d611b207424efef1919b83d439e0a99b | |
parent | 72b9fc8c1515c12600513fd9759f9b9034825726 (diff) | |
download | reduced_system_layer-22d045066fdcd8a27e76102102d966cf46abd422.zip |
LCD text rendering perf
-rw-r--r-- | graphics.c | 200 |
1 files changed, 151 insertions, 49 deletions
@@ -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, }; |