diff --git a/src/draw/lv_image_decoder.c b/src/draw/lv_image_decoder.c index 15be695eda..69c655ba58 100644 --- a/src/draw/lv_image_decoder.c +++ b/src/draw/lv_image_decoder.c @@ -422,12 +422,23 @@ static lv_cache_compare_res_t image_decoder_cache_compare_cb( static void image_decoder_cache_free_cb(lv_image_cache_data_t * entry, void * user_data) { - LV_UNUSED(user_data); /*Unused*/ - const lv_image_decoder_t * decoder = entry->decoder; - if(decoder && decoder->cache_free_cb) { + if(decoder == NULL) return; /* Why ? */ + + if(decoder->cache_free_cb) { + /* Decoder wants to free the cache by itself. */ decoder->cache_free_cb(entry, user_data); } + else { + /* Destroy the decoded draw buffer if necessary. */ + lv_draw_buf_t * decoded = (lv_draw_buf_t *)entry->decoded; + if(lv_draw_buf_has_flag(decoded, LV_IMAGE_FLAGS_ALLOCATED)) { + lv_draw_buf_destroy(decoded); + } + + /*Free the duplicated file name*/ + if(entry->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)entry->src); + } } static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc) diff --git a/src/draw/lv_image_decoder.h b/src/draw/lv_image_decoder.h index 2979f08fcf..a8cd0d4d46 100644 --- a/src/draw/lv_image_decoder.h +++ b/src/draw/lv_image_decoder.h @@ -278,6 +278,15 @@ void lv_image_decoder_set_get_area_cb(lv_image_decoder_t * decoder, lv_image_dec */ void lv_image_decoder_set_close_cb(lv_image_decoder_t * decoder, lv_image_decoder_close_f_t close_cb); +/** + * Set a custom method to free cache data. + * Normally this is not needed. If the custom decoder allocates additional memory other than dsc->decoded + * draw buffer, then you need to register your own method to free it. By default the cache entry is free'ed + * in `image_decoder_cache_free_cb`. + * + * @param decoder pointer to the image decoder + * @param cache_free_cb the custom callback to free cache data. Refer to `image_decoder_cache_free_cb`. + */ void lv_image_decoder_set_cache_free_cb(lv_image_decoder_t * decoder, lv_cache_free_cb_t cache_free_cb); #if LV_CACHE_DEF_SIZE > 0 diff --git a/src/draw/vg_lite/lv_vg_lite_decoder.c b/src/draw/vg_lite/lv_vg_lite_decoder.c index e575b3970d..c28dbbecff 100644 --- a/src/draw/vg_lite/lv_vg_lite_decoder.c +++ b/src/draw/vg_lite/lv_vg_lite_decoder.c @@ -17,13 +17,6 @@ * DEFINES *********************/ -/********************** - * TYPEDEFS - **********************/ - -/* If the original image can directly satisfy the GPU requirements, there is no need to create a copy */ -#define LV_VG_LITE_IMAGE_NO_DUP LV_IMAGE_FLAGS_USER1 - /* VG_LITE_INDEX1, 2, and 4 require endian flipping + bit flipping, * so for simplicity, they are uniformly converted to I8 for display. */ @@ -35,6 +28,14 @@ #define DEST_IMG_OFFSET \ LV_VG_LITE_ALIGN(LV_COLOR_INDEXED_PALETTE_SIZE(DEST_IMG_FORMAT) * sizeof(lv_color32_t), LV_DRAW_BUF_ALIGN) +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_draw_buf_t yuv; /*A draw buffer struct for yuv variable image*/ +} decoder_data_t; + /********************** * STATIC PROTOTYPES **********************/ @@ -42,7 +43,6 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); -static void decoder_cache_free(lv_image_cache_data_t * cached_data, void * user_data); static void image_color32_pre_mul(lv_color32_t * img_data, uint32_t px_size); /********************** @@ -63,7 +63,7 @@ void lv_vg_lite_decoder_init(void) lv_image_decoder_set_info_cb(decoder, decoder_info); lv_image_decoder_set_open_cb(decoder, decoder_open); lv_image_decoder_set_close_cb(decoder, decoder_close); - lv_image_decoder_set_cache_free_cb(decoder, (lv_cache_free_cb_t)decoder_cache_free); + lv_image_decoder_set_cache_free_cb(decoder, NULL); /*Use general cache free method*/ } void lv_vg_lite_decoder_deinit(void) @@ -185,13 +185,20 @@ static lv_result_t decoder_open_variable(lv_image_decoder_t * decoder, lv_image_ /* if is YUV format, no need to copy */ if(LV_COLOR_FORMAT_IS_YUV(src_cf)) { - lv_draw_buf_t * draw_buf = lv_malloc_zeroed(sizeof(lv_draw_buf_t)); - LV_ASSERT_MALLOC(draw_buf); + decoder_data_t * decoder_data = dsc->user_data; + if(decoder_data == NULL) { + decoder_data = lv_malloc_zeroed(sizeof(decoder_data_t)); + LV_ASSERT_MALLOC(decoder_data); + } + lv_draw_buf_t * draw_buf = &decoder_data->yuv; uint32_t stride = lv_draw_buf_width_to_stride(width, src_cf); lv_draw_buf_init(draw_buf, width, height, src_cf, stride, (void *)image_data, image_data_size); - /* mark no dup */ - draw_buf->header.flags |= LV_VG_LITE_IMAGE_NO_DUP; + /* Use alloced bit to indicate we should not free the memory */ + draw_buf->header.flags &= ~LV_IMAGE_FLAGS_ALLOCATED; + + /* Do not add this kind of image to cache, since its life is managed by user. */ + dsc->args.no_cache = true; dsc->decoded = draw_buf; return LV_RESULT_OK; @@ -354,9 +361,8 @@ failed: static void decoder_draw_buf_free(lv_draw_buf_t * draw_buf) { - if(draw_buf->header.flags & LV_VG_LITE_IMAGE_NO_DUP) { - /* free draw buf struct only */ - lv_free(draw_buf); + if((draw_buf->header.flags & LV_IMAGE_FLAGS_ALLOCATED) == 0) { + /* This must be the yuv variable image. */ return; } @@ -413,16 +419,9 @@ static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * if(dsc->args.no_cache || LV_CACHE_DEF_SIZE == 0) decoder_draw_buf_free((lv_draw_buf_t *)dsc->decoded); + if(decoder->user_data) free(decoder->user_data); else lv_cache_release(dsc->cache, dsc->cache_entry, NULL); } -static void decoder_cache_free(lv_image_cache_data_t * cached_data, void * user_data) -{ - LV_UNUSED(user_data); - - if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); - decoder_draw_buf_free((lv_draw_buf_t *)cached_data->decoded); -} - #endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/src/libs/bin_decoder/lv_bin_decoder.c b/src/libs/bin_decoder/lv_bin_decoder.c index 15c9dd754a..913aab8063 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.c +++ b/src/libs/bin_decoder/lv_bin_decoder.c @@ -71,8 +71,6 @@ 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 void bin_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data); - /********************** * STATIC VARIABLES **********************/ @@ -103,7 +101,7 @@ void lv_bin_decoder_init(void) lv_image_decoder_set_open_cb(decoder, lv_bin_decoder_open); lv_image_decoder_set_get_area_cb(decoder, lv_bin_decoder_get_area); lv_image_decoder_set_close_cb(decoder, lv_bin_decoder_close); - lv_image_decoder_set_cache_free_cb(decoder, (lv_cache_free_cb_t)bin_decoder_cache_free_cb); + lv_image_decoder_set_cache_free_cb(decoder, NULL); /*Use general cache free method*/ } lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) @@ -1144,11 +1142,3 @@ 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 void bin_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data) -{ - LV_UNUSED(user_data); /*Unused*/ - - lv_draw_buf_destroy((lv_draw_buf_t *)cached_data->decoded); - if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); -} diff --git a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c index 59803323c9..4ac33bbc65 100644 --- a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c +++ b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c @@ -38,7 +38,6 @@ static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * static lv_draw_buf_t * decode_jpeg_file(const char * filename); static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height); static void error_exit(j_common_ptr cinfo); -static void jpeg_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data); /********************** * STATIC VARIABLES **********************/ @@ -60,7 +59,7 @@ void lv_libjpeg_turbo_init(void) lv_image_decoder_set_info_cb(dec, decoder_info); lv_image_decoder_set_open_cb(dec, decoder_open); lv_image_decoder_set_close_cb(dec, decoder_close); - lv_image_decoder_set_cache_free_cb(dec, (lv_cache_free_cb_t)jpeg_decoder_cache_free_cb); + lv_image_decoder_set_cache_free_cb(dec, NULL); /*Use general cache free method*/ } void lv_libjpeg_turbo_deinit(void) @@ -448,12 +447,4 @@ static void error_exit(j_common_ptr cinfo) longjmp(myerr->jb, 1); } -static void jpeg_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data) -{ - LV_UNUSED(user_data); - - if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); - lv_draw_buf_destroy((lv_draw_buf_t *)cached_data->decoded); -} - #endif /*LV_USE_LIBJPEG_TURBO*/ diff --git a/src/libs/libpng/lv_libpng.c b/src/libs/libpng/lv_libpng.c index 3e76faea70..8f539b86b1 100644 --- a/src/libs/libpng/lv_libpng.c +++ b/src/libs/libpng/lv_libpng.c @@ -28,7 +28,6 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static lv_draw_buf_t * decode_png_file(const char * filename); -static void png_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data); /********************** * STATIC VARIABLES **********************/ @@ -50,7 +49,7 @@ void lv_libpng_init(void) lv_image_decoder_set_info_cb(dec, decoder_info); lv_image_decoder_set_open_cb(dec, decoder_open); lv_image_decoder_set_close_cb(dec, decoder_close); - lv_image_decoder_set_cache_free_cb(dec, (lv_cache_free_cb_t)png_decoder_cache_free_cb); + lv_image_decoder_set_cache_free_cb(dec, NULL); /*Use general cache free method*/ } void lv_libpng_deinit(void) @@ -285,12 +284,4 @@ static lv_draw_buf_t * decode_png_file(const char * filename) return decoded; } -static void png_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data) -{ - LV_UNUSED(user_data); - - if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); - lv_draw_buf_destroy((lv_draw_buf_t *)cached_data->decoded); -} - #endif /*LV_USE_LIBPNG*/ diff --git a/src/libs/lodepng/lv_lodepng.c b/src/libs/lodepng/lv_lodepng.c index 49a1e8825f..34b3bef870 100644 --- a/src/libs/lodepng/lv_lodepng.c +++ b/src/libs/lodepng/lv_lodepng.c @@ -29,7 +29,6 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d static void decoder_close(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc); static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt); static lv_draw_buf_t * decode_png_data(const void * png_data, size_t png_data_size); -static void lodepng_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data); /********************** * STATIC VARIABLES **********************/ @@ -51,7 +50,6 @@ void lv_lodepng_init(void) lv_image_decoder_set_info_cb(dec, decoder_info); lv_image_decoder_set_open_cb(dec, decoder_open); lv_image_decoder_set_close_cb(dec, decoder_close); - lv_image_decoder_set_cache_free_cb(dec, (lv_cache_free_cb_t)lodepng_decoder_cache_free_cb); } void lv_lodepng_deinit(void) @@ -271,12 +269,4 @@ static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt) } } -static void lodepng_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data) -{ - LV_UNUSED(user_data); - - if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); - lv_draw_buf_destroy((lv_draw_buf_t *)cached_data->decoded); -} - #endif /*LV_USE_LODEPNG*/