mirror of
https://github.com/lvgl/lvgl.git
synced 2026-06-01 00:51:49 +08:00
feat(image_decoder): add image decoder header cache (#5420)
This commit is contained in:
@@ -271,6 +271,10 @@
|
|||||||
*If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/
|
*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
|
#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.
|
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||||
#define LV_GRADIENT_MAX_STOPS 2
|
#define LV_GRADIENT_MAX_STOPS 2
|
||||||
|
|||||||
@@ -269,6 +269,18 @@ menu "LVGL configuration"
|
|||||||
save the continuous open/decode of images.
|
save the continuous open/decode of images.
|
||||||
However the opened images might consume additional RAM.
|
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
|
config LV_GRADIENT_MAX_STOPS
|
||||||
int "Number of stops allowed per gradient."
|
int "Number of stops allowed per gradient."
|
||||||
default 2
|
default 2
|
||||||
|
|||||||
@@ -261,6 +261,10 @@
|
|||||||
*will be dropped immediately after usage.*/
|
*will be dropped immediately after usage.*/
|
||||||
#define LV_CACHE_DEF_SIZE 0
|
#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.
|
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||||
#define LV_GRADIENT_MAX_STOPS 2
|
#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.*/
|
*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
|
#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.
|
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||||
#define LV_GRADIENT_MAX_STOPS 2
|
#define LV_GRADIENT_MAX_STOPS 2
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ typedef struct _lv_global_t {
|
|||||||
lv_cache_t * img_cache;
|
lv_cache_t * img_cache;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0
|
||||||
|
lv_cache_t * img_header_cache;
|
||||||
|
#endif
|
||||||
|
|
||||||
lv_draw_global_info_t draw_info;
|
lv_draw_global_info_t draw_info;
|
||||||
#if defined(LV_DRAW_SW_SHADOW_CACHE_SIZE) && LV_DRAW_SW_SHADOW_CACHE_SIZE > 0
|
#if defined(LV_DRAW_SW_SHADOW_CACHE_SIZE) && LV_DRAW_SW_SHADOW_CACHE_SIZE > 0
|
||||||
lv_draw_sw_shadow_cache_t sw_shadow_cache;
|
lv_draw_sw_shadow_cache_t sw_shadow_cache;
|
||||||
|
|||||||
+96
-17
@@ -18,6 +18,7 @@
|
|||||||
*********************/
|
*********************/
|
||||||
#define img_decoder_ll_p &(LV_GLOBAL_DEFAULT()->img_decoder_ll)
|
#define img_decoder_ll_p &(LV_GLOBAL_DEFAULT()->img_decoder_ll)
|
||||||
#define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache)
|
#define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache)
|
||||||
|
#define img_header_cache_p (LV_GLOBAL_DEFAULT()->img_header_cache)
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* 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);
|
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
|
#if LV_CACHE_DEF_SIZE > 0
|
||||||
static lv_cache_compare_res_t image_decoder_cache_compare_cb(const lv_image_cache_data_t * lhs,
|
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);
|
const lv_image_cache_data_t * rhs);
|
||||||
@@ -70,6 +77,16 @@ void _lv_image_decoder_init(void)
|
|||||||
.create_cb = NULL,
|
.create_cb = NULL,
|
||||||
.free_cb = (lv_cache_free_cb_t)image_decoder_cache_free_cb,
|
.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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +98,10 @@ void _lv_image_decoder_deinit(void)
|
|||||||
#if LV_CACHE_DEF_SIZE > 0
|
#if LV_CACHE_DEF_SIZE > 0
|
||||||
lv_cache_destroy(img_cache_p, NULL);
|
lv_cache_destroy(img_cache_p, NULL);
|
||||||
#endif
|
#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);
|
_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;
|
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) {
|
_LV_LL_READ(img_decoder_ll_p, decoder) {
|
||||||
/*Info and Open callbacks are required*/
|
/*Info and Open callbacks are required*/
|
||||||
if(decoder->info_cb && decoder->open_cb) {
|
if(decoder->info_cb && decoder->open_cb) {
|
||||||
lv_result_t res = decoder->info_cb(decoder, src, header);
|
lv_result_t res = decoder->info_cb(decoder, src, header);
|
||||||
if(res == LV_RESULT_OK) {
|
if(res == LV_RESULT_OK) {
|
||||||
if(header->stride == 0) header->stride = img_width_to_stride(header);
|
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)
|
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
|
#if LV_CACHE_DEF_SIZE > 0
|
||||||
static lv_cache_compare_res_t image_decoder_cache_compare_cb(
|
static lv_cache_compare_res_t image_decoder_cache_compare_cb(
|
||||||
const lv_image_cache_data_t * lhs,
|
const lv_image_cache_data_t * lhs,
|
||||||
const lv_image_cache_data_t * rhs)
|
const lv_image_cache_data_t * rhs)
|
||||||
{
|
{
|
||||||
if(lhs->src_type == rhs->src_type) {
|
return image_decoder_common_compare(lhs->src, lhs->src_type, rhs->src, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void image_decoder_cache_free_cb(lv_image_cache_data_t * entry, void * user_data)
|
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;
|
void * user_data;
|
||||||
} lv_image_cache_data_t;
|
} 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*/
|
/**Describe an image decoding session. Stores data about the decoding*/
|
||||||
struct _lv_image_decoder_dsc_t {
|
struct _lv_image_decoder_dsc_t {
|
||||||
/**The decoder which was able to open the image source*/
|
/**The decoder which was able to open the image source*/
|
||||||
|
|||||||
@@ -771,6 +771,16 @@
|
|||||||
#endif
|
#endif
|
||||||
#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.
|
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||||
#ifndef LV_GRADIENT_MAX_STOPS
|
#ifndef LV_GRADIENT_MAX_STOPS
|
||||||
|
|||||||
Reference in New Issue
Block a user