[gnome-desktop] gnome-bg: Cache resized wallpaper to help CPU at startup
- From: Vincent Untz <vuntz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-desktop] gnome-bg: Cache resized wallpaper to help CPU at startup
- Date: Thu, 25 Nov 2010 10:42:35 +0000 (UTC)
commit 63c36f78980a4982d364e37e6c1e6219af2ecd32
Author: Didier Roche <didrocks ubuntu com>
Date: Thu Nov 25 11:12:43 2010 +0100
gnome-bg: Cache resized wallpaper to help CPU at startup
Resized and transformed wallpapers are stored in ~/.cache/wallpaper/.
The cache is refreshed for each new current wallpaper depending on the
resolution or transformation, and each time the source image is
refreshed.
The source image format is preserved.
https://bugzilla.gnome.org/show_bug.cgi?id=608419
libgnome-desktop/gnome-bg.c | 238 ++++++++++++++++++++++++++++++++++++-------
1 files changed, 199 insertions(+), 39 deletions(-)
---
diff --git a/libgnome-desktop/gnome-bg.c b/libgnome-desktop/gnome-bg.c
index 9ad616b..7caaff6 100644
--- a/libgnome-desktop/gnome-bg.c
+++ b/libgnome-desktop/gnome-bg.c
@@ -34,6 +34,7 @@ Author: Soren Sandmann <sandmann redhat com>
#include <gio/gio.h>
#include <gdesktop-enums.h>
+#include <glib/gstdio.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
@@ -168,6 +169,7 @@ static gboolean get_thumb_annotations (GdkPixbuf *thumb,
/* Cache */
static GdkPixbuf *get_pixbuf_for_size (GnomeBG *bg,
+ gint num_monitor,
int width,
int height);
static void clear_cache (GnomeBG *bg);
@@ -529,6 +531,128 @@ gnome_bg_get_filename (GnomeBG *bg)
return bg->filename;
}
+static inline gchar *
+get_wallpaper_cache_dir ()
+{
+ return g_build_filename (g_get_user_cache_dir(), "wallpaper", NULL);
+}
+
+static inline gchar *
+get_wallpaper_cache_prefix_name (gint num_monitor,
+ GDesktopBackgroundStyle placement,
+ gint width,
+ gint height)
+{
+ return g_strdup_printf ("%i_%i_%i_%i", num_monitor, (gint) placement, width, height);
+}
+
+static char *
+get_wallpaper_cache_filename (const char *filename,
+ gint num_monitor,
+ GDesktopBackgroundStyle placement,
+ gint width,
+ gint height)
+{
+ gchar *cache_filename;
+ gchar *cache_prefix_name;
+ gchar *md5_filename;
+ gchar *cache_basename;
+ gchar *cache_dir;
+
+ md5_filename = g_compute_checksum_for_data (G_CHECKSUM_MD5, (const guchar *) filename, strlen (filename));
+ cache_prefix_name = get_wallpaper_cache_prefix_name (num_monitor, placement, width, height);
+ cache_basename = g_strdup_printf ("%s_%s", cache_prefix_name, md5_filename);
+ cache_dir = get_wallpaper_cache_dir ();
+ cache_filename = g_build_filename (cache_dir, cache_basename, NULL);
+
+ g_free (cache_prefix_name);
+ g_free (md5_filename);
+ g_free (cache_basename);
+ g_free (cache_dir);
+
+ return cache_filename;
+}
+
+static gboolean
+cache_file_is_valid (const char *filename,
+ const char *cache_filename)
+{
+ time_t mtime;
+ time_t cache_mtime;
+
+ if (!g_file_test (cache_filename, G_FILE_TEST_IS_REGULAR))
+ return FALSE;
+
+ mtime = get_mtime (filename);
+ cache_mtime = get_mtime (cache_filename);
+
+ return (mtime < cache_mtime);
+}
+
+static void
+refresh_cache_file (GnomeBG *bg,
+ GdkPixbuf *new_pixbuf,
+ gint num_monitor,
+ gint width,
+ gint height)
+{
+ gchar *cache_filename;
+ gchar *cache_dir;
+ GdkPixbufFormat *format;
+ gchar *format_name;
+ GDir *g_cache_dir;
+ gchar *monitor_prefix;
+ const gchar *file;
+
+ if ((num_monitor != -1) && (width > 300) && (height > 300))
+ return;
+
+ cache_filename = get_wallpaper_cache_filename (bg->filename, num_monitor, bg->placement, width, height);
+ cache_dir = get_wallpaper_cache_dir ();
+
+ /* Only refresh scaled file on disk if useful (and don't cache slideshow) */
+ if (!cache_file_is_valid (bg->filename, cache_filename)) {
+ format = gdk_pixbuf_get_file_info (bg->filename, NULL, NULL);
+
+ if (format != NULL) {
+ if (!g_file_test (cache_dir, G_FILE_TEST_IS_DIR)) {
+ g_mkdir_with_parents (cache_dir, 0700);
+ } else {
+ g_cache_dir = g_dir_open (cache_dir, 0, NULL);
+ monitor_prefix = g_strdup_printf ("%i_", num_monitor);
+
+ file = g_dir_read_name (g_cache_dir);
+ while (file != NULL) {
+ gchar *path;
+
+ path = g_build_filename (cache_dir, file, NULL);
+ /* purge files with same monitor id */
+ if (g_str_has_prefix (file, monitor_prefix) && g_file_test (path, G_FILE_TEST_IS_REGULAR))
+ g_unlink (path);
+ g_free (path);
+
+ file = g_dir_read_name (g_cache_dir);
+ }
+
+ g_free (monitor_prefix);
+ g_dir_close (g_cache_dir);
+ }
+
+ format_name = gdk_pixbuf_format_get_name (format);
+
+ if (strcmp (format_name, "jpeg") == 0)
+ gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, "quality", "100", NULL);
+ else
+ gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, NULL);
+
+ g_free (format_name);
+ }
+ }
+
+ g_free (cache_filename);
+ g_free (cache_dir);
+}
+
static void
file_changed (GFileMonitor *file_monitor,
GFile *child,
@@ -724,10 +848,11 @@ get_scaled_pixbuf (GDesktopBackgroundStyle placement,
}
static void
-draw_image_area (GDesktopBackgroundStyle placement,
- GdkPixbuf *pixbuf,
- GdkPixbuf *dest,
- GdkRectangle *area)
+draw_image_area (GnomeBG *bg,
+ gint num_monitor,
+ GdkPixbuf *pixbuf,
+ GdkPixbuf *dest,
+ GdkRectangle *area)
{
int dest_width = area->width;
int dest_height = area->height;
@@ -737,9 +862,9 @@ draw_image_area (GDesktopBackgroundStyle placement,
if (!pixbuf)
return;
- scaled = get_scaled_pixbuf (placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h);
+ scaled = get_scaled_pixbuf (bg->placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h);
- switch (placement) {
+ switch (bg->placement) {
case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER:
pixbuf_tile (scaled, dest);
break;
@@ -756,12 +881,14 @@ draw_image_area (GDesktopBackgroundStyle placement,
g_assert_not_reached ();
break;
}
-
+
+ refresh_cache_file (bg, scaled, num_monitor, dest_width, dest_height);
+
g_object_unref (scaled);
}
static void
-draw_image (GDesktopBackgroundStyle placement,
+draw_image_for_thumb (GnomeBG *bg,
GdkPixbuf *pixbuf,
GdkPixbuf *dest)
{
@@ -772,7 +899,7 @@ draw_image (GDesktopBackgroundStyle placement,
rect.width = gdk_pixbuf_get_width (dest);
rect.height = gdk_pixbuf_get_height (dest);
- draw_image_area (placement, pixbuf, dest, &rect);
+ draw_image_area (bg, -1, pixbuf, dest, &rect);
}
static void
@@ -782,15 +909,20 @@ draw_once (GnomeBG *bg,
{
GdkRectangle rect;
GdkPixbuf *pixbuf;
+ gint num_monitor;
+
+ /* we just draw on the whole screen */
+ num_monitor = 0;
rect.x = 0;
rect.y = 0;
rect.width = gdk_pixbuf_get_width (dest);
rect.height = gdk_pixbuf_get_height (dest);
- pixbuf = get_pixbuf_for_size (bg, gdk_pixbuf_get_width (dest), gdk_pixbuf_get_height (dest));
+ pixbuf = get_pixbuf_for_size (bg, num_monitor, rect.width, rect.height);
if (pixbuf) {
- draw_image_area (bg->placement,
+ draw_image_area (bg,
+ num_monitor,
pixbuf,
dest,
&rect);
@@ -811,9 +943,10 @@ draw_each_monitor (GnomeBG *bg,
for (monitor = 0; monitor < num_monitors; monitor++) {
GdkPixbuf *pixbuf;
gdk_screen_get_monitor_geometry (screen, monitor, &rect);
- pixbuf = get_pixbuf_for_size (bg, rect.width, rect.height);
+ pixbuf = get_pixbuf_for_size (bg, monitor, rect.width, rect.height);
if (pixbuf) {
- draw_image_area (bg->placement,
+ draw_image_area (bg,
+ monitor,
pixbuf,
dest, &rect);
g_object_unref (pixbuf);
@@ -985,7 +1118,7 @@ gnome_bg_is_dark (GnomeBG *bg,
color.green = (bg->primary.green + bg->secondary.green) / 2;
color.blue = (bg->primary.blue + bg->secondary.blue) / 2;
}
- pixbuf = get_pixbuf_for_size (bg, width, height);
+ pixbuf = get_pixbuf_for_size (bg, -1, width, height);
if (pixbuf) {
guint32 argb = pixbuf_average_value (pixbuf);
guchar a = (argb >> 24) & 0xff;
@@ -1155,7 +1288,7 @@ gnome_bg_create_thumbnail (GnomeBG *bg,
thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, -1);
if (thumb) {
- draw_image (bg->placement, thumb, result);
+ draw_image_for_thumb (bg, thumb, result);
g_object_unref (thumb);
}
}
@@ -1602,10 +1735,29 @@ file_cache_add_slide_show (GnomeBG *bg,
}
static GdkPixbuf *
+load_from_cache_file (GnomeBG *bg,
+ const char *filename,
+ gint num_monitor,
+ gint best_width,
+ gint best_height)
+{
+ GdkPixbuf *pixbuf = NULL;
+ gchar *cache_filename;
+
+ cache_filename = get_wallpaper_cache_filename (filename, num_monitor, bg->placement, best_width, best_height);
+ if (cache_file_is_valid (filename, cache_filename))
+ pixbuf = gdk_pixbuf_new_from_file (cache_filename, NULL);
+ g_free (cache_filename);
+
+ return pixbuf;
+}
+
+static GdkPixbuf *
get_as_pixbuf_for_size (GnomeBG *bg,
const char *filename,
- int best_width,
- int best_height)
+ gint num_monitor,
+ gint best_width,
+ gint best_height)
{
const FileCacheEntry *ent;
if ((ent = file_cache_lookup (bg, PIXBUF, filename))) {
@@ -1615,26 +1767,33 @@ get_as_pixbuf_for_size (GnomeBG *bg,
GdkPixbufFormat *format;
GdkPixbuf *pixbuf;
gchar *tmp;
+ pixbuf = NULL;
- /* If scalable choose maximum size */
- format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
+ /* Try to hit local cache first if relevant */
+ if (num_monitor != -1)
+ pixbuf = load_from_cache_file (bg, filename, num_monitor, best_width, best_height);
- if (format != NULL) {
- tmp = gdk_pixbuf_format_get_name (format);
- } else {
- tmp = NULL;
- }
+ if (!pixbuf) {
+ /* If scalable choose maximum size */
+ format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
- if (tmp != NULL &&
- strcmp (tmp, "svg") == 0 &&
- (best_width > 0 && best_height > 0) &&
- (bg->placement == G_DESKTOP_BACKGROUND_STYLE_STRETCHED ||
- bg->placement == G_DESKTOP_BACKGROUND_STYLE_SCALED ||
- bg->placement == G_DESKTOP_BACKGROUND_STYLE_ZOOM))
- pixbuf = gdk_pixbuf_new_from_file_at_size (filename, best_width, best_height, NULL);
- else
- pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
- g_free (tmp);
+ if (format != NULL) {
+ tmp = gdk_pixbuf_format_get_name (format);
+ } else {
+ tmp = NULL;
+ }
+
+ if (tmp != NULL &&
+ strcmp (tmp, "svg") == 0 &&
+ (best_width > 0 && best_height > 0) &&
+ (bg->placement == G_DESKTOP_BACKGROUND_STYLE_STRETCHED ||
+ bg->placement == G_DESKTOP_BACKGROUND_STYLE_SCALED ||
+ bg->placement == G_DESKTOP_BACKGROUND_STYLE_ZOOM))
+ pixbuf = gdk_pixbuf_new_from_file_at_size (filename, best_width, best_height, NULL);
+ else
+ pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+ g_free (tmp);
+ }
if (pixbuf)
file_cache_add_pixbuf (bg, filename, pixbuf);
@@ -2000,6 +2159,7 @@ find_best_size (GSList *sizes, gint width, gint height)
static GdkPixbuf *
get_pixbuf_for_size (GnomeBG *bg,
+ gint num_monitor,
gint best_width,
gint best_height)
{
@@ -2021,7 +2181,7 @@ get_pixbuf_for_size (GnomeBG *bg,
if (!hit_cache && bg->filename) {
bg->file_mtime = get_mtime (bg->filename);
- bg->pixbuf_cache = get_as_pixbuf_for_size (bg, bg->filename, best_width, best_height);
+ bg->pixbuf_cache = get_as_pixbuf_for_size (bg, bg->filename, num_monitor, best_width, best_height);
time_until_next_change = G_MAXUINT;
if (!bg->pixbuf_cache) {
SlideShow *show = get_as_slideshow (bg, bg->filename);
@@ -2037,15 +2197,15 @@ get_pixbuf_for_size (GnomeBG *bg,
if (slide->fixed) {
FileSize *size;
size = find_best_size (slide->file1, best_width, best_height);
- bg->pixbuf_cache = get_as_pixbuf_for_size (bg, size->file, best_width, best_height);
+ bg->pixbuf_cache = get_as_pixbuf_for_size (bg, size->file, num_monitor, best_width, best_height);
}
else {
FileSize *size;
GdkPixbuf *p1, *p2;
size = find_best_size (slide->file1, best_width, best_height);
- p1 = get_as_pixbuf_for_size (bg, size->file, best_width, best_height);
+ p1 = get_as_pixbuf_for_size (bg, size->file, num_monitor, best_width, best_height);
size = find_best_size (slide->file2, best_width, best_height);
- p2 = get_as_pixbuf_for_size (bg, size->file, best_width, best_height);
+ p2 = get_as_pixbuf_for_size (bg, size->file, num_monitor, best_width, best_height);
if (p1 && p2) {
bg->pixbuf_cache = blend (p1, p2, alpha);
@@ -2883,7 +3043,7 @@ gnome_bg_create_frame_thumbnail (GnomeBG *bg,
thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, frame_num + skipped);
if (thumb) {
- draw_image (bg->placement, thumb, result);
+ draw_image_for_thumb (bg, thumb, result);
g_object_unref (thumb);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]