1 /**
2 * @file lv_draw_sdl_texture_cache.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9
10 #include "../../lv_conf_internal.h"
11
12 #if LV_USE_GPU_SDL
13
14 #include "lv_draw_sdl_texture_cache.h"
15
16 #include "lv_draw_sdl_utils.h"
17
18 /*********************
19 * DEFINES
20 *********************/
21
22 /**********************
23 * TYPEDEFS
24 **********************/
25
26 typedef struct {
27 SDL_Texture * texture;
28 void * userdata;
29 lv_lru_free_t * userdata_free;
30 lv_draw_sdl_cache_flag_t flags;
31 } draw_cache_value_t;
32
33 typedef struct {
34 lv_sdl_cache_key_magic_t magic;
35 } temp_texture_key_t;
36
37 typedef struct {
38 lv_coord_t width, height;
39 } temp_texture_userdata_t;
40
41 static void draw_cache_free_value(draw_cache_value_t *);
42
43 static draw_cache_value_t * draw_cache_get_entry(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
44 bool * found);
45 /**********************
46 * STATIC VARIABLES
47 **********************/
48
49 /**********************
50 * MACROS
51 **********************/
52
53 /**********************
54 * GLOBAL FUNCTIONS
55 **********************/
56
lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx)57 void lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx)
58 {
59 ctx->internals->texture_cache = lv_lru_create(LV_GPU_SDL_LRU_SIZE, 65536,
60 (lv_lru_free_t *) draw_cache_free_value, NULL);
61 }
62
lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx)63 void lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx)
64 {
65 lv_lru_del(ctx->internals->texture_cache);
66 }
67
lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx,const void * key,size_t key_length,bool * found)68 SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, bool * found)
69 {
70 return lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_length, found, NULL);
71 }
72
lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx,const void * key,size_t key_length,bool * found,void ** userdata)73 SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
74 bool * found, void ** userdata)
75 {
76 draw_cache_value_t * value = draw_cache_get_entry(ctx, key, key_length, found);
77 if(!value) return NULL;
78 if(userdata) {
79 *userdata = value->userdata;
80 }
81 return value->texture;
82 }
83
lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx,const void * key,size_t key_length,SDL_Texture * texture)84 bool lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture)
85 {
86 return lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_length, texture, NULL, NULL, 0);
87 }
88
lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx,const void * key,size_t key_length,SDL_Texture * texture,void * userdata,void userdata_free (void *),lv_draw_sdl_cache_flag_t flags)89 bool lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
90 SDL_Texture * texture, void * userdata, void userdata_free(void *),
91 lv_draw_sdl_cache_flag_t flags)
92 {
93 lv_lru_t * lru = ctx->internals->texture_cache;
94 draw_cache_value_t * value = SDL_malloc(sizeof(draw_cache_value_t));
95 value->texture = texture;
96 value->userdata = userdata;
97 value->userdata_free = userdata_free;
98 value->flags = flags;
99 if(!texture) {
100 return lv_lru_set(lru, key, key_length, value, 1) == LV_LRU_OK;
101 }
102 if(flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED) {
103 /* Managed texture doesn't count into cache size */
104 LV_LOG_INFO("cache texture %p", texture);
105 return lv_lru_set(lru, key, key_length, value, 1) == LV_LRU_OK;
106 }
107 Uint32 format;
108 int access, width, height;
109 if(SDL_QueryTexture(texture, &format, &access, &width, &height) != 0) {
110 return false;
111 }
112 LV_LOG_INFO("cache texture %p, %d*%d@%dbpp", texture, width, height, SDL_BITSPERPIXEL(format));
113 return lv_lru_set(lru, key, key_length, value, width * height * SDL_BITSPERPIXEL(format) / 8) == LV_LRU_OK;
114 }
115
lv_draw_sdl_texture_img_key_create(const void * src,int32_t frame_id,size_t * size)116 lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id, size_t * size)
117 {
118 lv_draw_sdl_cache_key_head_img_t header;
119 /* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
120 SDL_memset(&header, 0, sizeof(header));
121 header.magic = LV_GPU_CACHE_KEY_MAGIC_IMG;
122 header.type = lv_img_src_get_type(src);
123 header.frame_id = frame_id;
124 void * key;
125 size_t key_size;
126 if(header.type == LV_IMG_SRC_FILE || header.type == LV_IMG_SRC_SYMBOL) {
127 size_t srclen = SDL_strlen(src);
128 key_size = sizeof(header) + srclen;
129 key = SDL_malloc(key_size);
130 SDL_memcpy(key, &header, sizeof(header));
131 /*Copy string content as key value*/
132 SDL_memcpy(key + sizeof(header), src, srclen);
133 }
134 else {
135 key_size = sizeof(header) + sizeof(void *);
136 key = SDL_malloc(key_size);
137 SDL_memcpy(key, &header, sizeof(header));
138 /*Copy address number as key value*/
139 SDL_memcpy(key + sizeof(header), &src, sizeof(void *));
140 }
141 *size = key_size;
142 return (lv_draw_sdl_cache_key_head_img_t *) key;
143 }
144
draw_cache_free_value(draw_cache_value_t * value)145 static void draw_cache_free_value(draw_cache_value_t * value)
146 {
147 if(value->texture && !(value->flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED)) {
148 LV_LOG_INFO("destroy texture %p", value->texture);
149 SDL_DestroyTexture(value->texture);
150 }
151 if(value->userdata_free) {
152 value->userdata_free(value->userdata);
153 }
154 SDL_free(value);
155 }
156
draw_cache_get_entry(lv_draw_sdl_ctx_t * ctx,const void * key,size_t key_length,bool * found)157 static draw_cache_value_t * draw_cache_get_entry(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
158 bool * found)
159 {
160 lv_lru_t * lru = ctx->internals->texture_cache;
161 draw_cache_value_t * value = NULL;
162 lv_lru_get(lru, key, key_length, (void **) &value);
163 if(!value) {
164 if(found) {
165 *found = false;
166 }
167 return NULL;
168 }
169 if(found) {
170 *found = true;
171 }
172 return value;
173 }
174
175 #endif /*LV_USE_GPU_SDL*/
176
177