NetSurf
image_cache.c
Go to the documentation of this file.
1/*
2 * Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * Cache implementation for bitmap images decoded into frontend format.
22 */
23
24#include <assert.h>
25#include <stdint.h>
26#include <stdbool.h>
27#include <string.h>
28#include <stdlib.h>
29
30#include "netsurf/inttypes.h"
31#include "utils/utils.h"
32#include "utils/log.h"
33#include "netsurf/misc.h"
34#include "netsurf/bitmap.h"
35#include "content/llcache.h"
38
39#include "image/image_cache.h"
40#include "image/image.h"
41
42/**
43 * Age of an entry within the cache
44 *
45 * type deffed away so it can be readily changed later perhaps to a
46 * wallclock time structure.
47 */
48typedef unsigned int cache_age;
49
50/**
51 * Image cache entry
52 */
54 struct image_cache_entry_s *next; /**< next cache entry in list */
55 struct image_cache_entry_s *prev; /**< previous cache entry in list */
56
57 /** content is used as a key */
59 /** associated bitmap entry */
60 struct bitmap *bitmap;
61 /** routine to convert content into bitmap */
63
64 /* Statistics for replacement algorithm */
65
66 unsigned int redraw_count; /**< number of times object has been drawn */
67 cache_age redraw_age; /**< Age of last redraw */
68 size_t bitmap_size; /**< size if storage occupied by bitmap */
69 cache_age bitmap_age; /**< Age of last conversion to a bitmap by cache*/
70
71 int conversion_count; /**< Number of times image has been converted */
72};
73
74/**
75 * Current state of the cache.
76 *
77 * Global state of the cache. entries "age" is determined based on a
78 * monotonically incrementing operation count. This avoids issues with
79 * using wall clock time while allowing the LRU algorithm to work
80 * sensibly.
81 */
83 /** Cache parameters */
85
86 /** The "age" of the current operation */
88
89 /* The objects the cache holds */
91
92
93 /* Statistics for management algorithm */
94
95 /** total size of bitmaps currently allocated */
97
98 /** Total count of bitmaps currently allocated */
100
101 /** Maximum size of bitmaps allocated at any one time */
103 /** The number of objects when maximum bitmap usage occurred */
105
106 /** Maximum count of bitmaps allocated at any one time */
108 /** The size of the bitmaps when the max count occurred */
110
111 /** Bitmap was not available at plot time required conversion */
113 uint64_t miss_size;
114 /** Bitmap was available at plot time required no conversion */
116 uint64_t hit_size;
117 /** Bitmap was not available at plot time and required
118 * conversion which failed.
119 */
121 uint64_t fail_size;
122
123 /* Cache entry freed without ever being redrawn */
125 /** Bitmap was available but never required - wasted conversions */
127
128 /** Total number of additional (after the first) conversions */
130 /** counts total number of images with more than one conversion */
132
133 /** Bitmap with most conversions was converted this many times */
135 /** Size of bitmap with most conversions */
137};
138
139/** image cache state */
140static struct image_cache_s *image_cache = NULL;
141
142
143/**
144 * Find a cache entry by index.
145 *
146 * \param entryn index of cache entry
147 * \return cache entry at index or NULL if not found.
148 */
149static struct image_cache_entry_s *image_cache__findn(int entryn)
150{
151 struct image_cache_entry_s *found;
152
153 found = image_cache->entries;
154 while ((found != NULL) && (entryn > 0)) {
155 entryn--;
156 found = found->next;
157 }
158 return found;
159}
160
161
162/**
163 * Find the cache entry for a content
164 *
165 * \param c The content to get an entry for
166 * \return The image cache entry or NULL if not found.
167 */
168static struct image_cache_entry_s *image_cache__find(const struct content *c)
169{
170 struct image_cache_entry_s *found;
171
172 found = image_cache->entries;
173 while ((found != NULL) && (found->content != c)) {
174 found = found->next;
175 }
176 return found;
177}
178
179/**
180 * Update the image cache statistics with an entry.
181 *
182 * \param centry The image cache entry to update the stats with.
183 */
185{
187 centry->conversion_count++;
188
191
195
196 }
197
201 }
202
203 if (centry->conversion_count == 2) {
205 }
206
207 if (centry->conversion_count > 1) {
209 }
210
216 }
217}
218
219static void image_cache__link(struct image_cache_entry_s *centry)
220{
221 centry->next = image_cache->entries;
222 centry->prev = NULL;
223 if (centry->next != NULL) {
224 centry->next->prev = centry;
225 }
226 image_cache->entries = centry;
227}
228
229static void image_cache__unlink(struct image_cache_entry_s *centry)
230{
231 /* unlink entry */
232 if (centry->prev == NULL) {
233 /* first in list */
234 if (centry->next != NULL) {
235 centry->next->prev = centry->prev;
236 image_cache->entries = centry->next;
237 } else {
238 /* empty list */
239 image_cache->entries = NULL;
240 }
241 } else {
242 centry->prev->next = centry->next;
243
244 if (centry->next != NULL) {
245 centry->next->prev = centry->prev;
246 }
247 }
248}
249
250/**
251 * free bitmap from an image cache entry
252 *
253 * \param centry The image cache entry to free bitmap from.
254 */
256{
257 if (centry->bitmap != NULL) {
258#ifdef IMAGE_CACHE_VERBOSE
259 NSLOG(netsurf, INFO,
260 "Freeing bitmap %p size %d age %d redraw count %d",
261 centry->bitmap,
262 centry->bitmap_size,
264 centry->redraw_count);
265#endif
266 guit->bitmap->destroy(centry->bitmap);
267 centry->bitmap = NULL;
270 if (centry->redraw_count == 0) {
272 }
273 }
274
275}
276
277/**
278 * free image cache entry
279 *
280 * \param centry The image cache entry to free.
281 */
283{
284#ifdef IMAGE_CACHE_VERBOSE
285 NSLOG(netsurf, INFO, "freeing %p ", centry);
286#endif
287
288 if (centry->redraw_count == 0) {
290 }
291
293
294 image_cache__unlink(centry);
295
296 free(centry);
297}
298
299/**
300 * Image cache cleaner
301 *
302 * \param icache The image cache context.
303 */
304static void image_cache__clean(struct image_cache_s *icache)
305{
306 struct image_cache_entry_s *centry = icache->entries;
307
308 while (centry != NULL) {
309 if ((icache->current_age - centry->redraw_age) >
310 icache->params.bg_clean_time) {
311 /* only consider older entries, avoids active entries */
312 if ((icache->total_bitmap_size >
313 (icache->params.limit - icache->params.hysteresis)) &&
314 (rand() > (RAND_MAX / 2))) {
316 }
317 }
318 centry=centry->next;
319 }
320}
321
322/**
323 * Cache background scheduled callback.
324 *
325 * \param p The image cache context.
326 */
328{
329 struct image_cache_s *icache = p;
330
331 /* increment current cache age */
332 icache->current_age += icache->params.bg_clean_time;
333
334#ifdef IMAGE_CACHE_VERBOSE
335 NSLOG(netsurf, INFO, "Cache age %ds", icache->current_age / 1000);
336#endif
337
338 image_cache__clean(icache);
339
342 icache);
343}
344
345/* exported interface documented in image_cache.h */
346struct bitmap *image_cache_get_bitmap(const struct content *c)
347{
348 struct image_cache_entry_s *centry;
349
350 centry = image_cache__find(c);
351 if (centry == NULL) {
352 return NULL;
353 }
354
355 if (centry->bitmap == NULL) {
356 if (centry->convert != NULL) {
357 centry->bitmap = centry->convert(centry->content);
358 }
359
360 if (centry->bitmap != NULL) {
364 } else {
367 }
368 } else {
370 image_cache->hit_size += centry->bitmap_size;
371 }
372
373 return centry->bitmap;
374}
375
376/* exported interface documented in image_cache.h */
378{
379 bool decision = false;
380
381 /* If the cache is below its target usage and the bitmap is
382 * small enough speculate.
383 */
386#ifdef IMAGE_CACHE_VERBOSE
387 NSLOG(netsurf, INFO,
388 "content size (%d) is smaller than minimum (%d)",
389 c->size,
391#endif
392 decision = true;
393 }
394
395#ifdef IMAGE_CACHE_VERBOSE
396 NSLOG(netsurf, INFO, "returning %d", decision);
397#endif
398 return decision;
399}
400
401/* exported interface documented in image_cache.h */
403{
404 struct image_cache_entry_s *centry;
405
406 centry = image_cache__find(c);
407 if (centry == NULL) {
408 return NULL;
409 }
410
411 return centry->bitmap;
412}
413
414/* exported interface documented in image_cache.h */
417{
418 image_cache = calloc(1, sizeof(struct image_cache_s));
419 if (image_cache == NULL) {
420 return NSERROR_NOMEM;
421 }
422
424
428
429 NSLOG(netsurf, INFO,
430 "Image cache initialised with a limit of %"PRIsizet" hysteresis of %"PRIsizet,
433
434 return NSERROR_OK;
435}
436
437/* exported interface documented in image_cache.h */
439{
440 unsigned int op_count;
441 uint64_t op_size;
442
444
445 NSLOG(netsurf, INFO, "Size at finish %"PRIsizet" (in %d)",
447
448 while (image_cache->entries != NULL) {
450 }
451
452 op_count = image_cache->hit_count +
455
456 op_size = image_cache->hit_size +
459
460 NSLOG(netsurf, INFO, "Age %ds", image_cache->current_age / 1000);
461 NSLOG(netsurf, INFO, "Peak size %"PRIsizet" (in %d)",
464 NSLOG(netsurf, INFO, "Peak image count %d (size %"PRIsizet")",
467
468 if ((op_count > 0) && (op_size >0)) {
469
470 NSLOG(netsurf, INFO,
471 "Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)",
472 op_count,
476 (image_cache->hit_count * 100) / op_count,
477 (image_cache->miss_count * 100) / op_count,
478 (image_cache->fail_count * 100) / op_count);
479 NSLOG(netsurf, INFO,
480 "Cache total/hit/miss/fail (size) %"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64" (100%%/%"PRId64"%%/%"PRId64"%%/%"PRId64"%%)",
481 op_size,
485 (image_cache->hit_size * 100) / op_size,
486 (image_cache->miss_size * 100) / op_size,
487 (image_cache->fail_size * 100) / op_size);
488 }
489
490 NSLOG(netsurf, INFO,
491 "Total images never rendered: %d (includes %d that were converted)",
494
495 NSLOG(netsurf, INFO,
496 "Total number of excessive conversions: %d (from %d images converted more than once)",
499
500 NSLOG(netsurf, INFO, "Bitmap of size %d had most (%d) conversions",
503
504 free(image_cache);
505
506 return NSERROR_OK;
507}
508
509/* exported interface documented in image_cache.h */
511 struct bitmap *bitmap,
513{
514 struct image_cache_entry_s *centry;
515
516 /* bump the cache age by a ms to ensure multiple items are not
517 * added at exactly the same time
518 */
520
521 centry = image_cache__find(content);
522 if (centry == NULL) {
523 /* new cache entry, content not previously added */
524 centry = calloc(1, sizeof(struct image_cache_entry_s));
525 if (centry == NULL) {
526 return NSERROR_NOMEM;
527 }
528 image_cache__link(centry);
529 centry->content = content;
530
531 centry->bitmap_size = content->width * content->height * 4llu;
532 }
533
534 NSLOG(netsurf, INFO, "centry %p, content %p, bitmap %p", centry,
535 content, bitmap);
536
537 centry->convert = convert;
538
539 /* set bitmap entry if one is passed, free extant one if present */
540 if (bitmap != NULL) {
541 if (centry->bitmap != NULL) {
542 guit->bitmap->destroy(centry->bitmap);
543 } else {
545 }
546 centry->bitmap = bitmap;
547 } else {
548 /* no bitmap, check to see if we should speculatively convert */
549 if ((centry->convert != NULL) &&
550 (image_cache_speculate(content) == true)) {
551 centry->bitmap = centry->convert(centry->content);
552
553 if (centry->bitmap != NULL) {
555 } else {
557 }
558 }
559 }
560
561
562
563 return NSERROR_OK;
564}
565
566/* exported interface documented in image_cache.h */
568{
569 struct image_cache_entry_s *centry;
570
571 /* get the cache entry */
572 centry = image_cache__find(content);
573 if (centry == NULL) {
574 NSLOG(netsurf, INFO,
575 "Could not find cache entry for content (%p)", content);
576 return NSERROR_NOT_FOUND;
577 }
578
580
581 return NSERROR_OK;
582}
583
584/* exported interface documented in image_cache.h */
585int image_cache_snsummaryf(char *string, size_t size, const char *fmt)
586{
587 size_t slen = 0; /* current output string length */
588 int fmtc = 0; /* current index into format string */
589 bool pct;
590 unsigned int op_count;
591 uint64_t op_size;
592
593 op_count = image_cache->hit_count +
596
597 op_size = image_cache->hit_size +
600
601 while((slen < size) && (fmt[fmtc] != 0)) {
602 if (fmt[fmtc] == '%') {
603 fmtc++;
604
605 /* check for percentage modifier */
606 if (fmt[fmtc] == 'p') {
607 fmtc++;
608 pct = true;
609 } else {
610 pct = false;
611 }
612
613#define FMTCHR(chr,fmt,var) case chr : \
614slen += snprintf(string + slen, size - slen, "%"fmt, image_cache->var); break
615
616#define FMTPCHR(chr,fmt,var,div) \
617case chr : \
618 if (pct) { \
619 if (div > 0) { \
620 slen += snprintf(string + slen, size - slen, "%"PRId64, (uint64_t)((image_cache->var * 100) / div)); \
621 } else { \
622 slen += snprintf(string + slen, size - slen, "100"); \
623 } \
624 } else { \
625 slen += snprintf(string + slen, size - slen, "%"fmt, image_cache->var); \
626 } break
627
628
629 switch (fmt[fmtc]) {
630 case '%':
631 string[slen] = '%';
632 slen++;
633 break;
634
635 FMTCHR('a', PRIsizet, params.limit);
636 FMTCHR('b', PRIsizet, params.hysteresis);
637 FMTCHR('c', PRIsizet, total_bitmap_size);
638 FMTCHR('d', "d", bitmap_count);
639 FMTCHR('e', "u", current_age / 1000);
640 FMTCHR('f', PRIsizet, max_bitmap_size);
641 FMTCHR('g', "d", max_bitmap_size_count);
642 FMTCHR('h', "d", max_bitmap_count);
643 FMTCHR('i', PRIsizet, max_bitmap_count_size);
644
645
646 case 'j':
647 slen += snprintf(string + slen, size - slen,
648 "%u", pct?100:op_count);
649 break;
650
651 FMTPCHR('k', "d", hit_count, op_count);
652 FMTPCHR('l', "d", miss_count, op_count);
653 FMTPCHR('m', "d", fail_count, op_count);
654
655 case 'n':
656 slen += snprintf(string + slen, size - slen,
657 "%"PRId64, pct?100:op_size);
658 break;
659
660 FMTPCHR('o', PRId64, hit_size, op_size);
661 FMTPCHR('q', PRId64, miss_size, op_size);
662 FMTPCHR('r', PRId64, fail_size, op_size);
663
664 FMTCHR('s', "d", total_unrendered);
665 FMTCHR('t', "d", specultive_miss_count);
666 FMTCHR('u', "d", total_extra_conversions);
667 FMTCHR('v', "d", total_extra_conversions_count);
668 FMTCHR('w', "u", peak_conversions_size);
669 FMTCHR('x', "d", peak_conversions);
670
671
672 }
673#undef FMTCHR
674#undef FMTPCHR
675
676 fmtc++;
677 } else {
678 string[slen] = fmt[fmtc];
679 slen++;
680 fmtc++;
681 }
682 }
683
684 /* Ensure that we NUL-terminate the output */
685 string[min(slen, size - 1)] = '\0';
686
687 return slen;
688}
689
690/* exported interface documented in image_cache.h */
691int
693 size_t size,
694 unsigned int entryn,
695 const char *fmt)
696{
697 struct image_cache_entry_s *centry;
698 size_t slen = 0; /* current output string length */
699 int fmtc = 0; /* current index into format string */
700 lwc_string *origin; /* current entry's origin */
701
702 centry = image_cache__findn(entryn);
703 if (centry == NULL)
704 return -1;
705
706 while((slen < size) && (fmt[fmtc] != 0)) {
707 if (fmt[fmtc] == '%') {
708 fmtc++;
709 switch (fmt[fmtc]) {
710 case 'e':
711 slen += snprintf(string + slen, size - slen,
712 "%u", entryn);
713 break;
714
715 case 'r':
716 slen += snprintf(string + slen, size - slen,
717 "%u", centry->redraw_count);
718 break;
719
720 case 'a':
721 slen += snprintf(string + slen, size - slen,
722 "%.2f", (float)((image_cache->current_age - centry->redraw_age)) / 1000);
723 break;
724
725
726 case 'c':
727 slen += snprintf(string + slen, size - slen,
728 "%d", centry->conversion_count);
729 break;
730
731 case 'g':
732 slen += snprintf(string + slen, size - slen,
733 "%.2f", (float)((image_cache->current_age - centry->bitmap_age)) / 1000);
734 break;
735
736 case 'k':
737 slen += snprintf(string + slen, size - slen,
738 "%p", centry->content);
739 break;
740
741 case 'U':
742 slen += snprintf(string + slen, size - slen,
744 break;
745
746 case 'o':
748 centry->content->llcache),
749 NSURL_HOST)) {
750 origin = nsurl_get_component(
752 centry->content->
753 llcache),
754 NSURL_HOST);
755
756 slen += snprintf(string + slen,
757 size - slen, "%s",
758 lwc_string_data(
759 origin));
760
761 lwc_string_unref(origin);
762 } else {
763 slen += snprintf(string + slen,
764 size - slen, "%s",
765 "localhost");
766 }
767 break;
768
769 case 's':
770 if (centry->bitmap != NULL) {
771 slen += snprintf(string + slen,
772 size - slen,
773 "%" PRIsizet,
774 centry->bitmap_size);
775 } else {
776 slen += snprintf(string + slen,
777 size - slen,
778 "0");
779 }
780 break;
781 }
782 fmtc++;
783 } else {
784 string[slen] = fmt[fmtc];
785 slen++;
786 fmtc++;
787 }
788 }
789
790 /* Ensure that we NUL-terminate the output */
791 string[min(slen, size - 1)] = '\0';
792
793 return slen;
794}
795
796
797/* exported interface documented in image_cache.h */
799 struct content_redraw_data *data,
800 const struct rect *clip,
801 const struct redraw_context *ctx)
802{
803 struct image_cache_entry_s *centry;
804
805 /* get the cache entry */
806 centry = image_cache__find(c);
807 if (centry == NULL) {
808 NSLOG(netsurf, INFO,
809 "Could not find cache entry for content (%p)", c);
810 return false;
811 }
812
813 if (centry->bitmap == NULL) {
814 if (centry->convert != NULL) {
815 centry->bitmap = centry->convert(centry->content);
816 }
817
818 if (centry->bitmap != NULL) {
822 } else {
825 return false;
826 }
827 } else {
829 image_cache->hit_size += centry->bitmap_size;
830 }
831
832
833 /* update statistics */
834 centry->redraw_count++;
836
837 return image_bitmap_plot(centry->bitmap, data, clip, ctx);
838}
839
840/* exported interface documented in image_cache.h */
842{
843 struct image_cache_entry_s *centry;
844
845 /* get the cache entry */
846 centry = image_cache__find(content);
847 if (centry == NULL) {
848 NSLOG(netsurf, INFO,
849 "Could not find cache entry for content (%p)", content);
850 } else {
852 }
853}
854
855/* exported interface documented in image_cache.h */
856void *image_cache_get_internal(const struct content *c, void *context)
857{
858 return image_cache_get_bitmap(c);
859}
860
861/* exported interface documented in image_cache.h */
863{
864 struct bitmap *bmp;
865 bmp = image_cache_get_bitmap(c);
866 if (bmp != NULL) {
867 return guit->bitmap->get_opaque(bmp);
868 }
869 return false;
870}
871
872/* exported interface documented in image_cache.h */
874{
875 return CONTENT_IMAGE;
876}
bool image_bitmap_plot(struct bitmap *bitmap, struct content_redraw_data *data, const struct rect *clip, const struct redraw_context *ctx)
Common image content handler bitmap plot call.
Definition: image.c:116
Initialisation/finalisation of image handlers.
Protected interface to Content handling.
content_type
The type of a content.
Definition: content_type.h:53
@ CONTENT_IMAGE
All images.
Definition: content_type.h:67
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOT_FOUND
Requested item not found.
Definition: errors.h:34
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
struct netsurf_table * guit
The global interface table.
Definition: gui_factory.c:49
Interface to core interface table.
static void image_cache__free_bitmap(struct image_cache_entry_s *centry)
free bitmap from an image cache entry
Definition: image_cache.c:255
struct bitmap * image_cache_get_bitmap(const struct content *c)
Obtain a bitmap from a content converting from source if neccessary.
Definition: image_cache.c:346
static void image_cache__background_update(void *p)
Cache background scheduled callback.
Definition: image_cache.c:327
static void image_cache__clean(struct image_cache_s *icache)
Image cache cleaner.
Definition: image_cache.c:304
content_type image_cache_content_type(void)
Definition: image_cache.c:873
void * image_cache_get_internal(const struct content *c, void *context)
Definition: image_cache.c:856
nserror image_cache_remove(struct content *content)
Definition: image_cache.c:567
bool image_cache_redraw(struct content *c, struct content_redraw_data *data, const struct rect *clip, const struct redraw_context *ctx)
Generic content redraw callback.
Definition: image_cache.c:798
bool image_cache_speculate(struct content *c)
Decide if a content should be speculatively converted.
Definition: image_cache.c:377
int image_cache_snentryf(char *string, size_t size, unsigned int entryn, const char *fmt)
Fill a buffer with information about a cache entry using a format.
Definition: image_cache.c:692
void image_cache_destroy(struct content *content)
Definition: image_cache.c:841
nserror image_cache_add(struct content *content, struct bitmap *bitmap, image_cache_convert_fn *convert)
adds an image content to be cached.
Definition: image_cache.c:510
static struct image_cache_s * image_cache
image cache state
Definition: image_cache.c:140
struct bitmap * image_cache_find_bitmap(struct content *c)
Obtain a bitmap from a content with no conversion.
Definition: image_cache.c:402
static struct image_cache_entry_s * image_cache__find(const struct content *c)
Find the cache entry for a content.
Definition: image_cache.c:168
static struct image_cache_entry_s * image_cache__findn(int entryn)
Find a cache entry by index.
Definition: image_cache.c:149
static void image_cache__unlink(struct image_cache_entry_s *centry)
Definition: image_cache.c:229
static void image_cache__link(struct image_cache_entry_s *centry)
Definition: image_cache.c:219
#define FMTPCHR(chr, fmt, var, div)
nserror image_cache_fini(void)
Definition: image_cache.c:438
static void image_cache__free_entry(struct image_cache_entry_s *centry)
free image cache entry
Definition: image_cache.c:282
#define FMTCHR(chr, fmt, var)
unsigned int cache_age
Age of an entry within the cache.
Definition: image_cache.c:48
static void image_cache_stats_bitmap_add(struct image_cache_entry_s *centry)
Update the image cache statistics with an entry.
Definition: image_cache.c:184
bool image_cache_is_opaque(struct content *c)
Definition: image_cache.c:862
int image_cache_snsummaryf(char *string, size_t size, const char *fmt)
Fill a buffer with information about the image cache using a format.
Definition: image_cache.c:585
nserror image_cache_init(const struct image_cache_parameters *image_cache_parameters)
Initialise the image cache.
Definition: image_cache.c:416
The image content handler intermediate image cache.
struct bitmap *() image_cache_convert_fn(struct content *content)
Definition: image_cache.h:47
Generic bitmap handling interface.
Interface to platform-specific miscellaneous browser operation table.
Netsurf additional integer type formatting macros.
#define PRIsizet
c99 standard printf formatting for size_t type
Definition: inttypes.h:53
#define PRIu64
Definition: inttypes.h:38
#define PRId64
Definition: inttypes.h:34
static struct llcache_s * llcache
low level cache state
Definition: llcache.c:267
nsurl * llcache_handle_get_url(const llcache_handle *handle)
Retrieve the post-redirect URL of a low-level cache object.
Definition: llcache.c:4195
Low-level resource cache (interface)
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
#define SPECULATE_SMALL
speculative pre-conversion small image size
Definition: netsurf.c:75
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
bool nsurl_has_component(const nsurl *url, nsurl_component part)
Enquire about the existence of componenets in a given URL.
lwc_string * nsurl_get_component(const nsurl *url, nsurl_component part)
Get part of a URL as a lwc_string, from a NetSurf URL object.
@ NSURL_HOST
Definition: nsurl.h:49
Interface to utility string handling.
RISC OS wimp toolkit bitmap.
Definition: bitmap.c:68
parameters to content redraw
Definition: content.h:40
Content which corresponds to a single URL.
int height
Height dimension, if applicable.
int width
Width dimension, if applicable.
struct llcache_handle * llcache
Low-level cache object.
unsigned int size
Estimated size of all data associated with this content.
void(* destroy)(void *bitmap)
Destroy a bitmap.
Definition: bitmap.h:143
bool(* get_opaque)(void *bitmap)
Get the opacity of a bitmap.
Definition: bitmap.h:159
nserror(* schedule)(int t, void(*callback)(void *p), void *p)
Schedule a callback.
Definition: misc.h:58
Image cache entry.
Definition: image_cache.c:53
struct content * content
content is used as a key
Definition: image_cache.c:58
unsigned int redraw_count
number of times object has been drawn
Definition: image_cache.c:66
int conversion_count
Number of times image has been converted.
Definition: image_cache.c:71
cache_age redraw_age
Age of last redraw.
Definition: image_cache.c:67
size_t bitmap_size
size if storage occupied by bitmap
Definition: image_cache.c:68
image_cache_convert_fn * convert
routine to convert content into bitmap
Definition: image_cache.c:62
struct image_cache_entry_s * prev
previous cache entry in list
Definition: image_cache.c:55
struct bitmap * bitmap
associated bitmap entry
Definition: image_cache.c:60
struct image_cache_entry_s * next
next cache entry in list
Definition: image_cache.c:54
cache_age bitmap_age
Age of last conversion to a bitmap by cache.
Definition: image_cache.c:69
size_t speculative_small
The speculative conversion "small" size.
Definition: image_cache.h:60
unsigned int bg_clean_time
How frequently the background cache clean process is run (ms)
Definition: image_cache.h:51
size_t limit
The target upper bound for the image cache size.
Definition: image_cache.h:54
size_t hysteresis
The hysteresis allowed round the target size.
Definition: image_cache.h:57
Current state of the cache.
Definition: image_cache.c:82
int max_bitmap_count
Maximum count of bitmaps allocated at any one time.
Definition: image_cache.c:107
cache_age current_age
The "age" of the current operation.
Definition: image_cache.c:87
struct image_cache_parameters params
Cache parameters.
Definition: image_cache.c:84
int total_extra_conversions_count
counts total number of images with more than one conversion
Definition: image_cache.c:131
uint64_t fail_size
Definition: image_cache.c:121
int total_unrendered
Definition: image_cache.c:124
int hit_count
Bitmap was available at plot time required no conversion.
Definition: image_cache.c:115
size_t max_bitmap_count_size
The size of the bitmaps when the max count occurred.
Definition: image_cache.c:109
int fail_count
Bitmap was not available at plot time and required conversion which failed.
Definition: image_cache.c:120
int specultive_miss_count
Bitmap was available but never required - wasted conversions.
Definition: image_cache.c:126
size_t max_bitmap_size
Maximum size of bitmaps allocated at any one time.
Definition: image_cache.c:102
size_t total_bitmap_size
total size of bitmaps currently allocated
Definition: image_cache.c:96
int peak_conversions
Bitmap with most conversions was converted this many times.
Definition: image_cache.c:134
int max_bitmap_size_count
The number of objects when maximum bitmap usage occurred.
Definition: image_cache.c:104
uint64_t hit_size
Definition: image_cache.c:116
int total_extra_conversions
Total number of additional (after the first) conversions.
Definition: image_cache.c:129
int bitmap_count
Total count of bitmaps currently allocated.
Definition: image_cache.c:99
struct image_cache_entry_s * entries
Definition: image_cache.c:90
int miss_count
Bitmap was not available at plot time required conversion.
Definition: image_cache.c:112
unsigned int peak_conversions_size
Size of bitmap with most conversions.
Definition: image_cache.c:136
uint64_t miss_size
Definition: image_cache.c:113
struct gui_misc_table * misc
Browser table.
Definition: gui_table.h:57
struct gui_bitmap_table * bitmap
Bitmap table.
Definition: gui_table.h:144
Rectangle coordinates.
Definition: types.h:40
Redraw context.
Definition: plotters.h:51
Interface to a number of general purpose functionality.
#define min(x, y)
Definition: utils.h:46
static nserror bitmap(const struct redraw_context *ctx, struct bitmap *bitmap, int x, int y, int width, int height, colour bg, bitmap_flags_t flags)
Plot a bitmap.
Definition: plot.c:857
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357