aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Ingebrigtsen2022-04-11 13:35:45 +0200
committerLars Ingebrigtsen2022-04-11 13:35:56 +0200
commit5141234acf85fe232adcaa3b0278f7766eb0d250 (patch)
treed46352aaa3261faa70db2b5ad75bfa385393cdb1 /src
parent07ee24d83debfeb0570a596fa27e7203bf55a4b3 (diff)
downloademacs-5141234acf85fe232adcaa3b0278f7766eb0d250.tar.gz
emacs-5141234acf85fe232adcaa3b0278f7766eb0d250.zip
Refactor the webp cache code to allow usage by gif_load, too
* src/image.c (struct anim_cache, anim_create_cache) (anim_prune_animation_cache, anim_get_animation_cache): Rename from webp_cache (etc) to prepare for usage in the gif animation implementation, too. (webp_load): Adjust cache usage.
Diffstat (limited to 'src')
-rw-r--r--src/image.c180
1 files changed, 97 insertions, 83 deletions
diff --git a/src/image.c b/src/image.c
index 3f9111a7093..a3c98684261 100644
--- a/src/image.c
+++ b/src/image.c
@@ -8431,6 +8431,95 @@ tiff_load (struct frame *f, struct image *img)
8431 8431
8432 8432
8433 8433
8434
8435
8436#if defined (HAVE_WEBP)
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->handle);
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 */
8522
8434/*********************************************************************** 8523/***********************************************************************
8435 GIF 8524 GIF
8436 ***********************************************************************/ 8525 ***********************************************************************/
@@ -9203,82 +9292,6 @@ init_webp_functions (void)
9203 9292
9204#endif /* WINDOWSNT */ 9293#endif /* WINDOWSNT */
9205 9294
9206/* To speed webp animations up, we keep a cache (based on EQ-ness of
9207 the image spec/object) where we put the libwebp animator
9208 iterator. */
9209
9210struct webp_cache
9211{
9212 Lisp_Object spec;
9213 WebPAnimDecoder* anim;
9214 int index, width, height, frames;
9215 struct timespec update_time;
9216 struct webp_cache *next;
9217};
9218
9219static struct webp_cache *webp_cache = NULL;
9220
9221static struct webp_cache *
9222webp_create_cache (Lisp_Object spec)
9223{
9224 struct webp_cache *cache = xmalloc (sizeof (struct webp_cache));
9225 cache->anim = NULL;
9226
9227 cache->index = 0;
9228 cache->next = NULL;
9229 /* FIXME: Does this need gc protection? */
9230 cache->spec = spec;
9231 return cache;
9232}
9233
9234/* Discard cached images that haven't been used for a minute. */
9235static void
9236webp_prune_animation_cache (void)
9237{
9238 struct webp_cache **pcache = &webp_cache;
9239 struct timespec old = timespec_sub (current_timespec (),
9240 make_timespec (60, 0));
9241
9242 while (*pcache)
9243 {
9244 struct webp_cache *cache = *pcache;
9245 if (timespec_cmp (old, cache->update_time) <= 0)
9246 pcache = &cache->next;
9247 else
9248 {
9249 if (cache->anim)
9250 WebPAnimDecoderDelete (cache->anim);
9251 *pcache = cache->next;
9252 xfree (cache);
9253 }
9254 }
9255}
9256
9257static struct webp_cache *
9258webp_get_animation_cache (Lisp_Object spec)
9259{
9260 struct webp_cache *cache;
9261 struct webp_cache **pcache = &webp_cache;
9262
9263 webp_prune_animation_cache ();
9264
9265 while (1)
9266 {
9267 cache = *pcache;
9268 if (! cache)
9269 {
9270 *pcache = cache = webp_create_cache (spec);
9271 break;
9272 }
9273 if (EQ (spec, cache->spec))
9274 break;
9275 pcache = &cache->next;
9276 }
9277
9278 cache->update_time = current_timespec ();
9279 return cache;
9280}
9281
9282/* Load WebP image IMG for use on frame F. Value is true if 9295/* Load WebP image IMG for use on frame F. Value is true if
9283 successful. */ 9296 successful. */
9284 9297
@@ -9371,14 +9384,14 @@ webp_load (struct frame *f, struct image *img)
9371 webp_data.size = size; 9384 webp_data.size = size;
9372 int timestamp; 9385 int timestamp;
9373 9386
9374 struct webp_cache* cache = webp_get_animation_cache (img->spec); 9387 struct anim_cache* cache = anim_get_animation_cache (img->spec);
9375 /* Get the next frame from the animation cache. */ 9388 /* Get the next frame from the animation cache. */
9376 if (cache->anim && cache->index == idx - 1) 9389 if (cache->handle && cache->index == idx - 1)
9377 { 9390 {
9378 WebPAnimDecoderGetNext (cache->anim, &decoded, &timestamp); 9391 WebPAnimDecoderGetNext (cache->handle, &decoded, &timestamp);
9379 delay = timestamp; 9392 delay = timestamp;
9380 cache->index++; 9393 cache->index++;
9381 anim = cache->anim; 9394 anim = cache->handle;
9382 width = cache->width; 9395 width = cache->width;
9383 height = cache->height; 9396 height = cache->height;
9384 frames = cache->frames; 9397 frames = cache->frames;
@@ -9386,8 +9399,8 @@ webp_load (struct frame *f, struct image *img)
9386 else 9399 else
9387 { 9400 {
9388 /* Start a new cache entry. */ 9401 /* Start a new cache entry. */
9389 if (cache->anim) 9402 if (cache->handle)
9390 WebPAnimDecoderDelete (cache->anim); 9403 WebPAnimDecoderDelete (cache->handle);
9391 9404
9392 /* Get the width/height of the total image. */ 9405 /* Get the width/height of the total image. */
9393 WebPDemuxer* demux = WebPDemux (&webp_data); 9406 WebPDemuxer* demux = WebPDemux (&webp_data);
@@ -9395,13 +9408,14 @@ webp_load (struct frame *f, struct image *img)
9395 cache->height = height = WebPDemuxGetI (demux, 9408 cache->height = height = WebPDemuxGetI (demux,
9396 WEBP_FF_CANVAS_HEIGHT); 9409 WEBP_FF_CANVAS_HEIGHT);
9397 cache->frames = frames = WebPDemuxGetI (demux, WEBP_FF_FRAME_COUNT); 9410 cache->frames = frames = WebPDemuxGetI (demux, WEBP_FF_FRAME_COUNT);
9411 cache->destructor = (void (*)(void *)) &WebPAnimDecoderDelete;
9398 WebPDemuxDelete (demux); 9412 WebPDemuxDelete (demux);
9399 9413
9400 WebPAnimDecoderOptions dec_options; 9414 WebPAnimDecoderOptions dec_options;
9401 WebPAnimDecoderOptionsInit (&dec_options); 9415 WebPAnimDecoderOptionsInit (&dec_options);
9402 anim = WebPAnimDecoderNew (&webp_data, &dec_options); 9416 anim = WebPAnimDecoderNew (&webp_data, &dec_options);
9403 9417
9404 cache->anim = anim; 9418 cache->handle = anim;
9405 cache->index = idx; 9419 cache->index = idx;
9406 9420
9407 while (WebPAnimDecoderHasMoreFrames (anim)) { 9421 while (WebPAnimDecoderHasMoreFrames (anim)) {