From 0527b4c4e1598b7612d65d7e1c0a63a0fe2384fc Mon Sep 17 00:00:00 2001 From: okay Date: Mon, 1 Feb 2021 20:33:26 -0800 Subject: [PATCH 1/2] [fb] speed up draw_rect functions --- src/rmkit/fb/fb.cpy | 87 +++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 27 deletions(-) diff --git a/src/rmkit/fb/fb.cpy b/src/rmkit/fb/fb.cpy index 5f371f98..1e745484 100644 --- a/src/rmkit/fb/fb.cpy +++ b/src/rmkit/fb/fb.cpy @@ -21,6 +21,9 @@ #include "../../vendor/stb/stb_image.h" #include "../../vendor/stb/stb_image_write.h" +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + using namespace std DEBUG_FB_INFO := getenv("DEBUG_FB_INFO") != NULL @@ -220,7 +223,7 @@ namespace framebuffer: self._set_pixel(i, j, WHITE) break default: - if dither != 1.0: + if unlikely(dither != 1.0): if fast_rand() / float(2 << 15) < dither: self._set_pixel(i, j, color) else: @@ -248,6 +251,12 @@ namespace framebuffer: // // note that dithering does not work with GRAY, RUBBER or ERASER inline void draw_rect(int o_x, o_y, w, h, color, fill=true, float dither=1.0): + update_dirty(dirty_area, o_x, o_y) + update_dirty(dirty_area, o_x+w, o_y+h) + + _draw_rect_fast(o_x, o_y, w, h, color, fill, dither) + + inline void _draw_rect_fast(int o_x, o_y, w, h, color, fill=true, float dither=1.0): self.dirty = 1 #ifdef DEBUG_FB fprintf(stderr, "DRAWING RECT X: %i Y: %i W: %i H: %i, COLOR: %i\n", o_x, o_y, w, h, color) @@ -256,19 +265,30 @@ namespace framebuffer: if o_y >= self.height || o_x >= self.width || o_y < 0 || o_x < 0: return - update_dirty(dirty_area, o_x, o_y) - update_dirty(dirty_area, o_x+w, o_y+h) + if likely(fill): + for j 0 h: + if j+o_y >= self.height: + break - for j 0 h: - if j+o_y >= self.height: - break + for i 0 w: + if i+o_x >= self.width: + break + + do_dithering(self.fbmem, i+o_x, j+o_y, color, dither) + else: + for j 0 h: + if j+o_y >= self.height: + break + + do_dithering(self.fbmem, o_x, j+o_y, color, dither) + do_dithering(self.fbmem, w+o_x-1, j+o_y, color, dither) for i 0 w: if i+o_x >= self.width: break - if fill || (j == 0 || i == 0 || j == h-1 || i == w-1): - do_dithering(self.fbmem, i+o_x, j+o_y, color, dither) + do_dithering(self.fbmem, i+o_x, o_y, color, dither) + do_dithering(self.fbmem, i+o_x, h+o_y-1, color, dither) inline remarkable_color to_rgb565(char *src, int offset): r := src[offset] @@ -454,15 +474,18 @@ namespace framebuffer: int w = stroke int h = stroke + update_dirty(dirty_area, x0-radius, y0-radius) + update_dirty(dirty_area, x0+radius, y0+radius) + while(x <= y): - self.draw_rect(x+x0, y+y0, w, h, color, true); - self.draw_rect(-x+x0, y+y0, w, h, color, true); - self.draw_rect(x+x0, -y+y0, w, h, color, true); - self.draw_rect(-x+x0, -y+y0, w, h, color, true); - self.draw_rect(y+x0, x+y0, w, h, color, true); - self.draw_rect(-y+x0, x+y0, w, h, color, true); - self.draw_rect(y+x0, -x+y0, w, h, color, true); - self.draw_rect(-y+x0, -x+y0, w, h, color, true); + _draw_rect_fast(x+x0, y+y0, w, h, color, true); + _draw_rect_fast(-x+x0, y+y0, w, h, color, true); + _draw_rect_fast(x+x0, -y+y0, w, h, color, true); + _draw_rect_fast(-x+x0, -y+y0, w, h, color, true); + _draw_rect_fast(y+x0, x+y0, w, h, color, true); + _draw_rect_fast(-y+x0, x+y0, w, h, color, true); + _draw_rect_fast(y+x0, -x+y0, w, h, color, true); + _draw_rect_fast(-y+x0, -x+y0, w, h, color, true); if(d <= 0): x++; @@ -478,7 +501,10 @@ namespace framebuffer: w := stroke h := stroke - self.draw_rect(x, y, w, h, color, true); + update_dirty(dirty_area, x0-r, y0-r) + update_dirty(dirty_area, x0+r, y0+r) + + _draw_rect_fast(x, y, w, h, color, true); d := (3-2*(int)r); while (x <= y): if (d <= 0): @@ -488,21 +514,24 @@ namespace framebuffer: y--; x++; - self.draw_rect(x+x0, y+y0, w, h, color, true); - self.draw_rect(-x+x0, y+y0, w, h, color, true); - self.draw_rect(x+x0, -y+y0, w, h, color, true); - self.draw_rect(-x+x0, -y+y0, w, h, color, true); - self.draw_rect(y+x0, x+y0, w, h, color, true); - self.draw_rect(-y+x0, x+y0, w, h, color, true); - self.draw_rect(y+x0, -x+y0, w, h, color, true); + _draw_rect_fast(x+x0, y+y0, w, h, color, true); + _draw_rect_fast(-x+x0, y+y0, w, h, color, true); + _draw_rect_fast(x+x0, -y+y0, w, h, color, true); + _draw_rect_fast(-x+x0, -y+y0, w, h, color, true); + _draw_rect_fast(y+x0, x+y0, w, h, color, true); + _draw_rect_fast(-y+x0, x+y0, w, h, color, true); + _draw_rect_fast(y+x0, -x+y0, w, h, color, true); - self.draw_rect(-y+x0, -x+y0, w, h, color, true); + _draw_rect_fast(-y+x0, -x+y0, w, h, color, true); def draw_circle_filled(int x0, y0, radius, stroke, color): + update_dirty(dirty_area, x0-radius, y0-radius) + update_dirty(dirty_area, x0+radius, y0+radius) + for x := -radius; x <= radius; x++: for y := -radius; y <= radius; y++: if (x*x+y*y) <= radius*radius: - self.draw_rect(x+x0, y+y0, stroke, stroke, color, true) + _draw_rect_fast(x+x0, y+y0, stroke, stroke, color, true) // function: draw_circle // @@ -548,13 +577,17 @@ namespace framebuffer: fprintf(stderr, "DRAWING LINE %i %i %i %i\n", x0, y0, x1, y1) #endif self.dirty = 1 + + update_dirty(dirty_area, x0, y0) + update_dirty(dirty_area, x1, y1) + dx := abs(x1-x0) sx := x0 Date: Wed, 3 Feb 2021 18:08:24 -0800 Subject: [PATCH 2/2] [fb] split draw_rect into cases based on review feedback --- src/rmkit/fb/fb.cpy | 71 ++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/src/rmkit/fb/fb.cpy b/src/rmkit/fb/fb.cpy index 1e745484..0b18b218 100644 --- a/src/rmkit/fb/fb.cpy +++ b/src/rmkit/fb/fb.cpy @@ -254,9 +254,15 @@ namespace framebuffer: update_dirty(dirty_area, o_x, o_y) update_dirty(dirty_area, o_x+w, o_y+h) - _draw_rect_fast(o_x, o_y, w, h, color, fill, dither) + if fill: + _draw_rect_fast(o_x, o_y, w, h, color, dither) + else: + _draw_rect_fast(o_x, o_y, w, 1, color, dither) + _draw_rect_fast(o_x, o_y+h-1, w, 1, color, dither) + _draw_rect_fast(o_x, o_y, 1, h, color, dither) + _draw_rect_fast(o_x+w-1, o_y, 1, h, color, dither) - inline void _draw_rect_fast(int o_x, o_y, w, h, color, fill=true, float dither=1.0): + inline void _draw_rect_fast(int o_x, o_y, w, h, color, float dither=1.0): self.dirty = 1 #ifdef DEBUG_FB fprintf(stderr, "DRAWING RECT X: %i Y: %i W: %i H: %i, COLOR: %i\n", o_x, o_y, w, h, color) @@ -265,30 +271,15 @@ namespace framebuffer: if o_y >= self.height || o_x >= self.width || o_y < 0 || o_x < 0: return - if likely(fill): - for j 0 h: - if j+o_y >= self.height: - break - - for i 0 w: - if i+o_x >= self.width: - break - - do_dithering(self.fbmem, i+o_x, j+o_y, color, dither) - else: - for j 0 h: - if j+o_y >= self.height: - break - - do_dithering(self.fbmem, o_x, j+o_y, color, dither) - do_dithering(self.fbmem, w+o_x-1, j+o_y, color, dither) + for j 0 h: + if j+o_y >= self.height: + break for i 0 w: if i+o_x >= self.width: break - do_dithering(self.fbmem, i+o_x, o_y, color, dither) - do_dithering(self.fbmem, i+o_x, h+o_y-1, color, dither) + do_dithering(self.fbmem, i+o_x, j+o_y, color, dither) inline remarkable_color to_rgb565(char *src, int offset): r := src[offset] @@ -478,14 +469,14 @@ namespace framebuffer: update_dirty(dirty_area, x0+radius, y0+radius) while(x <= y): - _draw_rect_fast(x+x0, y+y0, w, h, color, true); - _draw_rect_fast(-x+x0, y+y0, w, h, color, true); - _draw_rect_fast(x+x0, -y+y0, w, h, color, true); - _draw_rect_fast(-x+x0, -y+y0, w, h, color, true); - _draw_rect_fast(y+x0, x+y0, w, h, color, true); - _draw_rect_fast(-y+x0, x+y0, w, h, color, true); - _draw_rect_fast(y+x0, -x+y0, w, h, color, true); - _draw_rect_fast(-y+x0, -x+y0, w, h, color, true); + _draw_rect_fast(x+x0, y+y0, w, h, color); + _draw_rect_fast(-x+x0, y+y0, w, h, color); + _draw_rect_fast(x+x0, -y+y0, w, h, color); + _draw_rect_fast(-x+x0, -y+y0, w, h, color); + _draw_rect_fast(y+x0, x+y0, w, h, color); + _draw_rect_fast(-y+x0, x+y0, w, h, color); + _draw_rect_fast(y+x0, -x+y0, w, h, color); + _draw_rect_fast(-y+x0, -x+y0, w, h, color); if(d <= 0): x++; @@ -504,7 +495,7 @@ namespace framebuffer: update_dirty(dirty_area, x0-r, y0-r) update_dirty(dirty_area, x0+r, y0+r) - _draw_rect_fast(x, y, w, h, color, true); + _draw_rect_fast(x, y, w, h, color); d := (3-2*(int)r); while (x <= y): if (d <= 0): @@ -514,15 +505,15 @@ namespace framebuffer: y--; x++; - _draw_rect_fast(x+x0, y+y0, w, h, color, true); - _draw_rect_fast(-x+x0, y+y0, w, h, color, true); - _draw_rect_fast(x+x0, -y+y0, w, h, color, true); - _draw_rect_fast(-x+x0, -y+y0, w, h, color, true); - _draw_rect_fast(y+x0, x+y0, w, h, color, true); - _draw_rect_fast(-y+x0, x+y0, w, h, color, true); - _draw_rect_fast(y+x0, -x+y0, w, h, color, true); + _draw_rect_fast(x+x0, y+y0, w, h, color); + _draw_rect_fast(-x+x0, y+y0, w, h, color); + _draw_rect_fast(x+x0, -y+y0, w, h, color); + _draw_rect_fast(-x+x0, -y+y0, w, h, color); + _draw_rect_fast(y+x0, x+y0, w, h, color); + _draw_rect_fast(-y+x0, x+y0, w, h, color); + _draw_rect_fast(y+x0, -x+y0, w, h, color); - _draw_rect_fast(-y+x0, -x+y0, w, h, color, true); + _draw_rect_fast(-y+x0, -x+y0, w, h, color); def draw_circle_filled(int x0, y0, radius, stroke, color): update_dirty(dirty_area, x0-radius, y0-radius) @@ -531,7 +522,7 @@ namespace framebuffer: for x := -radius; x <= radius; x++: for y := -radius; y <= radius; y++: if (x*x+y*y) <= radius*radius: - _draw_rect_fast(x+x0, y+y0, stroke, stroke, color, true) + _draw_rect_fast(x+x0, y+y0, stroke, stroke, color) // function: draw_circle // @@ -587,7 +578,7 @@ namespace framebuffer: sy := y0