diff options
author | Bad Diode <bd@badd10de.dev> | 2022-10-12 12:10:26 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-10-12 12:10:26 +0200 |
commit | b9d7ed276d73f671f482ca88958ac38d618f2644 (patch) | |
tree | 8bce3d9ded5a6e92d5fdfb01dbbdd5c5a20b9fa4 | |
parent | e146eb61450f5c09ed81fe421eb6b8f1ca153296 (diff) | |
download | uxnfb-b9d7ed276d73f671f482ca88958ac38d618f2644.tar.gz uxnfb-b9d7ed276d73f671f482ca88958ac38d618f2644.zip |
[WIP] Update screen update/refresh to avoid forking
-rw-r--r-- | src/main.c | 127 | ||||
-rw-r--r-- | src/ppu.c | 46 |
2 files changed, 46 insertions, 127 deletions
@@ -523,7 +523,8 @@ main(int argc, char *argv[]) { | |||
523 | 523 | ||
524 | // Main loop. | 524 | // Main loop. |
525 | Time frame_time = time_now(); | 525 | Time frame_time = time_now(); |
526 | size_t frames = 0; | 526 | size_t frames_update = 0; |
527 | size_t frames_refresh = 0; | ||
527 | while (true) { | 528 | while (true) { |
528 | poll_input(); | 529 | poll_input(); |
529 | size_t elapsed = time_elapsed(frame_time); | 530 | size_t elapsed = time_elapsed(frame_time); |
@@ -535,26 +536,18 @@ main(int argc, char *argv[]) { | |||
535 | 536 | ||
536 | // Blit ppu.pixels to the framebuffer. | 537 | // Blit ppu.pixels to the framebuffer. |
537 | blit_framebuffer(); | 538 | blit_framebuffer(); |
538 | if (++frames > 5) { | 539 | // TODO: make update frames and refresh frames as parameters instead |
539 | // memset(framebuffer, 0xFF, screen_width * screen_height * bpp); | 540 | // of hardcoded |
540 | // system("echo 0 > /dev/graphics/fb0"); | 541 | if (++frames_update > 5) { |
541 | // redraw_screen(); | 542 | write(fb_file, "0", 0); |
542 | // blit_framebuffer(); | 543 | frames_update = 0; |
543 | 544 | } | |
544 | // FIXME: Thre HAS to be a better way to refresh the display lol. | 545 | // NOTE: Maybe this should happen on blit_framebuffer depending on |
545 | system("echo 0 > /dev/graphics/fb0"); | 546 | // the number of actual updates (uxn applications that don't modify |
546 | 547 | // the framebuffer shouldn't have to blink). | |
547 | // Time t = time_now(); | 548 | if (++frames_refresh > 360) { |
548 | // while (time_elapsed(t) < 16666666 * 2) { | 549 | write(refresh_file, "1", 1); |
549 | // // nop wait X frames for the refresh? | 550 | frames_refresh = 0; |
550 | // } | ||
551 | // wait(ret); | ||
552 | // memset(framebuffer, 0xFF, screen_width * screen_height * bpp); | ||
553 | // redraw_screen(); | ||
554 | // memset(framebuffer, 0x00, screen_width * screen_height * bpp); | ||
555 | // redraw_screen(); | ||
556 | |||
557 | frames = 0; | ||
558 | } | 551 | } |
559 | frame_time = time_now(); | 552 | frame_time = time_now(); |
560 | } | 553 | } |
@@ -562,95 +555,3 @@ main(int argc, char *argv[]) { | |||
562 | 555 | ||
563 | return 0; | 556 | return 0; |
564 | } | 557 | } |
565 | |||
566 | // int | ||
567 | // main(int argc, char *argv[]) { | ||
568 | // // FIXME: Experimental | ||
569 | // int fb = open("/dev/graphics/fb0", O_RDWR); | ||
570 | // if (fb <= 0) { | ||
571 | // fprintf(stderr, "error: couldn't open the framebuffer\n"); | ||
572 | // exit(EXIT_FAILURE); | ||
573 | // } | ||
574 | // struct fb_var_screeninfo info; | ||
575 | // if (ioctl(fb, FBIOGET_VSCREENINFO, &info) != 0) { | ||
576 | // fprintf(stderr, "error: couldn't get the framebuffer size\n"); | ||
577 | // exit(EXIT_FAILURE); | ||
578 | // } | ||
579 | // size_t screen_width = info.xres; | ||
580 | // size_t screen_height = info.yres; | ||
581 | // size_t bpp = info.bits_per_pixel / 8; | ||
582 | // size_t len = bpp * screen_width * screen_height; | ||
583 | // u8 *framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); | ||
584 | // if (framebuffer == MAP_FAILED) { | ||
585 | // fprintf(stderr, "error: couldn't mmap the framebuffer\n"); | ||
586 | // exit(EXIT_FAILURE); | ||
587 | // } | ||
588 | |||
589 | // // Print all relevant elements from the fb_var_screeninfo struct | ||
590 | // printf("> xres: %d\n" | ||
591 | // "> yres: %d\n" | ||
592 | // "> xres_virtual: %d\n" | ||
593 | // "> yres_virtual: %d\n" | ||
594 | // "> xoffset: %d\n" | ||
595 | // "> yoffset: %d\n" | ||
596 | // "> bits_per_pixel: %d\n" | ||
597 | // "> grayscale: %d\n" | ||
598 | // "> activate: %d\n" | ||
599 | // "> height: %d\n" | ||
600 | // "> width: %d\n" | ||
601 | // "> hsync_len: %d\n" | ||
602 | // "> vsync_len: %d\n" | ||
603 | // "> sync: %d\n" | ||
604 | // "> vmode: %d\n" | ||
605 | // "> rotate: %d\n" | ||
606 | // "> len: %d\n", | ||
607 | // info.xres, | ||
608 | // info.yres, | ||
609 | // info.xres_virtual, | ||
610 | // info.yres_virtual, | ||
611 | // info.xoffset, | ||
612 | // info.yoffset, | ||
613 | // info.bits_per_pixel, | ||
614 | // info.grayscale, | ||
615 | // info.activate, | ||
616 | // info.height, | ||
617 | // info.width, | ||
618 | // info.hsync_len, | ||
619 | // info.vsync_len, | ||
620 | // info.sync, | ||
621 | // info.vmode, | ||
622 | // info.rotate, | ||
623 | // len); | ||
624 | |||
625 | |||
626 | // // Clean screen | ||
627 | // // memset(framebuffer, 0x00, screen_width * screen_height * 2); // black | ||
628 | // memset(framebuffer, 0xFF, len); // white | ||
629 | // for (size_t i = 0, k = 0; i < (screen_width * screen_height) / 2; i++) { | ||
630 | // for (size_t b = 0; b < bpp; b++) { | ||
631 | // framebuffer[k++] = 0xF0; | ||
632 | // } | ||
633 | // // p[i] = 0xF0F0; | ||
634 | // // framebuffer[k++] = 0xFF; | ||
635 | // // framebuffer[k++] = 0x00; | ||
636 | // } | ||
637 | |||
638 | // // Main loop. | ||
639 | // Time frame_time = time_now(); | ||
640 | // size_t frames = 0; | ||
641 | // while (true) { | ||
642 | // size_t elapsed = time_elapsed(frame_time); | ||
643 | // if (elapsed >= 16666666) { | ||
644 | |||
645 | // // FIXME: Thre HAS to be a better way lol. | ||
646 | // frame_time = time_now(); | ||
647 | // frames++; | ||
648 | // if (frames > 10) { | ||
649 | // system("echo 0 > /dev/graphics/fb0"); | ||
650 | // frames = 0; | ||
651 | // } | ||
652 | // } | ||
653 | // } | ||
654 | |||
655 | // return 0; | ||
656 | // } | ||
@@ -25,6 +25,8 @@ | |||
25 | static size_t screen_width = 0; | 25 | static size_t screen_width = 0; |
26 | static size_t screen_height = 0; | 26 | static size_t screen_height = 0; |
27 | static size_t bpp = 0; | 27 | static size_t bpp = 0; |
28 | static int fb_file = 0; | ||
29 | static int refresh_file = 0; | ||
28 | 30 | ||
29 | static u8 *framebuffer = 0; | 31 | static u8 *framebuffer = 0; |
30 | 32 | ||
@@ -45,10 +47,13 @@ static u8 blending[5][16] = { | |||
45 | 47 | ||
46 | u16 | 48 | u16 |
47 | rgb565(u32 rgba) { | 49 | rgb565(u32 rgba) { |
48 | u16 r = rgba >> 16 & 0xFF; | 50 | u16 r = (rgba >> 16 & 0xFF); |
49 | u16 g = rgba >> 8 & 0xFF; | 51 | u16 g = (rgba >> 8 & 0xFF); |
50 | u16 b = rgba >> 0 & 0xFF; | 52 | u16 b = (rgba >> 0 & 0xFF); |
51 | return (r << 8) | (g << 3) | (b >> 3); | 53 | r = r >> 3; |
54 | g = g >> 2; | ||
55 | b = b >> 3; | ||
56 | return (r << 11) | (g << 5) | b; | ||
52 | } | 57 | } |
53 | 58 | ||
54 | void | 59 | void |
@@ -142,13 +147,20 @@ set_tty(bool graphics) { | |||
142 | int | 147 | int |
143 | ppu_init(void) { | 148 | ppu_init(void) { |
144 | // Open frambuffer and get the size. | 149 | // Open frambuffer and get the size. |
145 | int fb = open("/dev/graphics/fb0", O_RDWR); | 150 | fb_file = open("/dev/graphics/fb0", O_RDWR); |
146 | if (fb <= 0) { | 151 | if (fb_file <= 0) { |
147 | fprintf(stderr, "error: couldn't open the framebuffer\n"); | 152 | fprintf(stderr, "error: couldn't open the framebuffer\n"); |
148 | exit(EXIT_FAILURE); | 153 | exit(EXIT_FAILURE); |
149 | } | 154 | } |
155 | |||
156 | refresh_file = open("/sys/class/graphics/fb0/epd_refresh", O_RDWR); | ||
157 | if (refresh_file == 0) { | ||
158 | fprintf(stderr, "error: couldn't open the refresh file\n"); | ||
159 | exit(EXIT_FAILURE); | ||
160 | } | ||
161 | |||
150 | struct fb_var_screeninfo info; | 162 | struct fb_var_screeninfo info; |
151 | if (ioctl(fb, FBIOGET_VSCREENINFO, &info) != 0) { | 163 | if (ioctl(fb_file, FBIOGET_VSCREENINFO, &info) != 0) { |
152 | fprintf(stderr, "error: couldn't get the framebuffer size\n"); | 164 | fprintf(stderr, "error: couldn't get the framebuffer size\n"); |
153 | exit(EXIT_FAILURE); | 165 | exit(EXIT_FAILURE); |
154 | } | 166 | } |
@@ -156,9 +168,9 @@ ppu_init(void) { | |||
156 | // Mmap the framebuffer to a buffer object. | 168 | // Mmap the framebuffer to a buffer object. |
157 | screen_width = info.xres; | 169 | screen_width = info.xres; |
158 | screen_height = info.yres; | 170 | screen_height = info.yres; |
159 | bpp = info.bits_per_pixel / 8; | 171 | bpp = info.bits_per_pixel; |
160 | size_t len = bpp * screen_width * screen_height; | 172 | size_t len = bpp / 8 * screen_width * screen_height; |
161 | framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); | 173 | framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb_file, 0); |
162 | if (framebuffer == MAP_FAILED) { | 174 | if (framebuffer == MAP_FAILED) { |
163 | fprintf(stderr, "error: couldn't mmap the framebuffer\n"); | 175 | fprintf(stderr, "error: couldn't mmap the framebuffer\n"); |
164 | exit(EXIT_FAILURE); | 176 | exit(EXIT_FAILURE); |
@@ -208,10 +220,16 @@ blit_framebuffer(void) { | |||
208 | if (dirty_lines[j] != 0) { | 220 | if (dirty_lines[j] != 0) { |
209 | for (size_t i = 0; i < screen_width; i++) { | 221 | for (size_t i = 0; i < screen_width; i++) { |
210 | size_t idx = i + j * screen_width; | 222 | size_t idx = i + j * screen_width; |
211 | u16 *p = framebuffer; | 223 | if (bpp == 16) { |
212 | p[idx] = rgb565(palette[pixels_fg[idx] << 2 | pixels_bg[idx]]); | 224 | u16 *p = framebuffer; |
213 | // FIXME: can we generalize this to use bpp instead of having | 225 | p[idx] = rgb565(palette[pixels_fg[idx] << 2 | pixels_bg[idx]]); |
214 | // a version for 32/16 bit color? | 226 | } else if (bpp == 32) { |
227 | u32 *p = framebuffer; | ||
228 | p[idx] = palette[pixels_fg[idx] << 2 | pixels_bg[idx]]; | ||
229 | } else { | ||
230 | fprintf(stderr, "error: wrong bits per pixel (expected 16 or 32)\n"); | ||
231 | exit(EXIT_FAILURE); | ||
232 | } | ||
215 | } | 233 | } |
216 | } | 234 | } |
217 | dirty_lines[j] = 0; | 235 | dirty_lines[j] = 0; |