feat(img_cache): allow disabling image cacheing

related to #1954
This commit is contained in:
Gabor Kiss-Vamosi
2020-12-10 11:14:22 +01:00
parent 861f07bb77
commit 5fc66822b9
5 changed files with 79 additions and 52 deletions

View File

@@ -4,6 +4,7 @@
### New features ### New features
- feat(chart) add lv_chart_remove_series and lv_chart_hide_series - feat(chart) add lv_chart_remove_series and lv_chart_hide_series
- feat(img_cahce) allow disabling image cacheing
### Bugfixes ### Bugfixes

View File

@@ -240,7 +240,7 @@ typedef void * lv_fs_drv_user_data_t;
* (I.e. no new image decoder is added) * (I.e. no new image decoder is added)
* With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. * With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
* However the opened images might consume additional RAM. * However the opened images might consume additional RAM.
* LV_IMG_CACHE_DEF_SIZE must be >= 1 */ * Set it to 0 to disable caching */
#define LV_IMG_CACHE_DEF_SIZE 1 #define LV_IMG_CACHE_DEF_SIZE 1
/*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/ /*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/

View File

@@ -221,8 +221,9 @@ void lv_init(void)
_lv_indev_init(); _lv_indev_init();
_lv_img_decoder_init(); _lv_img_decoder_init();
#if LV_IMG_CACHE_DEF_SIZE
lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE); lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE);
#endif
/*Test if the IDE has UTF-8 encoding*/ /*Test if the IDE has UTF-8 encoding*/
char * txt = "Á"; char * txt = "Á";

View File

@@ -40,6 +40,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const
bool chroma_key, bool alpha_byte); bool chroma_key, bool alpha_byte);
static void show_error(const lv_area_t * coords, const lv_area_t * clip_area, const char * msg); static void show_error(const lv_area_t * coords, const lv_area_t * clip_area, const char * msg);
static void draw_cleanup(lv_img_cache_entry_t * cache);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@@ -267,9 +268,10 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords,
lv_area_t mask_com; /*Common area of mask and coords*/ lv_area_t mask_com; /*Common area of mask and coords*/
bool union_ok; bool union_ok;
union_ok = _lv_area_intersect(&mask_com, clip_area, &map_area_rot); union_ok = _lv_area_intersect(&mask_com, clip_area, &map_area_rot);
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
if(union_ok == false) { if(union_ok == false) {
return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn draw_cleanup(cdsc);
successfully.*/ return LV_RES_OK;
} }
lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, draw_dsc, chroma_keyed, alpha_byte); lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, draw_dsc, chroma_keyed, alpha_byte);
@@ -279,9 +281,10 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords,
lv_area_t mask_com; /*Common area of mask and coords*/ lv_area_t mask_com; /*Common area of mask and coords*/
bool union_ok; bool union_ok;
union_ok = _lv_area_intersect(&mask_com, clip_area, coords); union_ok = _lv_area_intersect(&mask_com, clip_area, coords);
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
if(union_ok == false) { if(union_ok == false) {
return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn draw_cleanup(cdsc);
successfully.*/ return LV_RES_OK;
} }
int32_t width = lv_area_get_width(&mask_com); int32_t width = lv_area_get_width(&mask_com);
@@ -306,6 +309,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords,
lv_img_decoder_close(&cdsc->dec_dsc); lv_img_decoder_close(&cdsc->dec_dsc);
LV_LOG_WARN("Image draw can't read the line"); LV_LOG_WARN("Image draw can't read the line");
_lv_mem_buf_release(buf); _lv_mem_buf_release(buf);
draw_cleanup(cdsc);
return LV_RES_INV; return LV_RES_INV;
} }
@@ -318,6 +322,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords,
_lv_mem_buf_release(buf); _lv_mem_buf_release(buf);
} }
draw_cleanup(cdsc);
return LV_RES_OK; return LV_RES_OK;
} }
@@ -649,3 +654,11 @@ static void show_error(const lv_area_t * coords, const lv_area_t * clip_area, co
lv_draw_label(coords, clip_area, &label_dsc, msg, NULL); lv_draw_label(coords, clip_area, &label_dsc, msg, NULL);
} }
static void draw_cleanup(lv_img_cache_entry_t * cache)
{
/*Automatically close images with no caching*/
#if LV_IMG_CACHE_DEF_SIZE == 0
lv_img_decoder_close(&cache->dec_dsc);
#endif
}

