1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

feat(draw): add layer memory allocation config support (#7038)

Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
Co-authored-by: liamHowatt <liamjmh0@gmail.com>
Co-authored-by: Liam <30486941+liamHowatt@users.noreply.github.com>
This commit is contained in:
Attila Kiss 2024-12-16 08:51:01 +01:00 committed by GitHub
parent c022f0896a
commit a7adce9d1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 48 additions and 6 deletions

View File

@ -202,6 +202,15 @@ menu "LVGL configuration"
it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks.
"Transformed layers" (if `transform_angle/zoom` are set) use larger buffers and can't be drawn in chunks.
config LV_DRAW_LAYER_MAX_MEMORY
int "The maximum amount of memory that can be used for layers"
default 0
help
Limit the max allocated memory for simple and transformed layers.
It should be at least `LV_DRAW_LAYER_SIMPLE_BUF_SIZE` sized but if transformed layers are also used
it should be enough to store the largest widget too (width x height x 4 area).
Set it to 0 to have no limit.
config LV_DRAW_THREAD_STACK_SIZE
int "Stack size of draw thread in bytes"
default 8192

View File

@ -144,6 +144,12 @@
/** The target buffer size for simple layer chunks. */
#define LV_DRAW_LAYER_SIMPLE_BUF_SIZE (24 * 1024) /**< [bytes]*/
/* Limit the max allocated memory for simple and transformed layers.
* It should be at least `LV_DRAW_LAYER_SIMPLE_BUF_SIZE` sized but if transformed layers are also used
* it should be enough to store the largest widget too (width x height x 4 area).
* Set it to 0 to have no limit. */
#define LV_DRAW_LAYER_MAX_MEMORY 0 /**< No limit by default [bytes]*/
/** Stack size of drawing thread.
* NOTE: If FreeType or ThorVG is enabled, it is recommended to set it to 32KB or more.
*/

View File

@ -36,7 +36,7 @@ static void lv_cleanup_task(lv_draw_task_t * t, lv_display_t * disp);
static inline uint32_t get_layer_size_kb(uint32_t size_byte)
{
return size_byte < 1024 ? 1 : size_byte >> 10;
return (size_byte + 1023) >> 10;
}
/**********************
@ -448,6 +448,15 @@ void * lv_draw_layer_alloc_buf(lv_layer_t * layer)
int32_t h = lv_area_get_height(&layer->buf_area);
uint32_t layer_size_byte = h * lv_draw_buf_width_to_stride(w, layer->color_format);
#if LV_DRAW_LAYER_MAX_MEMORY > 0
/* Do not allocate the layer if the sum of allocated layer sizes
* will exceed `LV_DRAW_LAYER_MAX_MEMORY` */
if((_draw_info.used_memory_for_layers + layer_size_byte) > LV_DRAW_LAYER_MAX_MEMORY) {
LV_LOG_WARN("LV_DRAW_LAYER_MAX_MEMORY was reached when allocating the layer.");
return NULL;
}
#endif
layer->draw_buf = lv_draw_buf_create(w, h, layer->color_format, 0);
if(layer->draw_buf == NULL) {
@ -456,8 +465,8 @@ void * lv_draw_layer_alloc_buf(lv_layer_t * layer)
return NULL;
}
_draw_info.used_memory_for_layers_kb += get_layer_size_kb(layer_size_byte);
LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB\n", _draw_info.used_memory_for_layers_kb);
_draw_info.used_memory_for_layers += layer_size_byte;
LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB", get_layer_size_kb(_draw_info.used_memory_for_layers));
if(lv_color_format_has_alpha(layer->color_format)) {
lv_draw_buf_clear(layer->draw_buf, NULL);
@ -535,8 +544,14 @@ static void lv_cleanup_task(lv_draw_task_t * t, lv_display_t * disp)
int32_t h = lv_area_get_height(&layer_drawn->buf_area);
uint32_t layer_size_byte = h * layer_drawn->draw_buf->header.stride;
_draw_info.used_memory_for_layers_kb -= get_layer_size_kb(layer_size_byte);
LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB\n", _draw_info.used_memory_for_layers_kb);
if(_draw_info.used_memory_for_layers >= layer_size_byte) {
_draw_info.used_memory_for_layers -= layer_size_byte;
}
else {
_draw_info.used_memory_for_layers = 0;
LV_LOG_WARN("More layers were freed than allocated");
}
LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB", get_layer_size_kb(_draw_info.used_memory_for_layers));
lv_draw_buf_destroy(layer_drawn->draw_buf);
layer_drawn->draw_buf = NULL;
}

View File

@ -178,7 +178,7 @@ struct _lv_draw_unit_t {
typedef struct {
lv_draw_unit_t * unit_head;
uint32_t unit_cnt;
uint32_t used_memory_for_layers_kb;
uint32_t used_memory_for_layers; /* measured as bytes */
#if LV_USE_OS
lv_thread_sync_t sync;
#else

View File

@ -352,6 +352,18 @@
#endif
#endif
/* Limit the max allocated memory for simple and transformed layers.
* It should be at least `LV_DRAW_LAYER_SIMPLE_BUF_SIZE` sized but if transformed layers are also used
* it should be enough to store the largest widget too (width x height x 4 area).
* Set it to 0 to have no limit. */
#ifndef LV_DRAW_LAYER_MAX_MEMORY
#ifdef CONFIG_LV_DRAW_LAYER_MAX_MEMORY
#define LV_DRAW_LAYER_MAX_MEMORY CONFIG_LV_DRAW_LAYER_MAX_MEMORY
#else
#define LV_DRAW_LAYER_MAX_MEMORY 0 /**< No limit by default [bytes]*/
#endif
#endif
/** Stack size of drawing thread.
* NOTE: If FreeType or ThorVG is enabled, it is recommended to set it to 32KB or more.
*/