1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

feat(decoder): put decoded image to cache in bin decoder (#4928)

Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
Neo Xu 2023-12-05 16:55:50 +08:00 committed by GitHub
parent 7b6f360d46
commit 668fd1cffa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -61,6 +61,9 @@ static lv_fs_res_t fs_read_file_at(lv_fs_file_t * f, uint32_t pos, void * buff,
static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image_compressed_t * compressed);
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
static void cache_invalidate_cb(lv_cache_entry_t * entry);
/**********************
* STATIC VARIABLES
**********************/
@ -160,7 +163,12 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
{
LV_UNUSED(decoder);
LV_UNUSED(args);
/*Check the cache first*/
if(try_cache(dsc) == LV_RESULT_OK) return LV_RESULT_OK;
lv_fs_res_t res = LV_RESULT_INVALID;
uint32_t t = lv_tick_get();
/*Open the file if it's a file*/
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
@ -257,8 +265,38 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
if(res != LV_RESULT_OK) {
free_decoder_data(dsc);
return res;
}
if(dsc->img_data == NULL) return LV_RESULT_OK;
/*Add it to cache*/
t = lv_tick_elaps(t);
lv_cache_lock();
lv_cache_entry_t * cache = lv_cache_add(NULL, 0, decoder->cache_data_type, dsc->header.w * dsc->header.h * 4);
if(cache == NULL) {
lv_cache_unlock();
free_decoder_data(dsc);
return LV_RESULT_INVALID;
}
cache->weight = t;
cache->data = dsc->img_data;
cache->invalidate_cb = cache_invalidate_cb;
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
cache->src = lv_strdup(dsc->src);
cache->src_type = LV_CACHE_SRC_TYPE_PATH;
}
else {
cache->src_type = LV_CACHE_SRC_TYPE_POINTER;
cache->src = dsc->src;
}
cache->user_data = dsc->user_data; /*Need to free data on cache invalidate instead of decoder_close*/
dsc->img_data = lv_cache_get_data(cache); /*@note: Must get from cache to increase reference count.*/
dsc->cache_entry = cache;
lv_cache_unlock();
return res;
}
@ -270,7 +308,10 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
void lv_bin_decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
{
LV_UNUSED(decoder); /*Unused*/
free_decoder_data(dsc);
lv_cache_lock();
lv_cache_release(dsc->cache_entry);
lv_cache_unlock();
}
lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc,
@ -891,3 +932,63 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image
decoder_data->decompressed = decompressed; /*Free on decoder close*/
return LV_RESULT_OK;
}
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
{
lv_cache_lock();
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
const char * fn = dsc->src;
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
if(cache) {
dsc->img_data = lv_cache_get_data(cache);
/**
* The img_data may not be consistent with dsc->header.cf
* For indexed image, it could be converted to ARGB8888 when enabled.
* For alpha only image, it's always converted to A8 format.
*/
if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(dsc->header.cf)) {
uint8_t bpp = lv_color_format_get_bpp(dsc->header.cf);
lv_image_header_t header;
lv_image_decoder_get_info(dsc->src, &header);
uint32_t w = (header.stride * 8) / bpp;
uint32_t buf_stride = (w * 8 + 7) >> 3; /*stride for img_data*/
dsc->header.cf = LV_COLOR_FORMAT_A8;
dsc->header.stride = buf_stride;
}
#if LV_BIN_DECODER_RAM_LOAD
else if(LV_COLOR_FORMAT_IS_INDEXED(dsc->header.cf)) {
dsc->header.stride = lv_draw_buf_width_to_stride(dsc->header.w, LV_COLOR_FORMAT_ARGB8888);
dsc->header.cf = LV_COLOR_FORMAT_ARGB8888;
}
#endif
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
lv_cache_unlock();
return LV_RESULT_OK;
}
}
else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
const lv_image_dsc_t * img_dsc = dsc->src;
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, img_dsc, LV_CACHE_SRC_TYPE_POINTER);
if(cache) {
dsc->img_data = lv_cache_get_data(cache);
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
lv_cache_unlock();
return LV_RESULT_OK;
}
}
lv_cache_unlock();
return LV_RESULT_INVALID;
}
static void cache_invalidate_cb(lv_cache_entry_t * entry)
{
lv_image_decoder_dsc_t fake = { 0 };
fake.user_data = entry->user_data;
free_decoder_data(&fake);
if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src);
}