mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-26 11:07:34 +08:00
perf(draw) reimplement circle drawing algorithms (#2374)
* perf(draw) reimplement circle drawing algorithms Imporve the speed of circle drawing Add circle draw caching Various other speed improvements * docs describe how to use masks * fix(draw) add missing GC root usage
This commit is contained in:
committed by
GitHub
parent
e23701e2c2
commit
637b706ddc
@@ -54,13 +54,13 @@ The difference between buffering modes regarding the drawing mechanism is the fo
|
||||
To use LVGL it's not required to know about the mechanisms described here, but you might find interesting to know how drawing works under hood.
|
||||
Knowing about masking comes in handy if you want to customize drawing.
|
||||
|
||||
To learn masking let's learn the steps of drawing first.
|
||||
To learn masking let's see the steps of drawing first.
|
||||
LVGL performs the following steps to render any shape, image or text. It can be considered as a drawing pipeline.
|
||||
|
||||
1. **Prepare the draw descriptors** Create a draw descriptor from an object's styles (e.g. `lv_draw_rect_dsc_t`). This gives us the parameters for drawing, for example the colors, widths, opacity, fonts, radius, etc.
|
||||
2. **Call the draw function** Call the draw function with the draw descriptor and some other parameters (e.g. `lv_draw_rect()`). It renders the primitive shape to the current draw buffer.
|
||||
3. **Create masks** If the shape is very simple and doesn't require masks go to #5. Else create the required masks (e.g. a rounded rectangle mask)
|
||||
4. **Calculate all the added mask**. It creates 0..255 values into a *mask buffer* with the "shape" of the created masks.
|
||||
2. **Call the draw function** Call the draw function with the draw descriptor and some other parameters (e.g. `lv_draw_rect()`). It will render the primitive shape to the current draw buffer.
|
||||
3. **Create masks** If the shape is very simple and doesn't require masks go to #5. Else create the required masks in the draw function. (e.g. a rounded rectangle mask)
|
||||
4. **Calculate all the added mask** It creates 0..255 values into a *mask buffer* with the "shape" of the created masks.
|
||||
E.g. in case of a "line mask" according to the parameters of the mask, keep one side of the buffer as it is (255 by default) and set the rest to 0 to indicate that this side should be removed.
|
||||
5. **Blend a color or image** During blending masks (make some pixels transparent or opaque), blending modes (additive, subtractive, etc) and opacity are handled.
|
||||
|
||||
@@ -81,6 +81,25 @@ Masks are used the create almost every basic primitives:
|
||||
- **arc drawing** A circle border is drawn, but an arc mask is applied too.
|
||||
- **ARGB images** The alpha channel is separated into a mask and the image is drawn as a normal RGB image.
|
||||
|
||||
### Using masks
|
||||
|
||||
Every mask type has a related paramter to describe the mask's data. The following paramater types exist:
|
||||
- `lv_draw_mask_line_param_t`
|
||||
- `lv_draw_mask_radius_param_t`
|
||||
- `lv_draw_mask_angle_param_t`
|
||||
- `lv_draw_mask_fade_param_t`
|
||||
- `lv_draw_mask_map_param_t`
|
||||
|
||||
1. Initialize a mask parameter with `lv_draw_mask_<type>_init`. See `lv_draw_mask.h` for the whole API.
|
||||
2. Add the mask parameter to the draw engine with `int16_t mask_id = lv_draw_mask_add(¶m, ptr)`. `ptr` can be any pointer to identify the mask, (`NULL` if unused).
|
||||
3. Call the draw functions
|
||||
4. Remove the mask from the draw engine with `lv_draw_mask_remove_id(mask_id)` of `lv_draw_mask_remove_custom(ptr)`.
|
||||
5. Free the parameter with `lv_draw_mask_free_param(¶m)`.
|
||||
|
||||
A parameter can be added and removed any number of times but it needs to be freed when not required anymore.
|
||||
|
||||
`lv_draw_mask_add` saves only the pointer of the mask so the parameter needs to be valid while in use.
|
||||
|
||||
## Hook drawing
|
||||
Although widgets can be very well customized by styles there might be cases when something really custom is required.
|
||||
To ensure a great level of flexibility LVGL sends a lot events during drawing with parameters that tell what LVGL is about to draw.
|
||||
|
||||
@@ -39,6 +39,8 @@ static void draw_event_cb(lv_event_t * e)
|
||||
lv_draw_rect(&a, dsc->clip_area, &draw_rect_dsc);
|
||||
|
||||
/*Remove the masks*/
|
||||
lv_draw_mask_free_param(&line_mask_param);
|
||||
lv_draw_mask_free_param(&fade_mask_param);
|
||||
lv_draw_mask_remove_id(line_mask_id);
|
||||
lv_draw_mask_remove_id(fade_mask_id);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ static void mask_event_cb(lv_event_t * e)
|
||||
lv_draw_mask_fade_param_t * fade_mask_bottom = lv_draw_mask_remove_id(mask_bottom_id);
|
||||
lv_mem_buf_release(fade_mask_top);
|
||||
lv_mem_buf_release(fade_mask_bottom);
|
||||
lv_draw_mask_free_param(&fade_mask_top);
|
||||
lv_draw_mask_free_param(&fade_mask_bottom);
|
||||
mask_top_id = -1;
|
||||
mask_bottom_id = -1;
|
||||
}
|
||||
|
||||
@@ -95,6 +95,13 @@
|
||||
*LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
|
||||
*Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/
|
||||
#define LV_SHADOW_CACHE_SIZE 0
|
||||
|
||||
/* Set number of maximally cached circle data.
|
||||
* The circumference of 1/4 circle are saved for anti-aliasing
|
||||
* radius * 4 bytes are used per circle (the most often used radiuses are saved)
|
||||
* 0: to disable caching */
|
||||
#define LV_CIRCLE_CACHE_SIZE 4
|
||||
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/*Default image cache size. Image caching keeps the images opened.
|
||||
|
||||
+3
-2
@@ -290,8 +290,9 @@ lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point)
|
||||
/*If the point is on this object check its children too*/
|
||||
if(lv_obj_hit_test(obj, point)) {
|
||||
int32_t i;
|
||||
for(i = lv_obj_get_child_cnt(obj) - 1; i >= 0; i--) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = child_cnt - 1; i >= 0; i--) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
found_p = lv_indev_search_obj(child, point);
|
||||
|
||||
/*If a child was found then break*/
|
||||
|
||||
@@ -421,7 +421,7 @@ static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coo
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||
lv_coord_t x_child = 0;
|
||||
@@ -476,7 +476,7 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||
lv_coord_t y_child = 0;
|
||||
|
||||
+2
-1
@@ -533,6 +533,7 @@ static void lv_obj_draw(lv_event_t * e)
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||
lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8);
|
||||
lv_draw_mask_free_param(param);
|
||||
lv_mem_buf_release(param);
|
||||
}
|
||||
#endif
|
||||
@@ -781,7 +782,7 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_mark_layout_as_dirty(child);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,7 +754,7 @@ void lv_obj_move_children_by(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_dif
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(ignore_floating && lv_obj_has_flag(child, LV_OBJ_FLAG_FLOATING)) continue;
|
||||
child->coords.x1 += x_diff;
|
||||
child->coords.y1 += y_diff;
|
||||
@@ -937,7 +937,7 @@ static void layout_update_core(lv_obj_t * obj)
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
layout_update_core(child);
|
||||
}
|
||||
|
||||
@@ -948,7 +948,7 @@ static void layout_update_core(lv_obj_t * obj)
|
||||
lv_obj_refr_size(obj);
|
||||
lv_obj_refr_pos(obj);
|
||||
|
||||
if(lv_obj_get_child_cnt(obj) > 0) {
|
||||
if(child_cnt > 0) {
|
||||
uint32_t layout_id = lv_obj_get_style_layout(obj, LV_PART_MAIN);
|
||||
if(layout_id > 0 && layout_id <= layout_cnt) {
|
||||
void * user_data = LV_GC_ROOT(_lv_layout_list)[layout_id -1].user_data;
|
||||
|
||||
@@ -139,7 +139,7 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj)
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
child_res = LV_MAX(child_res, child->coords.y2);
|
||||
}
|
||||
@@ -180,8 +180,8 @@ lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj)
|
||||
lv_coord_t x1 = LV_COORD_MAX;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
x1 = LV_MIN(x1, child->coords.x1);
|
||||
|
||||
}
|
||||
@@ -216,7 +216,7 @@ lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj)
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
child_res = LV_MAX(child_res, child->coords.x2);
|
||||
}
|
||||
|
||||
@@ -623,7 +623,7 @@ static void report_style_change_core(void * style, lv_obj_t * obj)
|
||||
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
report_style_change_core(style, lv_obj_get_child(obj, i));
|
||||
report_style_change_core(style, obj->spec_attr->children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,7 +637,7 @@ static void refresh_children_style(lv_obj_t * obj)
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_invalidate(child);
|
||||
lv_event_send(child, LV_EVENT_STYLE_CHANGED, NULL);
|
||||
lv_obj_invalidate(child);
|
||||
|
||||
+7
-3
@@ -236,6 +236,10 @@ void _lv_disp_refr_timer(lv_timer_t * tmr)
|
||||
lv_mem_buf_free_all();
|
||||
_lv_font_clean_up_fmt_txt();
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
_lv_draw_mask_cleanup();
|
||||
#endif
|
||||
|
||||
#if LV_USE_PERF_MONITOR && LV_USE_LABEL
|
||||
static lv_obj_t * perf_label = NULL;
|
||||
if(perf_label == NULL) {
|
||||
@@ -586,7 +590,7 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
found_p = lv_refr_get_top_obj(area_p, child);
|
||||
|
||||
/*If a children is ok then break*/
|
||||
@@ -634,7 +638,7 @@ static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p)
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(par);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(par, i);
|
||||
lv_obj_t * child = par->spec_attr->children[i];
|
||||
if(!go) {
|
||||
if(child == border_p) go = true;
|
||||
} else {
|
||||
@@ -707,7 +711,7 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p)
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_get_coords(child, &child_area);
|
||||
ext_size = _lv_obj_get_ext_draw_size(child);
|
||||
child_area.x1 -= ext_size;
|
||||
|
||||
@@ -159,6 +159,11 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin
|
||||
else {
|
||||
lv_draw_rect(&area_out, clip_area, &cir_dsc);
|
||||
}
|
||||
|
||||
lv_draw_mask_free_param(&mask_angle_param);
|
||||
lv_draw_mask_free_param(&mask_out_param);
|
||||
lv_draw_mask_free_param(&mask_in_param);
|
||||
|
||||
lv_draw_mask_remove_id(mask_angle_id);
|
||||
lv_draw_mask_remove_id(mask_out_id);
|
||||
lv_draw_mask_remove_id(mask_in_id);
|
||||
@@ -180,6 +185,7 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin
|
||||
|
||||
lv_draw_rect(&area_out, &clip_area2, &cir_dsc);
|
||||
lv_draw_mask_remove_id(mask_end_id);
|
||||
lv_draw_mask_free_param(&mask_end_param);
|
||||
}
|
||||
|
||||
get_rounded_area(end_angle, radius, width, &round_area);
|
||||
@@ -193,6 +199,7 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin
|
||||
|
||||
lv_draw_rect(&area_out, &clip_area2, &cir_dsc);
|
||||
lv_draw_mask_remove_id(mask_end_id);
|
||||
lv_draw_mask_free_param(&mask_end_param);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
+62
-86
@@ -73,22 +73,21 @@ static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_co
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_COLOR_SCREEN_TRANSP == 0
|
||||
#define FILL_NORMAL_MASK_PX(color) \
|
||||
if(*mask == LV_OPA_COVER) *disp_buf_first = color; \
|
||||
else *disp_buf_first = lv_color_mix(color, *disp_buf_first, *mask); \
|
||||
mask++; \
|
||||
disp_buf_first++;
|
||||
|
||||
#define FILL_NORMAL_MASK_PX(out_x, color) \
|
||||
if(*mask_tmp_x) { \
|
||||
if(*mask_tmp_x == LV_OPA_COVER) disp_buf_first[out_x] = color; \
|
||||
else disp_buf_first[out_x] = lv_color_mix(color, disp_buf_first[out_x], *mask_tmp_x); \
|
||||
} \
|
||||
mask_tmp_x++;
|
||||
|
||||
#define FILL_NORMAL_MASK_PX_SCR_TRANSP(out_x, color) \
|
||||
if(*mask_tmp_x) { \
|
||||
if(*mask_tmp_x == LV_OPA_COVER) disp_buf_first[out_x] = color; \
|
||||
else if(disp->driver->screen_transp) lv_color_mix_with_alpha(disp_buf_first[out_x], disp_buf_first[out_x].ch.alpha, \
|
||||
color, *mask_tmp_x, &disp_buf_first[out_x], &disp_buf_first[out_x].ch.alpha); \
|
||||
else disp_buf_first[out_x] = lv_color_mix(color, disp_buf_first[out_x], *mask_tmp_x); \
|
||||
} \
|
||||
mask_tmp_x++;
|
||||
#else
|
||||
#define FILL_NORMAL_MASK_PX(color) \
|
||||
if(*mask == LV_OPA_COVER) *disp_buf_first = color; \
|
||||
else if(disp->driver->screen_transp) lv_color_mix_with_alpha(*disp_buf_first, disp_buf_first->ch.alpha, color, *mask, disp_buf_first, &disp_buf_first->ch.alpha); \
|
||||
else *disp_buf_first = lv_color_mix(color, *disp_buf_first, *mask); \
|
||||
mask++; \
|
||||
disp_buf_first++;
|
||||
#endif
|
||||
|
||||
#define MAP_NORMAL_MASK_PX(x) \
|
||||
if(*mask_tmp_x) { \
|
||||
@@ -326,7 +325,6 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
|
||||
if(lv_gpu_nxp_vglite_fill(disp_buf, disp_w, lv_area_get_height(disp_area), draw_area, color, opa) == LV_RES_OK) {
|
||||
return;
|
||||
}
|
||||
/*Fall down to SW render in case of error*/
|
||||
}
|
||||
#elif LV_USE_GPU_STM32_DMA2D
|
||||
if(lv_area_get_size(draw_area) >= 240) {
|
||||
@@ -401,65 +399,55 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
|
||||
|
||||
int32_t x_end4 = draw_area_w - 4;
|
||||
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
uint32_t c32 = color.full + ((uint32_t)color.full << 16);
|
||||
#endif
|
||||
|
||||
/*Only the mask matters*/
|
||||
if(opa > LV_OPA_MAX) {
|
||||
for(y = 0; y < draw_area_h; y++) {
|
||||
const lv_opa_t * mask_tmp_x = mask;
|
||||
#if 0
|
||||
for(x = 0; x < draw_area_w; x++) {
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
|
||||
#else
|
||||
FILL_NORMAL_MASK_PX(x, color)
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
for(x = 0; x < draw_area_w && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) {
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
|
||||
#else
|
||||
FILL_NORMAL_MASK_PX(x, color)
|
||||
#endif
|
||||
for(x = 0; x < draw_area_w && ((lv_uintptr_t)(mask) & 0x3); x++) {
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
}
|
||||
|
||||
uint32_t * mask32 = (uint32_t *)mask_tmp_x;
|
||||
for(; x <= x_end4; x += 4) {
|
||||
if(*mask32) {
|
||||
if((*mask32) == 0xFFFFFFFF) {
|
||||
disp_buf_first[x] = color;
|
||||
disp_buf_first[x + 1] = color;
|
||||
disp_buf_first[x + 2] = color;
|
||||
disp_buf_first[x + 3] = color;
|
||||
uint32_t mask32 = *((uint32_t *)mask);
|
||||
if(mask32 == 0xFFFFFFFF) {
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
if((lv_uintptr_t)disp_buf_first & 0x3) {
|
||||
*(disp_buf_first + 0) = color;
|
||||
uint32_t * d = (uint32_t * )(disp_buf_first + 1);
|
||||
*d = c32;
|
||||
*(disp_buf_first + 3) = color;
|
||||
} else {
|
||||
uint32_t * d = (uint32_t * )disp_buf_first;
|
||||
*d = c32;
|
||||
*(d + 1) = c32;
|
||||
}
|
||||
else {
|
||||
mask_tmp_x = (const lv_opa_t *)mask32;
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
|
||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x + 1, color)
|
||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x + 2, color)
|
||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x + 3, color)
|
||||
#else
|
||||
FILL_NORMAL_MASK_PX(x, color)
|
||||
FILL_NORMAL_MASK_PX(x + 1, color)
|
||||
FILL_NORMAL_MASK_PX(x + 2, color)
|
||||
FILL_NORMAL_MASK_PX(x + 3, color)
|
||||
disp_buf_first[0] = color;
|
||||
disp_buf_first[1] = color;
|
||||
disp_buf_first[2] = color;
|
||||
disp_buf_first[3] = color;
|
||||
#endif
|
||||
}
|
||||
disp_buf_first+= 4;
|
||||
mask += 4;
|
||||
}
|
||||
else if(mask32) {
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
} else {
|
||||
mask += 4;
|
||||
disp_buf_first += 4;
|
||||
}
|
||||
mask32++;
|
||||
}
|
||||
|
||||
mask_tmp_x = (const lv_opa_t *)mask32;
|
||||
for(; x < draw_area_w ; x++) {
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
|
||||
#else
|
||||
FILL_NORMAL_MASK_PX(x, color)
|
||||
#endif
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
}
|
||||
#endif
|
||||
disp_buf_first += disp_w;
|
||||
mask += draw_area_w;
|
||||
disp_buf_first += (disp_w-draw_area_w);
|
||||
}
|
||||
}
|
||||
/*Handle opa and mask values too*/
|
||||
@@ -701,8 +689,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
|
||||
blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t);
|
||||
blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1));
|
||||
blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1));
|
||||
blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1;
|
||||
blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1;
|
||||
blit.src_area.x2 = blit.src_area.x1 + draw_area_w;
|
||||
blit.src_area.y2 = blit.src_area.y1 + draw_area_h;
|
||||
|
||||
blit.dst = disp_buf;
|
||||
blit.dst_width = lv_area_get_width(disp_area);
|
||||
@@ -710,8 +698,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
|
||||
blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t);
|
||||
blit.dst_area.x1 = draw_area->x1;
|
||||
blit.dst_area.y1 = draw_area->y1;
|
||||
blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1;
|
||||
blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1;
|
||||
blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w;
|
||||
blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h;
|
||||
|
||||
blit.opa = opa;
|
||||
|
||||
@@ -751,8 +739,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
|
||||
blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t);
|
||||
blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1));
|
||||
blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1));
|
||||
blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1;
|
||||
blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1;
|
||||
blit.src_area.x2 = blit.src_area.x1 + draw_area_w;
|
||||
blit.src_area.y2 = blit.src_area.y1 + draw_area_h;
|
||||
|
||||
blit.dst = disp_buf;
|
||||
blit.dst_width = lv_area_get_width(disp_area);
|
||||
@@ -760,8 +748,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
|
||||
blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t);
|
||||
blit.dst_area.x1 = draw_area->x1;
|
||||
blit.dst_area.y1 = draw_area->y1;
|
||||
blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1;
|
||||
blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1;
|
||||
blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w;
|
||||
blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h;
|
||||
|
||||
blit.opa = opa;
|
||||
|
||||
@@ -933,13 +921,7 @@ static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
|
||||
for(y = draw_area->y1; y <= draw_area->y2; y++) {
|
||||
for(x = draw_area->x1; x <= draw_area->x2; x++) {
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
if(map_buf_tmp[x].full != 0xff000000) {
|
||||
#else
|
||||
if(map_buf_tmp[x].full != 0) {
|
||||
#endif
|
||||
disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa);
|
||||
}
|
||||
disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa);
|
||||
}
|
||||
disp_buf_tmp += disp_w;
|
||||
map_buf_tmp += map_w;
|
||||
@@ -957,14 +939,7 @@ static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
for(x = draw_area->x1; x <= draw_area->x2; x++) {
|
||||
if(mask_tmp[x] == 0) continue;
|
||||
lv_opa_t opa_tmp = mask_tmp[x] >= LV_OPA_MAX ? opa : ((opa * mask_tmp[x]) >> 8);
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
if(map_buf_tmp[x].full != 0xff000000) {
|
||||
#else
|
||||
if(map_buf_tmp[x].full != 0) {
|
||||
#endif
|
||||
disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa_tmp);
|
||||
}
|
||||
|
||||
disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa_tmp);
|
||||
}
|
||||
disp_buf_tmp += disp_w;
|
||||
mask_tmp += draw_area_w;
|
||||
@@ -975,6 +950,9 @@ static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
|
||||
static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color_t bg, lv_opa_t opa)
|
||||
{
|
||||
|
||||
if(opa <= LV_OPA_MIN) return bg;
|
||||
|
||||
uint32_t tmp;
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
tmp = bg.full + fg.full;
|
||||
@@ -990,7 +968,6 @@ static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
tmp = bg.ch.green + fg.ch.green;
|
||||
fg.ch.green = LV_MIN(tmp, 7);
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
@@ -1004,7 +981,6 @@ static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color
|
||||
#endif
|
||||
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
tmp = bg.ch.green + fg.ch.green;
|
||||
fg.ch.green = LV_MIN(tmp, 255);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -474,6 +474,10 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_skew(const lv_point_t * point1, cons
|
||||
|
||||
lv_mem_buf_release(mask_buf);
|
||||
|
||||
lv_draw_mask_free_param(&mask_left_param);
|
||||
lv_draw_mask_free_param(&mask_right_param);
|
||||
if(mask_top_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_top_param);
|
||||
if(mask_bottom_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_bottom_param);
|
||||
lv_draw_mask_remove_id(mask_left_id);
|
||||
lv_draw_mask_remove_id(mask_right_id);
|
||||
lv_draw_mask_remove_id(mask_top_id);
|
||||
|
||||
+317
-209
File diff suppressed because it is too large
Load Diff
+28
-2
@@ -147,6 +147,18 @@ typedef struct {
|
||||
uint16_t delta_deg;
|
||||
} lv_draw_mask_angle_param_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t * buf;
|
||||
lv_opa_t * cir_opa; /*Opacity of values on the circumference of an 1/4 circle*/
|
||||
uint16_t * x_start_on_y; /*The x coordinate of the circle for each y value*/
|
||||
uint16_t * opa_start_on_y; /*The index of `cir_opa` for each y value*/
|
||||
int32_t life; /*How many times the entry way used*/
|
||||
uint32_t used_cnt; /*Like a semaphore to count the referencing masks*/
|
||||
lv_coord_t radius; /*The radius of the entry*/
|
||||
} _lv_draw_mask_radius_circle_dsc_t;
|
||||
|
||||
typedef _lv_draw_mask_radius_circle_dsc_t _lv_draw_mask_radius_circle_dsc_arr_t[LV_CIRCLE_CACHE_SIZE];
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
@@ -157,9 +169,8 @@ typedef struct {
|
||||
/*Invert the mask. 0: Keep the pixels inside.*/
|
||||
uint8_t outer: 1;
|
||||
} cfg;
|
||||
int32_t y_prev;
|
||||
lv_sqrt_res_t y_prev_x;
|
||||
|
||||
_lv_draw_mask_radius_circle_dsc_t * circle;
|
||||
} lv_draw_mask_radius_param_t;
|
||||
|
||||
|
||||
@@ -235,6 +246,21 @@ void * lv_draw_mask_remove_id(int16_t id);
|
||||
*/
|
||||
void * lv_draw_mask_remove_custom(void * custom_id);
|
||||
|
||||
/**
|
||||
* Free the data from the parameter.
|
||||
* It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom`
|
||||
* Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add`
|
||||
* and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom`
|
||||
* @param p pointer to a mask parameter
|
||||
*/
|
||||
void lv_draw_mask_free_param(void * p);
|
||||
|
||||
/**
|
||||
* Called by LVGL the rendering of a screen is ready to clean up
|
||||
* the temporal (cache) data of the masks
|
||||
*/
|
||||
void _lv_draw_mask_cleanup(void);
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
/**
|
||||
|
||||
+11
-3
@@ -228,7 +228,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_are
|
||||
y < coords_bg.y2 - rout - 1) {
|
||||
mask_res = LV_DRAW_MASK_RES_FULL_COVER;
|
||||
if(simple_mode == false) {
|
||||
lv_memset(mask_buf, opa, draw_area_w);
|
||||
lv_memset(mask_buf, 0xff, draw_area_w);
|
||||
mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h, draw_area_w);
|
||||
}
|
||||
}
|
||||
@@ -240,7 +240,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_are
|
||||
|
||||
/*If mask will taken into account its base opacity was already set by memset above*/
|
||||
if(mask_res == LV_DRAW_MASK_RES_CHANGED) {
|
||||
opa2 = LV_OPA_COVER;
|
||||
// opa2 = LV_OPA_COVER;
|
||||
}
|
||||
|
||||
/*Get the current line color*/
|
||||
@@ -329,6 +329,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_are
|
||||
if(grad_map) lv_mem_buf_release(grad_map);
|
||||
if(mask_buf) lv_mem_buf_release(mask_buf);
|
||||
lv_draw_mask_remove_id(mask_rout_id);
|
||||
if(mask_rout_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_rout_param);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -509,8 +510,10 @@ LV_ATTRIBUTE_FAST_MEM static void draw_border(const lv_area_t * coords, const lv
|
||||
fill_area.y2++;
|
||||
|
||||
}
|
||||
lv_draw_mask_free_param(&mask_rin_param);
|
||||
lv_draw_mask_free_param(&mask_rout_param);
|
||||
lv_draw_mask_remove_id(mask_rin_id);
|
||||
lv_draw_mask_remove_id(mask_rout_id);
|
||||
if(mask_rout_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_rout_id);
|
||||
lv_mem_buf_release(mask_buf);
|
||||
}
|
||||
#else /*LV_DRAW_COMPLEX*/
|
||||
@@ -1007,6 +1010,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_mask_free_param(&mask_rout_param);
|
||||
lv_draw_mask_remove_id(mask_rout_id);
|
||||
lv_mem_buf_release(mask_buf);
|
||||
lv_mem_buf_release(sh_buf);
|
||||
@@ -1064,6 +1068,8 @@ LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coord
|
||||
}
|
||||
lv_mem_buf_release(mask_line);
|
||||
|
||||
lv_draw_mask_free_param(&mask_param);
|
||||
|
||||
if(sw == 1) {
|
||||
int32_t i;
|
||||
lv_opa_t * res_buf = (lv_opa_t *)sh_buf;
|
||||
@@ -1394,6 +1400,8 @@ static void draw_full_border(const lv_area_t * area_inner, const lv_area_t * are
|
||||
|
||||
}
|
||||
}
|
||||
lv_draw_mask_free_param(&mask_rin_param);
|
||||
lv_draw_mask_free_param(&mask_rout_param);
|
||||
lv_draw_mask_remove_id(mask_rin_id);
|
||||
lv_draw_mask_remove_id(mask_rout_id);
|
||||
lv_mem_buf_release(mask_buf);
|
||||
|
||||
@@ -287,6 +287,8 @@ static void draw_disc_grad(lv_event_t * e)
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
lv_draw_mask_free_param(&mask_out_param);
|
||||
lv_draw_mask_free_param(&mask_in_param);
|
||||
lv_draw_mask_remove_id(mask_out_id);
|
||||
lv_draw_mask_remove_id(mask_in_id);
|
||||
#endif
|
||||
|
||||
@@ -414,7 +414,7 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c
|
||||
lv_draw_mask_radius_init(&outer_mask, &area_outer, LV_RADIUS_CIRCLE, false);
|
||||
int16_t outer_mask_id = lv_draw_mask_add(&outer_mask, NULL);
|
||||
|
||||
int16_t inner_act_mask_id = -1; /*Will be added later*/
|
||||
int16_t inner_act_mask_id = LV_MASK_ID_INV; /*Will be added later*/
|
||||
|
||||
uint32_t minor_cnt = scale->tick_major_nth ? scale->tick_major_nth - 1 : 0xFFFF;
|
||||
for(i = 0; i < scale->tick_cnt; i++) {
|
||||
@@ -530,6 +530,9 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c
|
||||
line_dsc.width = line_width_ori;
|
||||
|
||||
}
|
||||
lv_draw_mask_free_param(&inner_minor_mask);
|
||||
lv_draw_mask_free_param(&inner_major_mask);
|
||||
lv_draw_mask_free_param(&outer_mask);
|
||||
lv_draw_mask_remove_id(outer_mask_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,6 +250,19 @@
|
||||
# define LV_SHADOW_CACHE_SIZE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Set number of maximally cached circle data.
|
||||
* The circumference of 1/4 circle are saved for anti-aliasing
|
||||
* radius * 4 bytes are used per circle (the most often used radiuses are saved)
|
||||
* 0: to disable caching */
|
||||
#ifndef LV_CIRCLE_CACHE_SIZE
|
||||
# ifdef CONFIG_LV_CIRCLE_CACHE_SIZE
|
||||
# define LV_CIRCLE_CACHE_SIZE CONFIG_LV_CIRCLE_CACHE_SIZE
|
||||
# else
|
||||
# define LV_CIRCLE_CACHE_SIZE 4
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/*Default image cache size. Image caching keeps the images opened.
|
||||
|
||||
+9
-1
@@ -459,7 +459,15 @@ static inline uint32_t lv_color_to32(lv_color_t color)
|
||||
LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
|
||||
{
|
||||
lv_color_t ret;
|
||||
#if LV_COLOR_DEPTH != 1
|
||||
|
||||
#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 result = ((((fg - bg) * mix) >> 5) + bg) & 0x7E0F81F;
|
||||
ret.full = (uint16_t)((result >> 16) | result);
|
||||
#elif LV_COLOR_DEPTH != 1
|
||||
/*LV_COLOR_DEPTH == 8, 16 or 32*/
|
||||
LV_COLOR_SET_R(ret, LV_UDIV255((uint16_t) LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) *
|
||||
(255 - mix) + LV_COLOR_MIX_ROUND_OFS));
|
||||
|
||||
@@ -53,6 +53,7 @@ extern "C" {
|
||||
LV_DISPATCH_COND(f, _lv_img_cache_entry_t, _lv_img_cache_single, LV_IMG_CACHE_DEF, 0) \
|
||||
LV_DISPATCH(f, lv_timer_t*, _lv_timer_act) \
|
||||
LV_DISPATCH(f, lv_mem_buf_arr_t , lv_mem_buf) \
|
||||
LV_DISPATCH_COND(f, _lv_draw_mask_radius_circle_dsc_arr_t , _lv_circle_cache, LV_DRAW_COMPLEX, 1) \
|
||||
LV_DISPATCH_COND(f, _lv_draw_mask_saved_arr_t , _lv_draw_mask_list, LV_DRAW_COMPLEX, 1) \
|
||||
LV_DISPATCH(f, void * , _lv_theme_default_styles) \
|
||||
LV_DISPATCH_COND(f, uint8_t *, _lv_font_decompr_buf, LV_USE_FONT_COMPRESSED, 1)
|
||||
|
||||
@@ -486,6 +486,8 @@ static void draw_indic(lv_event_t * e)
|
||||
lv_draw_rect(&bar->indic_area, clip_area, &draw_rect_dsc);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
lv_draw_mask_free_param(&mask_indic_param);
|
||||
lv_draw_mask_free_param(&mask_bg_param);
|
||||
lv_draw_mask_remove_id(mask_indic_id);
|
||||
lv_draw_mask_remove_id(mask_bg_id);
|
||||
#endif
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
Reference in New Issue
Block a user