Skip to content

Commit

Permalink
[fb] speed up draw_rect functions
Browse files Browse the repository at this point in the history
  • Loading branch information
okay committed Feb 3, 2021
1 parent 1ac0cfd commit 0527b4c
Showing 1 changed file with 60 additions and 27 deletions.
87 changes: 60 additions & 27 deletions src/rmkit/fb/fb.cpy
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand All @@ -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]
Expand Down Expand Up @@ -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++;
Expand All @@ -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):
Expand All @@ -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
//
Expand Down Expand Up @@ -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<x1 ? 1 : -1
dy := -abs(y1-y0)
sy := y0<y1 ? 1 : -1
err := dx+dy /* error value e_xy */
while (true): /* loop */
self.draw_rect(x0, y0, width, width, color,true,dither)
_draw_rect_fast(x0, y0, width, width, color,true,dither)
// self.fbmem[y0*self.width + x0] = color
if (x0==x1 && y0==y1) break;
e2 := 2*err
Expand Down

0 comments on commit 0527b4c

Please sign in to comment.