mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-23 09:43:41 +08:00
feat(image_decoder): add image decoder header cache (#5420)
This commit is contained in:
parent
4a60e01f8c
commit
7b68aef4ab
@ -271,6 +271,10 @@
|
||||
*If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/
|
||||
#define LV_CACHE_DEF_SIZE 0
|
||||
|
||||
/*Default number of image header cache entries. The cache is used to store the headers of images
|
||||
*The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/
|
||||
#define LV_IMAGE_HEADER_CACHE_DEF_CNT 0
|
||||
|
||||
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||
#define LV_GRADIENT_MAX_STOPS 2
|
||||
|
12
Kconfig
12
Kconfig
@ -269,6 +269,18 @@ menu "LVGL configuration"
|
||||
save the continuous open/decode of images.
|
||||
However the opened images might consume additional RAM.
|
||||
|
||||
config LV_IMAGE_HEADER_CACHE_DEF_CNT
|
||||
int "Default image header cache count. 0 to disable caching."
|
||||
default 0
|
||||
depends on LV_USE_DRAW_SW
|
||||
help
|
||||
If only the built-in image formats are used there is no real advantage of caching.
|
||||
(I.e. no new image decoder is added).
|
||||
|
||||
With complex image decoders (e.g. PNG or JPG) caching can
|
||||
save the continuous getting header information of images.
|
||||
However the records of opened images headers might consume additional RAM.
|
||||
|
||||
config LV_GRADIENT_MAX_STOPS
|
||||
int "Number of stops allowed per gradient."
|
||||
default 2
|
||||
|
@ -261,6 +261,10 @@
|
||||
*will be dropped immediately after usage.*/
|
||||
#define LV_CACHE_DEF_SIZE 0
|
||||
|
||||
/*Default number of image header cache entries. The cache is used to store the headers of images
|
||||
*The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/
|
||||
#define LV_IMAGE_HEADER_CACHE_DEF_CNT 0
|
||||
|
||||
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||
#define LV_GRADIENT_MAX_STOPS 2
|
||||
|
@ -271,6 +271,10 @@
|
||||
*If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/
|
||||
#define LV_CACHE_DEF_SIZE 0
|
||||
|
||||
/*Default number of image header cache entries. The cache is used to store the headers of images
|
||||
*The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/
|
||||
#define LV_IMAGE_HEADER_CACHE_DEF_CNT 0
|
||||
|
||||
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||
#define LV_GRADIENT_MAX_STOPS 2
|
||||
|
@ -101,6 +101,10 @@ typedef struct _lv_global_t {
|
||||
lv_cache_t * img_cache;
|
||||
#endif
|
||||
|
||||
#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0
|
||||
lv_cache_t * img_header_cache;
|
||||
#endif
|
||||
|
||||
lv_draw_global_info_t draw_info;
|
||||
#if defined(LV_DRAW_SW_SHADOW_CACHE_SIZE) && LV_DRAW_SW_SHADOW_CACHE_SIZE > 0
|
||||
lv_draw_sw_shadow_cache_t sw_shadow_cache;
|
||||
|
@ -18,6 +18,7 @@
|
||||
*********************/
|
||||
#define img_decoder_ll_p &(LV_GLOBAL_DEFAULT()->img_decoder_ll)
|
||||
#define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache)
|
||||
#define img_header_cache_p (LV_GLOBAL_DEFAULT()->img_header_cache)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@ -37,6 +38,12 @@ static uint32_t img_width_to_stride(lv_image_header_t * header);
|
||||
*/
|
||||
static lv_image_decoder_t * image_decoder_get_info(const void * src, lv_image_header_t * header);
|
||||
|
||||
#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0
|
||||
static lv_cache_compare_res_t image_decoder_header_cache_compare_cb(const lv_image_header_cache_data_t * lhs,
|
||||
const lv_image_header_cache_data_t * rhs);
|
||||
static void image_decoder_header_cache_free_cb(lv_image_header_cache_data_t * entry, void * user_data);
|
||||
#endif
|
||||
|
||||
#if LV_CACHE_DEF_SIZE > 0
|
||||
static lv_cache_compare_res_t image_decoder_cache_compare_cb(const lv_image_cache_data_t * lhs,
|
||||
const lv_image_cache_data_t * rhs);
|
||||
@ -70,6 +77,16 @@ void _lv_image_decoder_init(void)
|
||||
.create_cb = NULL,
|
||||
.free_cb = (lv_cache_free_cb_t)image_decoder_cache_free_cb,
|
||||
});
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0
|
||||
img_header_cache_p = lv_cache_create(&lv_cache_class_lru_rb_count,
|
||||
sizeof(lv_image_header_cache_data_t), LV_IMAGE_HEADER_CACHE_DEF_CNT, (lv_cache_ops_t) {
|
||||
.compare_cb = (lv_cache_compare_cb_t)image_decoder_header_cache_compare_cb,
|
||||
.create_cb = NULL,
|
||||
.free_cb = (lv_cache_free_cb_t)image_decoder_header_cache_free_cb
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -81,6 +98,10 @@ void _lv_image_decoder_deinit(void)
|
||||
#if LV_CACHE_DEF_SIZE > 0
|
||||
lv_cache_destroy(img_cache_p, NULL);
|
||||
#endif
|
||||
|
||||
#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0
|
||||
lv_cache_destroy(img_header_cache_p, NULL);
|
||||
#endif
|
||||
_lv_ll_clear(img_decoder_ll_p);
|
||||
}
|
||||
|
||||
@ -295,17 +316,51 @@ static lv_image_decoder_t * image_decoder_get_info(const void * src, lv_image_he
|
||||
}
|
||||
|
||||
lv_image_decoder_t * decoder;
|
||||
|
||||
#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0
|
||||
lv_image_header_cache_data_t search_key;
|
||||
search_key.src_type = src_type;
|
||||
search_key.src = src;
|
||||
|
||||
lv_cache_entry_t * entry = lv_cache_acquire(img_header_cache_p, &search_key, NULL);
|
||||
|
||||
if(entry) {
|
||||
lv_image_header_cache_data_t * cached_data = lv_cache_entry_get_data(entry);
|
||||
*header = cached_data->header;
|
||||
decoder = cached_data->decoder;
|
||||
lv_cache_release(img_header_cache_p, entry, NULL);
|
||||
return decoder;
|
||||
}
|
||||
#endif
|
||||
|
||||
_LV_LL_READ(img_decoder_ll_p, decoder) {
|
||||
/*Info and Open callbacks are required*/
|
||||
if(decoder->info_cb && decoder->open_cb) {
|
||||
lv_result_t res = decoder->info_cb(decoder, src, header);
|
||||
if(res == LV_RESULT_OK) {
|
||||
if(header->stride == 0) header->stride = img_width_to_stride(header);
|
||||
return decoder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0
|
||||
if(decoder) {
|
||||
if(src_type == LV_IMAGE_SRC_FILE) search_key.src = lv_strdup(src);
|
||||
search_key.decoder = decoder;
|
||||
search_key.header = *header;
|
||||
entry = lv_cache_add(img_header_cache_p, &search_key, NULL);
|
||||
|
||||
if(entry == NULL) {
|
||||
if(src_type == LV_IMAGE_SRC_FILE) lv_free((void *)search_key.src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_cache_release(img_header_cache_p, entry, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
static uint32_t img_width_to_stride(lv_image_header_t * header)
|
||||
@ -318,26 +373,50 @@ static uint32_t img_width_to_stride(lv_image_header_t * header)
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_CACHE_DEF_SIZE > 0 || LV_IMAGE_HEADER_CACHE_DEF_CNT > 0
|
||||
inline static lv_cache_compare_res_t image_decoder_common_compare(const void * lhs_src, lv_image_src_t lhs_src_type,
|
||||
const void * rhs_src, lv_image_src_t rhs_src_type)
|
||||
{
|
||||
if(lhs_src_type == rhs_src_type) {
|
||||
if(lhs_src_type == LV_IMAGE_SRC_FILE) {
|
||||
int32_t cmp_res = lv_strcmp(lhs_src, rhs_src);
|
||||
if(cmp_res != 0) {
|
||||
return cmp_res > 0 ? 1 : -1;
|
||||
}
|
||||
}
|
||||
else if(lhs_src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||
if(lhs_src != rhs_src) {
|
||||
return lhs_src > rhs_src ? 1 : -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return lhs_src_type > rhs_src_type ? 1 : -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0
|
||||
static lv_cache_compare_res_t image_decoder_header_cache_compare_cb(
|
||||
const lv_image_header_cache_data_t * lhs,
|
||||
const lv_image_header_cache_data_t * rhs)
|
||||
{
|
||||
return image_decoder_common_compare(lhs->src, lhs->src_type, rhs->src, rhs->src_type);
|
||||
}
|
||||
|
||||
static void image_decoder_header_cache_free_cb(lv_image_header_cache_data_t * entry, void * user_data)
|
||||
{
|
||||
LV_UNUSED(user_data); /*Unused*/
|
||||
|
||||
if(entry->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)entry->src);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LV_CACHE_DEF_SIZE > 0
|
||||
static lv_cache_compare_res_t image_decoder_cache_compare_cb(
|
||||
const lv_image_cache_data_t * lhs,
|
||||
const lv_image_cache_data_t * rhs)
|
||||
{
|
||||
if(lhs->src_type == rhs->src_type) {
|
||||
if(lhs->src_type == LV_IMAGE_SRC_FILE) {
|
||||
int32_t cmp_res = lv_strcmp(lhs->src, rhs->src);
|
||||
if(cmp_res != 0) {
|
||||
return cmp_res > 0 ? 1 : -1;
|
||||
}
|
||||
}
|
||||
else if(lhs->src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||
if(lhs->src != rhs->src) {
|
||||
return lhs->src > rhs->src ? 1 : -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return lhs->src_type > rhs->src_type ? 1 : -1;
|
||||
return image_decoder_common_compare(lhs->src, lhs->src_type, rhs->src, rhs->src_type);
|
||||
}
|
||||
|
||||
static void image_decoder_cache_free_cb(lv_image_cache_data_t * entry, void * user_data)
|
||||
|
@ -125,6 +125,14 @@ typedef struct _lv_image_decoder_cache_data_t {
|
||||
void * user_data;
|
||||
} lv_image_cache_data_t;
|
||||
|
||||
typedef struct _lv_image_decoder_header_cache_data_t {
|
||||
const void * src;
|
||||
lv_image_src_t src_type;
|
||||
|
||||
lv_image_header_t header;
|
||||
lv_image_decoder_t * decoder;
|
||||
} lv_image_header_cache_data_t;
|
||||
|
||||
/**Describe an image decoding session. Stores data about the decoding*/
|
||||
struct _lv_image_decoder_dsc_t {
|
||||
/**The decoder which was able to open the image source*/
|
||||
|
@ -771,6 +771,16 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Default number of image header cache entries. The cache is used to store the headers of images
|
||||
*The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/
|
||||
#ifndef LV_IMAGE_HEADER_CACHE_DEF_CNT
|
||||
#ifdef CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT
|
||||
#define LV_IMAGE_HEADER_CACHE_DEF_CNT CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT
|
||||
#else
|
||||
#define LV_IMAGE_HEADER_CACHE_DEF_CNT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||
#ifndef LV_GRADIENT_MAX_STOPS
|
||||
|
Loading…
Reference in New Issue
Block a user