summaryrefslogtreecommitdiff
path: root/src/lib/evas/vg/evas_vg_cache.c
diff options
context:
space:
mode:
authorHermet Park <hermetpark@gmail.com>2018-12-07 18:42:45 +0900
committerHermet Park <hermetpark@gmail.com>2018-12-07 19:08:34 +0900
commit950059ce9a85b070a094d7e17ad43c27dd52065e (patch)
treefd57d967712b92b83fb2ded223a0677c44532459 /src/lib/evas/vg/evas_vg_cache.c
parent072f5a2fa0ec6d714de03a983a24330bfbf856a7 (diff)
evas vg: revise basic vg cache logic.
There was a big trouble that vg cache didn't free cached data properly. Plus, there was a unnecessary copy of vg tree data. This revised version is a improvement of our evas vg cache in stable and optmization.
Diffstat (limited to 'src/lib/evas/vg/evas_vg_cache.c')
-rw-r--r--src/lib/evas/vg/evas_vg_cache.c195
1 files changed, 119 insertions, 76 deletions
diff --git a/src/lib/evas/vg/evas_vg_cache.c b/src/lib/evas/vg/evas_vg_cache.c
index 49c8fd3ee4..ec5fc6b0be 100644
--- a/src/lib/evas/vg/evas_vg_cache.c
+++ b/src/lib/evas/vg/evas_vg_cache.c
@@ -69,7 +69,7 @@ _find_loader_module(const char *file)
69 return em; 69 return em;
70} 70}
71 71
72Vg_File_Data * 72static Vg_File_Data *
73_vg_load_from_file(const char *file, const char *key) 73_vg_load_from_file(const char *file, const char *key)
74{ 74{
75 Evas_Module *em; 75 Evas_Module *em;
@@ -136,9 +136,8 @@ _find_saver_module(const char *file)
136static void 136static void
137_evas_cache_vg_data_free_cb(void *data) 137_evas_cache_vg_data_free_cb(void *data)
138{ 138{
139 Vg_File_Data *val = data; 139 Vg_File_Data *vfd = data;
140 efl_unref(val->root); 140 vfd->loader->file_close(vfd);
141 free(val);
142} 141}
143 142
144static void 143static void
@@ -146,7 +145,21 @@ _evas_cache_vg_entry_free_cb(void *data)
146{ 145{
147 Vg_Cache_Entry *vg_entry = data; 146 Vg_Cache_Entry *vg_entry = data;
148 147
149 eina_stringshare_del(vg_entry->file); 148 if (vg_entry->vfd)
149 {
150 vg_entry->vfd->ref--;
151 if (vg_entry->vfd->ref <= 0)
152 {
153 Eina_Strbuf *hash_key = eina_strbuf_new();
154 eina_strbuf_append_printf(hash_key, "%s/%s",
155 vg_entry->file,
156 vg_entry->key);
157 if (!eina_hash_del(vg_cache->vfd_hash, eina_strbuf_string_get(hash_key), vg_entry->vfd))
158 ERR("Failed to delete vfd = (%p) from hash", vg_entry->vfd);
159 eina_strbuf_free(hash_key);
160 }
161 }
162
150 eina_stringshare_del(vg_entry->key); 163 eina_stringshare_del(vg_entry->key);
151 free(vg_entry->hash_key); 164 free(vg_entry->hash_key);
152 efl_unref(vg_entry->root); 165 efl_unref(vg_entry->root);
@@ -194,6 +207,65 @@ _vg_file_save(Vg_File_Data *vfd, const char *file, const char *key, const char *
194 return EINA_TRUE; 207 return EINA_TRUE;
195} 208}
196 209
210static Efl_VG*
211_cached_root_get(Vg_Cache_Entry *vg_entry)
212{
213 return vg_entry->root;
214}
215
216static void
217_caching_root_update(Vg_Cache_Entry *vg_entry)
218{
219 Vg_File_Data *vfd = vg_entry->vfd;
220
221 /* Optimization: static viewbox may have same root data regardless of size.
222 So we can't use the root data directly, but copy it for each vg_entries.
223 In the meantime, non-static viewbox root data may have difference instance for each
224 size. So it's affordable to share the root data for each vg_entries. */
225 if (vfd->static_viewbox)
226 {
227 /* TODO: Yet trivial but still we may have a better solution to
228 avoid this unnecessary copy. If the ector surface key is not
229 to this root pointer. */
230 vg_entry->root = efl_duplicate(vfd->root);
231 }
232 else if (vg_entry->root != vfd->root)
233 {
234 if (vg_entry->root) efl_unref(vg_entry->root);
235 vg_entry->root = efl_ref(vfd->root);
236 }
237}
238
239static void
240_local_transform(Efl_VG *root, double w, double h, Vg_File_Data *vfd)
241{
242 double sx = 0, sy= 0, scale;
243 Eina_Matrix3 m;
244
245 if (!vfd->static_viewbox) return;
246 if (vfd->view_box.w == w && vfd->view_box.h == h) return;
247
248 sx = w / vfd->view_box.w;
249 sy = h / vfd->view_box.h;
250
251 scale = sx < sy ? sx : sy;
252 eina_matrix3_identity(&m);
253
254 // align hcenter and vcenter
255 if (vfd->preserve_aspect)
256 {
257 eina_matrix3_translate(&m, (w - vfd->view_box.w * scale)/2.0, (h - vfd->view_box.h * scale)/2.0);
258 eina_matrix3_scale(&m, scale, scale);
259 eina_matrix3_translate(&m, -vfd->view_box.x, -vfd->view_box.y);
260 }
261 else
262 {
263 eina_matrix3_scale(&m, sx, sy);
264 eina_matrix3_translate(&m, -vfd->view_box.x, -vfd->view_box.y);
265 }
266 efl_canvas_vg_node_transformation_set(root, &m);
267}
268
197void 269void
198evas_cache_vg_init(void) 270evas_cache_vg_init(void)
199{ 271{
@@ -245,82 +317,26 @@ evas_cache_vg_file_open(const char *file, const char *key)
245 return vfd; 317 return vfd;
246} 318}
247 319
248static void 320Vg_Cache_Entry*
249_local_transformation(Efl_VG *root, double w, double h, Vg_File_Data *vfd) 321evas_cache_vg_entry_resize(Vg_Cache_Entry *vg_entry, int w, int h)
250{
251 double sx = 0, sy= 0, scale;
252 Eina_Matrix3 m;
253
254 if (vfd->view_box.w)
255 sx = w/vfd->view_box.w;
256 if (vfd->view_box.h)
257 sy = h/vfd->view_box.h;
258
259 scale = sx < sy ? sx: sy;
260 eina_matrix3_identity(&m);
261
262 // allign hcenter and vcenter
263 if (vfd->preserve_aspect)
264 {
265 eina_matrix3_translate(&m, (w - vfd->view_box.w * scale)/2.0, (h - vfd->view_box.h * scale)/2.0);
266 eina_matrix3_scale(&m, scale, scale);
267 eina_matrix3_translate(&m, -vfd->view_box.x, -vfd->view_box.y);
268 }
269 else
270 {
271 eina_matrix3_scale(&m, sx, sy);
272 eina_matrix3_translate(&m, -vfd->view_box.x, -vfd->view_box.y);
273 }
274 efl_canvas_vg_node_transformation_set(root, &m);
275}
276
277static Efl_VG *
278_evas_vg_dup_vg_tree(Vg_File_Data *vfd, double w, double h)
279{
280 Efl_VG *root;
281
282 if (!vfd) return NULL;
283 if (w < 1 || h < 1) return NULL;
284
285 root = efl_duplicate(vfd->root);
286 _local_transformation(root, w, h, vfd);
287
288 return root;
289}
290
291static void
292_evas_cache_vg_tree_update(Vg_Cache_Entry *vg_entry)
293{ 322{
294 Vg_File_Data *vfd = NULL; 323 return evas_cache_vg_entry_create(vg_entry->file, vg_entry->key, w, h);
295 if(!vg_entry) return;
296
297 if (!vg_entry->file)
298 {
299 vg_entry->root = NULL;
300 return;
301 }
302
303 vfd = evas_cache_vg_file_open(vg_entry->file, vg_entry->key);
304
305 vg_entry->root = _evas_vg_dup_vg_tree(vfd, vg_entry->w, vg_entry->h);
306 eina_stringshare_del(vg_entry->file);
307 eina_stringshare_del(vg_entry->key);
308 vg_entry->file = NULL;
309 vg_entry->key = NULL;
310} 324}
311 325
312Vg_Cache_Entry* 326Vg_Cache_Entry*
313evas_cache_vg_entry_find(const char *file, const char *key, 327evas_cache_vg_entry_create(const char *file,
314 int w, int h) 328 const char *key,
329 int w, int h)
315{ 330{
316 Vg_Cache_Entry* vg_entry; 331 Vg_Cache_Entry* vg_entry;
317 Eina_Strbuf *hash_key; 332 Eina_Strbuf *hash_key;
318 333
319 if (!vg_cache) return NULL; 334 if (!vg_cache) return NULL;
320 335
336 //TODO: zero-sized entry is useless. how to skip it?
337
321 hash_key = eina_strbuf_new(); 338 hash_key = eina_strbuf_new();
322 eina_strbuf_append_printf(hash_key, "%s/%s/%d/%d", 339 eina_strbuf_append_printf(hash_key, "%s/%s/%d/%d", file, key, w, h);
323 file, key, w, h);
324 vg_entry = eina_hash_find(vg_cache->vg_entry_hash, eina_strbuf_string_get(hash_key)); 340 vg_entry = eina_hash_find(vg_cache->vg_entry_hash, eina_strbuf_string_get(hash_key));
325 if (!vg_entry) 341 if (!vg_entry)
326 { 342 {
@@ -340,16 +356,42 @@ evas_cache_vg_entry_find(const char *file, const char *key,
340 } 356 }
341 eina_strbuf_free(hash_key); 357 eina_strbuf_free(hash_key);
342 vg_entry->ref++; 358 vg_entry->ref++;
359
360 vg_entry->vfd = evas_cache_vg_file_open(file, key);
361 //No File??
362 if (!vg_entry->vfd)
363 {
364 evas_cache_vg_entry_del(vg_entry);
365 return NULL;
366 }
367 vg_entry->vfd->ref++;
368
343 return vg_entry; 369 return vg_entry;
344} 370}
345 371
346Efl_VG* 372Efl_VG*
347evas_cache_vg_tree_get(Vg_Cache_Entry *vg_entry) 373evas_cache_vg_tree_get(Vg_Cache_Entry *vg_entry)
348{ 374{
349 if (vg_entry->root) return vg_entry->root; 375 if (!vg_entry) return NULL;
376 if ((vg_entry->w < 1) || (vg_entry->h < 1)) return NULL;
377
378 Vg_File_Data *vfd = vg_entry->vfd;
379 if (!vfd) return NULL;
350 380
351 if (vg_entry->file) 381 Efl_VG *root = _cached_root_get(vg_entry);
352 _evas_cache_vg_tree_update(vg_entry); 382 if (root) return root;
383
384 if (!vfd->static_viewbox)
385 {
386 vfd->view_box.w = vg_entry->w;
387 vfd->view_box.h = vg_entry->h;
388 }
389
390 if (!vfd->loader->file_data(vfd)) return NULL;
391
392 _caching_root_update(vg_entry);
393
394 _local_transform(vg_entry->root, vg_entry->w, vg_entry->h, vfd);
353 395
354 return vg_entry->root; 396 return vg_entry->root;
355} 397}
@@ -357,10 +399,11 @@ evas_cache_vg_tree_get(Vg_Cache_Entry *vg_entry)
357void 399void
358evas_cache_vg_entry_del(Vg_Cache_Entry *vg_entry) 400evas_cache_vg_entry_del(Vg_Cache_Entry *vg_entry)
359{ 401{
360 if (!vg_entry) return; 402 if (!vg_cache || !vg_entry) return;
361
362 vg_entry->ref--; 403 vg_entry->ref--;
363 // FIXME implement delete logic (LRU) 404 if (vg_entry->ref > 0) return;
405 if (!eina_hash_del(vg_cache->vg_entry_hash, vg_entry->hash_key, vg_entry))
406 ERR("Failed to delete vg_entry = (%p) from hash", vg_entry);
364} 407}
365 408
366Eina_Bool 409Eina_Bool