diff options
author | Gabor Kiss-Vamosi <kisvegabor@gmail.com> | 2023-11-18 15:33:58 +0100 |
---|---|---|
committer | Gabor Kiss-Vamosi <kisvegabor@gmail.com> | 2023-11-18 15:35:45 +0100 |
commit | 2f3e8d40667d27bb9bb56778439787426cae3d9f (patch) | |
tree | 1634609361eb686a75432d844b73f6d6b5b2e8c0 | |
parent | cd6b4db6e8239ef2711e8c43a954650dc13a9a20 (diff) | |
download | lvgl-2f3e8d40667d27bb9bb56778439787426cae3d9f.tar.gz lvgl-2f3e8d40667d27bb9bb56778439787426cae3d9f.zip |
feat(draw): add initial SDL renderer
It caches SW rendered bitmaps in textures.
The cache is also updated to support data and source separately.
E.g. source is a path to an image, and if that image changes all
related cache entries needs to found and invalidated.
Limitations of SDL rederer:
- not all draw task types are supported
- image transformation is not supported
- some textures (e.g. button matrix texts) are not detected as cached
- images are not cached
- images are supported only from path
58 files changed, 1050 insertions, 283 deletions
diff --git a/demos/vector_graphic/lv_demo_vector_graphic.c b/demos/vector_graphic/lv_demo_vector_graphic.c index 9aa870185..f5171c408 100644 --- a/demos/vector_graphic/lv_demo_vector_graphic.c +++ b/demos/vector_graphic/lv_demo_vector_graphic.c @@ -225,7 +225,7 @@ static void draw_vector(lv_layer_t * layer) void lv_demo_vector_graphic(void) { - static uint8_t canvas_buf[WIDTH * HEIGHT * 4]; + static uint8_t canvas_buf[LV_CANVAS_BUF_SIZE(WIDTH, HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; lv_obj_t * canvas = lv_canvas_create(lv_scr_act()); lv_canvas_set_buffer(canvas, canvas_buf, WIDTH, HEIGHT, LV_COLOR_FORMAT_ARGB8888); diff --git a/demos/widgets/lv_demo_widgets.c b/demos/widgets/lv_demo_widgets.c index a6806a300..33e11ce93 100644 --- a/demos/widgets/lv_demo_widgets.c +++ b/demos/widgets/lv_demo_widgets.c @@ -249,6 +249,7 @@ static void profile_create(lv_obj_t * parent) LV_IMAGE_DECLARE(img_demo_widgets_avatar); lv_obj_t * avatar = lv_image_create(panel1); lv_image_set_src(avatar, &img_demo_widgets_avatar); + // lv_image_set_src(avatar, "A:lvgl/demos/widgets/assets/avatar.png") lv_obj_t * name = lv_label_create(panel1); lv_label_set_text(name, "Elena Smith"); diff --git a/examples/widgets/canvas/lv_example_canvas_1.c b/examples/widgets/canvas/lv_example_canvas_1.c index 92c820953..ceada1b65 100644 --- a/examples/widgets/canvas/lv_example_canvas_1.c +++ b/examples/widgets/canvas/lv_example_canvas_1.c @@ -26,11 +26,11 @@ void lv_example_canvas_1(void) lv_draw_label_dsc_init(&label_dsc); label_dsc.color = lv_palette_main(LV_PALETTE_ORANGE); label_dsc.text = "Some text on text canvas"; - - static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; + /*Create a buffer for the canvas*/ + static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 16, LV_DRAW_BUF_STRIDE_ALIGN)]; lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); + lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_RGB565); lv_obj_center(canvas); lv_canvas_fill_bg(canvas, lv_palette_lighten(LV_PALETTE_GREY, 3), LV_OPA_COVER); @@ -47,11 +47,18 @@ void lv_example_canvas_1(void) /*Test the rotation. It requires another buffer where the original image is stored. *So copy the current image to buffer and rotate it to the canvas*/ - static uint8_t cbuf_tmp[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; + static uint8_t cbuf_tmp[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; + + /*Create a canvas and initialize its palette*/ + canvas = lv_canvas_create(lv_screen_active()); + lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); + lv_obj_center(canvas); + lv_memcpy(cbuf_tmp, cbuf, sizeof(cbuf_tmp)); lv_image_dsc_t img; img.data = (void *)cbuf_tmp; - img.header.cf = LV_COLOR_FORMAT_NATIVE; + img.header.cf = LV_COLOR_FORMAT_ARGB8888; img.header.w = CANVAS_WIDTH; img.header.h = CANVAS_HEIGHT; diff --git a/examples/widgets/canvas/lv_example_canvas_3.c b/examples/widgets/canvas/lv_example_canvas_3.c index 85049e423..65ff564d6 100644 --- a/examples/widgets/canvas/lv_example_canvas_3.c +++ b/examples/widgets/canvas/lv_example_canvas_3.c @@ -10,11 +10,11 @@ void lv_example_canvas_3(void) { /*Create a buffer for the canvas*/ - static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; + static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); + lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_obj_center(canvas); diff --git a/examples/widgets/canvas/lv_example_canvas_4.c b/examples/widgets/canvas/lv_example_canvas_4.c index a51b45b6a..7b9403ffc 100644 --- a/examples/widgets/canvas/lv_example_canvas_4.c +++ b/examples/widgets/canvas/lv_example_canvas_4.c @@ -10,11 +10,11 @@ void lv_example_canvas_4(void) { /*Create a buffer for the canvas*/ - static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; + static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); + lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_obj_center(canvas); diff --git a/examples/widgets/canvas/lv_example_canvas_5.c b/examples/widgets/canvas/lv_example_canvas_5.c index 5a32d8c02..34a52e0f8 100644 --- a/examples/widgets/canvas/lv_example_canvas_5.c +++ b/examples/widgets/canvas/lv_example_canvas_5.c @@ -10,11 +10,11 @@ void lv_example_canvas_5(void) { /*Create a buffer for the canvas*/ - static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; + static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); + lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_obj_center(canvas); diff --git a/examples/widgets/canvas/lv_example_canvas_6.c b/examples/widgets/canvas/lv_example_canvas_6.c index 34e9ecf48..c3edf7858 100644 --- a/examples/widgets/canvas/lv_example_canvas_6.c +++ b/examples/widgets/canvas/lv_example_canvas_6.c @@ -10,11 +10,11 @@ void lv_example_canvas_6(void) { /*Create a buffer for the canvas*/ - static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; + static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); + lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_obj_center(canvas); diff --git a/examples/widgets/canvas/lv_example_canvas_7.c b/examples/widgets/canvas/lv_example_canvas_7.c index da655b7fc..7bf29c40f 100644 --- a/examples/widgets/canvas/lv_example_canvas_7.c +++ b/examples/widgets/canvas/lv_example_canvas_7.c @@ -10,11 +10,11 @@ void lv_example_canvas_7(void) { /*Create a buffer for the canvas*/ - static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; + static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); + lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_obj_center(canvas); diff --git a/examples/widgets/canvas/lv_example_canvas_8.c b/examples/widgets/canvas/lv_example_canvas_8.c index 1022d4729..3bebdf69d 100644 --- a/examples/widgets/canvas/lv_example_canvas_8.c +++ b/examples/widgets/canvas/lv_example_canvas_8.c @@ -12,11 +12,11 @@ void lv_example_canvas_8(void) { /*Create a buffer for the canvas*/ - static uint8_t cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR(CANVAS_WIDTH, CANVAS_HEIGHT)]; + static uint8_t cbuf[LV_CANVAS_BUF_SIZE(CANVAS_WIDTH, CANVAS_HEIGHT, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_NATIVE); + lv_canvas_set_buffer(canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER); lv_obj_center(canvas); diff --git a/examples/widgets/img/lv_example_img_1.c b/examples/widgets/img/lv_example_img_1.c index e516f4df6..96e8da6fa 100644 --- a/examples/widgets/img/lv_example_img_1.c +++ b/examples/widgets/img/lv_example_img_1.c @@ -5,13 +5,17 @@ void lv_example_image_1(void) { LV_IMAGE_DECLARE(img_cogwheel_argb); lv_obj_t * img1 = lv_image_create(lv_screen_active()); - lv_image_set_src(img1, &img_cogwheel_argb); - lv_obj_align(img1, LV_ALIGN_CENTER, 0, -20); - lv_obj_set_size(img1, 200, 200); + lv_image_set_src(img1, "A:lvgl/demos/widgets/assets/avatar.png"); + lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0); + lv_image_set_scale_x(img1, 512); + lv_image_set_scale_y(img1, 128); + lv_image_set_rotation(img1, 10); lv_obj_t * img2 = lv_image_create(lv_screen_active()); lv_image_set_src(img2, LV_SYMBOL_OK "Accept"); lv_obj_align_to(img2, img1, LV_ALIGN_OUT_BOTTOM_MID, 0, 20); + + lv_obj_set_style_bg_opa(img1, 100, 0); } #endif diff --git a/lv_conf_template.h b/lv_conf_template.h index f488fd12b..c8dd84802 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -127,6 +127,9 @@ /* Use NXP's PXP on iMX RTxxx platforms. */ #define LV_USE_DRAW_PXP 0 +/* Draw using cached SDL textures*/ +#define LV_USE_DRAW_SDL 0 + /*================= * OPERATING SYSTEM *=================*/ diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index 950b2190e..d1bcf5880 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -93,7 +93,7 @@ void lv_refr_now(lv_display_t * disp) void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj) { - lv_area_t clip_area_ori = layer->clip_area; + lv_area_t clip_area_ori = layer->_clip_area; lv_area_t clip_coords_for_obj; /*Truncate the clip area to `obj size + ext size` area*/ @@ -104,7 +104,7 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj) if(!_lv_area_intersect(&clip_coords_for_obj, &clip_area_ori, &obj_coords_ext)) return; /*If the object is visible on the current clip area*/ - layer->clip_area = clip_coords_for_obj; + layer->_clip_area = clip_coords_for_obj; lv_obj_send_event(obj, LV_EVENT_DRAW_MAIN_BEGIN, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_MAIN, layer); @@ -139,14 +139,14 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj) uint32_t child_cnt = lv_obj_get_child_count(obj); if(child_cnt == 0) { /*If the object was visible on the clip area call the post draw events too*/ - layer->clip_area = clip_coords_for_obj; + layer->_clip_area = clip_coords_for_obj; /*If all the children are redrawn make 'post draw' draw*/ lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_POST_END, layer); } else { - layer->clip_area = clip_coords_for_children; + layer->_clip_area = clip_coords_for_children; bool clip_corner = lv_obj_get_style_clip_corner(obj, LV_PART_MAIN); int32_t radius = 0; @@ -162,7 +162,7 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj) } /*If the object was visible on the clip area call the post draw events too*/ - layer->clip_area = clip_coords_for_obj; + layer->_clip_area = clip_coords_for_obj; /*If all the children are redrawn make 'post draw' draw*/ lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer); lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer); @@ -228,7 +228,7 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj) mid.y1 += rout; mid.y2 -= rout; if(_lv_area_intersect(&mid, &mid, &clip_area_ori)) { - layer->clip_area = mid; + layer->_clip_area = mid; for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; refr_obj(layer, child); @@ -245,7 +245,7 @@ void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj) } } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } /** @@ -606,12 +606,12 @@ static void refr_area(const lv_area_t * area_p) if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL) { disp_refr->last_part = 1; - layer->clip_area = disp_area; + layer->_clip_area = disp_area; refr_area_part(layer); } else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) { disp_refr->last_part = disp_refr->last_area; - layer->clip_area = *area_p; + layer->_clip_area = *area_p; refr_area_part(layer); } return; @@ -638,7 +638,7 @@ static void refr_area(const lv_area_t * area_p) layer->buf = disp_refr->buf_act; layer->buf_area = sub_area; layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format); - layer->clip_area = sub_area; + layer->_clip_area = sub_area; if(sub_area.y2 > y2) sub_area.y2 = y2; row_last = sub_area.y2; if(y2 == row_last) disp_refr->last_part = 1; @@ -654,7 +654,7 @@ static void refr_area(const lv_area_t * area_p) sub_area.y2 = y2; layer->buf = disp_refr->buf_act; layer->buf_area = sub_area; - layer->clip_area = sub_area; + layer->_clip_area = sub_area; disp_refr->last_part = 1; refr_area_part(layer); } @@ -662,7 +662,7 @@ static void refr_area(const lv_area_t * area_p) static void refr_area_part(lv_layer_t * layer) { - disp_refr->refreshed_area = layer->clip_area; + disp_refr->refreshed_area = layer->_clip_area; /* In single buffered mode wait here until the buffer is freed. * Else we would draw into the buffer while it's still being transferred to the display*/ @@ -680,9 +680,9 @@ static void refr_area_part(lv_layer_t * layer) lv_obj_t * top_prev_scr = NULL; /*Get the most top object which is not covered by others*/ - top_act_scr = lv_refr_get_top_obj(&layer->clip_area, lv_display_get_screen_active(disp_refr)); + top_act_scr = lv_refr_get_top_obj(&layer->_clip_area, lv_display_get_screen_active(disp_refr)); if(disp_refr->prev_scr) { - top_prev_scr = lv_refr_get_top_obj(&layer->clip_area, disp_refr->prev_scr); + top_prev_scr = lv_refr_get_top_obj(&layer->_clip_area, disp_refr->prev_scr); } /*Draw a bottom layer background if there is no top object*/ @@ -824,7 +824,7 @@ static lv_result_t layer_get_area(lv_layer_t * layer, lv_obj_t * obj, lv_layer_t lv_area_t clip_coords_for_obj; lv_area_t tranf_coords = obj_coords_ext; lv_obj_get_transformed_area(obj, &tranf_coords, false, false); - if(!_lv_area_intersect(&clip_coords_for_obj, &layer->clip_area, &tranf_coords)) { + if(!_lv_area_intersect(&clip_coords_for_obj, &layer->_clip_area, &tranf_coords)) { return LV_RESULT_INVALID; } @@ -842,7 +842,7 @@ static lv_result_t layer_get_area(lv_layer_t * layer, lv_obj_t * obj, lv_layer_t } else if(layer_type == LV_LAYER_TYPE_SIMPLE) { lv_area_t clip_coords_for_obj; - if(!_lv_area_intersect(&clip_coords_for_obj, &layer->clip_area, &obj_coords_ext)) { + if(!_lv_area_intersect(&clip_coords_for_obj, &layer->_clip_area, &obj_coords_ext)) { return LV_RESULT_INVALID; } *layer_area_out = clip_coords_for_obj; diff --git a/src/dev/sdl/lv_sdl_window.c b/src/dev/sdl/lv_sdl_window.c index f9fbd71d9..f0465efec 100644 --- a/src/dev/sdl/lv_sdl_window.c +++ b/src/dev/sdl/lv_sdl_window.c @@ -15,6 +15,8 @@ #define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/ #include LV_SDL_INCLUDE_PATH +#include <SDL2/SDL_image.h> + /********************* * DEFINES *********************/ @@ -74,6 +76,12 @@ lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res) SDL_StartTextInput(); event_handler_timer = lv_timer_create(sdl_event_handler, 5, NULL); lv_tick_set_cb(SDL_GetTicks); + + if(!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) { + fprintf(stderr, "could not initialize sdl2_image: %s\n", IMG_GetError()); + return NULL; + } + inited = true; } @@ -147,6 +155,12 @@ void lv_sdl_window_set_title(lv_display_t * disp, const char * title) SDL_SetWindowTitle(dsc->window, title); } +SDL_Renderer * lv_sdl_window_get_renderer(lv_display_t * disp) +{ + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + return dsc->renderer; +} + void lv_sdl_quit() { if(inited) { @@ -260,6 +274,7 @@ static void window_create(lv_display_t * disp) dsc->renderer = SDL_CreateRenderer(dsc->window, -1, SDL_RENDERER_SOFTWARE); texture_resize(disp); + uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp)); lv_memset(dsc->fb1, 0xff, hor_res * ver_res * px_size); #if LV_SDL_DIRECT_MODE_2_BUF @@ -273,6 +288,7 @@ static void window_create(lv_display_t * disp) static void window_update(lv_display_t * disp) { lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); +#if LV_USE_DRAW_SDL == 0 int32_t hor_res = lv_display_get_horizontal_resolution(disp); uint32_t stride = lv_draw_buf_width_to_stride(hor_res, lv_display_get_color_format(disp)); SDL_UpdateTexture(dsc->texture, NULL, dsc->fb_act, stride); @@ -281,6 +297,7 @@ static void window_update(lv_display_t * disp) /*Update the renderer with the texture containing the rendered image*/ SDL_RenderCopy(dsc->renderer, dsc->texture, NULL, NULL); +#endif SDL_RenderPresent(dsc->renderer); } diff --git a/src/dev/sdl/lv_sdl_window.h b/src/dev/sdl/lv_sdl_window.h index 765685896..7f97ab22e 100644 --- a/src/dev/sdl/lv_sdl_window.h +++ b/src/dev/sdl/lv_sdl_window.h @@ -18,6 +18,7 @@ extern "C" { #include "../../indev/lv_indev.h" #if LV_USE_SDL +#include LV_SDL_INCLUDE_PATH /********************* * DEFINES @@ -41,6 +42,8 @@ lv_display_t * _lv_sdl_get_disp_from_win_id(uint32_t win_id); void lv_sdl_window_set_title(lv_display_t * disp, const char * title); +SDL_Renderer * lv_sdl_window_get_renderer(lv_display_t * disp); + void lv_sdl_quit(); /********************** diff --git a/src/draw/lv_draw.c b/src/draw/lv_draw.c index 63ca87030..dc9b40d2c 100644 --- a/src/draw/lv_draw.c +++ b/src/draw/lv_draw.c @@ -83,7 +83,7 @@ lv_draw_task_t * lv_draw_add_task(lv_layer_t * layer, const lv_area_t * coords) lv_draw_task_t * new_task = lv_malloc_zeroed(sizeof(lv_draw_task_t)); new_task->area = *coords; - new_task->clip_area = layer->clip_area; + new_task->clip_area = layer->_clip_area; new_task->state = LV_DRAW_TASK_STATE_QUEUED; /*Find the tail*/ @@ -110,13 +110,14 @@ void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t) /*Send LV_EVENT_DRAW_TASK_ADDED and dispatch only on the "main" draw_task *and not on the draw tasks added in the event. - *Sending LV_EVENT_DRAW_TASK_ADDED events might cause recursive event sends - *Dispatching might remove the "main" draw task while it's still being used in the event*/ + *Sending LV_EVENT_DRAW_TASK_ADDED events might cause recursive event sends and besides + *dispatching might remove the "main" draw task while it's still being used in the event*/ if(info->task_running == false) { - info->task_running = true; if(base_dsc->obj && lv_obj_has_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS)) { + info->task_running = true; lv_obj_send_event(base_dsc->obj, LV_EVENT_DRAW_TASK_ADDED, t); + info->task_running = false; } /*Let the draw units set their preference score*/ @@ -129,7 +130,6 @@ void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t) } lv_draw_dispatch(); - info->task_running = false; } else { /*Let the draw units set their preference score*/ @@ -292,17 +292,17 @@ lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_tas { LV_PROFILER_BEGIN; /*If the first task is screen sized, there cannot be independent areas*/ - if(layer->draw_task_head) { - int32_t hor_res = lv_display_get_horizontal_resolution(_lv_refr_get_disp_refreshing()); - int32_t ver_res = lv_display_get_vertical_resolution(_lv_refr_get_disp_refreshing()); - lv_draw_task_t * t = layer->draw_task_head; - if(t->state != LV_DRAW_TASK_STATE_QUEUED && - t->area.x1 <= 0 && t->area.x2 >= hor_res - 1 && - t->area.y1 <= 0 && t->area.y2 >= ver_res - 1) { - LV_PROFILER_END; - return NULL; - } - } + // if(layer->draw_task_head) { + // int32_t hor_res = lv_display_get_horizontal_resolution(_lv_refr_get_disp_refreshing()); + // int32_t ver_res = lv_display_get_vertical_resolution(_lv_refr_get_disp_refreshing()); + // lv_draw_task_t * t = layer->draw_task_head; + // if(t->state != LV_DRAW_TASK_STATE_QUEUED && + // t->area.x1 <= 0 && t->area.x2 >= hor_res - 1 && + // t->area.y1 <= 0 && t->area.y2 >= ver_res - 1) { + // LV_PROFILER_END; + // return NULL; + // } + // } lv_draw_task_t * t = t_prev ? t_prev->next : layer->draw_task_head; while(t) { @@ -328,7 +328,7 @@ lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t c if(new_layer == NULL) return NULL; new_layer->parent = parent_layer; - new_layer->clip_area = *area; + new_layer->_clip_area = *area; new_layer->buf_area = *area; new_layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(area), color_format); new_layer->color_format = color_format; diff --git a/src/draw/lv_draw.h b/src/draw/lv_draw.h index 6ee9a36d1..c729f1c2e 100644 --- a/src/draw/lv_draw.h +++ b/src/draw/lv_draw.h @@ -152,21 +152,24 @@ typedef struct _lv_layer_t { void * buf; uint32_t buf_stride; + + /** The absolute coordinates of the buffer */ lv_area_t buf_area; + + /** The color format of the layer. LV_COLOR_FORMAT_... */ lv_color_format_t color_format; /** + * NEVER USE IT DRAW UNITS. USED INTERNALLY DURING DRAW TASK CREATION. * The current clip area with absolute coordinates, always the same or smaller than `buf_area` * Can be set before new draw tasks are added to indicate the clip area of the draw tasks. * Therefore `lv_draw_add_task()` always saves it in the new draw task to know the clip area when the draw task was added. * During drawing the draw units also sees the saved clip_area and should use it during drawing. * During drawing the layer's clip area shouldn't be used as it might be already changed for other draw tasks. */ - lv_area_t clip_area; + lv_area_t _clip_area; - /** - * Linked list of draw tasks - */ + /** Linked list of draw tasks */ lv_draw_task_t * draw_task_head; struct _lv_layer_t * parent; @@ -181,6 +184,8 @@ typedef struct { uint32_t id1; uint32_t id2; lv_layer_t * layer; + size_t dsc_size; + void * user_data; } lv_draw_dsc_base_t; typedef struct { diff --git a/src/draw/lv_draw_image.c b/src/draw/lv_draw_image.c index 9f94a1517..527825c99 100644 --- a/src/draw/lv_draw_image.c +++ b/src/draw/lv_draw_image.c @@ -46,6 +46,7 @@ void lv_draw_image_dsc_init(lv_draw_image_dsc_t * dsc) dsc->scale_x = LV_SCALE_NONE; dsc->scale_y = LV_SCALE_NONE; dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0; + dsc->base.dsc_size = sizeof(lv_draw_image_dsc_t); } void lv_draw_layer(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords) diff --git a/src/draw/lv_draw_label.c b/src/draw/lv_draw_label.c index 7ad6ed65c..cc215ae2a 100644 --- a/src/draw/lv_draw_label.c +++ b/src/draw/lv_draw_label.c @@ -58,6 +58,7 @@ void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc) dsc->sel_color = lv_color_black(); dsc->sel_bg_color = lv_palette_main(LV_PALETTE_BLUE); dsc->bidi_dir = LV_BASE_DIR_LTR; + dsc->base.dsc_size = sizeof(lv_draw_label_dsc_t); } void lv_draw_letter_dsc_init(lv_draw_glyph_dsc_t * dsc) diff --git a/src/draw/lv_draw_rect.c b/src/draw/lv_draw_rect.c index 682f4eca5..f5cafb880 100644 --- a/src/draw/lv_draw_rect.c +++ b/src/draw/lv_draw_rect.c @@ -59,6 +59,7 @@ void lv_draw_fill_dsc_init(lv_draw_fill_dsc_t * dsc) { lv_memzero(dsc, sizeof(*dsc)); dsc->opa = LV_OPA_COVER; + dsc->base.dsc_size = sizeof(lv_draw_fill_dsc_t); } void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc) @@ -66,18 +67,21 @@ void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc) lv_memzero(dsc, sizeof(*dsc)); dsc->opa = LV_OPA_COVER; dsc->side = LV_BORDER_SIDE_FULL; + dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t); } void lv_draw_box_shadow_dsc_init(lv_draw_box_shadow_dsc_t * dsc) { lv_memzero(dsc, sizeof(*dsc)); dsc->opa = LV_OPA_COVER; + dsc->base.dsc_size = sizeof(lv_draw_box_shadow_dsc_t); } void lv_draw_bg_image_dsc_init(lv_draw_bg_image_dsc_t * dsc) { lv_memzero(dsc, sizeof(*dsc)); dsc->opa = LV_OPA_COVER; + dsc->base.dsc_size = sizeof(lv_draw_bg_image_dsc_t); } void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) @@ -133,6 +137,7 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a lv_draw_box_shadow_dsc_t * shadow_dsc = lv_malloc(sizeof(lv_draw_box_shadow_dsc_t)); t->draw_dsc = shadow_dsc; shadow_dsc->base = dsc->base; + shadow_dsc->base.dsc_size = sizeof(lv_draw_box_shadow_dsc_t); shadow_dsc->radius = dsc->radius; shadow_dsc->color = dsc->shadow_color; shadow_dsc->width = dsc->shadow_width; @@ -158,13 +163,16 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a t = lv_draw_add_task(layer, &bg_coords); lv_draw_fill_dsc_t * bg_dsc = lv_malloc(sizeof(lv_draw_fill_dsc_t)); + lv_draw_fill_dsc_init(bg_dsc); t->draw_dsc = bg_dsc; bg_dsc->base = dsc->base; + bg_dsc->base.dsc_size = sizeof(lv_draw_fill_dsc_t); bg_dsc->radius = dsc->radius; bg_dsc->color = dsc->bg_color; bg_dsc->grad = dsc->bg_grad; bg_dsc->opa = dsc->bg_opa; t->type = LV_DRAW_TASK_TYPE_FILL; + lv_draw_finalize_task_creation(layer, t); } @@ -190,6 +198,7 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a lv_draw_bg_image_dsc_t * bg_image_dsc = lv_malloc(sizeof(lv_draw_bg_image_dsc_t)); t->draw_dsc = bg_image_dsc; bg_image_dsc->base = dsc->base; + bg_image_dsc->base.dsc_size = sizeof(lv_draw_bg_image_dsc_t); bg_image_dsc->radius = dsc->radius; bg_image_dsc->src = dsc->bg_image_src; bg_image_dsc->font = dsc->bg_image_symbol_font; @@ -209,6 +218,7 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a lv_draw_border_dsc_t * border_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t)); t->draw_dsc = border_dsc; border_dsc->base = dsc->base; + border_dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t); border_dsc->radius = dsc->radius; border_dsc->color = dsc->border_color; border_dsc->opa = dsc->border_opa; @@ -226,6 +236,7 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a lv_draw_border_dsc_t * outline_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t)); t->draw_dsc = outline_dsc; outline_dsc->base = dsc->base; + outline_dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t); outline_dsc->radius = dsc->radius == LV_RADIUS_CIRCLE ? LV_RADIUS_CIRCLE : dsc->radius + dsc->outline_width + dsc->outline_pad; outline_dsc->color = dsc->outline_color; diff --git a/src/draw/lv_draw_vector.c b/src/draw/lv_draw_vector.c index 34d221eaf..b43a41b1b 100644 --- a/src/draw/lv_draw_vector.c +++ b/src/draw/lv_draw_vector.c @@ -476,7 +476,7 @@ lv_vector_dsc_t * lv_vector_dsc_create(lv_layer_t * layer) lv_matrix_identity(&(stroke_dsc->matrix)); // identity matrix dsc->current_dsc.blend_mode = LV_VECTOR_BLEND_SRC_OVER; - dsc->current_dsc.scissor_area = layer->clip_area; + dsc->current_dsc.scissor_area = layer->_clip_area; lv_matrix_identity(&(dsc->current_dsc.matrix)); // identity matrix dsc->tasks.task_list = NULL; return dsc; @@ -638,7 +638,7 @@ void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, const lv_gr void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path) { lv_area_t rect; - if(!_lv_area_intersect(&rect, &(dsc->layer->clip_area), &(dsc->current_dsc.scissor_area))) { + if(!_lv_area_intersect(&rect, &(dsc->layer->_clip_area), &(dsc->current_dsc.scissor_area))) { return; } @@ -666,7 +666,7 @@ void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path void lv_vector_clear_area(lv_vector_dsc_t * dsc, const lv_area_t * rect) { lv_area_t r; - if(!_lv_area_intersect(&r, &(dsc->layer->clip_area), &(dsc->current_dsc.scissor_area))) { + if(!_lv_area_intersect(&r, &(dsc->layer->_clip_area), &(dsc->current_dsc.scissor_area))) { return; } @@ -691,7 +691,7 @@ void lv_draw_vector(lv_vector_dsc_t * dsc) lv_layer_t * layer = dsc->layer; - lv_draw_task_t * t = lv_draw_add_task(layer, &(layer->clip_area)); + lv_draw_task_t * t = lv_draw_add_task(layer, &(layer->_clip_area)); t->type = LV_DRAW_TASK_TYPE_VECTOR; t->draw_dsc = lv_malloc(sizeof(lv_draw_vector_task_dsc_t)); lv_memcpy(t->draw_dsc, &(dsc->tasks), sizeof(lv_draw_vector_task_dsc_t)); diff --git a/src/draw/lv_image_decoder.h b/src/draw/lv_image_decoder.h index 4d966099c..1a5bb40b1 100644 --- a/src/draw/lv_image_decoder.h +++ b/src/draw/lv_image_decoder.h @@ -94,6 +94,7 @@ typedef struct _lv_image_decoder_t { lv_image_decoder_open_f_t open_cb; lv_image_decoder_get_area_cb_t get_area_cb; lv_image_decoder_close_f_t close_cb; + uint32_t cache_data_type; void * user_data; } lv_image_decoder_t; diff --git a/src/draw/sdl/lv_draw_sdl.c b/src/draw/sdl/lv_draw_sdl.c new file mode 100644 index 000000000..f39248694 --- /dev/null +++ b/src/draw/sdl/lv_draw_sdl.c @@ -0,0 +1,400 @@ +/** + * @file lv_draw_sdl.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../lv_draw.h" +#if LV_USE_DRAW_SDL +#include LV_SDL_INCLUDE_PATH +#include <SDL2/SDL_image.h> + +#include "lv_draw_sdl.h" +#include "../../core/lv_refr.h" +#include "../../display/lv_display_private.h" +#include "../../stdlib/lv_string.h" +#include "../../dev/sdl/lv_sdl_window.h" + +/********************* + * DEFINES + *********************/ +#define DRAW_UNIT_ID_SDL 100 + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_draw_dsc_base_t * draw_dsc; + int32_t w; + int32_t h; + SDL_Texture * texture; +} cache_data_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void execute_drawing(lv_draw_sdl_unit_t * u); + +static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); + +static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); + +/********************** + * GLOBAL PROTOTYPES + **********************/ +static uint8_t sdl_render_buf[2048 * 1024 * 4]; + +/********************** + * STATIC VARIABLES + **********************/ +static SDL_Texture * layer_get_texture(lv_layer_t * layer); + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_sdl_init(void) +{ + lv_draw_sdl_unit_t * draw_sdl_unit = lv_draw_create_unit(sizeof(lv_draw_sdl_unit_t)); + draw_sdl_unit->base_unit.dispatch_cb = dispatch; + draw_sdl_unit->base_unit.evaluate_cb = evaluate; + draw_sdl_unit->texture_cache_data_type = lv_cache_register_data_type(); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +{ + lv_draw_sdl_unit_t * draw_sdl_unit = (lv_draw_sdl_unit_t *) draw_unit; + + /*Return immediately if it's busy with a draw task*/ + if(draw_sdl_unit->task_act) return 0; + + lv_draw_task_t * t = NULL; + t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_SDL); + if(t == NULL) return -1; + + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Texture * texture = layer_get_texture(layer); + if(layer != disp->layer_head && texture == NULL) { + void * buf = lv_draw_layer_alloc_buf(layer); + if(buf == NULL) return -1; + + SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp); + int32_t w = lv_area_get_width(&layer->buf_area); + int32_t h = lv_area_get_height(&layer->buf_area); + layer->user_data = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_TARGET, w, h); + } + + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; + draw_sdl_unit->base_unit.target_layer = layer; + draw_sdl_unit->base_unit.clip_area = &t->clip_area; + draw_sdl_unit->task_act = t; + + execute_drawing(draw_sdl_unit); + + draw_sdl_unit->task_act->state = LV_DRAW_TASK_STATE_READY; + draw_sdl_unit->task_act = NULL; + + /*The draw unit is free now. Request a new dispatching as it can get a new task*/ + lv_draw_dispatch_request(); + return 1; +} + +static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task) +{ + LV_UNUSED(draw_unit); + + if(((lv_draw_dsc_base_t *)task->draw_dsc)->user_data == NULL) { + task->preference_score = 0; + task->preferred_draw_unit_id = DRAW_UNIT_ID_SDL; + } + return 0; +} + +bool compare_cb(const void * data1, const void * data2, size_t data_size) +{ + LV_UNUSED(data_size); + const cache_data_t * d1 = data1; + const cache_data_t * d2 = data2; + + if(d1->w != d2->w) return false; + if(d1->h != d2->h) return false; + + if(d1->draw_dsc->dsc_size != d2->draw_dsc->dsc_size) return false; + + if(memcmp(d1->draw_dsc, d2->draw_dsc, d1->draw_dsc->dsc_size)) return false; + + return true; + +} + +void invalidate_cb(lv_cache_entry_t * e) +{ + const cache_data_t * d = e->data; + lv_free((void *)d->draw_dsc); + SDL_DestroyTexture(d->texture); + lv_free((void *)d); + e->data = NULL; + e->data_size = 0; +} + +static lv_cache_entry_t * draw_to_texture(lv_draw_sdl_unit_t * u) +{ + lv_draw_task_t * task = u->task_act; + + lv_layer_t dest_layer; + lv_memzero(&dest_layer, sizeof(dest_layer)); + dest_layer.buf = lv_draw_buf_align(sdl_render_buf, LV_COLOR_FORMAT_ARGB8888); + dest_layer.color_format = LV_COLOR_FORMAT_ARGB8888; + + lv_area_t a; + _lv_area_intersect(&a, u->base_unit.clip_area, &task->area); + dest_layer.buf_area = task->area; + dest_layer._clip_area = task->area; + lv_memzero(sdl_render_buf, lv_area_get_size(&dest_layer.buf_area) * 4 + 100); + + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + + uint32_t tick = lv_tick_get(); + SDL_Texture * texture = NULL; + switch(task->type) { + case LV_DRAW_TASK_TYPE_FILL: { + lv_draw_fill_dsc_t * fill_dsc = task->draw_dsc; + lv_draw_rect_dsc_t rect_dsc; + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.base.user_data = lv_sdl_window_get_renderer(disp); + rect_dsc.bg_color = fill_dsc->color; + rect_dsc.bg_grad = fill_dsc->grad; + rect_dsc.radius = fill_dsc->radius; + rect_dsc.bg_opa = fill_dsc->opa; + + lv_draw_rect(&dest_layer, &rect_dsc, &task->area); + } + break; + case LV_DRAW_TASK_TYPE_BORDER: { + lv_draw_border_dsc_t * border_dsc = task->draw_dsc;; + lv_draw_rect_dsc_t rect_dsc; + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.base.user_data = lv_sdl_window_get_renderer(disp); + rect_dsc.bg_opa = LV_OPA_TRANSP; + rect_dsc.radius = border_dsc->radius; + rect_dsc.border_color = border_dsc->color; + rect_dsc.border_opa = border_dsc->opa; + rect_dsc.border_side = border_dsc->side; + rect_dsc.border_width = border_dsc->width; + lv_draw_rect(&dest_layer, &rect_dsc, &task->area); + break; + } + case LV_DRAW_TASK_TYPE_LABEL: { + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + lv_memcpy(&label_dsc, task->draw_dsc, sizeof(label_dsc)); + label_dsc.base.user_data = lv_sdl_window_get_renderer(disp); + lv_draw_label(&dest_layer, &label_dsc, &task->area); + } + break; + case LV_DRAW_TASK_TYPE_IMAGE: { + lv_draw_image_dsc_t * image_dsc = task->draw_dsc; + // SDL_Surface* loadImage(std::string path) { + const char * path = image_dsc->src; + SDL_Surface * surface = IMG_Load(&path[2]); + if(surface == NULL) { + fprintf(stderr, "could not load image: %s\n", IMG_GetError()); + return NULL; + } + + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp); + texture = SDL_CreateTextureFromSurface(renderer, surface); + break; + } + default: + return NULL; + break; + } + + while(dest_layer.draw_task_head) { + lv_draw_dispatch_layer(disp, &dest_layer); + if(dest_layer.draw_task_head) { + lv_draw_dispatch_wait_for_request(); + } + } + + SDL_Rect rect; + rect.x = dest_layer.buf_area.x1; + rect.y = dest_layer.buf_area.y1; + rect.w = lv_area_get_width(&dest_layer.buf_area); + rect.h = lv_area_get_height(&dest_layer.buf_area); + + if(texture == NULL) { + texture = SDL_CreateTexture(lv_sdl_window_get_renderer(disp), SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STATIC, rect.w, rect.h); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_UpdateTexture(texture, NULL, sdl_render_buf, rect.w * 4); + } + else { + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + } + + cache_data_t * data = lv_malloc(sizeof(cache_data_t)); + lv_draw_dsc_base_t * base_dsc = task->draw_dsc; + + data->draw_dsc = lv_malloc(base_dsc->dsc_size); + lv_memcpy((void *)data->draw_dsc, base_dsc, base_dsc->dsc_size); + data->w = lv_area_get_width(&task->area); + data->h = lv_area_get_height(&task->area); + data->texture = texture; + + lv_cache_entry_t * e = lv_cache_add(data, sizeof(cache_data_t), u->texture_cache_data_type, + lv_area_get_size(&task->area) * 4); + e->compare_cb = compare_cb; + e->invalidate_cb = invalidate_cb; + e->weight = lv_tick_elaps(tick); + e->weight += lv_area_get_size(&task->area) / 10000; + if(e->weight == 0) e->weight++; + return e; +} + +static void blend_texture_layer(lv_draw_sdl_unit_t * u) +{ + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp); + + SDL_Rect clip_rect; + clip_rect.x = u->base_unit.clip_area->x1; + clip_rect.y = u->base_unit.clip_area->y1; + clip_rect.w = lv_area_get_width(u->base_unit.clip_area); + clip_rect.h = lv_area_get_height(u->base_unit.clip_area); + + lv_draw_task_t * t = u->task_act; + SDL_Rect rect; + rect.x = t->area.x1; + rect.y = t->area.y1; + rect.w = lv_area_get_width(&t->area); + rect.h = lv_area_get_height(&t->area); + + lv_draw_image_dsc_t * draw_dsc = t->draw_dsc; + lv_layer_t * src_layer = (lv_layer_t *)draw_dsc->src; + SDL_Texture * src_texture = layer_get_texture(src_layer); + + SDL_SetTextureAlphaMod(src_texture, draw_dsc->opa); + SDL_SetTextureBlendMode(src_texture, SDL_BLENDMODE_BLEND); + SDL_SetRenderTarget(renderer, layer_get_texture(u->base_unit.target_layer)); + SDL_RenderSetClipRect(renderer, &clip_rect); + SDL_RenderCopy(renderer, src_texture, NULL, &rect); + SDL_DestroyTexture(src_texture); + SDL_RenderSetClipRect(renderer, NULL); +} + +static void draw_from_cached_texture(lv_draw_sdl_unit_t * u) +{ + lv_draw_task_t * t = u->task_act; + + cache_data_t data_to_find; + data_to_find.draw_dsc = (lv_draw_dsc_base_t *)t->draw_dsc; + lv_draw_dsc_base_t * base_dsc = t->draw_dsc; + + data_to_find.w = lv_area_get_width(&t->area); + data_to_find.h = lv_area_get_height(&t->area); + data_to_find.texture = NULL; + + /*user_data stores the renderer to differentiate it from SW rendered tasks. + *However the cached texture is independent from the renderer so use NULL user_data*/ + void * user_data_saved = data_to_find.draw_dsc->user_data; + data_to_find.draw_dsc->user_data = NULL; + + lv_cache_lock(); + lv_cache_entry_t * e = lv_cache_find_by_data(&data_to_find, sizeof(data_to_find), u->texture_cache_data_type); + data_to_find.draw_dsc->user_data = user_data_saved; + if(e == NULL) { + printf("cache_miss %d\n", t->type); + e = draw_to_texture(u); + } + + if(e == NULL) { + lv_cache_unlock(); + return; + } + + const cache_data_t * data_cached = lv_cache_get_data(e); + SDL_Texture * texture = data_cached->texture; + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp); + + lv_layer_t * dest_layer = u->base_unit.target_layer; + SDL_Rect clip_rect; + clip_rect.x = u->base_unit.clip_area->x1 - dest_layer->buf_area.x1; + clip_rect.y = u->base_unit.clip_area->y1 - dest_layer->buf_area.y1; + clip_rect.w = lv_area_get_width(u->base_unit.clip_area); + clip_rect.h = lv_area_get_height(u->base_unit.clip_area); + + SDL_Rect rect; + + SDL_SetRenderTarget(renderer, layer_get_texture(dest_layer)); + + if(t->type == LV_DRAW_TASK_TYPE_IMAGE) { + lv_draw_image_dsc_t * draw_dsc = t->draw_dsc; + lv_area_t image_area; + image_area.x1 = 0; + image_area.y1 = 0; + image_area.x2 = draw_dsc->header.w - 1; + image_area.y2 = draw_dsc->header.h - 1; + + lv_area_move(&image_area, t->area.x1 - dest_layer->buf_area.x1, t->area.y1 - dest_layer->buf_area.y1); + rect.x = image_area.x1; + rect.y = image_area.y1; + rect.w = lv_area_get_width(&image_area); + rect.h = lv_area_get_height(&image_area); + + SDL_RenderSetClipRect(renderer, &clip_rect); + SDL_RenderCopy(renderer, texture, NULL, &rect); + } + else { + rect.x = t->area.x1 - dest_layer->buf_area.x1; + rect.y = t->area.y1 - dest_layer->buf_area.y1; + rect.w = lv_area_get_width(&t->area); + rect.h = lv_area_get_height(&t->area); + + SDL_RenderSetClipRect(renderer, &clip_rect); + SDL_RenderCopy(renderer, texture, NULL, &rect); + } + + SDL_RenderSetClipRect(renderer, NULL); + + lv_cache_release(e); + lv_cache_unlock(); +} + +static void execute_drawing(lv_draw_sdl_unit_t * u) +{ + lv_draw_task_t * t = u->task_act; + + if(t->type == LV_DRAW_TASK_TYPE_BOX_SHADOW) return; + if(t->type == LV_DRAW_TASK_TYPE_LINE) return; + if(t->type == LV_DRAW_TASK_TYPE_TRIANGLE) return; + if(t->type == LV_DRAW_TASK_TYPE_BG_IMG) return; + + if(t->type == LV_DRAW_TASK_TYPE_LAYER) { + blend_texture_layer(u); + } + else { + draw_from_cached_texture(u); + } +} + +static SDL_Texture * layer_get_texture(lv_layer_t * layer) +{ + return layer->user_data; +} + +#endif /*LV_USE_DRAW_SDL*/ diff --git a/src/draw/sdl/lv_draw_sdl.h b/src/draw/sdl/lv_draw_sdl.h new file mode 100644 index 000000000..b834e5d9c --- /dev/null +++ b/src/draw/sdl/lv_draw_sdl.h @@ -0,0 +1,89 @@ +/** + * @file lv_draw_sw.h + * + */ + +#ifndef LV_DRAW_SW_H +#define LV_DRAW_SW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_draw.h" +#if LV_USE_DRAW_SDL + +#include "../../misc/lv_area.h" +#include "../../misc/lv_color.h" +#include "../../display/lv_display.h" +#include "../../osal/lv_os.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_draw_unit_t base_unit; + struct _lv_draw_task_t * task_act; + uint32_t texture_cache_data_type; +} lv_draw_sdl_unit_t; + +#if LV_DRAW_SW_SHADOW_CACHE_SIZE +typedef struct { + uint8_t cache[LV_DRAW_SW_SHADOW_CACHE_SIZE * LV_DRAW_SW_SHADOW_CACHE_SIZE]; + int32_t cache_size; + int32_t cache_r; +} lv_draw_sw_shadow_cache_t; +#endif + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_sdl_init(void); + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sdl_image(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +void lv_draw_sdl_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_sdl_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_sdl_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_sdl_bg_image(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_sdl_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_sdl_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords); + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sdl_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); + +void lv_draw_sdl_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * coords); + +void lv_draw_sdl_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc); + +void lv_draw_sdl_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc, const lv_area_t * coords); + +/*********************** + * GLOBAL VARIABLES + ***********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_SDL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_H*/ diff --git a/src/draw/sw/lv_draw_sw.c b/src/draw/sw/lv_draw_sw.c index dbbf8111d..8381fe340 100644 --- a/src/draw/sw/lv_draw_sw.c +++ b/src/draw/sw/lv_draw_sw.c @@ -40,7 +40,9 @@ static void execute_drawing(lv_draw_sw_unit_t * u); -static int32_t lv_draw_sw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); +static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); +static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); +static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit); /********************** @@ -66,7 +68,8 @@ void lv_draw_sw_init(void) uint32_t i; for(i = 0; i < LV_DRAW_SW_DRAW_UNIT_CNT; i++) { lv_draw_sw_unit_t * draw_sw_unit = lv_draw_create_unit(sizeof(lv_draw_sw_unit_t)); - draw_sw_unit->base_unit.dispatch_cb = lv_draw_sw_dispatch; + draw_sw_unit->base_unit.dispatch_cb = dispatch; + draw_sw_unit->base_unit.evaluate_cb = evaluate; draw_sw_unit->idx = i; draw_sw_unit->base_unit.delete_cb = LV_USE_OS ? lv_draw_sw_delete : NULL; @@ -114,7 +117,18 @@ static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit) * STATIC FUNCTIONS **********************/ -static int32_t lv_draw_sw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task) +{ + LV_UNUSED(draw_unit); + + if(task->preference_score >= 100) { + task->preference_score = 100; + task->preferred_draw_unit_id = DRAW_UNIT_ID_SW; + } + return 0; +} + +static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) { lv_draw_sw_unit_t * draw_sw_unit = (lv_draw_sw_unit_t *) draw_unit; diff --git a/src/libs/barcode/lv_barcode.c b/src/libs/barcode/lv_barcode.c index e3f3d11c7..4f04afbe4 100644 --- a/src/libs/barcode/lv_barcode.c +++ b/src/libs/barcode/lv_barcode.c @@ -197,7 +197,7 @@ static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj lv_image_dsc_t * img = lv_canvas_get_image(obj); lv_cache_lock(); - lv_cache_invalidate(lv_cache_find(img, LV_CACHE_SRC_TYPE_PTR, 0, 0)); + lv_cache_invalidate_by_src(img, LV_CACHE_SRC_TYPE_POINTER); lv_cache_unlock(); if(!img->data) { @@ -205,9 +205,9 @@ static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj return; } - LV_LOG_INFO("free canvas buffer: %p", img->data); + LV_LOG_INFO("free canvas buffer: %p", lv_canvas_get_buf(obj)); - lv_draw_buf_free((void *)img->data); + lv_draw_buf_free((void *)lv_canvas_get_buf(obj)); img->data = NULL; } @@ -216,12 +216,13 @@ static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h) LV_ASSERT_NULL(obj); LV_ASSERT(w > 0); - lv_image_dsc_t * img = lv_canvas_get_image(obj); - void * buf = (void *)img->data; + void * buf = (void *)lv_canvas_get_buf(obj); + lv_draw_buf_free((void *)buf); uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_I1); uint32_t buf_size = stride * h; - buf = lv_draw_buf_malloc(buf_size, LV_COLOR_FORMAT_I1); + /*+8 for the 2x4 byte pallette*/ + buf = lv_draw_buf_malloc(buf_size + 8, LV_COLOR_FORMAT_I1); LV_ASSERT_MALLOC(buf); if(!buf) { @@ -229,7 +230,6 @@ static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h) return false; } - lv_draw_buf_free((void *)img->data); lv_canvas_set_buffer(obj, buf, w, h, LV_COLOR_FORMAT_I1); LV_LOG_INFO("set canvas buffer: %p, width = %d", buf, (int)w); return true; diff --git a/src/libs/gif/lv_gif.c b/src/libs/gif/lv_gif.c index 5d2b32973..b21b5909b 100644 --- a/src/libs/gif/lv_gif.c +++ b/src/libs/gif/lv_gif.c @@ -63,7 +63,7 @@ void lv_gif_set_src(lv_obj_t * obj, const void * src) /*Close previous gif if any*/ if(gifobj->gif) { lv_cache_lock(); - lv_cache_invalidate(lv_cache_find(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_PTR, 0, 0)); + lv_cache_invalidate_by_src(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_POINTER); lv_cache_unlock(); gd_close_gif(gifobj->gif); @@ -127,7 +127,7 @@ static void lv_gif_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_gif_t * gifobj = (lv_gif_t *) obj; lv_cache_lock(); - lv_cache_invalidate(lv_cache_find(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_PTR, 0, 0)); + lv_cache_invalidate_by_src(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_POINTER); lv_cache_unlock(); if(gifobj->gif) @@ -155,7 +155,7 @@ static void next_frame_task_cb(lv_timer_t * t) gd_render_frame(gifobj->gif, (uint8_t *)gifobj->imgdsc.data); lv_cache_lock(); - lv_cache_invalidate(lv_cache_find(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_PTR, 0, 0)); + lv_cache_invalidate_by_src(lv_image_get_src(obj), LV_CACHE_SRC_TYPE_POINTER); lv_cache_unlock(); lv_obj_invalidate(obj); } diff --git a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c index df5d2ba24..0d2b0fe2d 100644 --- a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c +++ b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c @@ -39,6 +39,7 @@ static const void * decode_jpeg_file(const char * filename); static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height); static void error_exit(j_common_ptr cinfo); static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc); +static void cache_invalidate_cb(lv_cache_entry_t * entry); /********************** * STATIC VARIABLES @@ -61,6 +62,7 @@ void lv_libjpeg_turbo_init(void) lv_image_decoder_set_info_cb(dec, decoder_info); lv_image_decoder_set_open_cb(dec, decoder_open); lv_image_decoder_set_close_cb(dec, decoder_close); + dec->cache_data_type = lv_cache_register_data_type(); } void lv_libjpeg_turbo_deinit(void) @@ -155,26 +157,26 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d if(dsc->src_type == LV_IMAGE_SRC_FILE) { const char * fn = dsc->src; + uint32_t t = lv_tick_get(); + const void * decoded_img = decode_jpeg_file(fn); + t = lv_tick_elaps(t); + lv_cache_lock(); - lv_cache_entry_t * cache = lv_cache_add(dsc->header.w * dsc->header.h * JPEG_PIXEL_SIZE); + lv_cache_entry_t * cache = lv_cache_add(decoded_img, 0, dsc->header.w * dsc->header.h * JPEG_PIXEL_SIZE, + decoder->cache_data_type); if(cache == NULL) { lv_cache_unlock(); return LV_RESULT_INVALID; } - uint32_t t = lv_tick_get(); - const void * decoded_img = decode_jpeg_file(fn); - t = lv_tick_elaps(t); cache->weight = t; - cache->data = decoded_img; - cache->free_data = 1; + cache->invalidate_cb = cache_invalidate_cb; if(dsc->src_type == LV_IMAGE_SRC_FILE) { cache->src = lv_strdup(dsc->src); - cache->src_type = LV_CACHE_SRC_TYPE_STR; - cache->free_src = 1; + cache->src_type = LV_CACHE_SRC_TYPE_PATH; } else { - cache->src_type = LV_CACHE_SRC_TYPE_PTR; + cache->src_type = LV_CACHE_SRC_TYPE_POINTER; cache->src = dsc->src; } @@ -205,7 +207,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc) if(dsc->src_type == LV_IMAGE_SRC_FILE) { const char * fn = dsc->src; - lv_cache_entry_t * cache = lv_cache_find(fn, LV_CACHE_SRC_TYPE_STR, 0, 0); + lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH); if(cache) { dsc->img_data = lv_cache_get_data(cache); dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/ @@ -473,4 +475,12 @@ static void error_exit(j_common_ptr cinfo) longjmp(myerr->jb, 1); } + +static void cache_invalidate_cb(lv_cache_entry_t * entry) +{ + if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src); + lv_free((void *)entry->data); +} + + #endif /*LV_USE_LIBJPEG_TURBO*/ diff --git a/src/libs/libpng/lv_libpng.c b/src/libs/libpng/lv_libpng.c index ca0ab2927..59be1f007 100644 --- a/src/libs/libpng/lv_libpng.c +++ b/src/libs/libpng/lv_libpng.c @@ -28,6 +28,7 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static const void * decode_png_file(const char * filename); static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc); +static void cache_invalidate_cb(lv_cache_entry_t * entry); /********************** * STATIC VARIABLES @@ -50,6 +51,7 @@ void lv_libpng_init(void) lv_image_decoder_set_info_cb(dec, decoder_info); lv_image_decoder_set_open_cb(dec, decoder_open); lv_image_decoder_set_close_cb(dec, decoder_close); + dec->cache_data_type = lv_cache_register_data_type(); } void lv_libpng_deinit(void) @@ -129,26 +131,26 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d /*If it's a PNG file...*/ if(dsc->src_type == LV_IMAGE_SRC_FILE) { const char * fn = dsc->src; + uint32_t t = lv_tick_get(); + const void * decoded_img = decode_png_file(fn); + t = lv_tick_elaps(t); + lv_cache_lock(); - lv_cache_entry_t * cache = lv_cache_add(dsc->header.w * dsc->header.h * sizeof(uint32_t)); + lv_cache_entry_t * cache = lv_cache_add(decoded_img, 0, decoder->cache_data_type, + dsc->header.w * dsc->header.h * sizeof(uint32_t)); if(cache == NULL) { lv_cache_unlock(); return LV_RESULT_INVALID; } - uint32_t t = lv_tick_get(); - const void * decoded_img = decode_png_file(fn); - t = lv_tick_elaps(t); cache->weight = t; - cache->data = decoded_img; - cache->free_data = 1; + cache->invalidate_cb = cache_invalidate_cb; if(dsc->src_type == LV_IMAGE_SRC_FILE) { cache->src = lv_strdup(dsc->src); - cache->src_type = LV_CACHE_SRC_TYPE_STR; - cache->free_src = 1; + cache->src_type = LV_CACHE_SRC_TYPE_PATH; } else { - cache->src_type = LV_CACHE_SRC_TYPE_PTR; + cache->src_type = LV_CACHE_SRC_TYPE_POINTER; cache->src = dsc->src; } @@ -180,7 +182,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc) if(dsc->src_type == LV_IMAGE_SRC_FILE) { const char * fn = dsc->src; - lv_cache_entry_t * cache = lv_cache_find(fn, LV_CACHE_SRC_TYPE_STR, 0, 0); + lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH); if(cache) { dsc->img_data = lv_cache_get_data(cache); dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/ @@ -299,4 +301,11 @@ static const void * decode_png_file(const char * filename) return image_data; } + +static void cache_invalidate_cb(lv_cache_entry_t * entry) +{ + lv_free((void *)entry->src); + lv_free((void *)entry->data); +} + #endif /*LV_USE_LIBPNG*/ diff --git a/src/libs/lodepng/lv_lodepng.c b/src/libs/lodepng/lv_lodepng.c index 9400b177f..db753ba06 100644 --- a/src/libs/lodepng/lv_lodepng.c +++ b/src/libs/lodepng/lv_lodepng.c @@ -20,6 +20,9 @@ /********************** * TYPEDEFS **********************/ +typedef struct { + +} cache_data_t; /********************** * STATIC PROTOTYPES @@ -30,6 +33,7 @@ static void decoder_close(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt); static const void * decode_png_data(const void * png_data, size_t png_data_size); static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc); +static void cache_invalidate_cb(lv_cache_entry_t * entry); /********************** * STATIC VARIABLES @@ -52,6 +56,7 @@ void lv_lodepng_init(void) lv_image_decoder_set_info_cb(dec, decoder_info); lv_image_decoder_set_open_cb(dec, decoder_open); lv_image_decoder_set_close_cb(dec, decoder_close); + dec->cache_data_type = lv_cache_register_data_type(); } void lv_lodepng_deinit(void) @@ -182,7 +187,7 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d } lv_cache_lock(); - lv_cache_entry_t * cache = lv_cache_add(dsc->header.w * dsc->header.h * 4); + lv_cache_entry_t * cache = lv_cache_add(NULL, 0, decoder->cache_data_type, dsc->header.w * dsc->header.h * 4); if(cache == NULL) { lv_cache_unlock(); return LV_RESULT_INVALID; @@ -193,15 +198,14 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d t = lv_tick_elaps(t); cache->weight = t; cache->data = decoded_img; - cache->free_data = 1; + cache->invalidate_cb = cache_invalidate_cb; if(dsc->src_type == LV_IMAGE_SRC_FILE) { cache->src = lv_strdup(dsc->src); - cache->src_type = LV_CACHE_SRC_TYPE_STR; - cache->free_src = 1; + cache->src_type = LV_CACHE_SRC_TYPE_PATH; lv_free((void *)png_data); } else { - cache->src_type = LV_CACHE_SRC_TYPE_PTR; + cache->src_type = LV_CACHE_SRC_TYPE_POINTER; cache->src = dsc->src; } @@ -233,7 +237,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc) if(dsc->src_type == LV_IMAGE_SRC_FILE) { const char * fn = dsc->src; - lv_cache_entry_t * cache = lv_cache_find(fn, LV_CACHE_SRC_TYPE_STR, 0, 0); + lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH); if(cache) { dsc->img_data = lv_cache_get_data(cache); dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/ @@ -245,7 +249,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc) else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { const lv_image_dsc_t * img_dsc = dsc->src; - lv_cache_entry_t * cache = lv_cache_find(img_dsc, LV_CACHE_SRC_TYPE_PTR, 0, 0); + lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, img_dsc, LV_CACHE_SRC_TYPE_POINTER); if(cache) { dsc->img_data = lv_cache_get_data(cache); dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/ @@ -294,4 +298,10 @@ static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt) } } +static void cache_invalidate_cb(lv_cache_entry_t * entry) +{ + if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src); + lv_free((void *)entry->data); +} + #endif /*LV_USE_LODEPNG*/ diff --git a/src/libs/qrcode/lv_qrcode.c b/src/libs/qrcode/lv_qrcode.c index ebea012ba..6db4c9df2 100644 --- a/src/libs/qrcode/lv_qrcode.c +++ b/src/libs/qrcode/lv_qrcode.c @@ -66,7 +66,7 @@ void lv_qrcode_set_size(lv_obj_t * obj, int32_t size) lv_image_dsc_t * img_dsc = lv_canvas_get_image(obj); void * buf = (void *)img_dsc->data; - uint32_t buf_size = LV_CANVAS_BUF_SIZE_INDEXED_1BIT(size, size); + uint32_t buf_size = LV_CANVAS_BUF_SIZE(size, size, 1, LV_DRAW_BUF_STRIDE_ALIGN); buf = lv_realloc(buf, buf_size); LV_ASSERT_MALLOC(buf); if(buf == NULL) { @@ -226,14 +226,14 @@ static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_image_dsc_t * img_dsc = lv_canvas_get_image(obj); lv_cache_lock(); - lv_cache_invalidate(lv_cache_find(img_dsc, LV_CACHE_SRC_TYPE_PTR, 0, 0)); + lv_cache_invalidate_by_src(img_dsc, LV_CACHE_SRC_TYPE_POINTER); lv_cache_unlock(); if(!img_dsc->data) { return; } - lv_free((void *)img_dsc->data); + lv_free((void *)lv_canvas_get_image(obj)); img_dsc->data = NULL; } diff --git a/src/libs/tiny_ttf/lv_tiny_ttf.c b/src/libs/tiny_ttf/lv_tiny_ttf.c index 750375c59..2592038dc 100644 --- a/src/libs/tiny_ttf/lv_tiny_ttf.c +++ b/src/libs/tiny_ttf/lv_tiny_ttf.c @@ -121,6 +121,12 @@ static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * d return true; /*true: glyph found; false: glyph was not found*/ } +static void cache_invalidate_cb(lv_cache_entry_t * entry) +{ + lv_draw_buf_free((void *)entry->data); +} + + static const uint8_t * ttf_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter, uint8_t * bitmap_buf) { LV_UNUSED(bitmap_buf); @@ -139,37 +145,50 @@ static const uint8_t * ttf_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_A8); lv_cache_lock(); uint32_t cp = unicode_letter; - lv_cache_entry_t * cache = lv_cache_find(font, LV_CACHE_SRC_TYPE_PTR, font->line_height, cp); + lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, font, LV_CACHE_SRC_TYPE_POINTER); + while(cache) { + if(cache->param1 == (int32_t)font->line_height && cache->param2 == (int32_t)cp) break; + cache = lv_cache_find_by_src(cache, font, LV_CACHE_SRC_TYPE_POINTER); + } if(cache) { uint8_t * buffer = (uint8_t *)lv_cache_get_data(cache); + lv_cache_release(cache); lv_cache_unlock(); return buffer; } + size_t szb = h * stride; - lv_cache_entry_t * entry = lv_cache_add(szb); + + uint8_t * buffer = lv_draw_buf_malloc(szb, LV_COLOR_FORMAT_A8); + if(NULL == buffer) { + LV_LOG_ERROR("tiny_ttf: out of memory\n"); + lv_cache_unlock(); + return NULL; + } + + lv_cache_entry_t * entry = lv_cache_add(buffer, 0, LV_CACHE_DATA_TYPE_NOT_SET, szb); if(entry == NULL) { lv_cache_unlock(); + lv_draw_buf_free(buffer); LV_LOG_ERROR("tiny_ttf: cache not allocated\n"); return NULL; } /* This smells. We add the codepoint to the base pointer to get a key. */ entry->src = font; - entry->src_type = LV_CACHE_SRC_TYPE_PTR; + entry->src_type = LV_CACHE_SRC_TYPE_POINTER; entry->param1 = font->line_height; entry->param2 = cp; - uint8_t * buffer = lv_draw_buf_malloc(szb, LV_COLOR_FORMAT_A8); - if(NULL == buffer) { - LV_LOG_ERROR("tiny_ttf: out of memory\n"); - lv_cache_invalidate(entry); - lv_cache_unlock(); - return NULL; - } - entry->data = buffer; - entry->free_data = 1; + entry->invalidate_cb = cache_invalidate_cb; + + /*Just to increment life*/ + lv_cache_get_data(entry); + memset(buffer, 0, szb); - stbtt_MakeGlyphBitmap(info, buffer, w, h, stride, dsc->scale, dsc->scale, g1); + stbtt_MakeGlyphBitmap(info, bitmap_buf, w, h, stride, dsc->scale, dsc->scale, g1); + lv_memcpy(buffer, bitmap_buf, stride * h); + lv_cache_release(entry); lv_cache_unlock(); - return buffer; /*Or NULL if not found*/ + return bitmap_buf; /*Or NULL if not found*/ } static lv_result_t lv_tiny_ttf_create(lv_font_t * out_font, const char * path, const void * data, size_t data_size, @@ -268,4 +287,6 @@ void lv_tiny_ttf_destroy(lv_font_t * font) } } } + + #endif diff --git a/src/libs/tiny_ttf/lv_tiny_ttf.h b/src/libs/tiny_ttf/lv_tiny_ttf.h index 23d9ea743..d9ee80d5c 100644 --- a/src/libs/tiny_ttf/lv_tiny_ttf.h +++ b/src/libs/tiny_ttf/lv_tiny_ttf.h @@ -28,6 +28,7 @@ extern "C" { /********************** * GLOBAL PROTOTYPES **********************/ + #if LV_TINY_TTF_FILE_SUPPORT !=0 /* create a font from the specified file or path with the specified line height.*/ lv_result_t lv_tiny_ttf_create_file(lv_font_t * font, const char * path, int32_t font_size); diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 7b735ec58..fa74c0133 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -325,6 +325,15 @@ #endif #endif +/* Draw using cached SDL textures*/ +#ifndef LV_USE_DRAW_SDL + #ifdef CONFIG_LV_USE_DRAW_SDL + #define LV_USE_DRAW_SDL CONFIG_LV_USE_DRAW_SDL + #else + #define LV_USE_DRAW_SDL 0 + #endif +#endif + /*================= * OPERATING SYSTEM *=================*/ diff --git a/src/lv_init.c b/src/lv_init.c index 9c8b7726b..1e458c826 100644 --- a/src/lv_init.c +++ b/src/lv_init.c @@ -164,6 +164,10 @@ void lv_init(void) lv_draw_pxp_init(); #endif +#if LV_USE_DRAW_SDL + lv_draw_sdl_init(); +#endif + _lv_obj_style_init(); /*Initialize the screen refresh system*/ diff --git a/src/misc/lv_cache.c b/src/misc/lv_cache.c index 203944ca8..1ebf1e918 100644 --- a/src/misc/lv_cache.c +++ b/src/misc/lv_cache.c @@ -56,7 +56,7 @@ void lv_cache_set_manager(lv_cache_manager_t * manager) else if(_cache_manager.set_max_size_cb != NULL) _cache_manager.set_max_size_cb(0); _cache_manager.add_cb = manager->add_cb; - _cache_manager.find_cb = manager->find_cb; + _cache_manager.find_by_data_cb = manager->find_by_data_cb; _cache_manager.invalidate_cb = manager->invalidate_cb; _cache_manager.get_data_cb = manager->get_data_cb; _cache_manager.release_cb = manager->release_cb; @@ -66,20 +66,28 @@ void lv_cache_set_manager(lv_cache_manager_t * manager) if(_cache_manager.set_max_size_cb != NULL) _cache_manager.set_max_size_cb(_cache_manager.max_size); } -lv_cache_entry_t * lv_cache_add(size_t size) +lv_cache_entry_t * lv_cache_add(const void * data, size_t data_size, uint32_t data_type, size_t memory_usage) { LV_ASSERT(_cache_manager.locked); if(_cache_manager.add_cb == NULL) return NULL; - return _cache_manager.add_cb(size); + return _cache_manager.add_cb(data, data_size, data_type, memory_usage); } -lv_cache_entry_t * lv_cache_find(const void * src_ptr, lv_cache_src_type_t src_type, uint32_t param1, uint32_t param2) +lv_cache_entry_t * lv_cache_find_by_data(const void * data, size_t data_size, uint32_t data_type) { LV_ASSERT(_cache_manager.locked); - if(_cache_manager.find_cb == NULL) return NULL; + if(_cache_manager.find_by_data_cb == NULL) return NULL; - return _cache_manager.find_cb(src_ptr, src_type, param1, param2); + return _cache_manager.find_by_data_cb(data, data_size, data_type); +} + +lv_cache_entry_t * lv_cache_find_by_src(lv_cache_entry_t * entry, const void * src, lv_cache_src_type_t src_type) +{ + LV_ASSERT(_cache_manager.locked); + if(_cache_manager.find_by_src_cb == NULL) return NULL; + + return _cache_manager.find_by_src_cb(entry, src, src_type); } void lv_cache_invalidate(lv_cache_entry_t * entry) @@ -90,6 +98,16 @@ void lv_cache_invalidate(lv_cache_entry_t * entry) _cache_manager.invalidate_cb(entry); } +void lv_cache_invalidate_by_src(const void * src, lv_cache_src_type_t src_type) +{ + LV_ASSERT(_cache_manager.locked); + lv_cache_entry_t * entry = lv_cache_find_by_src(NULL, src, src_type); + while(entry) { + lv_cache_invalidate(entry); + entry = lv_cache_find_by_src(entry, src, src_type); + } +} + const void * lv_cache_get_data(lv_cache_entry_t * entry) { LV_ASSERT(_cache_manager.locked); @@ -133,6 +151,12 @@ void lv_cache_unlock(void) lv_mutex_unlock(&_cache_manager.mutex); } +uint32_t lv_cache_register_data_type(void) +{ + _cache_manager.last_data_type++; + return _cache_manager.last_data_type; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/misc/lv_cache.h b/src/misc/lv_cache.h index 5a60ea900..f22bc6875 100644 --- a/src/misc/lv_cache.h +++ b/src/misc/lv_cache.h @@ -15,41 +15,77 @@ extern "C" { *********************/ #include <stdint.h> #include <stddef.h> +#include <stdbool.h> #include "../osal/lv_os.h" /********************* * DEFINES *********************/ +#define LV_CACHE_DATA_TYPE_NOT_SET 0xFFFFFFFF /********************** * TYPEDEFS **********************/ typedef enum { - LV_CACHE_SRC_TYPE_PTR, - LV_CACHE_SRC_TYPE_STR, - _LV_CACHE_SRC_TYPE_LAST, + LV_CACHE_SRC_TYPE_PATH, + LV_CACHE_SRC_TYPE_POINTER, } lv_cache_src_type_t; typedef struct _lv_cache_entry_t { - /**The image source or other source related to the cache content.*/ + + /** + * The data to cache. + * Can be just a pointer to a byte array, or pointer to a complex structure, or anything else*/ + const void * data; + + /** + * Size of data in bytes. + * It's not the size of the cached data, just the size of the structure pointed by `data` + * E.g. `data` can point to descriptor struct and the size of that struct needs to be stored here. + * It can be used in the `compary_cb` to compare `data` fields of the entries with a requested one*/ + uint32_t data_size; + + /**An integer ID to tell the type of the cached data. + * If set to `LV_CACHE_DATA_TYPE_NOT_SET` `lv_cache_find_by_data` cannot be used*/ + uint32_t data_type; + + /** + * The source from which the cache is created. + * It's can or cannot be the same as data, or different, or NULL. + * It's used to find the cache entries which are relted to same source. + * E.g. the same image, font, etc. */ const void * src; lv_cache_src_type_t src_type; - /** Some extra parameters to describe the source. E.g. the current frame of an animation*/ - uint32_t param1; - uint32_t param2; + /**Arbitrary parameters to better identify the source*/ + int32_t param1; + int32_t param2; + + /** Memory in bytes used by data. */ + uint32_t memory_usage; + + /** + * Called to compare the data of cache entries. + * Before calling this function LVGL checks that `data_size` of both entries are the same. + * This callback look into `data` and check all the pointers and their content on any level. + * @param data1 first data to compare + * @param data2 second data to compare + * @param data_size size of data + * @return true: `data1` and `data2` are the same + */ + bool (*compare_cb)(const void * data1, const void * data2, size_t data_size); + + /** + * Called when the entry is invalidated to free its data + * @param e the cache entry to free + */ + void (*invalidate_cb)(struct _lv_cache_entry_t * e); /** User processing tag*/ uint32_t process_state; - /** The data to cache*/ - const void * data; - - /** Size of data in bytes*/ - uint32_t data_size; - /** On access to any cache entry, `life` of each cache entry will be incremented by their own `weight` to keep the entry alive longer*/ uint32_t weight; @@ -61,12 +97,6 @@ typedef struct _lv_cache_entry_t { * A data will dropped from the cache only if its usage_count is zero */ uint32_t usage_count; - /** Call `lv_free` on `src` when the entry is removed from the cache */ - uint32_t free_src : 1; - - /** Call `lv_draw_buf_free` on `data` when the entry is removed from the cache */ - uint32_t free_data : 1; - /** The cache entry was larger then the max cache size so only a temporary entry was allocated * The entry will be closed and freed in `lv_cache_release` automatically*/ uint32_t temporary : 1; @@ -79,21 +109,33 @@ typedef struct _lv_cache_entry_t { * Add a new entry to the cache with the given size. * It won't allocate any buffers just free enough space to be a new entry * with `size` bytes fits. - * @param size the size of the new entry in bytes - * @return a handler for the new cache entry + * @param data data the cache, can be a complex structure too + * @param data_size the size of data (if it's a struct then the size of the struct) + * @param data_type type of data to identify the kind of this cache entry + * @param memory_usage the size of memory used by this entry (`data` might contain pointers so it's size of all buffers related to entry) + * @return a handler for the new cache entry */ -typedef lv_cache_entry_t * (*lv_cache_add_cb)(size_t size); +typedef lv_cache_entry_t * (*lv_cache_add_cb)(const void * data, size_t data_size, uint32_t data_type, + size_t memory_usage); /** - * Find a cache entry - * @param src_ptr pointer to the source data - * @param src_type source type (`LV_CACHE_SRC_TYPE_PTR` or `LV_CACHE_SRC_TYPE_STR`) - * @param param1 param1, which was set when the cache was added - * @param param2 param2, which was set when the cache was added - * @return the cache entry with given source and parameters or NULL if not found + * Find a cache entry based on its data + * @param data the data to find + * @param data_size size of data + * @param data_type ID for the data type + * @return the cache entry with given `data` or NULL if not found */ -typedef lv_cache_entry_t * (*lv_cache_find_cb)(const void * src_ptr, lv_cache_src_type_t src_type, uint32_t param1, - uint32_t param2); +typedef lv_cache_entry_t * (*lv_cache_find_by_data_cb)(const void * data, size_t data_size, uint32_t data_type); + +/** + * Get the next entry which has the given source and parameters + * @param prev_entry pointer to the previous entry from which the nest should be found. NULL means to start from the beginning. + * @param src a pointer or a string + * @param src_type element of lv_cache_src_type_t + * @return the cache entry with given source or NULL if not found + */ +typedef lv_cache_entry_t * (*lv_cache_find_by_src_cb)(lv_cache_entry_t * entry, const void * src, + lv_cache_src_type_t src_type); /** * Invalidate (drop) a cache entry @@ -130,7 +172,8 @@ typedef void (*lv_cache_empty_cb)(void); typedef struct { lv_cache_add_cb add_cb; - lv_cache_find_cb find_cb; + lv_cache_find_by_data_cb find_by_data_cb; + lv_cache_find_by_src_cb find_by_src_cb; lv_cache_invalidate_cb invalidate_cb; lv_cache_get_data_cb get_data_cb; lv_cache_release_cb release_cb; @@ -140,6 +183,7 @@ typedef struct { lv_mutex_t mutex; size_t max_size; uint32_t locked : 1; /**< Show the mutex state, used to log unlocked cache access*/ + uint32_t last_data_type; } lv_cache_manager_t; /********************** @@ -166,28 +210,46 @@ void lv_cache_set_manager(lv_cache_manager_t * manager); * Add a new entry to the cache with the given size. * It won't allocate any buffers just free enough space to be a new entry * with `size` bytes fits. - * @param size the size of the new entry in bytes - * @return a handler for the new cache entry + * @param data data the cache, can be a complex structure too + * @param data_size the size of data (if it's a struct then the size of the struct) + * @param data_type type of data to identify the kind of this cache entry + * @param memory_usage the size of memory used by this entry (`data` might contain pointers so it's size of all buffers related to entry) + * @return a handler for the new cache entry */ -lv_cache_entry_t * lv_cache_add(size_t size); +lv_cache_entry_t * lv_cache_add(const void * data, size_t data_size, uint32_t data_type, size_t memory_usage); /** - * Find a cache entry with pointer source type - * @param src_ptr pointer to the source data - * @param src_type source type (`LV_CACHE_SRC_TYPE_PTR` or `LV_CACHE_SRC_TYPE_STR`) - * @param param1 param1, which was set when the cache was added - * @param param2 param2, which was set when the cache was added - * @return the cache entry with given source and parameters or NULL if not found + * Find a cache entry based on its data + * @param data the data to find + * @param data_size size of data + * @param data_type ID of data type + * @return the cache entry with given `data` or NULL if not found */ -lv_cache_entry_t * lv_cache_find(const void * src, lv_cache_src_type_t src_type, uint32_t param1, uint32_t param2); +lv_cache_entry_t * lv_cache_find_by_data(const void * data, size_t data_size, uint32_t data_type); /** - * Invalidate (drop) a cache entry + * Get the next entry which has the given source and parameters + * @param prev_entry pointer to the previous entry from which the nest should be found. NULL means to start from the beginning. + * @param src a pointer or a string + * @param src_type element of lv_cache_src_type_t + * @return the cache entry with given source or NULL if not found + */ +lv_cache_entry_t * lv_cache_find_by_src(lv_cache_entry_t * entry, const void * src, lv_cache_src_type_t src_type); + +/** + * Invalidate (drop) a cache entry. It will call the entry's `invalidate_cb` to free the resources * @param entry the entry to invalidate. (can be retrieved by `lv_cache_find()`) */ void lv_cache_invalidate(lv_cache_entry_t * entry); /** + * Invalidate all cache entries with a given source + * @param src a pointer or a string + * @param src_type element of lv_cache_src_type_t + */ +void lv_cache_invalidate_by_src(const void * src, lv_cache_src_type_t src_type); + +/** * Get the data of a cache entry. * It is considered a cached data access so the cache manager can count that * this entry was used on more times, and therefore it's more relevant. @@ -227,6 +289,12 @@ void lv_cache_lock(void); */ void lv_cache_unlock(void); +/** + * Register a data type which can be used as `entry->data_type`. + * @return the registered unique data type ID. + */ +uint32_t lv_cache_register_data_type(void); + /********************** * MACROS **********************/ diff --git a/src/misc/lv_cache_builtin.c b/src/misc/lv_cache_builtin.c index 223da5b35..8b98eb3b6 100644 --- a/src/misc/lv_cache_builtin.c +++ b/src/misc/lv_cache_builtin.c @@ -25,8 +25,9 @@ /********************** * STATIC PROTOTYPES **********************/ -static lv_cache_entry_t * add_cb(size_t size); -static lv_cache_entry_t * find_cb(const void * src, lv_cache_src_type_t src_type, uint32_t param1, uint32_t param2); +static lv_cache_entry_t * add_cb(const void * data, size_t data_size, uint32_t data_type, size_t memory_usage); +static lv_cache_entry_t * find_by_data_cb(const void * data, size_t data_size, uint32_t data_type); +static lv_cache_entry_t * find_by_src_cb(lv_cache_entry_t * entry, const void * src, lv_cache_src_type_t src_type); static void invalidate_cb(lv_cache_entry_t * entry); static const void * get_data_cb(lv_cache_entry_t * entry); static void release_cb(lv_cache_entry_t * entry); @@ -57,7 +58,8 @@ void _lv_cache_builtin_init(void) _lv_ll_init(&dsc.entry_ll, sizeof(lv_cache_entry_t)); _cache_manager.add_cb = add_cb; - _cache_manager.find_cb = find_cb; + _cache_manager.find_by_data_cb = find_by_data_cb; + _cache_manager.find_by_src_cb = find_by_src_cb; _cache_manager.invalidate_cb = invalidate_cb; _cache_manager.get_data_cb = get_data_cb; _cache_manager.release_cb = release_cb; @@ -74,15 +76,15 @@ void _lv_cache_builtin_deinit(void) * STATIC FUNCTIONS **********************/ -static lv_cache_entry_t * add_cb(size_t size) +static lv_cache_entry_t * add_cb(const void * data, size_t data_size, uint32_t data_type, size_t memory_usage) { size_t max_size = lv_cache_get_max_size(); /*Can't cache data larger than max size*/ - bool temporary = size > max_size ? true : false; + bool temporary = memory_usage > max_size ? true : false; if(!temporary) { /*Keep dropping items until there is enough space*/ - while(dsc.cur_size + size > _cache_manager.max_size) { + while(dsc.cur_size + memory_usage > _cache_manager.max_size) { bool ret = drop_youngest(); /*No item could be dropped. @@ -96,29 +98,32 @@ static lv_cache_entry_t * add_cb(size_t size) lv_cache_entry_t * entry = _lv_ll_ins_head(&dsc.entry_ll); lv_memzero(entry, sizeof(lv_cache_entry_t)); - entry->data_size = size; + entry->memory_usage = memory_usage; entry->weight = 1; entry->temporary = temporary; + entry->data = data; + entry->data_size = data_size; + entry->data_type = data_type; if(temporary) { - LV_TRACE_CACHE("Add temporary cache: %lu bytes", (unsigned long)size); + LV_TRACE_CACHE("Add temporary cache: %lu bytes", (unsigned long)memory_usage); } else { - LV_TRACE_CACHE("Add cache: %lu bytes", (unsigned long)size); - dsc.cur_size += size; + LV_TRACE_CACHE("Add cache: %lu bytes", (unsigned long)memory_usage); + dsc.cur_size += memory_usage; } return entry; } -static lv_cache_entry_t * find_cb(const void * src, lv_cache_src_type_t src_type, uint32_t param1, uint32_t param2) +static lv_cache_entry_t * find_by_data_cb(const void * data, size_t data_size, uint32_t data_type) { lv_cache_entry_t * entry = _lv_ll_get_head(&dsc.entry_ll); while(entry) { - if(param1 == entry->param1 && param2 == entry->param2 && src_type == entry->src_type && - ((src_type == LV_CACHE_SRC_TYPE_PTR && src == entry->src) || - (src_type == LV_CACHE_SRC_TYPE_STR && strcmp(src, entry->src) == 0))) { - return entry; + if(entry->data_type == data_type && entry->data_size == data_size) { + if(entry->compare_cb(entry->data, data, data_size)) { + return entry; + } } entry = _lv_ll_get_next(&dsc.entry_ll, entry); @@ -127,15 +132,28 @@ static lv_cache_entry_t * find_cb(const void * src, lv_cache_src_type_t src_type return NULL; } +static lv_cache_entry_t * find_by_src_cb(lv_cache_entry_t * entry, const void * src, lv_cache_src_type_t src_type) +{ + if(entry == NULL) entry = _lv_ll_get_head(&dsc.entry_ll); + else entry = _lv_ll_get_next(&dsc.entry_ll, entry); + + while(entry) { + if(src_type == LV_CACHE_SRC_TYPE_POINTER && entry->src == src) return entry; + if(src_type == LV_CACHE_SRC_TYPE_PATH && lv_strcmp(entry->src, src) == 0) return entry; + entry = _lv_ll_get_next(&dsc.entry_ll, entry); + } + + return NULL; +} + static void invalidate_cb(lv_cache_entry_t * entry) { if(entry == NULL) return; - dsc.cur_size -= entry->data_size; - LV_TRACE_CACHE("Drop cache: %u bytes", (uint32_t)entry->data_size); + dsc.cur_size -= entry->memory_usage; + LV_TRACE_CACHE("Drop cache: %u bytes", (uint32_t)entry->memory_usage); - if(entry->free_src) lv_free((void *)entry->src); - if(entry->free_data) lv_draw_buf_free((void *)entry->data); + if(entry->invalidate_cb) entry->invalidate_cb(entry); _lv_ll_remove(&dsc.entry_ll, entry); lv_free(entry); diff --git a/src/others/snapshot/lv_snapshot.c b/src/others/snapshot/lv_snapshot.c index 68c31ce68..c35af26a6 100644 --- a/src/others/snapshot/lv_snapshot.c +++ b/src/others/snapshot/lv_snapshot.c @@ -129,7 +129,7 @@ lv_result_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_color_format_t cf, lv_ima layer.buf_area.x2 = snapshot_area.x1 + w - 1; layer.buf_area.y2 = snapshot_area.y1 + h - 1; layer.color_format = cf; - layer.clip_area = snapshot_area; + layer._clip_area = snapshot_area; lv_display_t * disp_old = _lv_refr_get_disp_refreshing(); lv_display_t * disp_new = lv_obj_get_disp(obj); diff --git a/src/stdlib/builtin/lv_string_builtin.c b/src/stdlib/builtin/lv_string_builtin.c index 3e0d5a8b6..aa20626b5 100644 --- a/src/stdlib/builtin/lv_string_builtin.c +++ b/src/stdlib/builtin/lv_string_builtin.c @@ -171,6 +171,15 @@ char * lv_strcpy(char * dst, const char * src) return tmp; } +int32_t lv_strcmp(const char * s1, const char * s2) +{ + while(*s1 && (*s1 == *s2)) { + s1++; + s2++; + } + return *(const unsigned char *)s1 - *(const unsigned char *)s2; +} + char * lv_strdup(const char * src) { size_t len = lv_strlen(src) + 1; diff --git a/src/stdlib/clib/lv_string_clib.c b/src/stdlib/clib/lv_string_clib.c index 93aacbe60..76a3c159a 100644 --- a/src/stdlib/clib/lv_string_clib.c +++ b/src/stdlib/clib/lv_string_clib.c @@ -68,6 +68,11 @@ char * lv_strcpy(char * dst, const char * src) return strcpy(dst, src); } +int32_t lv_strcmp(const char * s1, const char * s2) +{ + return strcmp(s1, s2); +} + char * lv_strdup(const char * src) { /*strdup uses malloc, so use the built in malloc if it's enabled */ diff --git a/src/stdlib/lv_string.h b/src/stdlib/lv_string.h index 126aca9fb..01798a4de 100644 --- a/src/stdlib/lv_string.h +++ b/src/stdlib/lv_string.h @@ -84,6 +84,21 @@ char * lv_strncpy(char * dst, const char * src, size_t dest_size); char * lv_strcpy(char * dst, const char * src); /** + * Compare 2 strings + * @param s1 pointer to the first string + * @param s2 pointer to the first string + * @return the difference between the value of the first unmatching character. + */ +int32_t lv_strcmp(const char * s1, const char * s2); + +/** + * @brief Duplicate a string by allocating a new one and copying the content. + * @param src Pointer to the source of data to be copied. + * @return A pointer to the new allocated string. NULL if failed. + */ +char * lv_strdup(const char * src); + +/** * @brief Duplicate a string by allocating a new one and copying the content. * @param src Pointer to the source of data to be copied. * @return A pointer to the new allocated string. NULL if failed. diff --git a/src/widgets/bar/lv_bar.c b/src/widgets/bar/lv_bar.c index 88d034a25..09e5b0b04 100644 --- a/src/widgets/bar/lv_bar.c +++ b/src/widgets/bar/lv_bar.c @@ -453,7 +453,7 @@ static void draw_indic(lv_event_t * e) draw_rect_dsc.shadow_width = 0; lv_area_t indic_clip_area; - if(_lv_area_intersect(&indic_clip_area, &indic_area, &layer->clip_area)) { + if(_lv_area_intersect(&indic_clip_area, &indic_area, &layer->_clip_area)) { lv_layer_t * layer_indic = lv_draw_layer_create(layer, LV_COLOR_FORMAT_ARGB8888, &indic_area); lv_draw_rect(layer_indic, &draw_rect_dsc, &indic_area); diff --git a/src/widgets/canvas/lv_canvas.c b/src/widgets/canvas/lv_canvas.c index 212e4e2a6..3eadc69a4 100644 --- a/src/widgets/canvas/lv_canvas.c +++ b/src/widgets/canvas/lv_canvas.c @@ -70,16 +70,17 @@ void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, int32_t w, int32_t h, lv_c lv_canvas_t * canvas = (lv_canvas_t *)obj; + canvas->buf_unaligned = buf; canvas->dsc.header.cf = cf; canvas->dsc.header.w = w; canvas->dsc.header.h = h; - canvas->dsc.header.stride = lv_draw_buf_width_to_stride(w, cf); /*Let LVGL calculate it automatically*/ - canvas->dsc.data = buf; + canvas->dsc.header.stride = lv_draw_buf_width_to_stride(w, cf); + canvas->dsc.data = lv_draw_buf_align(buf, cf); canvas->dsc.data_size = w * h * lv_color_format_get_size(cf); lv_image_set_src(obj, &canvas->dsc); lv_cache_lock(); - lv_cache_invalidate(lv_cache_find(&canvas->dsc, LV_CACHE_SRC_TYPE_PTR, 0, 0)); + lv_cache_invalidate_by_src(&canvas->dsc, LV_CACHE_SRC_TYPE_POINTER); lv_cache_unlock(); } @@ -205,6 +206,15 @@ lv_image_dsc_t * lv_canvas_get_image(lv_obj_t * obj) return &canvas->dsc; } +const void * lv_canvas_get_buf(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + return canvas->buf_unaligned; + +} + /*===================== * Other functions *====================*/ @@ -298,7 +308,7 @@ void lv_canvas_init_layer(lv_obj_t * canvas, lv_layer_t * layer) layer->buf = lv_draw_buf_align((uint8_t *)dsc->data, dsc->header.cf); layer->color_format = dsc->header.cf; layer->buf_area = canvas_area; - layer->clip_area = canvas_area; + layer->_clip_area = canvas_area; layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format); } @@ -340,7 +350,7 @@ static void lv_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_canvas_t * canvas = (lv_canvas_t *)obj; lv_cache_lock(); - lv_cache_invalidate(lv_cache_find(&canvas->dsc, LV_CACHE_SRC_TYPE_PTR, 0, 0)); + lv_cache_invalidate_by_src(&canvas->dsc, LV_CACHE_SRC_TYPE_POINTER); lv_cache_unlock(); } diff --git a/src/widgets/canvas/lv_canvas.h b/src/widgets/canvas/lv_canvas.h index fa7b16fbc..e2aac005e 100644 --- a/src/widgets/canvas/lv_canvas.h +++ b/src/widgets/canvas/lv_canvas.h @@ -33,6 +33,7 @@ LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_canvas_class; typedef struct { lv_image_t img; lv_image_dsc_t dsc; + const void * buf_unaligned; } lv_canvas_t; /********************** @@ -91,6 +92,15 @@ lv_color32_t lv_canvas_get_px(lv_obj_t * obj, int32_t x, int32_t y); */ lv_image_dsc_t * lv_canvas_get_image(lv_obj_t * canvas); +/** + * Return the pointer for the buffer. + * It's recommended to use this function instead of the buffer form the + * return value of lv_canvas_get_image() as is can be aligned + * @param canvas pointer to a canvas object + * @return pointer to the buffer + */ +const void * lv_canvas_get_buf(lv_obj_t * canvas); + /*===================== * Other functions *====================*/ @@ -122,21 +132,8 @@ void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer); /********************** * MACROS **********************/ -#define LV_CANVAS_BUF_SIZE_TRUE_COLOR(w, h) LV_IMAGE_BUF_SIZE_TRUE_COLOR(w, h) -#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) LV_IMAGE_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) -#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) LV_IMAGE_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) - -/*+ 1: to be sure no fractional row*/ -#define LV_CANVAS_BUF_SIZE_ALPHA_1BIT(w, h) LV_IMAGE_BUF_SIZE_ALPHA_1BIT(w, h) -#define LV_CANVAS_BUF_SIZE_ALPHA_2BIT(w, h) LV_IMAGE_BUF_SIZE_ALPHA_2BIT(w, h) -#define LV_CANVAS_BUF_SIZE_ALPHA_4BIT(w, h) LV_IMAGE_BUF_SIZE_ALPHA_4BIT(w, h) -#define LV_CANVAS_BUF_SIZE_ALPHA_8BIT(w, h) LV_IMAGE_BUF_SIZE_ALPHA_8BIT(w, h) - -/*4 * X: for palette*/ -#define LV_CANVAS_BUF_SIZE_INDEXED_1BIT(w, h) LV_IMAGE_BUF_SIZE_INDEXED_1BIT(w, h) -#define LV_CANVAS_BUF_SIZE_INDEXED_2BIT(w, h) LV_IMAGE_BUF_SIZE_INDEXED_2BIT(w, h) -#define LV_CANVAS_BUF_SIZE_INDEXED_4BIT(w, h) LV_IMAGE_BUF_SIZE_INDEXED_4BIT(w, h) -#define LV_CANVAS_BUF_SIZE_INDEXED_8BIT(w, h) LV_IMAGE_BUF_SIZE_INDEXED_8BIT(w, h) + +#define LV_CANVAS_BUF_SIZE(w, h, bpp, stride) (((((w * bpp + 7) >> 3) + stride - 1) & ~(stride - 1)) * h + LV_DRAW_BUF_ALIGN) #endif /*LV_USE_CANVAS*/ diff --git a/src/widgets/chart/lv_chart.c b/src/widgets/chart/lv_chart.c index acb4368c3..e16e4ecd8 100644 --- a/src/widgets/chart/lv_chart.c +++ b/src/widgets/chart/lv_chart.c @@ -719,11 +719,11 @@ static void draw_div_lines(lv_obj_t * obj, lv_layer_t * layer) lv_chart_t * chart = (lv_chart_t *)obj; lv_area_t series_clip_area; - bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->clip_area); + bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->_clip_area); if(mask_ret == false) return; - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = series_clip_area; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = series_clip_area; int16_t i; int16_t i_start; @@ -787,16 +787,16 @@ static void draw_div_lines(lv_obj_t * obj, lv_layer_t * layer) } } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer) { lv_area_t clip_area; - if(_lv_area_intersect(&clip_area, &obj->coords, &layer->clip_area) == false) return; + if(_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area) == false) return; - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = clip_area; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; lv_chart_t * chart = (lv_chart_t *)obj; if(chart->point_cnt < 2) return; @@ -812,7 +812,7 @@ static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer) lv_chart_series_t * ser; lv_area_t series_clip_area; - bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->clip_area); + bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->_clip_area); if(mask_ret == false) return; lv_draw_line_dsc_t line_dsc; @@ -934,17 +934,17 @@ static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer) } } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } static void draw_series_scatter(lv_obj_t * obj, lv_layer_t * layer) { lv_area_t clip_area; - if(_lv_area_intersect(&clip_area, &obj->coords, &layer->clip_area) == false) return; + if(_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area) == false) return; - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = clip_area; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; lv_chart_t * chart = (lv_chart_t *)obj; @@ -1054,17 +1054,17 @@ static void draw_series_scatter(lv_obj_t * obj, lv_layer_t * layer) } line_dsc.base.id1++; point_dsc_default.base.id1++; - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } } static void draw_series_bar(lv_obj_t * obj, lv_layer_t * layer) { lv_area_t clip_area; - if(_lv_area_intersect(&clip_area, &obj->coords, &layer->clip_area) == false) return; + if(_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area) == false) return; - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = clip_area; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; lv_chart_t * chart = (lv_chart_t *)obj; @@ -1128,7 +1128,7 @@ static void draw_series_bar(lv_obj_t * obj, lv_layer_t * layer) col_dsc.base.id1++; } } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } static void draw_cursors(lv_obj_t * obj, lv_layer_t * layer) @@ -1139,10 +1139,10 @@ static void draw_cursors(lv_obj_t * obj, lv_layer_t * layer) if(_lv_ll_is_empty(&chart->cursor_ll)) return; lv_area_t clip_area; - if(!_lv_area_intersect(&clip_area, &layer->clip_area, &obj->coords)) return; + if(!_lv_area_intersect(&clip_area, &layer->_clip_area, &obj->coords)) return; - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = clip_area; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; lv_chart_cursor_t * cursor; @@ -1226,7 +1226,7 @@ static void draw_cursors(lv_obj_t * obj, lv_layer_t * layer) point_dsc_ori.base.id1++; } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } /** diff --git a/src/widgets/dropdown/lv_dropdown.c b/src/widgets/dropdown/lv_dropdown.c index 3bdfd3a7d..db4bb84af 100644 --- a/src/widgets/dropdown/lv_dropdown.c +++ b/src/widgets/dropdown/lv_dropdown.c @@ -908,10 +908,10 @@ static void draw_list(lv_event_t * e) * the selected option can be drawn on only the background*/ lv_area_t clip_area_core; bool has_common; - has_common = _lv_area_intersect(&clip_area_core, &layer->clip_area, &dropdown->list->coords); + has_common = _lv_area_intersect(&clip_area_core, &layer->_clip_area, &dropdown->list->coords); if(has_common) { - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = clip_area_core; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area_core; if(dropdown->selected_highlight) { if(dropdown->pr_opt_id == dropdown->sel_opt_id) { draw_box(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED); @@ -928,7 +928,7 @@ static void draw_list(lv_event_t * e) draw_box(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED); draw_box_label(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED); } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } } @@ -1005,13 +1005,13 @@ static void draw_box_label(lv_obj_t * dropdown_obj, lv_layer_t * layer, uint32_t area_sel.x2 = list_obj->coords.x2; lv_area_t mask_sel; bool area_ok; - area_ok = _lv_area_intersect(&mask_sel, &layer->clip_area, &area_sel); + area_ok = _lv_area_intersect(&mask_sel, &layer->_clip_area, &area_sel); if(area_ok) { - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = mask_sel; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = mask_sel; label_dsc.text = lv_label_get_text(label); lv_draw_label(layer, &label_dsc, &label->coords); - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } list_obj->state = state_orig; list_obj->skip_trans = 0; diff --git a/src/widgets/image/lv_image.c b/src/widgets/image/lv_image.c index b0f951452..74da95960 100644 --- a/src/widgets/image/lv_image.c +++ b/src/widgets/image/lv_image.c @@ -360,7 +360,7 @@ void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom) if(zoom == 0) zoom = 1; - scale_update(obj, img->scale_y, zoom); + scale_update(obj, img->scale_x, zoom); } void lv_image_set_antialias(lv_obj_t * obj, bool antialias) @@ -664,7 +664,7 @@ static void draw_image(lv_event_t * e) lv_draw_image_dsc_init(&draw_dsc); lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &draw_dsc); - lv_area_t clip_area_ori = layer->clip_area; + lv_area_t clip_area_ori = layer->_clip_area; lv_image_get_pivot(obj, &draw_dsc.pivot); draw_dsc.scale_x = img->scale_x; @@ -680,17 +680,17 @@ static void draw_image(lv_event_t * e) lv_area_align(&obj->coords, &img_area, img->align, img->offset.x, img->offset.y); } else if(img->align == LV_IMAGE_ALIGN_TILE) { - _lv_area_intersect(&layer->clip_area, &layer->clip_area, &obj->coords); + _lv_area_intersect(&layer->_clip_area, &layer->_clip_area, &obj->coords); lv_area_move(&img_area, img->offset.x, img->offset.y); lv_area_move(&img_area, - ((layer->clip_area.x1 - img_area.x1 - (img->w - 1)) / img->w) * img->w, - ((layer->clip_area.y1 - img_area.y1 - (img->h - 1)) / img->h) * img->h); + ((layer->_clip_area.x1 - img_area.x1 - (img->w - 1)) / img->w) * img->w, + ((layer->_clip_area.y1 - img_area.y1 - (img->h - 1)) / img->h) * img->h); draw_dsc.tile = 1; } lv_draw_image(layer, &draw_dsc, &img_area); - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } else if(img->src_type == LV_IMAGE_SRC_SYMBOL) { diff --git a/src/widgets/imgbtn/lv_imgbtn.c b/src/widgets/imgbtn/lv_imgbtn.c index c8c2f7b42..9c402c4f2 100644 --- a/src/widgets/imgbtn/lv_imgbtn.c +++ b/src/widgets/imgbtn/lv_imgbtn.c @@ -262,12 +262,12 @@ static void draw_main(lv_event_t * e) clip_area_center.y2 = coords.y2; bool comm_res; - comm_res = _lv_area_intersect(&clip_area_center, &clip_area_center, &layer->clip_area); + comm_res = _lv_area_intersect(&clip_area_center, &clip_area_center, &layer->_clip_area); if(comm_res) { int32_t i; - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = clip_area_center; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area_center; coords_part.x1 = coords.x1 + left_w; coords_part.y1 = coords.y1; @@ -280,7 +280,7 @@ static void draw_main(lv_event_t * e) coords_part.x1 = coords_part.x2 + 1; coords_part.x2 += src_info->header.w; } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } } } diff --git a/src/widgets/label/lv_label.c b/src/widgets/label/lv_label.c index 8d44d4b09..83a66da2f 100644 --- a/src/widgets/label/lv_label.c +++ b/src/widgets/label/lv_label.c @@ -754,7 +754,7 @@ static void draw_main(lv_event_t * e) } lv_area_t txt_clip; - bool is_common = _lv_area_intersect(&txt_clip, &txt_coords, &layer->clip_area); + bool is_common = _lv_area_intersect(&txt_clip, &txt_coords, &layer->_clip_area); if(!is_common) { return; } @@ -765,17 +765,17 @@ static void draw_main(lv_event_t * e) txt_coords.y2 = obj->coords.y2; } if(label->long_mode == LV_LABEL_LONG_SCROLL || label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = txt_clip; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = txt_clip; lv_draw_label(layer, &label_draw_dsc, &txt_coords); - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } else { lv_draw_label(layer, &label_draw_dsc, &txt_coords); } - lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = txt_clip; + lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = txt_clip; if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { lv_point_t size; @@ -800,7 +800,7 @@ static void draw_main(lv_event_t * e) } } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } static void overwrite_anim_property(lv_anim_t * dest, const lv_anim_t * src, lv_label_long_mode_t mode) diff --git a/src/widgets/roller/lv_roller.c b/src/widgets/roller/lv_roller.c index 36eb871b2..b48ae3d78 100644 --- a/src/widgets/roller/lv_roller.c +++ b/src/widgets/roller/lv_roller.c @@ -485,7 +485,7 @@ static void draw_main(lv_event_t * e) get_sel_area(obj, &sel_area); lv_area_t mask_sel; bool area_ok; - area_ok = _lv_area_intersect(&mask_sel, &layer->clip_area, &sel_area); + area_ok = _lv_area_intersect(&mask_sel, &layer->_clip_area, &sel_area); if(area_ok) { lv_obj_t * label = get_label(obj); @@ -523,11 +523,11 @@ static void draw_main(lv_event_t * e) label_sel_area.y2 = label_sel_area.y1 + res_p.y; label_dsc.flag |= LV_TEXT_FLAG_EXPAND; - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = mask_sel; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = mask_sel; label_dsc.text = lv_label_get_text(label); lv_draw_label(layer, &label_dsc, &label_sel_area); - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } } } @@ -547,10 +547,10 @@ static void draw_label(lv_event_t * e) /*If the roller has shadow or outline it has some ext. draw size *therefore the label can overflow the roller's boundaries. *To solve this limit the clip area to the "plain" roller.*/ - const lv_area_t clip_area_ori = layer->clip_area; + const lv_area_t clip_area_ori = layer->_clip_area; lv_area_t roller_clip_area; - if(!_lv_area_intersect(&roller_clip_area, &layer->clip_area, &roller->coords)) return; - layer->clip_area = roller_clip_area; + if(!_lv_area_intersect(&roller_clip_area, &layer->_clip_area, &roller->coords)) return; + layer->_clip_area = roller_clip_area; lv_area_t sel_area; get_sel_area(roller, &sel_area); @@ -560,27 +560,27 @@ static void draw_label(lv_event_t * e) clip2.y1 = label_obj->coords.y1; clip2.x2 = label_obj->coords.x2; clip2.y2 = sel_area.y1; - if(_lv_area_intersect(&clip2, &layer->clip_area, &clip2)) { - const lv_area_t clip_area_ori2 = layer->clip_area; - layer->clip_area = clip2; + if(_lv_area_intersect(&clip2, &layer->_clip_area, &clip2)) { + const lv_area_t clip_area_ori2 = layer->_clip_area; + layer->_clip_area = clip2; label_draw_dsc.text = lv_label_get_text(label_obj); lv_draw_label(layer, &label_draw_dsc, &label_obj->coords); - layer->clip_area = clip_area_ori2; + layer->_clip_area = clip_area_ori2; } clip2.x1 = label_obj->coords.x1; clip2.y1 = sel_area.y2; clip2.x2 = label_obj->coords.x2; clip2.y2 = label_obj->coords.y2; - if(_lv_area_intersect(&clip2, &layer->clip_area, &clip2)) { - const lv_area_t clip_area_ori2 = layer->clip_area; - layer->clip_area = clip2; + if(_lv_area_intersect(&clip2, &layer->_clip_area, &clip2)) { + const lv_area_t clip_area_ori2 = layer->_clip_area; + layer->_clip_area = clip2; label_draw_dsc.text = lv_label_get_text(label_obj); lv_draw_label(layer, &label_draw_dsc, &label_obj->coords); - layer->clip_area = clip_area_ori2; + layer->_clip_area = clip_area_ori2; } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } static void get_sel_area(lv_obj_t * obj, lv_area_t * sel_area) diff --git a/src/widgets/span/lv_span.c b/src/widgets/span/lv_span.c index 33f317ea5..4e40a30e8 100644 --- a/src/widgets/span/lv_span.c +++ b/src/widgets/span/lv_span.c @@ -806,9 +806,9 @@ static void lv_draw_span(lv_obj_t * obj, lv_layer_t * layer) /* return if no draw area */ lv_area_t clip_area; - if(!_lv_area_intersect(&clip_area, &coords, &layer->clip_area)) return; - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = clip_area; + if(!_lv_area_intersect(&clip_area, &coords, &layer->_clip_area)) return; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; /* init draw variable */ lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE; @@ -1056,12 +1056,12 @@ Next_line_init: txt_pos.x = coords.x1; txt_pos.y += max_line_h; if(is_end_line || txt_pos.y > clip_area.y2 + 1) { - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; return; } max_w = max_width; } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } static void refresh_self_size(lv_obj_t * obj) diff --git a/src/widgets/table/lv_table.c b/src/widgets/table/lv_table.c index 5d53c6962..6f54d39d4 100644 --- a/src/widgets/table/lv_table.c +++ b/src/widgets/table/lv_table.c @@ -651,10 +651,10 @@ static void draw_main(lv_event_t * e) lv_table_t * table = (lv_table_t *)obj; lv_layer_t * layer = lv_event_get_layer(e); lv_area_t clip_area; - if(!_lv_area_intersect(&clip_area, &obj->coords, &layer->clip_area)) return; + if(!_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area)) return; - const lv_area_t clip_area_ori = layer->clip_area; - layer->clip_area = clip_area; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; lv_point_t txt_size; lv_area_t cell_area; @@ -819,10 +819,10 @@ static void draw_main(lv_event_t * e) bool label_mask_ok; label_mask_ok = _lv_area_intersect(&label_clip_area, &clip_area, &cell_area); if(label_mask_ok) { - layer->clip_area = label_clip_area; + layer->_clip_area = label_clip_area; label_dsc_act.text = table->cell_data[cell]->txt; lv_draw_label(layer, &label_dsc_act, &txt_area); - layer->clip_area = clip_area; + layer->_clip_area = clip_area; } } @@ -831,7 +831,7 @@ static void draw_main(lv_event_t * e) } } - layer->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } /* Refreshes size of the table starting from @start_row row */ diff --git a/tests/ref_imgs/libs/tiny_ttf_1.png b/tests/ref_imgs/libs/tiny_ttf_1.png Binary files differindex c4ec1a0d2..9cccd3818 100644 --- a/tests/ref_imgs/libs/tiny_ttf_1.png +++ b/tests/ref_imgs/libs/tiny_ttf_1.png diff --git a/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_center.png b/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_center.png Binary files differindex 07e50c81a..d679dfd92 100644 --- a/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_center.png +++ b/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_center.png diff --git a/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_top_left.png b/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_top_left.png Binary files differindex 220c4a530..2fa4ba1a7 100644 --- a/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_top_left.png +++ b/tests/ref_imgs/widgets/image_rotate_and_scale_pivot_top_left.png diff --git a/tests/ref_imgs/widgets/image_transform_align.png b/tests/ref_imgs/widgets/image_transform_align.png Binary files differindex c99818ec5..2cce9a4c5 100644 --- a/tests/ref_imgs/widgets/image_transform_align.png +++ b/tests/ref_imgs/widgets/image_transform_align.png diff --git a/tests/ref_imgs/widgets/image_transform_align_offset.png b/tests/ref_imgs/widgets/image_transform_align_offset.png Binary files differindex a8b1543e5..100ba9b1b 100644 --- a/tests/ref_imgs/widgets/image_transform_align_offset.png +++ b/tests/ref_imgs/widgets/image_transform_align_offset.png diff --git a/tests/src/test_cases/draw/test_draw_vector.c b/tests/src/test_cases/draw/test_draw_vector.c index f3f5398ca..f533ccb83 100644 --- a/tests/src/test_cases/draw/test_draw_vector.c +++ b/tests/src/test_cases/draw/test_draw_vector.c @@ -202,9 +202,9 @@ static void draw_lines(lv_layer_t * layer) static void canvas_draw(const char * name, void (*draw_cb)(lv_layer_t *)) { - static uint8_t canvas_buf[CANVAS_WIDTH_TO_STRIDE(640, 4) * 480 + LV_DRAW_BUF_ALIGN]; + static uint8_t canvas_buf[LV_CANVAS_BUF_SIZE(640, 480, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_canvas_set_buffer(canvas, lv_draw_buf_align(canvas_buf, LV_COLOR_FORMAT_ARGB8888), 640, 480, + lv_canvas_set_buffer(canvas, canvas_buf, 640, 480, LV_COLOR_FORMAT_ARGB8888); lv_layer_t layer; |