1 /**
2 * @file lv_image_header_cache.c
3 *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 
10 #include "../../draw/lv_image_decoder_private.h"
11 #include "../lv_assert.h"
12 #include "../../core/lv_global.h"
13 
14 #include "lv_image_header_cache.h"
15 #include "../lv_iter.h"
16 
17 /*********************
18  *      DEFINES
19  *********************/
20 
21 #define CACHE_NAME  "IMAGE_HEADER"
22 
23 #define img_header_cache_p (LV_GLOBAL_DEFAULT()->img_header_cache)
24 
25 /**********************
26  *      TYPEDEFS
27  **********************/
28 
29 /**********************
30  *  STATIC PROTOTYPES
31  **********************/
32 
33 static lv_cache_compare_res_t image_header_cache_compare_cb(const lv_image_header_cache_data_t * lhs,
34                                                             const lv_image_header_cache_data_t * rhs);
35 static void image_header_cache_free_cb(lv_image_header_cache_data_t * entry, void * user_data);
36 static void iter_inspect_cb(void * elem);
37 
38 /**********************
39  *  GLOBAL VARIABLES
40  **********************/
41 
42 /**********************
43  *  STATIC VARIABLES
44  **********************/
45 
46 /**********************
47  *      MACROS
48  **********************/
49 
50 /**********************
51  *   GLOBAL FUNCTIONS
52  **********************/
53 
lv_image_header_cache_init(uint32_t count)54 lv_result_t lv_image_header_cache_init(uint32_t count)
55 {
56     if(img_header_cache_p != NULL) {
57         return LV_RESULT_OK;
58     }
59 
60     img_header_cache_p = lv_cache_create(&lv_cache_class_lru_rb_count,
61     sizeof(lv_image_header_cache_data_t), count, (lv_cache_ops_t) {
62         .compare_cb = (lv_cache_compare_cb_t) image_header_cache_compare_cb,
63         .create_cb = NULL,
64         .free_cb = (lv_cache_free_cb_t) image_header_cache_free_cb
65     });
66 
67     lv_cache_set_name(img_header_cache_p, CACHE_NAME);
68     return img_header_cache_p != NULL ? LV_RESULT_OK : LV_RESULT_INVALID;
69 }
70 
lv_image_header_cache_resize(uint32_t count,bool evict_now)71 void lv_image_header_cache_resize(uint32_t count, bool evict_now)
72 {
73     lv_cache_set_max_size(img_header_cache_p, count, NULL);
74     if(evict_now) {
75         lv_cache_reserve(img_header_cache_p, count, NULL);
76     }
77 }
78 
lv_image_header_cache_drop(const void * src)79 void lv_image_header_cache_drop(const void * src)
80 {
81     if(src == NULL) {
82         lv_cache_drop_all(img_header_cache_p, NULL);
83         return;
84     }
85 
86     lv_image_header_cache_data_t search_key = {
87         .src = src,
88         .src_type = lv_image_src_get_type(src),
89     };
90 
91     lv_cache_drop(img_header_cache_p, &search_key, NULL);
92 }
93 
lv_image_header_cache_is_enabled(void)94 bool lv_image_header_cache_is_enabled(void)
95 {
96     return lv_cache_is_enabled(img_header_cache_p);
97 }
98 
lv_image_header_cache_iter_create(void)99 lv_iter_t * lv_image_header_cache_iter_create(void)
100 {
101     return lv_cache_iter_create(img_header_cache_p);
102 }
103 
lv_image_header_cache_dump(void)104 void lv_image_header_cache_dump(void)
105 {
106     lv_iter_t * iter = lv_image_cache_iter_create();
107     if(iter == NULL) return;
108 
109     LV_LOG_USER("Image cache dump:");
110     LV_LOG_USER("\tsize\tdata_size\tcf\trc\ttype\tdecoded\t\t\tsrc");
111     lv_iter_inspect(iter, iter_inspect_cb);
112 }
113 
114 /**********************
115  *   STATIC FUNCTIONS
116  **********************/
117 
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)118 inline static lv_cache_compare_res_t image_cache_common_compare(const void * lhs_src, lv_image_src_t lhs_src_type,
119                                                                 const void * rhs_src, lv_image_src_t rhs_src_type)
120 {
121     if(lhs_src_type == rhs_src_type) {
122         if(lhs_src_type == LV_IMAGE_SRC_FILE) {
123             int32_t cmp_res = lv_strcmp(lhs_src, rhs_src);
124             if(cmp_res != 0) {
125                 return cmp_res > 0 ? 1 : -1;
126             }
127         }
128         else if(lhs_src_type == LV_IMAGE_SRC_VARIABLE) {
129             if(lhs_src != rhs_src) {
130                 return lhs_src > rhs_src ? 1 : -1;
131             }
132         }
133         return 0;
134     }
135     return lhs_src_type > rhs_src_type ? 1 : -1;
136 }
137 
image_header_cache_compare_cb(const lv_image_header_cache_data_t * lhs,const lv_image_header_cache_data_t * rhs)138 static lv_cache_compare_res_t image_header_cache_compare_cb(
139     const lv_image_header_cache_data_t * lhs,
140     const lv_image_header_cache_data_t * rhs)
141 {
142     return image_cache_common_compare(lhs->src, lhs->src_type, rhs->src, rhs->src_type);
143 }
144 
image_header_cache_free_cb(lv_image_header_cache_data_t * entry,void * user_data)145 static void image_header_cache_free_cb(lv_image_header_cache_data_t * entry, void * user_data)
146 {
147     LV_UNUSED(user_data); /*Unused*/
148 
149     if(entry->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)entry->src);
150 }
151 
iter_inspect_cb(void * elem)152 static void iter_inspect_cb(void * elem)
153 {
154     lv_image_cache_data_t * data = (lv_image_cache_data_t *)elem;
155     lv_draw_buf_t * decoded = (lv_draw_buf_t *)data->decoded;
156     lv_image_header_t * header = &decoded->header;
157     lv_cache_entry_t * entry = lv_cache_entry_get_entry(data, img_header_cache_p->node_size);
158 
159     LV_UNUSED(decoded);
160     LV_UNUSED(header);
161     LV_UNUSED(entry);
162 
163     /*  size    data_size   cf  rc  type    decoded         src*/
164 #define IMAGE_CACHE_DUMP_FORMAT "	%4dx%-4d	%9"LV_PRIu32"	%d	%" LV_PRId32 "	"
165     switch(data->src_type) {
166         case LV_IMAGE_SRC_FILE:
167             LV_LOG_USER(IMAGE_CACHE_DUMP_FORMAT "file\t%-12p\t%s", header->w, header->h, decoded->data_size, header->cf,
168                         lv_cache_entry_get_ref(entry), (void *)data->decoded, (char *)data->src);
169             break;
170         case LV_IMAGE_SRC_VARIABLE:
171             LV_LOG_USER(IMAGE_CACHE_DUMP_FORMAT "var \t%-12p\t%p", header->w, header->h, decoded->data_size, header->cf,
172                         lv_cache_entry_get_ref(entry), (void *)data->decoded, data->src);
173             break;
174         default:
175             LV_LOG_USER(IMAGE_CACHE_DUMP_FORMAT "unkn\t%-12p\t%p", header->w, header->h, decoded->data_size, header->cf,
176                         lv_cache_entry_get_ref(entry), (void *)data->decoded, data->src);
177             break;
178     }
179 }
180