/** * @file lv_image_cache.c * */ /********************* * INCLUDES *********************/ #include "../../draw/lv_image_decoder_private.h" #include "../lv_assert.h" #include "../../core/lv_global.h" #include "../../misc/lv_iter.h" #include "lv_image_cache.h" #include "lv_image_header_cache.h" /********************* * DEFINES *********************/ #define CACHE_NAME "IMAGE" #define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache) #define image_cache_draw_buf_handlers &(LV_GLOBAL_DEFAULT()->image_cache_draw_buf_handlers) /********************** * TYPEDEFS **********************/ /********************** * STATIC PROTOTYPES **********************/ static lv_cache_compare_res_t image_cache_compare_cb(const lv_image_cache_data_t * lhs, const lv_image_cache_data_t * rhs); static void image_cache_free_cb(lv_image_cache_data_t * entry, void * user_data); static void iter_inspect_cb(void * elem); /********************** * GLOBAL VARIABLES **********************/ /********************** * STATIC VARIABLES **********************/ /********************** * MACROS **********************/ /********************** * GLOBAL FUNCTIONS **********************/ lv_result_t lv_image_cache_init(uint32_t size) { if(img_cache_p != NULL) { return LV_RESULT_OK; } img_cache_p = lv_cache_create(&lv_cache_class_lru_rb_size, sizeof(lv_image_cache_data_t), size, (lv_cache_ops_t) { .compare_cb = (lv_cache_compare_cb_t) image_cache_compare_cb, .create_cb = NULL, .free_cb = (lv_cache_free_cb_t) image_cache_free_cb, }); lv_cache_set_name(img_cache_p, CACHE_NAME); return img_cache_p != NULL ? LV_RESULT_OK : LV_RESULT_INVALID; } void lv_image_cache_resize(uint32_t new_size, bool evict_now) { lv_cache_set_max_size(img_cache_p, new_size, NULL); if(evict_now) { lv_cache_reserve(img_cache_p, new_size, NULL); } } void lv_image_cache_drop(const void * src) { /*If user invalidate image, the header cache should be invalidated too.*/ lv_image_header_cache_drop(src); if(src == NULL) { lv_cache_drop_all(img_cache_p, NULL); return; } lv_image_cache_data_t search_key = { .src = src, .src_type = lv_image_src_get_type(src), }; lv_cache_drop(img_cache_p, &search_key, NULL); } bool lv_image_cache_is_enabled(void) { return lv_cache_is_enabled(img_cache_p); } lv_iter_t * lv_image_cache_iter_create(void) { return lv_cache_iter_create(img_cache_p); } void lv_image_cache_dump(void) { lv_iter_t * iter = lv_image_cache_iter_create(); if(iter == NULL) return; LV_LOG_USER("Image cache dump:"); LV_LOG_USER("\tsize\tdata_size\tcf\trc\ttype\tdecoded\t\t\tsrc"); lv_iter_inspect(iter, iter_inspect_cb); } /********************** * STATIC FUNCTIONS **********************/ inline static lv_cache_compare_res_t image_cache_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; } static lv_cache_compare_res_t image_cache_compare_cb( const lv_image_cache_data_t * lhs, const lv_image_cache_data_t * rhs) { return image_cache_common_compare(lhs->src, lhs->src_type, rhs->src, rhs->src_type); } static void image_cache_free_cb(lv_image_cache_data_t * entry, void * user_data) { LV_UNUSED(user_data); /* 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 void iter_inspect_cb(void * elem) { lv_image_cache_data_t * data = (lv_image_cache_data_t *)elem; lv_draw_buf_t * decoded = (lv_draw_buf_t *)data->decoded; lv_image_header_t * header = &decoded->header; lv_cache_entry_t * entry = lv_cache_entry_get_entry(data, img_cache_p->node_size); LV_UNUSED(decoded); LV_UNUSED(header); LV_UNUSED(entry); /* size data_size cf rc type decoded src*/ #define IMAGE_CACHE_DUMP_FORMAT " %4dx%-4d %9"LV_PRIu32" %d %"LV_PRId32" " switch(data->src_type) { case LV_IMAGE_SRC_FILE: LV_LOG_USER(IMAGE_CACHE_DUMP_FORMAT "file\t%-12p\t%s", header->w, header->h, decoded->data_size, header->cf, lv_cache_entry_get_ref(entry), (void *)data->decoded, (char *)data->src); break; case LV_IMAGE_SRC_VARIABLE: LV_LOG_USER(IMAGE_CACHE_DUMP_FORMAT "var \t%-12p\t%p", header->w, header->h, decoded->data_size, header->cf, lv_cache_entry_get_ref(entry), (void *)data->decoded, data->src); break; default: LV_LOG_USER(IMAGE_CACHE_DUMP_FORMAT "unkn\t%-12p\t%p", header->w, header->h, decoded->data_size, header->cf, lv_cache_entry_get_ref(entry), (void *)data->decoded, data->src); break; } }