diff options
| author | Lars Ingebrigtsen | 2022-04-11 15:18:41 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-04-11 15:18:41 +0200 |
| commit | 68ec0ffa2181d7e061bc4799798be0b2344d6a6b (patch) | |
| tree | 58f6ca1288394f2f26969641d1fd9244cf525068 /src | |
| parent | 0347969bdfa3ec689c49537a7b29f4a506f732a2 (diff) | |
| download | emacs-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.c | 174 |
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 | |||
| 2790 | struct 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 | |||
| 2804 | static struct anim_cache *anim_cache = NULL; | ||
| 2805 | |||
| 2806 | static struct anim_cache * | ||
| 2807 | anim_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. */ | ||
| 2820 | static void | ||
| 2821 | anim_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 | |||
| 2844 | static struct anim_cache * | ||
| 2845 | anim_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 | |||
| 8441 | struct 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 | |||
| 8455 | static struct anim_cache *anim_cache = NULL; | ||
| 8456 | |||
| 8457 | static struct anim_cache * | ||
| 8458 | anim_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. */ | ||
| 8472 | static void | ||
| 8473 | anim_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 | |||
| 8496 | static struct anim_cache * | ||
| 8497 | anim_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 | /*********************************************************************** |