summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Petrashin <kirill8201@yandex.ru>2026-06-22 18:11:53 +0300
committerKirill Petrashin <kirill8201@yandex.ru>2026-06-22 18:11:53 +0300
commit4d871b697295f892c76b2204ca50ad513d508788 (patch)
tree6f221561f4ab2c043895bee3d1f93af330572479
parent769abee99e0fcf27c7700dc57e48e51ca50ccbc2 (diff)
downloadwafflestone-4d871b697295f892c76b2204ca50ad513d508788.tar.xz
Optimize fb_print()
-rw-r--r--framebuffer.c53
-rw-r--r--framebuffer.h2
2 files changed, 45 insertions, 10 deletions
diff --git a/framebuffer.c b/framebuffer.c
index 36969e0..b4c2f6e 100644
--- a/framebuffer.c
+++ b/framebuffer.c
@@ -3,8 +3,10 @@
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
+#include <string.h>
#include "framebuffer.h"
+#include "uint8toa.h"
size_t term_width = 0,
term_height = 0;
@@ -29,20 +31,29 @@ Framebuffer fb_new(size_t width, size_t height) {
}
}
+ fb.print_buf = malloc(42 * width * height);
+ if (fb.print_buf == NULL) {
+ /* FIXME: see above */
+ fb.fb = NULL;
+ return fb;
+ }
+
fb.width = width;
fb.height = height;
return fb;
}
void fb_free(Framebuffer *fb) {
- if (fb->fb == NULL) goto ret;
-
- for (size_t i = 0; i < fb->height; i++) {
- free(fb->fb[i]);
+ if (fb->fb != NULL) {
+ for (size_t i = 0; i < fb->height; i++) {
+ free(fb->fb[i]);
+ }
+ free(fb->fb);
}
- free(fb->fb);
-ret:
+ if (fb->print_buf != NULL)
+ free(fb->print_buf);
+
fb->width = 0;
fb->height = 0;
return;
@@ -108,24 +119,46 @@ void term_update_size(void) {
#endif
}
+/* Converts pixel to ascii and puts it in buf, used in fb_print().
+ * This is faster than sprinf().
+ * TODO: maybe less memcpy()s will be better? */
+static inline void pixel_to_ascii(char *buf, Pixel p) {
+ memcpy(buf, "\x1b[38;2;XXX;XXX;XXXm\x1b[48;2;XXX;XXX;XXXmXXXX", 42);
+ memcpy(buf + 7, uint8toa[p.fg.r], 3);
+ memcpy(buf + 11, uint8toa[p.fg.g], 3);
+ memcpy(buf + 15, uint8toa[p.fg.b], 3);
+ memcpy(buf + 26, uint8toa[p.bg.r], 3);
+ memcpy(buf + 30, uint8toa[p.bg.g], 3);
+ memcpy(buf + 34, uint8toa[p.bg.b], 3);
+ memcpy(buf + 38, &p.ch, 4);
+}
+
void fb_print(Framebuffer fb) {
+ /* TODO: move this to buffer, maybe? to avoid an extra write every 'frame' */
write(STDOUT_FILENO, "\x1b[H", 3); /* Move cursor to top-left */
+ /* 'cursor' of print_buf, used to build it */
+ char *cur = fb.print_buf;
+
+ /* build the buffer */
for (size_t row = 0; row < fb.height; row++) {
for (size_t col = 0; col < fb.width; col++) {
- set_fg(fb.fb[row][col].fg);
- set_bg(fb.fb[row][col].bg);
- write(STDOUT_FILENO, &(fb.fb[row][col].ch), sizeof(wchar_t));
+ pixel_to_ascii(cur, fb.fb[row][col]);
+ cur += 42;
}
}
- fflush(stdout);
+
+ /* flush the buffer */
+ write(STDOUT_FILENO, fb.print_buf, 42 * fb.width * fb.height);
}
+__attribute__((unused))
static inline void set_fg(Colour col) {
fprintf(stdout, "\x1b[38;2;%u;%u;%um", col.r, col.g, col.g);
fflush(stdout);
}
+__attribute__((unused))
static inline void set_bg(Colour col) {
fprintf(stdout, "\x1b[48;2;%u;%u;%um", col.r, col.g, col.g);
fflush(stdout);
diff --git a/framebuffer.h b/framebuffer.h
index cadcb00..2a26454 100644
--- a/framebuffer.h
+++ b/framebuffer.h
@@ -44,6 +44,8 @@ typedef struct Pixel_s {
typedef struct Framebuffer_s {
Pixel **fb; /* Adressed as fb[row][col] or fb[x][y] */
size_t width, height;
+ char *print_buf; /* is of size (42 * width * height)
+ * 42 is ANSI 24-bit fg and bg + one wchar_t */
} Framebuffer;
/* Check if fb == NULL in case malloc() fails */