View File

@@ -19,7 +19,7 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
/*Decrement life with this value in every open*/ /*Decrement life with this value on every open*/
#define LV_IMG_CACHE_AGING 1 #define LV_IMG_CACHE_AGING 1
/*Boost life by this factor (multiply time_to_open with this value)*/ /*Boost life by this factor (multiply time_to_open with this value)*/
@@ -29,10 +29,6 @@
* "die" from very high values */ * "die" from very high values */
#define LV_IMG_CACHE_LIFE_LIMIT 1000 #define LV_IMG_CACHE_LIFE_LIMIT 1000
#if LV_IMG_CACHE_DEF_SIZE < 1
#error "LV_IMG_CACHE_DEF_SIZE must be >= 1. See lv_conf.h"
#endif
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@@ -40,11 +36,16 @@
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
#if LV_IMG_CACHE_DEF_SIZE == 0
static lv_img_cache_entry_t cache_temp;
#endif
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
#if LV_IMG_CACHE_DEF_SIZE
static uint16_t entry_cnt; static uint16_t entry_cnt;
#endif
/********************** /**********************
* MACROS * MACROS
@@ -64,6 +65,10 @@ static uint16_t entry_cnt;
*/ */
lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color) lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color)
{ {
/*Is the image cached?*/
lv_img_cache_entry_t * cached_src = NULL;
#if LV_IMG_CACHE_DEF_SIZE
if(entry_cnt == 0) { if(entry_cnt == 0) {
LV_LOG_WARN("lv_img_cache_open: the cache size is 0"); LV_LOG_WARN("lv_img_cache_open: the cache size is 0");
return NULL; return NULL;
@@ -79,8 +84,6 @@ lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color)
} }
} }
/*Is the image cached?*/
lv_img_cache_entry_t * cached_src = NULL;
for(i = 0; i < entry_cnt; i++) { for(i = 0; i < entry_cnt; i++) {
bool match = false; bool match = false;
lv_img_src_t src_type = lv_img_src_get_type(cache[i].dec_dsc.src); lv_img_src_t src_type = lv_img_src_get_type(cache[i].dec_dsc.src);
@@ -104,48 +107,51 @@ lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color)
} }
/*The image is not cached then cache it now*/ /*The image is not cached then cache it now*/
if(cached_src == NULL) { if(cached_src) return cached_src;
/*Find an entry to reuse. Select the entry with the least life*/
cached_src = &cache[0];
for(i = 1; i < entry_cnt; i++) {
if(cache[i].life < cached_src->life) {
cached_src = &cache[i];
}
}
/*Close the decoder to reuse if it was opened (has a valid source)*/ /*Find an entry to reuse. Select the entry with the least life*/
if(cached_src->dec_dsc.src) { cached_src = &cache[0];
lv_img_decoder_close(&cached_src->dec_dsc); for(i = 1; i < entry_cnt; i++) {
LV_LOG_INFO("image draw: cache miss, close and reuse an entry"); if(cache[i].life < cached_src->life) {
cached_src = &cache[i];
} }
else {
LV_LOG_INFO("image draw: cache miss, cached to an empty entry");
}
/*Open the image and measure the time to open*/
uint32_t t_start;
t_start = lv_tick_get();
cached_src->dec_dsc.time_to_open = 0;
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color);
if(open_res == LV_RES_INV) {
LV_LOG_WARN("Image draw cannot open the image resource");
lv_img_decoder_close(&cached_src->dec_dsc);
_lv_memset_00(&cached_src->dec_dsc, sizeof(lv_img_decoder_dsc_t));
_lv_memset_00(cached_src, sizeof(lv_img_cache_entry_t));
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its use */
return NULL;
}
cached_src->life = 0;
/*If `time_to_open` was not set in the open function set it here*/
if(cached_src->dec_dsc.time_to_open == 0) {
cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start);
}
if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1;
} }
/*Close the decoder to reuse if it was opened (has a valid source)*/
if(cached_src->dec_dsc.src) {
lv_img_decoder_close(&cached_src->dec_dsc);
LV_LOG_INFO("image draw: cache miss, close and reuse an entry");
}
else {
LV_LOG_INFO("image draw: cache miss, cached to an empty entry");
}
#else
cached_src = &cache_temp;
#endif
/*Open the image and measure the time to open*/
uint32_t t_start;
t_start = lv_tick_get();
cached_src->dec_dsc.time_to_open = 0;
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color);
if(open_res == LV_RES_INV) {
LV_LOG_WARN("Image draw cannot open the image resource");
lv_img_decoder_close(&cached_src->dec_dsc);
_lv_memset_00(&cached_src->dec_dsc, sizeof(lv_img_decoder_dsc_t));
_lv_memset_00(cached_src, sizeof(lv_img_cache_entry_t));
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its use */
return NULL;
}
cached_src->life = 0;
/*If `time_to_open` was not set in the open function set it here*/
if(cached_src->dec_dsc.time_to_open == 0) {
cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start);
}
if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1;
return cached_src; return cached_src;
} }
@@ -157,6 +163,10 @@ lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color)
*/ */
void lv_img_cache_set_size(uint16_t new_entry_cnt) void lv_img_cache_set_size(uint16_t new_entry_cnt)
{ {
#if LV_IMG_CACHE_DEF_SIZE == 0
LV_UNUSED(new_entry_cnt);
LV_LOG_WARN("Can't change cache size because it's disabled by LV_IMG_CACHE_DEF_SIZE = 0");
#else
if(LV_GC_ROOT(_lv_img_cache_array) != NULL) { if(LV_GC_ROOT(_lv_img_cache_array) != NULL) {
/*Clean the cache before free it*/ /*Clean the cache before free it*/
lv_img_cache_invalidate_src(NULL); lv_img_cache_invalidate_src(NULL);
@@ -178,6 +188,7 @@ void lv_img_cache_set_size(uint16_t new_entry_cnt)
_lv_memset_00(&LV_GC_ROOT(_lv_img_cache_array)[i].dec_dsc, sizeof(lv_img_decoder_dsc_t)); _lv_memset_00(&LV_GC_ROOT(_lv_img_cache_array)[i].dec_dsc, sizeof(lv_img_decoder_dsc_t));
_lv_memset_00(&LV_GC_ROOT(_lv_img_cache_array)[i], sizeof(lv_img_cache_entry_t)); _lv_memset_00(&LV_GC_ROOT(_lv_img_cache_array)[i], sizeof(lv_img_cache_entry_t));
} }
#endif
} }
/** /**
@@ -187,7 +198,7 @@ void lv_img_cache_set_size(uint16_t new_entry_cnt)
*/ */
void lv_img_cache_invalidate_src(const void * src) void lv_img_cache_invalidate_src(const void * src)
{ {
#if LV_IMG_CACHE_DEF_SIZE
lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array); lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
uint16_t i; uint16_t i;
@@ -201,6 +212,7 @@ void lv_img_cache_invalidate_src(const void * src)
_lv_memset_00(&cache[i], sizeof(lv_img_cache_entry_t)); _lv_memset_00(&cache[i], sizeof(lv_img_cache_entry_t));
} }
} }
#endif
} }
/********************** /**********************