aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Ingebrigtsen2022-04-11 15:18:41 +0200
committerLars Ingebrigtsen2022-04-11 15:18:41 +0200
commit68ec0ffa2181d7e061bc4799798be0b2344d6a6b (patch)
tree58f6ca1288394f2f26969641d1fd9244cf525068 /src
parent0347969bdfa3ec689c49537a7b29f4a506f732a2 (diff)
downloademacs-68ec0ffa2181d7e061bc4799798be0b2344d6a6b.tar.gz
emacs-68ec0ffa2181d7e061bc4799798be0b2344d6a6b.zip
Fix anim_cache garbage collection
* src/image.c (struct anim_cache): Move earlier. (mark_image_cache): Mark the Lisp_Object in the anim cache.
Diffstat (limited to 'src')
-rw-r--r--src/image.c174
1 files changed, 89 insertions, 85 deletions
diff --git a/src/image.c b/src/image.c
index 4b2a038cc14..f28eb5eb6e1 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2782,6 +2782,90 @@ cache_image (struct frame *f, struct image *img)
2782} 2782}
2783 2783
2784 2784
2785#if defined (HAVE_WEBP) || defined (HAVE_GIF)
2786
2787/* To speed animations up, we keep a cache (based on EQ-ness of the
2788 image spec/object) where we put the animator iterator. */
2789
2790struct anim_cache
2791{
2792 Lisp_Object spec;
2793 /* For webp, this will be an iterator, and for libgif, a gif handle. */
2794 void *handle;
2795 /* If we need to maintain temporary data of some sort. */
2796 void *temp;
2797 /* A function to call to free the handle. */
2798 void (*destructor) (void *);
2799 int index, width, height, frames;
2800 struct timespec update_time;
2801 struct anim_cache *next;
2802};
2803
2804static struct anim_cache *anim_cache = NULL;
2805
2806static struct anim_cache *
2807anim_create_cache (Lisp_Object spec)
2808{
2809 struct anim_cache *cache = xmalloc (sizeof (struct anim_cache));
2810 cache->handle = NULL;
2811 cache->temp = NULL;
2812
2813 cache->index = 0;
2814 cache->next = NULL;
2815 cache->spec = spec;
2816 return cache;
2817}
2818
2819/* Discard cached images that haven't been used for a minute. */
2820static void
2821anim_prune_animation_cache (void)
2822{
2823 struct anim_cache **pcache = &anim_cache;
2824 struct timespec old = timespec_sub (current_timespec (),
2825 make_timespec (60, 0));
2826
2827 while (*pcache)
2828 {
2829 struct anim_cache *cache = *pcache;
2830 if (timespec_cmp (old, cache->update_time) <= 0)
2831 pcache = &cache->next;
2832 else
2833 {
2834 if (cache->handle)
2835 cache->destructor (cache);
2836 if (cache->temp)
2837 xfree (cache->temp);
2838 *pcache = cache->next;
2839 xfree (cache);
2840 }
2841 }
2842}
2843
2844static struct anim_cache *
2845anim_get_animation_cache (Lisp_Object spec)
2846{
2847 struct anim_cache *cache;
2848 struct anim_cache **pcache = &anim_cache;
2849
2850 anim_prune_animation_cache ();
2851
2852 while (1)
2853 {
2854 cache = *pcache;
2855 if (! cache)
2856 {
2857 *pcache = cache = anim_create_cache (spec);
2858 break;
2859 }
2860 if (EQ (spec, cache->spec))
2861 break;
2862 pcache = &cache->next;
2863 }
2864
2865 cache->update_time = current_timespec ();
2866 return cache;
2867}
2868
2785/* Call FN on every image in the image cache of frame F. Used to mark 2869/* Call FN on every image in the image cache of frame F. Used to mark
2786 Lisp Objects in the image cache. */ 2870 Lisp Objects in the image cache. */
2787 2871
@@ -2808,6 +2892,11 @@ mark_image_cache (struct image_cache *c)
2808 if (c->images[i]) 2892 if (c->images[i])
2809 mark_image (c->images[i]); 2893 mark_image (c->images[i]);
2810 } 2894 }
2895
2896#if defined HAVE_WEBP || defined HAVE_GIF
2897 for (struct anim_cache *cache = anim_cache; cache; cache = cache->next)
2898 mark_object (cache->spec);
2899#endif
2811} 2900}
2812 2901
2813 2902
@@ -8433,91 +8522,6 @@ tiff_load (struct frame *f, struct image *img)
8433 8522
8434 8523
8435 8524
8436#if defined (HAVE_WEBP) || defined (HAVE_GIF)
8437
8438/* To speed animations up, we keep a cache (based on EQ-ness of the
8439 image spec/object) where we put the animator iterator. */
8440
8441struct anim_cache
8442{
8443 Lisp_Object spec;
8444 /* For webp, this will be an iterator, and for libgif, a gif handle. */
8445 void *handle;
8446 /* If we need to maintain temporary data of some sort. */
8447 void *temp;
8448 /* A function to call to free the handle. */
8449 void (*destructor)(void*);
8450 int index, width, height, frames;
8451 struct timespec update_time;
8452 struct anim_cache *next;
8453};
8454
8455static struct anim_cache *anim_cache = NULL;
8456
8457static struct anim_cache *
8458anim_create_cache (Lisp_Object spec)
8459{
8460 struct anim_cache *cache = xmalloc (sizeof (struct anim_cache));
8461 cache->handle = NULL;
8462 cache->temp = NULL;
8463
8464 cache->index = 0;
8465 cache->next = NULL;
8466 /* FIXME: Does this need gc protection? */
8467 cache->spec = spec;
8468 return cache;
8469}
8470
8471/* Discard cached images that haven't been used for a minute. */
8472static void
8473anim_prune_animation_cache (void)
8474{
8475 struct anim_cache **pcache = &anim_cache;
8476 struct timespec old = timespec_sub (current_timespec (),
8477 make_timespec (60, 0));
8478
8479 while (*pcache)
8480 {
8481 struct anim_cache *cache = *pcache;
8482 if (timespec_cmp (old, cache->update_time) <= 0)
8483 pcache = &cache->next;
8484 else
8485 {
8486 if (cache->handle)
8487 cache->destructor (cache);
8488 if (cache->temp)
8489 xfree (cache->temp);
8490 *pcache = cache->next;
8491 xfree (cache);
8492 }
8493 }
8494}
8495
8496static struct anim_cache *
8497anim_get_animation_cache (Lisp_Object spec)
8498{
8499 struct anim_cache *cache;
8500 struct anim_cache **pcache = &anim_cache;
8501
8502 anim_prune_animation_cache ();
8503
8504 while (1)
8505 {
8506 cache = *pcache;
8507 if (! cache)
8508 {
8509 *pcache = cache = anim_create_cache (spec);
8510 break;
8511 }
8512 if (EQ (spec, cache->spec))
8513 break;
8514 pcache = &cache->next;
8515 }
8516
8517 cache->update_time = current_timespec ();
8518 return cache;
8519}
8520
8521#endif /* HAVE_GIF || HAVE_WEBP */ 8525#endif /* HAVE_GIF || HAVE_WEBP */
8522 8526
8523/*********************************************************************** 8527/***********************************************************************