[WIP] Update screen update/refresh to avoid forking

This commit is contained in:
Bad Diode 2022-10-12 12:10:26 +02:00
parent e146eb6145
commit b9d7ed276d
2 changed files with 46 additions and 127 deletions

View File

@ -523,7 +523,8 @@ main(int argc, char *argv[]) {
// Main loop. // Main loop.
Time frame_time = time_now(); Time frame_time = time_now();
size_t frames = 0; size_t frames_update = 0;
size_t frames_refresh = 0;
while (true) { while (true) {
poll_input(); poll_input();
size_t elapsed = time_elapsed(frame_time); size_t elapsed = time_elapsed(frame_time);
@ -535,26 +536,18 @@ main(int argc, char *argv[]) {
// Blit ppu.pixels to the framebuffer. // Blit ppu.pixels to the framebuffer.
blit_framebuffer(); blit_framebuffer();
if (++frames > 5) { // TODO: make update frames and refresh frames as parameters instead
// memset(framebuffer, 0xFF, screen_width * screen_height * bpp); // of hardcoded
// system("echo 0 > /dev/graphics/fb0"); if (++frames_update > 5) {
// redraw_screen(); write(fb_file, "0", 0);
// blit_framebuffer(); frames_update = 0;
}
// FIXME: Thre HAS to be a better way to refresh the display lol. // NOTE: Maybe this should happen on blit_framebuffer depending on
system("echo 0 > /dev/graphics/fb0"); // the number of actual updates (uxn applications that don't modify
// the framebuffer shouldn't have to blink).
// Time t = time_now(); if (++frames_refresh > 360) {
// while (time_elapsed(t) < 16666666 * 2) { write(refresh_file, "1", 1);
// // nop wait X frames for the refresh? frames_refresh = 0;
// }
// wait(ret);
// memset(framebuffer, 0xFF, screen_width * screen_height * bpp);
// redraw_screen();
// memset(framebuffer, 0x00, screen_width * screen_height * bpp);
// redraw_screen();
frames = 0;
} }
frame_time = time_now(); frame_time = time_now();
} }
@ -562,95 +555,3 @@ main(int argc, char *argv[]) {
return 0; 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;
// }

View File

@ -25,6 +25,8 @@
static size_t screen_width = 0; static size_t screen_width = 0;
static size_t screen_height = 0; static size_t screen_height = 0;
static size_t bpp = 0; static size_t bpp = 0;
static int fb_file = 0;
static int refresh_file = 0;
static u8 *framebuffer = 0; static u8 *framebuffer = 0;
@ -45,10 +47,13 @@ static u8 blending[5][16] = {
u16 u16
rgb565(u32 rgba) { rgb565(u32 rgba) {
u16 r = rgba >> 16 & 0xFF; u16 r = (rgba >> 16 & 0xFF);
u16 g = rgba >> 8 & 0xFF; u16 g = (rgba >> 8 & 0xFF);
u16 b = rgba >> 0 & 0xFF; u16 b = (rgba >> 0 & 0xFF);
return (r << 8) | (g << 3) | (b >> 3); r = r >> 3;
g = g >> 2;
b = b >> 3;
return (r << 11) | (g << 5) | b;
} }
void void
@ -142,13 +147,20 @@ set_tty(bool graphics) {
int int
ppu_init(void) { ppu_init(void) {
// Open frambuffer and get the size. // Open frambuffer and get the size.
int fb = open("/dev/graphics/fb0", O_RDWR); fb_file = open("/dev/graphics/fb0", O_RDWR);
if (fb <= 0) { if (fb_file <= 0) {
fprintf(stderr, "error: couldn't open the framebuffer\n"); fprintf(stderr, "error: couldn't open the framebuffer\n");
exit(EXIT_FAILURE); 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; 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"); fprintf(stderr, "error: couldn't get the framebuffer size\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -156,9 +168,9 @@ ppu_init(void) {
// Mmap the framebuffer to a buffer object. // Mmap the framebuffer to a buffer object.
screen_width = info.xres; screen_width = info.xres;
screen_height = info.yres; screen_height = info.yres;
bpp = info.bits_per_pixel / 8; bpp = info.bits_per_pixel;
size_t len = bpp * screen_width * screen_height; size_t len = bpp / 8 * screen_width * screen_height;
framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb_file, 0);
if (framebuffer == MAP_FAILED) { if (framebuffer == MAP_FAILED) {
fprintf(stderr, "error: couldn't mmap the framebuffer\n"); fprintf(stderr, "error: couldn't mmap the framebuffer\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -208,10 +220,16 @@ blit_framebuffer(void) {
if (dirty_lines[j] != 0) { if (dirty_lines[j] != 0) {
for (size_t i = 0; i < screen_width; i++) { for (size_t i = 0; i < screen_width; i++) {
size_t idx = i + j * screen_width; size_t idx = i + j * screen_width;
u16 *p = framebuffer; if (bpp == 16) {
p[idx] = rgb565(palette[pixels_fg[idx] << 2 | pixels_bg[idx]]); u16 *p = framebuffer;
// FIXME: can we generalize this to use bpp instead of having p[idx] = rgb565(palette[pixels_fg[idx] << 2 | pixels_bg[idx]]);
// a version for 32/16 bit color? } 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; dirty_lines[j] = 0;