diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2022-06-04 16:28:18 +0200 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2022-06-04 16:37:25 +0200 |
commit | 8bba456b1470b0e7f2c8291e50bff37c001d8f44 (patch) | |
tree | fb210a5f9de8a0566d2d41fd28a5db19fc48bd1f | |
parent | bb97445a967c610c9aed9a88a34549b04221c422 (diff) | |
download | fiv-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.c | 41 |
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); |