From b9d7ed276d73f671f482ca88958ac38d618f2644 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Wed, 12 Oct 2022 12:10:26 +0200 Subject: [WIP] Update screen update/refresh to avoid forking --- src/main.c | 127 +++++++------------------------------------------------------ src/ppu.c | 46 +++++++++++++++------- 2 files changed, 46 insertions(+), 127 deletions(-) diff --git a/src/main.c b/src/main.c index 53aa5c3..f2d373b 100644 --- a/src/main.c +++ b/src/main.c @@ -523,7 +523,8 @@ main(int argc, char *argv[]) { // Main loop. Time frame_time = time_now(); - size_t frames = 0; + size_t frames_update = 0; + size_t frames_refresh = 0; while (true) { poll_input(); size_t elapsed = time_elapsed(frame_time); @@ -535,26 +536,18 @@ main(int argc, char *argv[]) { // Blit ppu.pixels to the framebuffer. blit_framebuffer(); - if (++frames > 5) { - // memset(framebuffer, 0xFF, screen_width * screen_height * bpp); - // system("echo 0 > /dev/graphics/fb0"); - // redraw_screen(); - // blit_framebuffer(); - - // FIXME: Thre HAS to be a better way to refresh the display lol. - system("echo 0 > /dev/graphics/fb0"); - - // Time t = time_now(); - // while (time_elapsed(t) < 16666666 * 2) { - // // nop wait X frames for the refresh? - // } - // wait(ret); - // memset(framebuffer, 0xFF, screen_width * screen_height * bpp); - // redraw_screen(); - // memset(framebuffer, 0x00, screen_width * screen_height * bpp); - // redraw_screen(); - - frames = 0; + // TODO: make update frames and refresh frames as parameters instead + // of hardcoded + if (++frames_update > 5) { + write(fb_file, "0", 0); + frames_update = 0; + } + // NOTE: Maybe this should happen on blit_framebuffer depending on + // the number of actual updates (uxn applications that don't modify + // the framebuffer shouldn't have to blink). + if (++frames_refresh > 360) { + write(refresh_file, "1", 1); + frames_refresh = 0; } frame_time = time_now(); } @@ -562,95 +555,3 @@ main(int argc, char *argv[]) { return 0; } - -// int -// main(int argc, char *argv[]) { -// // FIXME: Experimental -// int fb = open("/dev/graphics/fb0", O_RDWR); -// if (fb <= 0) { -// fprintf(stderr, "error: couldn't open the framebuffer\n"); -// exit(EXIT_FAILURE); -// } -// struct fb_var_screeninfo info; -// if (ioctl(fb, FBIOGET_VSCREENINFO, &info) != 0) { -// fprintf(stderr, "error: couldn't get the framebuffer size\n"); -// exit(EXIT_FAILURE); -// } -// size_t screen_width = info.xres; -// size_t screen_height = info.yres; -// size_t bpp = info.bits_per_pixel / 8; -// size_t len = bpp * screen_width * screen_height; -// u8 *framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); -// if (framebuffer == MAP_FAILED) { -// fprintf(stderr, "error: couldn't mmap the framebuffer\n"); -// exit(EXIT_FAILURE); -// } - -// // Print all relevant elements from the fb_var_screeninfo struct -// printf("> xres: %d\n" -// "> yres: %d\n" -// "> xres_virtual: %d\n" -// "> yres_virtual: %d\n" -// "> xoffset: %d\n" -// "> yoffset: %d\n" -// "> bits_per_pixel: %d\n" -// "> grayscale: %d\n" -// "> activate: %d\n" -// "> height: %d\n" -// "> width: %d\n" -// "> hsync_len: %d\n" -// "> vsync_len: %d\n" -// "> sync: %d\n" -// "> vmode: %d\n" -// "> rotate: %d\n" -// "> len: %d\n", -// info.xres, -// info.yres, -// info.xres_virtual, -// info.yres_virtual, -// info.xoffset, -// info.yoffset, -// info.bits_per_pixel, -// info.grayscale, -// info.activate, -// info.height, -// info.width, -// info.hsync_len, -// info.vsync_len, -// info.sync, -// info.vmode, -// info.rotate, -// len); - - -// // Clean screen -// // memset(framebuffer, 0x00, screen_width * screen_height * 2); // black -// memset(framebuffer, 0xFF, len); // white -// for (size_t i = 0, k = 0; i < (screen_width * screen_height) / 2; i++) { -// for (size_t b = 0; b < bpp; b++) { -// framebuffer[k++] = 0xF0; -// } -// // p[i] = 0xF0F0; -// // framebuffer[k++] = 0xFF; -// // framebuffer[k++] = 0x00; -// } - -// // Main loop. -// Time frame_time = time_now(); -// size_t frames = 0; -// while (true) { -// size_t elapsed = time_elapsed(frame_time); -// if (elapsed >= 16666666) { - -// // FIXME: Thre HAS to be a better way lol. -// frame_time = time_now(); -// frames++; -// if (frames > 10) { -// system("echo 0 > /dev/graphics/fb0"); -// frames = 0; -// } -// } -// } - -// return 0; -// } diff --git a/src/ppu.c b/src/ppu.c index 175b2a7..3afa533 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -25,6 +25,8 @@ static size_t screen_width = 0; static size_t screen_height = 0; static size_t bpp = 0; +static int fb_file = 0; +static int refresh_file = 0; static u8 *framebuffer = 0; @@ -45,10 +47,13 @@ static u8 blending[5][16] = { u16 rgb565(u32 rgba) { - u16 r = rgba >> 16 & 0xFF; - u16 g = rgba >> 8 & 0xFF; - u16 b = rgba >> 0 & 0xFF; - return (r << 8) | (g << 3) | (b >> 3); + u16 r = (rgba >> 16 & 0xFF); + u16 g = (rgba >> 8 & 0xFF); + u16 b = (rgba >> 0 & 0xFF); + r = r >> 3; + g = g >> 2; + b = b >> 3; + return (r << 11) | (g << 5) | b; } void @@ -142,13 +147,20 @@ set_tty(bool graphics) { int ppu_init(void) { // Open frambuffer and get the size. - int fb = open("/dev/graphics/fb0", O_RDWR); - if (fb <= 0) { + fb_file = open("/dev/graphics/fb0", O_RDWR); + if (fb_file <= 0) { fprintf(stderr, "error: couldn't open the framebuffer\n"); exit(EXIT_FAILURE); } + + refresh_file = open("/sys/class/graphics/fb0/epd_refresh", O_RDWR); + if (refresh_file == 0) { + fprintf(stderr, "error: couldn't open the refresh file\n"); + exit(EXIT_FAILURE); + } + struct fb_var_screeninfo info; - if (ioctl(fb, FBIOGET_VSCREENINFO, &info) != 0) { + if (ioctl(fb_file, FBIOGET_VSCREENINFO, &info) != 0) { fprintf(stderr, "error: couldn't get the framebuffer size\n"); exit(EXIT_FAILURE); } @@ -156,9 +168,9 @@ ppu_init(void) { // Mmap the framebuffer to a buffer object. screen_width = info.xres; screen_height = info.yres; - bpp = info.bits_per_pixel / 8; - size_t len = bpp * screen_width * screen_height; - framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); + bpp = info.bits_per_pixel; + size_t len = bpp / 8 * screen_width * screen_height; + framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb_file, 0); if (framebuffer == MAP_FAILED) { fprintf(stderr, "error: couldn't mmap the framebuffer\n"); exit(EXIT_FAILURE); @@ -208,10 +220,16 @@ blit_framebuffer(void) { if (dirty_lines[j] != 0) { for (size_t i = 0; i < screen_width; i++) { size_t idx = i + j * screen_width; - u16 *p = framebuffer; - p[idx] = rgb565(palette[pixels_fg[idx] << 2 | pixels_bg[idx]]); - // FIXME: can we generalize this to use bpp instead of having - // a version for 32/16 bit color? + if (bpp == 16) { + u16 *p = framebuffer; + p[idx] = rgb565(palette[pixels_fg[idx] << 2 | pixels_bg[idx]]); + } else if (bpp == 32) { + u32 *p = framebuffer; + p[idx] = palette[pixels_fg[idx] << 2 | pixels_bg[idx]]; + } else { + fprintf(stderr, "error: wrong bits per pixel (expected 16 or 32)\n"); + exit(EXIT_FAILURE); + } } } dirty_lines[j] = 0; -- cgit v1.2.1