Hi,I forgot to attach the patches in the last mail. Here are the updated patches.
Best Regards, Zhang Boyang
From 540b82ac07c5a582da3d6e6ad1cdc2fd83c36b2e Mon Sep 17 00:00:00 2001 From: Zhang Boyang <zhangboyang...@gmail.com> Date: Mon, 23 May 2022 14:10:52 +0800 Subject: [PATCH v3 1/4] Better font reload handling Previous font reload code will leak a mmap on each reload. This patch adds the ability to munmap old font after reload. However, this also introduces a bug, if font reload is triggered while drawing in progress, after signal handler returns, the drawing code will continue to use old font which has been freed, causing crash. So the munmap is temporarily disabled until we fix async-signal-safety problems completely. --- bogl-bgf.c | 63 +++++++++++++++++++++++++++++++++++++++++++----------- bogl-bgf.h | 1 + bterm.c | 9 ++++---- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/bogl-bgf.c b/bogl-bgf.c index 1032028..beed3c8 100644 --- a/bogl-bgf.c +++ b/bogl-bgf.c @@ -5,38 +5,55 @@ #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> +#include <stddef.h> #include "bogl.h" #include "boglP.h" #include "bogl-font.h" +#include "bogl-bgf.h" + +struct bogl_bgf { + void *f; /* mmap area */ + off_t size; /* size of mmap area */ + struct bogl_font font; /* font descriptor */ +}; +#define bgf_of(font) \ + ((struct bogl_bgf *)((char *)(font) - offsetof(struct bogl_bgf, font))) struct bogl_font *bogl_mmap_font(char *file) { - int fd; + struct bogl_bgf *bgf = NULL; + struct bogl_font *font = NULL; + int fd = -1; struct stat buf; - void *f; - struct bogl_font *font; + void *f = MAP_FAILED; + + bgf = (struct bogl_bgf *)malloc(sizeof(struct bogl_bgf)); + if (!bgf) + goto fail; + font = &bgf->font; fd = open(file, O_RDONLY); if (fd == -1) - return 0; + goto fail; if (bogl_cloexec(fd) < 0) - return 0; + goto fail; if (fstat(fd, &buf)) - return 0; + goto fail; + bgf->size = buf.st_size; + + if (buf.st_size < 4) + goto fail; f = mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (f == (void *)-1) - return 0; + if (f == MAP_FAILED) + goto fail; + bgf->f = f; if (memcmp("BGF1", f, 4)) - return 0; - - font = (struct bogl_font *)malloc(sizeof(struct bogl_font)); - if (!font) - return 0; + goto fail; memcpy(font, f + 4, sizeof(*font)); font->name = ((void *)font->name - (void *)0) + f; @@ -44,5 +61,25 @@ struct bogl_font *bogl_mmap_font(char *file) font->index = ((void *)font->index - (void *)0) + f; font->content = ((void *)font->content - (void *)0) + f; +done: + if (fd != -1) + close(fd); return font; + +fail: + if (bgf) { + free(bgf); + bgf = NULL; + font = NULL; + } + if (f != MAP_FAILED) + munmap(f, buf.st_size); + goto done; +} + +void bogl_munmap_font(struct bogl_font *font) +{ + struct bogl_bgf *bgf = bgf_of(font); + munmap(bgf->f, bgf->size); + free(bgf); } diff --git a/bogl-bgf.h b/bogl-bgf.h index e9fb994..f14a260 100644 --- a/bogl-bgf.h +++ b/bogl-bgf.h @@ -1,2 +1,3 @@ struct bogl_font *bogl_mmap_font(char *file); +void bogl_munmap_font(struct bogl_font *font); diff --git a/bterm.c b/bterm.c index 605644f..dfae8b9 100644 --- a/bterm.c +++ b/bterm.c @@ -224,11 +224,10 @@ void reload_font(int sig) return; } - /* This leaks a mmap. Since the font reloading feature is only expected - to be used once per session (for instance, in debian-installer, after - the font is replaced with a larger version containing more characters), - we don't worry about the leak. */ - free(term->font); + /* BUG: Unmapping old font in this signal handler may cause crash if + drawing is in progress, so disable this temporarily until we fix + async-signal-safety problems completely. */ + //bogl_munmap_font(term->font); term->font = font; term->xstep = bogl_font_glyph(term->font, ' ', 0); -- 2.30.2
From b222a9a15b0a2706927ecde8ce163243b076bbcb Mon Sep 17 00:00:00 2001 From: Zhang Boyang <zhangboyang...@gmail.com> Date: Tue, 24 May 2022 12:58:01 +0800 Subject: [PATCH v3 2/4] Fix incorrect signal handling There are problems in signal handlers. Signal handlers must not call any non-async-signal-safe functions, and they must save-restore errno if errno is modified inside signal handlers. This patch fixes these problems by deferring real tasks to main loop. This patch also introduces bogl_signal(), which wraps around sigaction() thus signal handlers can be installed in a portable way. Since signal related problems are fixed, the previously temporarily disabled font unmapping is now re-enabled. --- bogl.c | 50 +++++++++++++++++++++++++------------------------- bogl.h | 2 ++ boglP.h | 2 ++ bterm.c | 35 +++++++++++++++++++++++++---------- 4 files changed, 54 insertions(+), 35 deletions(-) diff --git a/bogl.c b/bogl.c index 6b9996b..86bc1e0 100644 --- a/bogl.c +++ b/bogl.c @@ -65,6 +65,7 @@ /* Global variables. */ int bogl_xres, bogl_yres, bogl_bpp; /* bogl.h */ int bogl_refresh; +volatile int vt_switch_pending = 0; volatile char *bogl_frame; /* boglP.h */ int bogl_drawing; int bogl_line_len; @@ -120,7 +121,7 @@ static void draw_disable (void); static void kbd_init (void); static void kbd_done (void); -static void vt_switch (int); +static void sigusr2 (int); static struct fb_fix_screeninfo fb_fix; /* Initialize BOGL. */ @@ -181,7 +182,7 @@ bogl_init (void) mode.relsig = SIGUSR2; mode.acqsig = SIGUSR2; - signal (SIGUSR2, vt_switch); + bogl_signal (SIGUSR2, sigusr2); if (-1 == ioctl (tty, VT_SETMODE, &mode)) return bogl_fail ("can't set VT mode: %s", strerror (errno)); @@ -295,7 +296,7 @@ bogl_done (void) munmap ((void *) bogl_frame, fb_fix.smem_len); - signal (SIGUSR2, SIG_DFL); + bogl_signal (SIGUSR2, SIG_DFL); ioctl (tty, KDSETMODE, KD_TEXT); @@ -583,32 +584,18 @@ draw_disable (void) /* Signal handler called whenever the kernel wants to switch to or from our tty. */ static void -vt_switch (int sig unused) +sigusr2 (int sig unused) { - signal (SIGUSR2, vt_switch); + vt_switch_pending = 1; +} +void +vt_switch (void) +{ + vt_switch_pending = 0; - /* If a BOGL drawing function is in progress then we cannot mode - switch right now because the drawing function would continue to - scribble on the screen after the switch. So disable further - drawing and schedule an alarm to try again in .1 second. */ if (bogl_drawing) { - draw_disable (); - - signal (SIGALRM, vt_switch); - - { - struct itimerval duration; - - duration.it_interval.tv_sec = 0; - duration.it_interval.tv_usec = 0; - duration.it_value.tv_sec = 0; - duration.it_value.tv_usec = 100000; - if (-1 == setitimer (ITIMER_REAL, &duration, NULL)) - bogl_fail ("can't set timer: %s", strerror (errno)); - } - - return; + abort(); } if (visible) @@ -666,3 +653,16 @@ bogl_cloexec(int fd) return 0; } + +/* Install signal handler in a portable way (i.e. sigaction wrapper) */ +int +bogl_signal(int signum, void (*handler) (int)) +{ + struct sigaction sa; + + sa.sa_handler = handler; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + return sigaction (signum, &sa, NULL); +} diff --git a/bogl.h b/bogl.h index 3b2cb83..4d99788 100644 --- a/bogl.h +++ b/bogl.h @@ -69,6 +69,8 @@ extern int bogl_xres, bogl_yres, bogl_ncols; /* 1=Must refresh screen due to tty change. */ extern int bogl_refresh; +extern volatile int vt_switch_pending; +extern void vt_switch (void); /* Generic routines. */ int bogl_init (void); diff --git a/boglP.h b/boglP.h index be99979..9a2b4aa 100644 --- a/boglP.h +++ b/boglP.h @@ -27,4 +27,6 @@ int bogl_fail (const char *, ...); int bogl_cloexec (int fd); +int bogl_signal (int signum, void (*handler) (int)); + #endif /* boglP_h */ diff --git a/bterm.c b/bterm.c index dfae8b9..1d478f9 100644 --- a/bterm.c +++ b/bterm.c @@ -160,7 +160,6 @@ void sigchld(int sig) quit_status = status; quit = 1; } - signal(SIGCHLD, sigchld); errno = errsv; } @@ -176,7 +175,7 @@ void spawn_shell(int ptyfd, int ttyfd, char * const *command_args) child_pid = fork(); if (child_pid) { /* Change ownership and permissions of ttyfd device! */ - signal(SIGCHLD, sigchld); + bogl_signal(SIGCHLD, sigchld); return; } @@ -212,10 +211,16 @@ void set_window_size(int ttyfd, int x, int y) static char *font_name; static struct bogl_term *term; +static volatile int reload_font_pending = 0; -void reload_font(int sig) +void sighup(int sig) +{ + reload_font_pending = 1; +} +void reload_font(void) { struct bogl_font *font; + reload_font_pending = 0; font = bogl_mmap_font (font_name); if (font == NULL) @@ -224,14 +229,14 @@ void reload_font(int sig) return; } - /* BUG: Unmapping old font in this signal handler may cause crash if - drawing is in progress, so disable this temporarily until we fix - async-signal-safety problems completely. */ - //bogl_munmap_font(term->font); + bogl_munmap_font(term->font); term->font = font; term->xstep = bogl_font_glyph(term->font, ' ', 0); term->ystep = bogl_font_height(term->font); + + /* Request redraw */ + bogl_refresh = 2; } /* @@ -243,6 +248,7 @@ int main(int argc, char *argv[]) { struct termios ntio; int ret; + int errsv; char buf[8192]; struct timeval tv; int ptyfd, ttyfd; @@ -342,8 +348,8 @@ int main(int argc, char *argv[]) } spawn_shell(ptyfd, ttyfd, command_args); - signal(SIGHUP, reload_font); - signal(SIGTERM, sigterm); + bogl_signal(SIGHUP, sighup); + bogl_signal(SIGTERM, sigterm); ntio = ttysave; ntio.c_lflag &= ~(ECHO|ISIG|ICANON|XCASE); @@ -363,6 +369,10 @@ int main(int argc, char *argv[]) if (quit) break; + if (reload_font_pending) + reload_font(); + if (vt_switch_pending) + vt_switch(); if(pending) { @@ -380,9 +390,14 @@ int main(int argc, char *argv[]) if (ptyfd > max) max = ptyfd; ret = select(max+1, &fds, NULL, NULL, &tv); + errsv = errno; if (quit) break; + if (reload_font_pending) + reload_font(); + if (vt_switch_pending) + vt_switch(); if (bogl_refresh) { /* Handle VT switching. */ @@ -397,7 +412,7 @@ int main(int argc, char *argv[]) bogl_refresh = 0; bogl_term_redraw(term); } - if (ret == 0 || (ret < 0 && errno == EINTR)) + if (ret == 0 || (ret < 0 && errsv == EINTR)) { if(pending) { -- 2.30.2
From 77da4f8d36f7b35f647ab897d120c8a20e295a09 Mon Sep 17 00:00:00 2001 From: Zhang Boyang <zhangboyang...@gmail.com> Date: Tue, 24 May 2022 23:49:31 +0800 Subject: [PATCH v3 3/4] Font scaler Current fonts is too small to see on HiDPI displays. This patch introduces a BGF font scaler, which can scale font glyphs on the fly when loading. The scale factor can be automatically determined by screen resolution or specified by a new command line argument '-s'. This patch also adds support for BGF fonts wider than 32 pixels. --- bogl-bgf.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++--- bogl-bgf.h | 2 +- bogl-pcfb.c | 8 ++-- bogl-tcfb.c | 8 ++-- bogl-vga16.c | 33 +++++++++----- bterm.1 | 4 ++ bterm.c | 32 ++++++++++---- 7 files changed, 175 insertions(+), 35 deletions(-) diff --git a/bogl-bgf.c b/bogl-bgf.c index beed3c8..54af37b 100644 --- a/bogl-bgf.c +++ b/bogl-bgf.c @@ -12,6 +12,16 @@ #include "bogl-font.h" #include "bogl-bgf.h" +/* Set font struct, let it point to font data in the given memory region */ +static inline void set_font(struct bogl_font *font, void *mem) +{ + memcpy(font, mem + 4, sizeof(*font)); + font->name = ((void *)font->name - (void *)0) + mem; + font->offset = ((void *)font->offset - (void *)0) + mem; + font->index = ((void *)font->index - (void *)0) + mem; + font->content = ((void *)font->content - (void *)0) + mem; +} + struct bogl_bgf { void *f; /* mmap area */ off_t size; /* size of mmap area */ @@ -20,7 +30,109 @@ struct bogl_bgf { #define bgf_of(font) \ ((struct bogl_bgf *)((char *)(font) - offsetof(struct bogl_bgf, font))) -struct bogl_font *bogl_mmap_font(char *file) +/* Scale the font (both width and height) + Declare as inline function, will run faster if scale factor is constant */ +static inline void __attribute__((always_inline)) +bgf_scale_inline(struct bogl_bgf *bgf, int scale) +{ + void *new_f = MAP_FAILED; + off_t new_size; + struct bogl_font new_font; + + /* old_size*pow(scale,2) should enough and have some waste here */ + new_size = bgf->size * scale * scale; + + /* Allocate new memory */ + new_f = mmap(0, new_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (new_f == MAP_FAILED) { + /* If memory allocation failed, skip scaling silently */ + goto fail; + } + + /* Copy old font data to new memory */ + memcpy(new_f, bgf->f, bgf->size); + + /* Set font metadata */ + struct bogl_font *font = &new_font; + set_font(font, new_f); + font->height = bgf->font.height * scale; + + /* Scale each glyph */ + int mask = font->index_mask; + for (int j = 0; j <= mask; j++) { + for (int i = font->offset[j]; font->index[i]; i += 2) { + int old_height = bgf->font.height; + int old_width = (font->index[i] & mask); + if (old_width * scale > mask) { + /* Scaled glyph width can't fit in mask, fail */ + goto fail; + } + font->index[i] = (font->index[i] & ~mask) | (old_width * scale); + font->index[i + 1] *= scale * scale; + u_int32_t *in_bitmap = &bgf->font.content[bgf->font.index[i + 1]]; + int in_pitch = (old_width + 31) / 32; + u_int32_t *out_bitmap = &font->content[font->index[i + 1]]; + int out_pitch = (old_width * scale + 31) / 32; + for (int y = 0; y < old_height * scale; y++) { + const int outlined = 0; /* Useful for debugging */ + if (y % scale == 0 || outlined) { + u_int32_t *in_ptr = in_bitmap + in_pitch * (y / scale); + u_int32_t *out_ptr = out_bitmap + out_pitch * y; + memset(out_ptr, 0, sizeof(u_int32_t) * out_pitch); + for (int x = 0; x < old_width * scale; x++) { + int in_off = (x / scale) / 32, in_bit = 31 - (x / scale) % 32; + int out_off = x / 32, out_bit = 31 - x % 32; + u_int32_t pixel = (in_ptr[in_off] >> in_bit) & 1; + if (outlined) + if (0 < x % scale && x % scale < scale - 1) + if (0 < y % scale && y % scale < scale - 1) + pixel = 0; + out_ptr[out_off] |= pixel << out_bit; + } + } else { + u_int32_t *last_line = out_bitmap + out_pitch * (y - 1); + u_int32_t *curr_line = out_bitmap + out_pitch * y; + memcpy(curr_line, last_line, sizeof(u_int32_t) * out_pitch); + } + } + } + } + + /* Replace old font with new font */ + munmap(bgf->f, bgf->size); + bgf->f = new_f; + bgf->size = new_size; + bgf->font = new_font; + return; +fail: + if (new_f != MAP_FAILED) + munmap(new_f, new_size); +} +static void __attribute__((noinline)) +bgf_scale_noinline(struct bogl_bgf *bgf, int scale) +{ + bgf_scale_inline(bgf, scale); +} +static void __attribute__((noinline)) bgf_scale_2x(struct bogl_bgf *bgf) +{ + bgf_scale_inline(bgf, 2); +} +static void __attribute__((noinline)) bgf_scale_4x(struct bogl_bgf *bgf) +{ + bgf_scale_inline(bgf, 4); +} +static void bgf_scale(struct bogl_bgf *bgf, int scale) +{ + switch (scale) { + /* Use fast implementation if possible */ + case 2: bgf_scale_2x(bgf); return; + case 4: bgf_scale_4x(bgf); return; + /* Universal implementation as fallback */ + default: bgf_scale_noinline(bgf, scale); return; + } +} + +struct bogl_font *bogl_mmap_font(char *file, int scale) { struct bogl_bgf *bgf = NULL; struct bogl_font *font = NULL; @@ -55,11 +167,10 @@ struct bogl_font *bogl_mmap_font(char *file) if (memcmp("BGF1", f, 4)) goto fail; - memcpy(font, f + 4, sizeof(*font)); - font->name = ((void *)font->name - (void *)0) + f; - font->offset = ((void *)font->offset - (void *)0) + f; - font->index = ((void *)font->index - (void *)0) + f; - font->content = ((void *)font->content - (void *)0) + f; + set_font(font, f); + + if (scale >= 2) + bgf_scale(bgf, scale); done: if (fd != -1) diff --git a/bogl-bgf.h b/bogl-bgf.h index f14a260..978da61 100644 --- a/bogl-bgf.h +++ b/bogl-bgf.h @@ -1,3 +1,3 @@ -struct bogl_font *bogl_mmap_font(char *file); +struct bogl_font *bogl_mmap_font(char *file, int scale); void bogl_munmap_font(struct bogl_font *font); diff --git a/bogl-pcfb.c b/bogl-pcfb.c index c737d38..b16c804 100644 --- a/bogl-pcfb.c +++ b/bogl-pcfb.c @@ -142,6 +142,7 @@ bogl_pcfb_text (int xx, int yy, const char *s, int n, int fg, int bg, int ul, u_int32_t *character = NULL; int w = bogl_font_glyph (font, wc, &character); + int pitch = (w + 31) / 32; int x, y, h1 = ul ? h - 1 : h; @@ -153,16 +154,15 @@ bogl_pcfb_text (int xx, int yy, const char *s, int n, int fg, int bg, int ul, for (y = 0; y < h1; y++) { - u_int32_t c = *character++; + u_int32_t *c = character; + character += pitch; for (x = 0; x < w; x++) { - if (c & 0x80000000) + if ((c[x / 32] & (1 << (31 - x % 32)))) put_var (dst, xx+x, cmap_lookup(fg), bpp); else if (bg != -1) put_var (dst, xx+x, cmap_lookup(bg), bpp); - - c <<= 1; } dst += bogl_line_len; diff --git a/bogl-tcfb.c b/bogl-tcfb.c index 76f44da..5e14892 100644 --- a/bogl-tcfb.c +++ b/bogl-tcfb.c @@ -169,6 +169,7 @@ bogl_tcfb_text (int xx, int yy, const char *s, int n, int fg, int bg, int ul, u_int32_t *character = NULL; int w = bogl_font_glyph (font, wc, &character); + int pitch = (w + 31) / 32; int x, y, h1 = ul ? h - 1 : h; unsigned cfg = cmap_lookup (fg), cbg = cmap_lookup (bg); @@ -181,16 +182,15 @@ bogl_tcfb_text (int xx, int yy, const char *s, int n, int fg, int bg, int ul, for (y = 0; y < h1; y++) { - u_int32_t c = *character++; + u_int32_t *c = character; + character += pitch; for (x = 0; x < w; x++) { - if (c & 0x80000000) + if ((c[x / 32] & (1 << (31 - x % 32)))) put_var (dst, xx+x, cfg, bpp); else if (bg != -1) put_var (dst, xx+x, cbg, bpp); - - c <<= 1; } dst += bogl_line_len; diff --git a/bogl-vga16.c b/bogl-vga16.c index 6e7f0b0..3fcbe51 100644 --- a/bogl-vga16.c +++ b/bogl-vga16.c @@ -394,25 +394,34 @@ bogl_vga16_text (int xx, int yy, const char *s, int n, int fg, int bg, int ul, { u_int32_t *character = NULL; int width = bogl_font_glyph (font, wc, &character); + int pitch = (width + ul_bits - 1) / ul_bits; if (character == NULL) continue; - for (y = 0; y < h; y++) - bits[y] |= character[y] >> x; - x += width; - - if (x >= (int) ul_bits) - { - plot (bg); + int i, w; + for (i = 0; i < pitch; i++) + { + w = width - i * ul_bits; + if (w > ul_bits) + w = ul_bits; - x -= ul_bits; for (y = 0; y < h; y++) - bits[y] = character[y] << (width - x); + bits[y] |= character[y * pitch + i] >> x; + x += w; - xx += ul_bits; - if (xx >= bogl_xres) - goto done; + if (x >= (int) ul_bits) + { + plot (bg); + + x -= ul_bits; + for (y = 0; y < h; y++) + bits[y] = character[y * pitch + i] << (w - x - 1) << 1; + + xx += ul_bits; + if (xx >= bogl_xres) + goto done; + } } } plot (bg); diff --git a/bterm.1 b/bterm.1 index 8b96b99..e62d3ee 100644 --- a/bterm.1 +++ b/bterm.1 @@ -21,6 +21,7 @@ bterm - framebuffer terminal emulator .B bterm .B -f .RI font.bgf +.RI "[-s " scale "]" .RI "[-l " locale "]" .RI "[" program "]" .SH DESCRIPTION @@ -36,6 +37,9 @@ Specify the font. BGF fonts are produced by .BR bdftobogl (1) from standard BDF font files. .TP +.B -s scale +Specify the font scale factor, 0 for auto. +.TP .B -l locale Specify a locale for .B bterm diff --git a/bterm.c b/bterm.c index 1d478f9..305f9b1 100644 --- a/bterm.c +++ b/bterm.c @@ -210,6 +210,7 @@ void set_window_size(int ttyfd, int x, int y) } static char *font_name; +static int font_scale; static struct bogl_term *term; static volatile int reload_font_pending = 0; @@ -222,7 +223,7 @@ void reload_font(void) struct bogl_font *font; reload_font_pending = 0; - font = bogl_mmap_font (font_name); + font = bogl_mmap_font (font_name, font_scale); if (font == NULL) { fprintf(stderr, "Bad font\n"); @@ -241,7 +242,7 @@ void reload_font(void) /* * The usage is very simple: - * bterm -f font.bgf [ -l locale ] [ program ] + * bterm -f font.bgf [ -s scale ] [ -l locale ] [ program ] */ int main(int argc, char *argv[]) @@ -265,6 +266,7 @@ int main(int argc, char *argv[]) switch (argv[i][1]) { case 'f': + case 's': case 'l': o = argv[i][1]; break; @@ -288,6 +290,11 @@ int main(int argc, char *argv[]) o = ' '; break; + case 's': + font_scale = atoi(argv[i]); + o = ' '; + break; + case 'l': locale = argv[i]; o = ' '; @@ -301,16 +308,11 @@ int main(int argc, char *argv[]) setlocale(LC_CTYPE, locale); if (font_name == NULL) { - fprintf(stderr, "Usage: %s -f font.bgf [ -l locale ] [ program ]\n", argv[0]); + fprintf(stderr, "Usage: %s -f font.bgf [ -s scale ] [ -l locale ] [ program ]\n", argv[0]); return 1; } - if ((font = bogl_mmap_font(font_name)) == NULL) { - fprintf(stderr, "Bad font\n"); - return 1; - } - tcgetattr(0, &ttysave); if (!bogl_init()) { @@ -318,6 +320,20 @@ int main(int argc, char *argv[]) return 1; } + if (font_scale == 0) { + if (bogl_xres > 3840 && bogl_yres > 2160) + font_scale = 4; + else if (bogl_xres > 1920 && bogl_yres > 1080) + font_scale = 2; + else + font_scale = 1; + } + + if ((font = bogl_mmap_font(font_name, font_scale)) == NULL) { + fprintf(stderr, "Bad font\n"); + return 1; + } + term = bogl_term_new(font); if (!term) exit(1); -- 2.30.2
From e0e6a00ebb6d072e6d4d1fc2e21c6af614d70291 Mon Sep 17 00:00:00 2001 From: Zhang Boyang <zhangboyang...@gmail.com> Date: Mon, 23 May 2022 22:07:37 +0800 Subject: [PATCH v3 4/4] Use ioctl(FBIOPAN_DISPLAY) to update screen after drawing This patch introduces bogl_update(), which should be called after redrawing to notify device to update screen. In fact, this should not be necessary, but some buggy framebuffer drivers (e.g. i915 on skylake, and some non-standard fbdev implementations found in embedded systems) require an explicit notification after modifying screen contents, otherwise modifications in graphics buffer will not be reflected on screen. This patch uses FBIOPAN_DISPLAY to do this notify. --- bogl-term.c | 1 + bogl.c | 26 +++++++++++++++++++++++++- bogl.h | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/bogl-term.c b/bogl-term.c index 66901e0..2d35d1d 100644 --- a/bogl-term.c +++ b/bogl-term.c @@ -863,4 +863,5 @@ bogl_term_redraw (struct bogl_term *term) { show_cursor(term, 1); } + bogl_update(); } diff --git a/bogl.c b/bogl.c index 86bc1e0..da20981 100644 --- a/bogl.c +++ b/bogl.c @@ -124,12 +124,12 @@ static void kbd_done (void); static void sigusr2 (int); static struct fb_fix_screeninfo fb_fix; +static struct fb_var_screeninfo fb_var; /* Initialize BOGL. */ int bogl_init (void) { unsigned long bogl_frame_offset, bogl_frame_len; - struct fb_var_screeninfo fb_var; struct vt_stat vts; int PAGE_MASK = ~(sysconf(_SC_PAGESIZE) - 1); @@ -457,6 +457,30 @@ bogl_fb_set_palette (int c, int nc, const unsigned char palette[][3]) ioctl (fb, FBIOPUTCMAP, &cmap); } +/* Update screen. This should not be necessary, but some buggy framebuffer + drivers (e.g. i915 on skylake, and some non-standard fbdev implementations + found in embedded systems) require an explicit notification after + modifying screen contents, otherwise modifications in graphics buffer + will not be reflected on screen. */ +void +bogl_update (void) +{ +#if BOGL_VGA16_FB + if (type == FB_TYPE_VGA_PLANES) + { + /* There is no need to call FBIOPAN_DISPLAY when using vga16fb driver. + What's worse, it may cause screen flicker on certain hardwares. + So make bogl_update() a no-op here. */ + return; + } +#endif + /* The FBIOPAN_DISPLAY ioctl can be used to update the screen. There are + many libraries using FBIOPAN_DISPLAY to implement double buffering on + fbdev. However, we are not using double buffering, so just hope this + will not hit hidden bugs. */ + ioctl (fb, FBIOPAN_DISPLAY, &fb_var); +} + /* Returns the oldest error message since this function was last called. Clears the error state. Returns a null pointer if no errors have occurred. The caller must free the returned diff --git a/bogl.h b/bogl.h index 4d99788..61b0275 100644 --- a/bogl.h +++ b/bogl.h @@ -79,6 +79,7 @@ const char *bogl_error (void); void bogl_gray_scale (int make_gray); void bogl_fb_set_palette (int c, int nc, const unsigned char palette[][3]); +void bogl_update(void); void bogl_rectangle (int x1, int y1, int x2, int y2, int c); int bogl_metrics (const char *s, int n, const struct bogl_font *font); -- 2.30.2