From 0daebca18b2e7d4c51d5b53e7f2a60df634850f2 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 27 Sep 2024 11:50:27 +0200 Subject: [PATCH] feat(render): basic of tiled rendering (#6761) --- docs/porting/display.rst | 37 ++++++ src/core/lv_refr.c | 201 +++++++++++++++++++------------ src/display/lv_display.c | 25 ++++ src/display/lv_display.h | 14 +++ src/display/lv_display_private.h | 2 + src/draw/lv_draw.c | 53 +++++--- src/draw/lv_draw.h | 13 +- src/draw/sw/lv_draw_sw.c | 26 ++-- src/draw/sw/lv_draw_sw_img.c | 6 +- src/drivers/sdl/lv_sdl_window.c | 1 - 10 files changed, 266 insertions(+), 112 deletions(-) diff --git a/docs/porting/display.rst b/docs/porting/display.rst index ee941cbb3..2e55f73a1 100644 --- a/docs/porting/display.rst +++ b/docs/porting/display.rst @@ -239,6 +239,43 @@ In full and direct modes, the buffer size should be large enough for the whole s As LVGL can not handle fractional width make sure to round the horizontal resolution to 8- (For example 90 to 96) + +Tiled Rendering +--------------- + +When multiple CPU cores are available and a large area needs to be redrawn, LVGL must identify independent areas that can be rendered in parallel. + +For example, if there are 4 CPU cores, one core can draw the screen's background while the other 3 must wait until it is finished. If there are 2 buttons on the screen, those 2 buttons can be rendered in parallel, but 2 cores will still remain idle. + +Due to dependencies among different areas, CPU cores cannot always be fully utilized. + +To address this, LVGL can divide large areas that need to be updated into smaller tiles. These tiles are independent, making it easier to find areas that can be rendered concurrently. + +Specifically, if there are 4 tiles and 4 cores, there will always be an independent area for each core within one of the tiles. + +The maximum number of tiles can be set using the function :cpp:func:`lv_display_set_tile_cnt(disp, cnt)`. The default value is :cpp:expr:`LV_DRAW_SW_DRAW_UNIT_CNT` (or 1 if software rendering is not enabled). + +Small areas are not further divided into smaller tiles because the overhead of spinning up 4 cores would outweigh the benefits. + +The ideal tile size is calculated as ``ideal_tile_size = draw_buf_size / tile_cnt``. For example, in :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_DIRECT` mode on an 800x480 screen, the display buffer is 800x480 = 375k pixels. If there are 4 tiles, the ideal tile size is approximately 93k pixels. Based on this, core utilization is as follows: + +- 30k pixels: 1 core +- 90k pixels: 1 core +- 95k pixels: 2 cores (above 93k pixels, 2 cores are used) +- 150k pixels: 2 cores +- 200k pixels: 3 cores (above 186k pixels, 3 cores are used) +- 300k pixels: 4 cores (above 279k pixels, 4 cores are used) +- 375k pixels: 4 cores + +In :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_DIRECT`, the screen-sized draw buffer is divided by the tile count to determine the ideal tile sizes. If smaller areas are refreshed, it may result in fewer cores being used. + +In :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_FULL`, the maximum number of tiles is always created as the entire screen is refreshed. + +In :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_PARTIAL`, the partial buffer is divided into tiles. For example, if the draw buffer is 1/10th the size of the screen and there are 2 tiles, then 1/20th + 1/20th of the screen area will be rendered at once. + +Tiled rendering only affects the rendering process, and the ``flush_cb`` is called once for each invalidated area. Therefore, tiling is not visible from the flushing point of view. + + User data --------- diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index 92b4878e3..d43ab80f2 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -43,7 +43,7 @@ static void lv_refr_join_area(void); static void refr_invalid_areas(void); static void refr_sync_areas(void); static void refr_area(const lv_area_t * area_p); -static void refr_area_part(lv_layer_t * layer); +static void refr_configured_layer(lv_layer_t * layer); static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj); static void refr_obj_and_children(lv_layer_t * layer, lv_obj_t * top_obj); static void refr_obj(lv_layer_t * layer, lv_obj_t * obj); @@ -581,11 +581,50 @@ static void refr_invalid_areas(void) for(i = 0; i < (int32_t)disp_refr->inv_p; i++) { /*Refresh the unjoined areas*/ - if(disp_refr->inv_area_joined[i] == 0) { + if(disp_refr->inv_area_joined[i]) continue; - if(i == last_i) disp_refr->last_area = 1; - disp_refr->last_part = 0; + if(i == last_i) disp_refr->last_area = 1; + disp_refr->last_part = 0; + + lv_area_t inv_a = disp_refr->inv_areas[i]; + if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_PARTIAL) { + /*Calculate the max row num*/ + int32_t w = lv_area_get_width(&inv_a); + int32_t h = lv_area_get_height(&inv_a); + + int32_t max_row = get_max_row(disp_refr, w, h); + + int32_t row; + int32_t row_last = 0; + lv_area_t sub_area; + sub_area.x1 = inv_a.x1; + sub_area.x2 = inv_a.x2; + for(row = inv_a.y1; row + max_row - 1 <= inv_a.y2; row += max_row) { + /*Calc. the next y coordinates of draw_buf*/ + sub_area.y1 = row; + sub_area.y2 = row + max_row - 1; + if(sub_area.y2 > inv_a.y2) sub_area.y2 = inv_a.y2; + row_last = sub_area.y2; + if(inv_a.y2 == row_last) disp_refr->last_part = 1; + refr_area(&sub_area); + draw_buf_flush(disp_refr); + } + + /*If the last y coordinates are not handled yet ...*/ + if(inv_a.y2 != row_last) { + /*Calc. the next y coordinates of draw_buf*/ + sub_area.y1 = row; + sub_area.y2 = inv_a.y2; + disp_refr->last_part = 1; + refr_area(&sub_area); + draw_buf_flush(disp_refr); + } + } + else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL || + disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) { + disp_refr->last_part = 1; refr_area(&disp_refr->inv_areas[i]); + draw_buf_flush(disp_refr); } } @@ -618,91 +657,106 @@ static void refr_area(const lv_area_t * area_p) LV_PROFILER_REFR_BEGIN; lv_layer_t * layer = disp_refr->layer_head; layer->draw_buf = disp_refr->buf_act; + layer->_clip_area = *area_p; + layer->phy_clip_area = *area_p; -#if LV_DRAW_TRANSFORM_USE_MATRIX - lv_matrix_identity(&layer->matrix); -#endif + if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL) { + /*In full mode the area is always the full screen, so the buffer area to it too*/ + layer->buf_area = *area_p; + layer_reshape_draw_buf(layer, layer->draw_buf->header.stride); - /*With full refresh just redraw directly into the buffer*/ - /*In direct mode draw directly on the absolute coordinates of the buffer*/ - if(disp_refr->render_mode != LV_DISPLAY_RENDER_MODE_PARTIAL) { + } + else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_PARTIAL) { + /*In partial mode render this area to the buffer*/ + layer->buf_area = *area_p; + layer_reshape_draw_buf(layer, LV_STRIDE_AUTO); + } + else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) { + /*In direct mode the the buffer area is always the whole screen*/ layer->buf_area.x1 = 0; layer->buf_area.y1 = 0; layer->buf_area.x2 = lv_display_get_horizontal_resolution(disp_refr) - 1; layer->buf_area.y2 = lv_display_get_vertical_resolution(disp_refr) - 1; - lv_area_t disp_area; - lv_area_set(&disp_area, 0, 0, lv_display_get_horizontal_resolution(disp_refr) - 1, - lv_display_get_vertical_resolution(disp_refr) - 1); + layer_reshape_draw_buf(layer, layer->draw_buf->header.stride); + } - if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL) { - disp_refr->last_part = 1; - layer_reshape_draw_buf(layer, layer->draw_buf->header.stride); - layer->_clip_area = disp_area; - layer->phy_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_reshape_draw_buf(layer, layer->draw_buf->header.stride); - layer->_clip_area = *area_p; - layer->phy_clip_area = *area_p; - refr_area_part(layer); - } + /*Try to divide the area to smaller tiles*/ + uint32_t tile_cnt = 1; + int32_t tile_h = lv_area_get_height(area_p); + if(LV_COLOR_FORMAT_IS_INDEXED(layer->color_format) == false) { + /* Assume that the the buffer size (can be screen sized or smaller in case of partial mode) + * and max tile size are the optimal scenario. From this calculate the ideal tile size + * and set the tile count and tile height accordingly. + */ + uint32_t max_tile_cnt = disp_refr->tile_cnt; + uint32_t total_buf_size = layer->draw_buf->data_size; + uint32_t ideal_tile_size = total_buf_size / max_tile_cnt; + uint32_t area_buf_size = lv_area_get_size(area_p) * lv_color_format_get_size(layer->color_format); + + tile_cnt = (area_buf_size + (ideal_tile_size - 1)) / ideal_tile_size; /*Round up*/ + tile_h = lv_area_get_height(area_p) / tile_cnt; + } + + /* Don't draw to the layers buffer of the display but create smaller dummy layers which are using the + * display's layer buffer. These will be the tiles. By using tiles it's more likely that there will + * be independent areas for each draw unit. */ + lv_layer_t * tile_layers = lv_malloc(tile_cnt * sizeof(lv_layer_t)); + LV_ASSERT_MALLOC(tile_layers); + if(tile_layers == NULL) { + disp_refr->refreshed_area = *area_p; LV_PROFILER_REFR_END; return; } + uint32_t i; + for(i = 0; i < tile_cnt; i++) { + lv_area_t tile_area; + lv_area_set(&tile_area, area_p->x1, area_p->y1 + i * tile_h, + area_p->x2, area_p->y1 + (i + 1) * tile_h - 1); - /*Normal refresh: draw the area in parts*/ - /*Calculate the max row num*/ - int32_t w = lv_area_get_width(area_p); - int32_t h = lv_area_get_height(area_p); - int32_t y2 = area_p->y2 >= lv_display_get_vertical_resolution(disp_refr) ? - lv_display_get_vertical_resolution(disp_refr) - 1 : area_p->y2; + if(i == tile_cnt - 1) { + tile_area.y2 = area_p->y2; + } - int32_t max_row = get_max_row(disp_refr, w, h); - - int32_t row; - int32_t row_last = 0; - lv_area_t sub_area; - for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) { - /*Calc. the next y coordinates of draw_buf*/ - sub_area.x1 = area_p->x1; - sub_area.x2 = area_p->x2; - sub_area.y1 = row; - sub_area.y2 = row + max_row - 1; - layer->draw_buf = disp_refr->buf_act; - layer->buf_area = sub_area; - layer->_clip_area = sub_area; - layer->phy_clip_area = sub_area; - layer_reshape_draw_buf(layer, LV_STRIDE_AUTO); - if(sub_area.y2 > y2) sub_area.y2 = y2; - row_last = sub_area.y2; - if(y2 == row_last) disp_refr->last_part = 1; - refr_area_part(layer); + lv_layer_t * tile_layer = &tile_layers[i]; + lv_draw_layer_init(tile_layer, NULL, layer->color_format, &tile_area); + tile_layer->buf_area = layer->buf_area; /*the buffer is still large*/ + tile_layer->draw_buf = layer->draw_buf; + refr_configured_layer(tile_layer); } - /*If the last y coordinates are not handled yet ...*/ - if(y2 != row_last) { - /*Calc. the next y coordinates of draw_buf*/ - sub_area.x1 = area_p->x1; - sub_area.x2 = area_p->x2; - sub_area.y1 = row; - sub_area.y2 = y2; - layer->draw_buf = disp_refr->buf_act; - layer->buf_area = sub_area; - layer->_clip_area = sub_area; - layer->phy_clip_area = sub_area; - layer_reshape_draw_buf(layer, LV_STRIDE_AUTO); - disp_refr->last_part = 1; - refr_area_part(layer); + + /*Wait until all tiles are ready and destroy remove them*/ + for(i = 0; i < tile_cnt; i++) { + lv_layer_t * tile_layer = &tile_layers[i]; + while(tile_layer->draw_task_head) { + lv_draw_dispatch_wait_for_request(); + lv_draw_dispatch(); + } + + lv_layer_t * layer_i = disp_refr->layer_head; + while(layer_i) { + if(layer_i->next == tile_layer) { + layer_i->next = tile_layer->next; + break; + } + layer_i = layer_i->next; + } + + if(disp_refr->layer_deinit) disp_refr->layer_deinit(disp_refr, tile_layer); } + lv_free(tile_layers); + + disp_refr->refreshed_area = *area_p; LV_PROFILER_REFR_END; } -static void refr_area_part(lv_layer_t * layer) +static void refr_configured_layer(lv_layer_t * layer) { LV_PROFILER_REFR_BEGIN; - disp_refr->refreshed_area = layer->_clip_area; + +#if LV_DRAW_TRANSFORM_USE_MATRIX + lv_matrix_identity(&layer->matrix); +#endif /* 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*/ @@ -711,13 +765,7 @@ static void refr_area_part(lv_layer_t * layer) } /*If the screen is transparent initialize it when the flushing is ready*/ if(lv_color_format_has_alpha(disp_refr->color_format)) { - lv_area_t a = disp_refr->refreshed_area; - if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_PARTIAL) { - /*The area always starts at 0;0*/ - lv_area_move(&a, -disp_refr->refreshed_area.x1, -disp_refr->refreshed_area.y1); - } - - lv_draw_buf_clear(layer->draw_buf, &a); + lv_draw_buf_clear(layer->draw_buf, &layer->_clip_area); } lv_obj_t * top_act_scr = NULL; @@ -759,7 +807,6 @@ static void refr_area_part(lv_layer_t * layer) refr_obj_and_children(layer, lv_display_get_layer_top(disp_refr)); refr_obj_and_children(layer, lv_display_get_layer_sys(disp_refr)); - draw_buf_flush(disp_refr); LV_PROFILER_REFR_END; } diff --git a/src/display/lv_display.c b/src/display/lv_display.c index bf933c45a..0362c59b2 100644 --- a/src/display/lv_display.c +++ b/src/display/lv_display.c @@ -77,6 +77,13 @@ lv_display_t * lv_display_create(int32_t hor_res, int32_t ver_res) disp->dpi = LV_DPI_DEF; disp->color_format = LV_COLOR_FORMAT_NATIVE; + +#if defined(LV_DRAW_SW_DRAW_UNIT_CNT) + disp->tile_cnt = LV_DRAW_SW_DRAW_UNIT_CNT; +#else + disp->tile_cnt = 1; +#endif + disp->layer_head = lv_malloc_zeroed(sizeof(lv_layer_t)); LV_ASSERT_MALLOC(disp->layer_head); if(disp->layer_head == NULL) return NULL; @@ -488,6 +495,24 @@ lv_color_format_t lv_display_get_color_format(lv_display_t * disp) return disp->color_format; } +void lv_display_set_tile_cnt(lv_display_t * disp, uint32_t tile_cnt) +{ + LV_ASSERT_FORMAT_MSG(tile_cnt < 256, "tile_cnt must be smaller than 256 (%d was used)", tile_cnt); + + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->tile_cnt = tile_cnt; +} + +uint32_t lv_display_get_tile_cnt(lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return 0; + + return disp->tile_cnt; +} + void lv_display_set_antialiasing(lv_display_t * disp, bool en) { if(disp == NULL) disp = lv_display_get_default(); diff --git a/src/display/lv_display.h b/src/display/lv_display.h index e017db11d..b1ba7ea9e 100644 --- a/src/display/lv_display.h +++ b/src/display/lv_display.h @@ -293,6 +293,20 @@ void lv_display_set_color_format(lv_display_t * disp, lv_color_format_t color_fo */ lv_color_format_t lv_display_get_color_format(lv_display_t * disp); +/** + * Set the number of tiles for parallel rendering. + * @param disp pointer to a display + * @param tile_cnt number of tiles (1 =< tile_cnt < 256) + */ +void lv_display_set_tile_cnt(lv_display_t * disp, uint32_t tile_cnt); + +/** + * Get the number of tiles used for parallel rendering + * @param disp pointer to a display + * @return number of tiles + */ +uint32_t lv_display_get_tile_cnt(lv_display_t * disp); + /** * Enable anti-aliasing for the render engine * @param disp pointer to a display diff --git a/src/display/lv_display_private.h b/src/display/lv_display_private.h index 427bea70d..d831ec486 100644 --- a/src/display/lv_display_private.h +++ b/src/display/lv_display_private.h @@ -91,6 +91,8 @@ struct _lv_display_t { lv_display_render_mode_t render_mode; uint32_t antialiasing : 1; /**< 1: anti-aliasing is enabled on this display.*/ + uint32_t tile_cnt : 8; /**< Divide the display buffer into these number of tiles */ + /** 1: The current screen rendering is in progress*/ uint32_t rendering_in_progress : 1; diff --git a/src/draw/lv_draw.c b/src/draw/lv_draw.c index 1e09d352b..1086109be 100644 --- a/src/draw/lv_draw.c +++ b/src/draw/lv_draw.c @@ -398,7 +398,6 @@ uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check) lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t color_format, const lv_area_t * area) { LV_PROFILER_DRAW_BEGIN; - lv_display_t * disp = lv_refr_get_disp_refreshing(); lv_layer_t * new_layer = lv_malloc_zeroed(sizeof(lv_layer_t)); LV_ASSERT_MALLOC(new_layer); if(new_layer == NULL) { @@ -406,29 +405,45 @@ lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t c return NULL; } - new_layer->parent = parent_layer; - new_layer->_clip_area = *area; - new_layer->buf_area = *area; - new_layer->phy_clip_area = *area; - new_layer->color_format = color_format; - -#if LV_DRAW_TRANSFORM_USE_MATRIX - lv_matrix_identity(&new_layer->matrix); -#endif - - if(disp->layer_head) { - lv_layer_t * tail = disp->layer_head; - while(tail->next) tail = tail->next; - tail->next = new_layer; - } - else { - disp->layer_head = new_layer; - } + lv_draw_layer_init(new_layer, parent_layer, color_format, area); LV_PROFILER_DRAW_END; return new_layer; } +void lv_draw_layer_init(lv_layer_t * layer, lv_layer_t * parent_layer, lv_color_format_t color_format, + const lv_area_t * area) +{ + LV_PROFILER_DRAW_BEGIN; + LV_ASSERT_NULL(layer); + lv_memzero(layer, sizeof(lv_layer_t)); + lv_display_t * disp = lv_refr_get_disp_refreshing(); + + layer->parent = parent_layer; + layer->_clip_area = *area; + layer->buf_area = *area; + layer->phy_clip_area = *area; + layer->color_format = color_format; + +#if LV_DRAW_TRANSFORM_USE_MATRIX + lv_matrix_identity(&layer->matrix); +#endif + + if(disp->layer_init) disp->layer_init(disp, layer); + + if(disp->layer_head) { + lv_layer_t * tail = disp->layer_head; + while(tail->next) tail = tail->next; + tail->next = layer; + } + else { + disp->layer_head = layer; + } + + LV_PROFILER_DRAW_END; +} + + void * lv_draw_layer_alloc_buf(lv_layer_t * layer) { /*If the buffer of the layer is already allocated return it*/ diff --git a/src/draw/lv_draw.h b/src/draw/lv_draw.h index ebd5fc0be..6f69f69d1 100644 --- a/src/draw/lv_draw.h +++ b/src/draw/lv_draw.h @@ -212,7 +212,7 @@ lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_tas uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check); /** - * Create a new layer on a parent layer + * Create (allocate) a new layer on a parent layer * @param parent_layer the parent layer to which the layer will be merged when it's rendered * @param color_format the color format of the layer * @param area the areas of the layer (absolute coordinates) @@ -220,6 +220,17 @@ uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check); */ lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t color_format, const lv_area_t * area); +/** + * Initialize a layer which is allocated by the user + * @param layer pointer the layer to initialize (its lifetime needs to be managed by the user) + * @param parent_layer the parent layer to which the layer will be merged when it's rendered + * @param color_format the color format of the layer + * @param area the areas of the layer (absolute coordinates) + * @return the new target_layer or NULL on error + */ +void lv_draw_layer_init(lv_layer_t * layer, lv_layer_t * parent_layer, lv_color_format_t color_format, + const lv_area_t * area); + /** * Try to allocate a buffer for the layer. * @param layer pointer to a layer diff --git a/src/draw/sw/lv_draw_sw.c b/src/draw/sw/lv_draw_sw.c index a7287eb8a..04bea8d11 100644 --- a/src/draw/sw/lv_draw_sw.c +++ b/src/draw/sw/lv_draw_sw.c @@ -553,14 +553,18 @@ static void execute_drawing(lv_draw_sw_unit_t * u) draw_unit_tmp = draw_unit_tmp->next; idx++; } - lv_draw_rect_dsc_t rect_dsc; - lv_draw_rect_dsc_init(&rect_dsc); - rect_dsc.bg_color = lv_palette_main(idx % LV_PALETTE_LAST); - rect_dsc.border_color = rect_dsc.bg_color; - rect_dsc.bg_opa = LV_OPA_10; - rect_dsc.border_opa = LV_OPA_80; - rect_dsc.border_width = 1; - lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area); + lv_draw_fill_dsc_t fill_dsc; + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST); + fill_dsc.opa = LV_OPA_10; + lv_draw_sw_fill((lv_draw_unit_t *)u, &fill_dsc, &draw_area); + + lv_draw_border_dsc_t border_dsc; + lv_draw_border_dsc_init(&border_dsc); + border_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST); + border_dsc.opa = LV_OPA_60; + border_dsc.width = 1; + lv_draw_sw_border((lv_draw_unit_t *)u, &border_dsc, &draw_area); lv_point_t txt_size; lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE); @@ -571,9 +575,9 @@ static void execute_drawing(lv_draw_sw_unit_t * u) txt_area.x2 = draw_area.x1 + txt_size.x - 1; txt_area.y2 = draw_area.y1 + txt_size.y - 1; - lv_draw_rect_dsc_init(&rect_dsc); - rect_dsc.bg_color = lv_color_white(); - lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area); + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.color = lv_color_white(); + lv_draw_sw_fill((lv_draw_unit_t *)u, &fill_dsc, &txt_area); char buf[8]; lv_snprintf(buf, sizeof(buf), "%d", idx); diff --git a/src/draw/sw/lv_draw_sw_img.c b/src/draw/sw/lv_draw_sw_img.c index 42179a2a2..067eca6c0 100644 --- a/src/draw/sw/lv_draw_sw_img.c +++ b/src/draw/sw/lv_draw_sw_img.c @@ -127,7 +127,7 @@ void lv_draw_sw_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dr } lv_draw_fill_dsc_t fill_dsc; - lv_draw_rect_dsc_init(&fill_dsc); + lv_draw_fill_dsc_init(&fill_dsc); fill_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST); fill_dsc.opa = LV_OPA_10; lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot); @@ -135,8 +135,8 @@ void lv_draw_sw_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dr lv_draw_border_dsc_t border_dsc; lv_draw_border_dsc_init(&border_dsc); border_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST); - border_dsc.opa = LV_OPA_100; - border_dsc.width = 2; + border_dsc.opa = LV_OPA_60; + border_dsc.width = 1; lv_draw_sw_border(draw_unit, &border_dsc, &area_rot); lv_point_t txt_size; diff --git a/src/drivers/sdl/lv_sdl_window.c b/src/drivers/sdl/lv_sdl_window.c index 143da987e..c27e5d450 100644 --- a/src/drivers/sdl/lv_sdl_window.c +++ b/src/drivers/sdl/lv_sdl_window.c @@ -132,7 +132,6 @@ lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res) lv_display_set_render_mode(disp, LV_DISPLAY_RENDER_MODE_DIRECT); #endif /*LV_USE_DRAW_SDL == 0*/ lv_display_add_event_cb(disp, res_chg_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL); - /*Process the initial events*/ sdl_event_handler(NULL);