aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-06-04 16:28:18 +0200
committerPřemysl Eric Janouch <p@janouch.name>2022-06-04 16:37:25 +0200
commit8bba456b1470b0e7f2c8291e50bff37c001d8f44 (patch)
treefb210a5f9de8a0566d2d41fd28a5db19fc48bd1f
parentbb97445a967c610c9aed9a88a34549b04221c422 (diff)
downloadfiv-8bba456b1470b0e7f2c8291e50bff37c001d8f44.tar.gz
fiv-8bba456b1470b0e7f2c8291e50bff37c001d8f44.tar.xz
fiv-8bba456b1470b0e7f2c8291e50bff37c001d8f44.zip
Cache thumbnails across reloads
This will speed up sort changes, as well as simple reloads, at the cost of an extra hash map from URIs to Cairo surface references. It seems unnecessary to provide an explicit option to flush this cache, as it may be cleared by changing either the directory or the current thumbnail size.
-rw-r--r--fiv-browser.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/fiv-browser.c b/fiv-browser.c
index 1b01f77..df2b63d 100644
--- a/fiv-browser.c
+++ b/fiv-browser.c
@@ -72,6 +72,8 @@ struct _FivBrowser {
double drag_begin_x; ///< Viewport start X coordinate or -1
double drag_begin_y; ///< Viewport start Y coordinate or -1
+ GHashTable *thumbnail_cache; ///< [URI]cairo_surface_t, for item_size
+
Thumbnailer *thumbnailers; ///< Parallelized thumbnailers
size_t thumbnailers_len; ///< Thumbnailers array size
GList *thumbnailers_queue; ///< Queued up Entry pointers
@@ -431,9 +433,18 @@ entry_add_thumbnail(gpointer data, gpointer user_data)
g_clear_pointer(&self->thumbnail, cairo_surface_destroy);
FivBrowser *browser = FIV_BROWSER(user_data);
- self->thumbnail = rescale_thumbnail(
- fiv_thumbnail_lookup(self->uri, self->mtime_msec, browser->item_size),
- browser->item_height);
+ cairo_surface_t *cached =
+ g_hash_table_lookup(browser->thumbnail_cache, self->uri);
+ if (cached &&
+ (intptr_t) cairo_surface_get_user_data(
+ cached, &fiv_browser_key_mtime_msec) == self->mtime_msec) {
+ self->thumbnail = cairo_surface_reference(cached);
+ } else {
+ cairo_surface_t *found = fiv_thumbnail_lookup(
+ self->uri, self->mtime_msec, browser->item_size);
+ self->thumbnail = rescale_thumbnail(found, browser->item_height);
+ }
+
if (self->thumbnail) {
// This choice of mtime favours unnecessary thumbnail reloading.
cairo_surface_set_user_data(self->thumbnail,
@@ -515,8 +526,18 @@ reload_thumbnails(FivBrowser *self)
g_thread_pool_push(pool, &g_array_index(self->entries, Entry, i), NULL);
g_thread_pool_free(pool, FALSE, TRUE);
- for (guint i = 0; i < self->entries->len; i++)
- materialize_icon(self, &g_array_index(self->entries, Entry, i));
+ // Once a URI disappears from the model, its thumbnail is forgotten.
+ g_hash_table_remove_all(self->thumbnail_cache);
+
+ for (guint i = 0; i < self->entries->len; i++) {
+ Entry *entry = &g_array_index(self->entries, Entry, i);
+ if (entry->thumbnail) {
+ g_hash_table_insert(self->thumbnail_cache, g_strdup(entry->uri),
+ cairo_surface_reference(entry->thumbnail));
+ }
+
+ materialize_icon(self, entry);
+ }
gtk_widget_queue_resize(GTK_WIDGET(self));
}
@@ -928,6 +949,8 @@ fiv_browser_finalize(GObject *gobject)
g_clear_object(&self->model);
}
+ g_hash_table_destroy(self->thumbnail_cache);
+
cairo_surface_destroy(self->glow);
g_clear_object(&self->pointer);
@@ -972,6 +995,8 @@ set_item_size(FivBrowser *self, FivThumbnailSize size)
if (size != self->item_size) {
self->item_size = size;
self->item_height = fiv_thumbnail_sizes[self->item_size].size;
+
+ g_hash_table_remove_all(self->thumbnail_cache);
reload_thumbnails(self);
thumbnailers_start(self);
@@ -1688,6 +1713,9 @@ fiv_browser_init(FivBrowser *self)
g_array_set_clear_func(self->layouted_rows, (GDestroyNotify) row_free);
abort_button_tracking(self);
+ self->thumbnail_cache = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) cairo_surface_destroy);
+
self->thumbnailers_len = g_get_num_processors();
self->thumbnailers =
g_malloc0_n(self->thumbnailers_len, sizeof *self->thumbnailers);
@@ -1703,6 +1731,7 @@ fiv_browser_init(FivBrowser *self)
// --- Public interface --------------------------------------------------------
+// TODO(p): Later implement any arguments of this FivIoModel signal.
static void
on_model_files_changed(FivIoModel *model, FivBrowser *self)
{
@@ -1712,8 +1741,6 @@ on_model_files_changed(FivIoModel *model, FivBrowser *self)
if (self->selected)
selected_uri = g_strdup(self->selected->uri);
- // TODO(p): Later implement arguments of this FivIoModel signal.
- // Or ensure somehow else that thumbnails won't be reloaded unnecessarily.
thumbnailers_abort(self);
g_array_set_size(self->entries, 0);
g_array_set_size(self->layouted_rows, 0);