perf(draw) reimplement rectangle drawing algorithms

No functionalty has changed only make them more readable and faster.
This commit is contained in:
Gabor Kiss-Vamosi
2021-07-28 17:11:26 +02:00
parent f61b2ca455
commit 5b3d3dc8b3
12 changed files with 1305 additions and 852 deletions
+10 -15
View File
@@ -140,16 +140,11 @@ LV_ATTRIBUTE_FAST_MEM void _lv_blend_fill(const lv_area_t * clip_area, const lv_
/*Get clipped fill area which is the real draw area.
*It is always the same or inside `fill_area`*/
lv_area_t draw_area;
bool is_common;
is_common = _lv_area_intersect(&draw_area, clip_area, fill_area);
if(!is_common) return;
if(!_lv_area_intersect(&draw_area, clip_area, fill_area)) return;
/*Now `draw_area` has absolute coordinates.
*Make it relative to `disp_area` to simplify draw to `disp_buf`*/
draw_area.x1 -= disp_area->x1;
draw_area.y1 -= disp_area->y1;
draw_area.x2 -= disp_area->x1;
draw_area.y2 -= disp_area->y1;
*Make it relative to `disp_area` to simplify the drawing to `disp_buf`*/
lv_area_move(&draw_area, -disp_area->x1, -disp_area->y1);
/*Round the values in the mask if anti-aliasing is disabled*/
if(mask && disp->driver->antialiasing == 0 && mask) {
@@ -390,13 +385,6 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
}
/*Masked*/
else {
/*Buffer the result color to avoid recalculating the same color*/
lv_color_t last_dest_color;
lv_color_t last_res_color;
lv_opa_t last_mask = LV_OPA_TRANSP;
last_dest_color.full = disp_buf_first[0].full;
last_res_color.full = disp_buf_first[0].full;
int32_t x_end4 = draw_area_w - 4;
#if LV_COLOR_DEPTH == 16
@@ -452,7 +440,14 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
}
/*Handle opa and mask values too*/
else {
/*Buffer the result color to avoid recalculating the same color*/
lv_color_t last_dest_color;
lv_color_t last_res_color;
lv_opa_t last_mask = LV_OPA_TRANSP;
last_dest_color.full = disp_buf_first[0].full;
last_res_color.full = disp_buf_first[0].full;
lv_opa_t opa_tmp = LV_OPA_TRANSP;
for(y = draw_area->y1; y <= draw_area->y2; y++) {
const lv_opa_t * mask_tmp_x = mask;
for(x = 0; x < draw_area_w; x++) {
+15
View File
@@ -211,6 +211,11 @@ LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void)
return cnt;
}
bool lv_draw_mask_is_any(void)
{
return LV_GC_ROOT(_lv_draw_mask_list[0]).param ? true : false;
}
/**
*Initialize a line mask from two points.
* @param param pointer to a `lv_draw_mask_param_t` to initialize
@@ -1203,10 +1208,20 @@ static void circ_calc_aa4(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t radi
if(c->buf) lv_mem_free(c->buf);
c->buf = lv_mem_alloc(radius * 6 + 6); /*Use uint16_t for opa_start_on_y and x_start_on_y*/
LV_ASSERT_MALLOC(c->buf);
c->cir_opa = c->buf;
c->opa_start_on_y = (uint16_t *) (c->buf + 2 * radius + 2);
c->x_start_on_y = (uint16_t *) (c->buf + 4 * radius + 4);
/*Special case, handle manually*/
if(radius == 1) {
c->cir_opa[0] = 180;
c->opa_start_on_y[0] = 0;
c->opa_start_on_y[1] = 1;
c->x_start_on_y[0] = 0;
return;
}
lv_coord_t * cir_x = lv_mem_buf_get((radius + 1) * 2 * 2 * sizeof(lv_coord_t));
lv_coord_t * cir_y = &cir_x[(radius + 1) * 2];
+12
View File
@@ -58,6 +58,11 @@ typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM];
static inline uint8_t lv_draw_mask_get_cnt(void) {
return 0;
}
static inline bool lv_draw_mask_is_any(void) {
return false;
}
#endif
#if LV_DRAW_COMPLEX
@@ -269,6 +274,13 @@ void _lv_draw_mask_cleanup(void);
*/
LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void);
/**
* Check is there is any added draw mask
* @return true: there is t least 1 draw mask; false: there are no draw masks
*/
bool lv_draw_mask_is_any(void);
//! @endcond
/**
+713 -833
View File
File diff suppressed because it is too large Load Diff
+38
View File
@@ -280,6 +280,44 @@ bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coo
return true;
}
/**
* Check if an area is fully out of an other
* @param aout_p pointer to an area which could be in 'aholder_p'
* @param aholder_p pointer to an area which could involve 'ain_p'
* @param radius radius of `aholder_p` (e.g. for rounded rectangle)
* @return true: `aout_p` is fully outside `aholder_p`
*/
bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_coord_t radius)
{
if(aout_p->x2 < aholder_p->x1 || aout_p->y2 < aholder_p->y1 || aout_p->x1 > aholder_p->x2 ||
aout_p->y1 > aholder_p->y2) {
return true;
}
if(radius == 0) return true;
/*Check if the corner points are outside the radius or not*/
lv_point_t p;
p.x = aout_p->x1;
p.y = aout_p->y1;
if(_lv_area_is_point_on(aholder_p, &p, radius)) return false;
p.x = aout_p->x2;
p.y = aout_p->y1;
if(_lv_area_is_point_on(aholder_p, &p, radius)) return false;
p.x = aout_p->x1;
p.y = aout_p->y2;
if(_lv_area_is_point_on(aholder_p, &p, radius)) return false;
p.x = aout_p->x2;
p.y = aout_p->y2;
if(_lv_area_is_point_on(aholder_p, &p, radius)) return false;
return true;
}
/**
* Align an area to an other
* @param base an are where the other will be aligned
+10
View File
@@ -221,6 +221,16 @@ bool _lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p);
*/
bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coord_t radius);
/**
* Check if an area is fully out of an other
* @param aout_p pointer to an area which could be in 'aholder_p'
* @param aholder_p pointer to an area which could involve 'ain_p'
* @param radius radius of `aholder_p` (e.g. for rounded rectangle)
* @return true: `aout_p` is fully outside `aholder_p`
*/
bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_coord_t radius);
/**
* Align an area to an other
* @param base an are where the other will be aligned
+9 -4
View File
@@ -463,8 +463,8 @@ LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_co
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0
/*Source: https://stackoverflow.com/a/50012418/1999969*/
mix = ( mix + 4 ) >> 3;
uint32_t bg = (c2.full | (c2.full << 16)) & 0x7E0F81F; /*0b00000111111000001111100000011111*/
uint32_t fg = (c1.full | (c1.full << 16)) & 0x7E0F81F;
uint32_t bg = (uint32_t)((uint32_t)c2.full | ((uint32_t)c2.full << 16)) & 0x7E0F81F; /*0b00000111111000001111100000011111*/
uint32_t fg = (uint32_t)((uint32_t)c1.full | (uint32_t)(c1.full << 16)) & 0x7E0F81F;
uint32_t result = ((((fg - bg) * mix) >> 5) + bg) & 0x7E0F81F;
ret.full = (uint16_t)((result >> 16) | result);
#elif LV_COLOR_DEPTH != 1
@@ -512,8 +512,13 @@ LV_ATTRIBUTE_FAST_MEM static inline void lv_color_premult(lv_color_t c, uint8_t
LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix_premult(uint16_t * premult_c1, lv_color_t c2, uint8_t mix)
{
lv_color_t ret;
#if LV_COLOR_DEPTH != 1
/*LV_COLOR_DEPTH == 8, 16 or 32*/
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0
/*For compatibility with lv_color_mix on 16 bit color depth*/
LV_COLOR_SET_R(ret, (premult_c1[0] + LV_COLOR_GET_R(c2) * mix) >> 8);
LV_COLOR_SET_G(ret, (premult_c1[1] + LV_COLOR_GET_G(c2) * mix) >> 8);
LV_COLOR_SET_B(ret, (premult_c1[2] + LV_COLOR_GET_B(c2) * mix) >> 8);
#elif LV_COLOR_DEPTH != 1
/*LV_COLOR_DEPTH == 8 or 32*/
LV_COLOR_SET_R(ret, LV_UDIV255(premult_c1[0] + LV_COLOR_GET_R(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
LV_COLOR_SET_G(ret, LV_UDIV255(premult_c1[1] + LV_COLOR_GET_G(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
LV_COLOR_SET_B(ret, LV_UDIV255(premult_c1[2] + LV_COLOR_GET_B(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
+1
View File
@@ -731,6 +731,7 @@ static void lv_arc_draw(lv_event_t * e)
part_draw_dsc.arc_dsc = &arc_dsc;
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc);
if(arc_dsc.width > part_draw_dsc.radius) arc_dsc.width = part_draw_dsc.radius;
lv_draw_arc(center.x, center.y, part_draw_dsc.radius, arc->indic_angle_start +arc->rotation,
arc->indic_angle_end + arc->rotation, clip_area,
&arc_dsc);
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 18 KiB

+1
View File
@@ -422,6 +422,7 @@ void test_dropdown_render_2(void)
lv_dropdown_set_options(dd7, "1aaa\n2\n3");
lv_dropdown_set_dir(dd7, LV_DIR_LEFT);
lv_dropdown_set_symbol(dd7, LV_SYMBOL_LEFT);
lv_obj_align(dd7, LV_ALIGN_BOTTOM_RIGHT, -20, -20);
lv_dropdown_open(dd7);
TEST_ASSERT_EQUAL_SCREENSHOT("dropdown_2.png");