mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-30 13:14:37 +08:00
feat(img_cache): add support for alternate img cache algorithm (#3798)
Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com> Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
parent
1e07853533
commit
ef62275ffb
@ -316,6 +316,42 @@ Let's say you have loaded a PNG image into a `lv_img_dsc_t my_png` variable and
|
||||
|
||||
To do this, use `lv_img_cache_invalidate_src(&my_png)`. If `NULL` is passed as a parameter, the whole cache will be cleaned.
|
||||
|
||||
### Custom cache algorithm
|
||||
If you want to implement your own cache algorithm, you can refer to the following code to replace the LVGL built-in image cache manager:
|
||||
```c
|
||||
static _lv_img_cache_entry_t * my_img_cache_open(const void * src, lv_color_t color, int32_t frame_id)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
static void my_img_cache_set_size(uint16_t new_entry_cnt)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
static void my_img_cache_invalidate_src(const void * src)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
void my_img_cache_init(void)
|
||||
{
|
||||
/* Before replacing the image cache manager,
|
||||
* you should ensure that all caches are cleared to prevent memory leaks.
|
||||
*/
|
||||
lv_img_cache_invalidate_src(NULL);
|
||||
|
||||
/*Initialize image cache manager.*/
|
||||
lv_img_cache_manager_t manager;
|
||||
lv_img_cache_manager_init(&manager);
|
||||
manager.open_cb = my_img_cache_open;
|
||||
manager.set_size_cb = my_img_cache_set_size;
|
||||
manager.invalidate_src_cb = my_img_cache_invalidate_src;
|
||||
|
||||
/*Apply image cache manager to LVGL.*/
|
||||
lv_img_cache_manager_apply(&manager);
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "lv_theme.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../draw/lv_draw.h"
|
||||
#include "../draw/lv_img_cache_builtin.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../misc/lv_timer.h"
|
||||
#include "../misc/lv_async.h"
|
||||
@ -158,9 +159,9 @@ void lv_init(void)
|
||||
_lv_refr_init();
|
||||
|
||||
_lv_img_decoder_init();
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE);
|
||||
#endif
|
||||
|
||||
_lv_img_cache_builtin_init();
|
||||
|
||||
/*Test if the IDE has UTF-8 encoding*/
|
||||
const char * txt = "Á";
|
||||
|
||||
|
@ -6,25 +6,11 @@
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "lv_img_cache.h"
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "../hal/lv_hal_tick.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Decrement life with this value on every open*/
|
||||
#define LV_IMG_CACHE_AGING 1
|
||||
|
||||
/*Boost life by this factor (multiply time_to_open with this value)*/
|
||||
#define LV_IMG_CACHE_LIFE_GAIN 1
|
||||
|
||||
/*Don't let life to be greater than this limit because it would require a lot of time to
|
||||
* "die" from very high values*/
|
||||
#define LV_IMG_CACHE_LIFE_LIMIT 1000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@ -33,16 +19,12 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static uint16_t entry_cnt;
|
||||
#endif
|
||||
|
||||
static lv_img_cache_manager_t img_cache_manager = { 0 };
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@ -52,164 +34,36 @@
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Open an image using the image decoder interface and cache it.
|
||||
* The image will be left open meaning if the image decoder open callback allocated memory then it will remain.
|
||||
* The image is closed if a new image is opened and the new image takes its place in the cache.
|
||||
* @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable
|
||||
* @param color color The color of the image with `LV_IMG_CF_ALPHA_...`
|
||||
* @return pointer to the cache entry or NULL if can open the image
|
||||
*/
|
||||
void lv_img_cache_manager_init(lv_img_cache_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_memzero(manager, sizeof(lv_img_cache_manager_t));
|
||||
}
|
||||
|
||||
void lv_img_cache_manager_apply(const lv_img_cache_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_memcpy(&img_cache_manager, manager, sizeof(lv_img_cache_manager_t));
|
||||
}
|
||||
|
||||
_lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, int32_t frame_id)
|
||||
{
|
||||
/*Is the image cached?*/
|
||||
_lv_img_cache_entry_t * cached_src = NULL;
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
if(entry_cnt == 0) {
|
||||
LV_LOG_WARN("the cache size is 0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
/*Decrement all lifes. Make the entries older*/
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(cache[i].life > INT32_MIN + LV_IMG_CACHE_AGING) {
|
||||
cache[i].life -= LV_IMG_CACHE_AGING;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(color.full == cache[i].dec_dsc.color.full &&
|
||||
frame_id == cache[i].dec_dsc.frame_id &&
|
||||
lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
/*If opened increment its life.
|
||||
*Image difficult to open should live longer to keep avoid frequent their recaching.
|
||||
*Therefore increase `life` with `time_to_open`*/
|
||||
cached_src = &cache[i];
|
||||
cached_src->life += cached_src->dec_dsc.time_to_open * LV_IMG_CACHE_LIFE_GAIN;
|
||||
if(cached_src->life > LV_IMG_CACHE_LIFE_LIMIT) cached_src->life = LV_IMG_CACHE_LIFE_LIMIT;
|
||||
LV_LOG_TRACE("image source found in the cache");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*The image is not cached then cache it now*/
|
||||
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)*/
|
||||
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 = &LV_GC_ROOT(_lv_img_cache_single);
|
||||
#endif
|
||||
/*Open the image and measure the time to open*/
|
||||
uint32_t t_start = lv_tick_get();
|
||||
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color, frame_id);
|
||||
if(open_res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw cannot open the image resource");
|
||||
lv_memzero(cached_src, sizeof(_lv_img_cache_entry_t));
|
||||
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its us*/
|
||||
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;
|
||||
LV_ASSERT_NULL(img_cache_manager.open_cb);
|
||||
return img_cache_manager.open_cb(src, color, frame_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of images to be cached.
|
||||
* More cached images mean more opened image at same time which might mean more memory usage.
|
||||
* E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache.
|
||||
* @param new_entry_cnt number of image to cache
|
||||
*/
|
||||
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) {
|
||||
/*Clean the cache before free it*/
|
||||
lv_img_cache_invalidate_src(NULL);
|
||||
lv_free(LV_GC_ROOT(_lv_img_cache_array));
|
||||
}
|
||||
|
||||
/*Reallocate the cache*/
|
||||
LV_GC_ROOT(_lv_img_cache_array) = lv_malloc(sizeof(_lv_img_cache_entry_t) * new_entry_cnt);
|
||||
LV_ASSERT_MALLOC(LV_GC_ROOT(_lv_img_cache_array));
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) == NULL) {
|
||||
entry_cnt = 0;
|
||||
return;
|
||||
}
|
||||
entry_cnt = new_entry_cnt;
|
||||
|
||||
/*Clean the cache*/
|
||||
lv_memzero(LV_GC_ROOT(_lv_img_cache_array), entry_cnt * sizeof(_lv_img_cache_entry_t));
|
||||
#endif
|
||||
LV_ASSERT_NULL(img_cache_manager.set_size_cb);
|
||||
img_cache_manager.set_size_cb(new_entry_cnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate an image source in the cache.
|
||||
* Useful if the image source is updated therefore it needs to be cached again.
|
||||
* @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable.
|
||||
*/
|
||||
void lv_img_cache_invalidate_src(const void * src)
|
||||
{
|
||||
LV_UNUSED(src);
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(src == NULL || lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
if(cache[i].dec_dsc.src != NULL) {
|
||||
lv_img_decoder_close(&cache[i].dec_dsc);
|
||||
}
|
||||
|
||||
lv_memzero(&cache[i], sizeof(_lv_img_cache_entry_t));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
LV_ASSERT_NULL(img_cache_manager.invalidate_src_cb);
|
||||
img_cache_manager.invalidate_src_cb(src);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2)
|
||||
{
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src1);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE)
|
||||
return src1 == src2;
|
||||
if(src_type != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
if(lv_img_src_get_type(src2) != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
return strcmp(src1, src2) == 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -37,10 +37,28 @@ typedef struct {
|
||||
int32_t life;
|
||||
} _lv_img_cache_entry_t;
|
||||
|
||||
typedef struct {
|
||||
_lv_img_cache_entry_t * (*open_cb)(const void * src, lv_color_t color, int32_t frame_id);
|
||||
void (*set_size_cb)(uint16_t new_entry_cnt);
|
||||
void (*invalidate_src_cb)(const void * src);
|
||||
} lv_img_cache_manager_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the img cache manager
|
||||
* @param manager Pointer to the img cache manager
|
||||
*/
|
||||
void lv_img_cache_manager_init(lv_img_cache_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Apply the img cache manager
|
||||
* @param manager Pointer to the img cache manager
|
||||
*/
|
||||
void lv_img_cache_manager_apply(const lv_img_cache_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Open an image using the image decoder interface and cache it.
|
||||
* The image will be left open meaning if the image decoder open callback allocated memory then it will remain.
|
||||
@ -58,7 +76,7 @@ _lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, i
|
||||
* E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache.
|
||||
* @param new_entry_cnt number of image to cache
|
||||
*/
|
||||
void lv_img_cache_set_size(uint16_t new_slot_num);
|
||||
void lv_img_cache_set_size(uint16_t new_entry_cnt);
|
||||
|
||||
/**
|
||||
* Invalidate an image source in the cache.
|
||||
|
235
src/draw/lv_img_cache_builtin.c
Normal file
235
src/draw/lv_img_cache_builtin.c
Normal file
@ -0,0 +1,235 @@
|
||||
/**
|
||||
* @file lv_img_cache_builtin.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img_cache.h"
|
||||
#include "lv_img_cache_builtin.h"
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "../hal/lv_hal_tick.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Decrement life with this value on every open*/
|
||||
#define LV_IMG_CACHE_AGING 1
|
||||
|
||||
/*Boost life by this factor (multiply time_to_open with this value)*/
|
||||
#define LV_IMG_CACHE_LIFE_GAIN 1
|
||||
|
||||
/*Don't let life to be greater than this limit because it would require a lot of time to
|
||||
* "die" from very high values*/
|
||||
#define LV_IMG_CACHE_LIFE_LIMIT 1000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static _lv_img_cache_entry_t * _lv_img_cache_open_builtin(const void * src, lv_color_t color, int32_t frame_id);
|
||||
static void lv_img_cache_set_size_builtin(uint16_t new_entry_cnt);
|
||||
static void lv_img_cache_invalidate_src_builtin(const void * src);
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static uint16_t entry_cnt;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_img_cache_builtin_init(void)
|
||||
{
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
lv_img_cache_set_size_builtin(LV_IMG_CACHE_DEF_SIZE);
|
||||
#endif
|
||||
|
||||
lv_img_cache_manager_t manager;
|
||||
lv_img_cache_manager_init(&manager);
|
||||
manager.open_cb = _lv_img_cache_open_builtin;
|
||||
manager.set_size_cb = lv_img_cache_set_size_builtin;
|
||||
manager.invalidate_src_cb = lv_img_cache_invalidate_src_builtin;
|
||||
lv_img_cache_manager_apply(&manager);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Open an image using the image decoder interface and cache it.
|
||||
* The image will be left open meaning if the image decoder open callback allocated memory then it will remain.
|
||||
* The image is closed if a new image is opened and the new image takes its place in the cache.
|
||||
* @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable
|
||||
* @param color color The color of the image with `LV_IMG_CF_ALPHA_...`
|
||||
* @return pointer to the cache entry or NULL if can open the image
|
||||
*/
|
||||
static _lv_img_cache_entry_t * _lv_img_cache_open_builtin(const void * src, lv_color_t color, int32_t frame_id)
|
||||
{
|
||||
/*Is the image cached?*/
|
||||
_lv_img_cache_entry_t * cached_src = NULL;
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
if(entry_cnt == 0) {
|
||||
LV_LOG_WARN("the cache size is 0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
/*Decrement all lifes. Make the entries older*/
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(cache[i].life > INT32_MIN + LV_IMG_CACHE_AGING) {
|
||||
cache[i].life -= LV_IMG_CACHE_AGING;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(color.full == cache[i].dec_dsc.color.full &&
|
||||
frame_id == cache[i].dec_dsc.frame_id &&
|
||||
lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
/*If opened increment its life.
|
||||
*Image difficult to open should live longer to keep avoid frequent their recaching.
|
||||
*Therefore increase `life` with `time_to_open`*/
|
||||
cached_src = &cache[i];
|
||||
cached_src->life += cached_src->dec_dsc.time_to_open * LV_IMG_CACHE_LIFE_GAIN;
|
||||
if(cached_src->life > LV_IMG_CACHE_LIFE_LIMIT) cached_src->life = LV_IMG_CACHE_LIFE_LIMIT;
|
||||
LV_LOG_TRACE("image source found in the cache");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*The image is not cached then cache it now*/
|
||||
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)*/
|
||||
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 = &LV_GC_ROOT(_lv_img_cache_single);
|
||||
#endif
|
||||
/*Open the image and measure the time to open*/
|
||||
uint32_t t_start = lv_tick_get();
|
||||
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color, frame_id);
|
||||
if(open_res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw cannot open the image resource");
|
||||
lv_memzero(cached_src, sizeof(_lv_img_cache_entry_t));
|
||||
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its us*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of images to be cached.
|
||||
* More cached images mean more opened image at same time which might mean more memory usage.
|
||||
* E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache.
|
||||
* @param new_entry_cnt number of image to cache
|
||||
*/
|
||||
static void lv_img_cache_set_size_builtin(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) {
|
||||
/*Clean the cache before free it*/
|
||||
lv_img_cache_invalidate_src_builtin(NULL);
|
||||
lv_free(LV_GC_ROOT(_lv_img_cache_array));
|
||||
}
|
||||
|
||||
/*Reallocate the cache*/
|
||||
LV_GC_ROOT(_lv_img_cache_array) = lv_malloc(sizeof(_lv_img_cache_entry_t) * new_entry_cnt);
|
||||
LV_ASSERT_MALLOC(LV_GC_ROOT(_lv_img_cache_array));
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) == NULL) {
|
||||
entry_cnt = 0;
|
||||
return;
|
||||
}
|
||||
entry_cnt = new_entry_cnt;
|
||||
|
||||
/*Clean the cache*/
|
||||
lv_memzero(LV_GC_ROOT(_lv_img_cache_array), entry_cnt * sizeof(_lv_img_cache_entry_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate an image source in the cache.
|
||||
* Useful if the image source is updated therefore it needs to be cached again.
|
||||
* @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable.
|
||||
*/
|
||||
static void lv_img_cache_invalidate_src_builtin(const void * src)
|
||||
{
|
||||
LV_UNUSED(src);
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(src == NULL || lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
if(cache[i].dec_dsc.src != NULL) {
|
||||
lv_img_decoder_close(&cache[i].dec_dsc);
|
||||
}
|
||||
|
||||
lv_memzero(&cache[i], sizeof(_lv_img_cache_entry_t));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2)
|
||||
{
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src1);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE)
|
||||
return src1 == src2;
|
||||
if(src_type != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
if(lv_img_src_get_type(src2) != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
return strcmp(src1, src2) == 0;
|
||||
}
|
||||
#endif
|
39
src/draw/lv_img_cache_builtin.h
Normal file
39
src/draw/lv_img_cache_builtin.h
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @file lv_img_cache_builtin.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_CACHE_BUILTIN_H
|
||||
#define LV_IMG_CACHE_BUILTIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void _lv_img_cache_builtin_init(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMG_CACHE_BUILTIN_H*/
|
Loading…
Reference in New Issue
Block a user