From a5265365dd268e15a461a58000a10b122d0bccba Mon Sep 17 00:00:00 2001 From: Daniel van Vugt Date: Thu, 23 May 2019 18:15:28 +0800 Subject: [PATCH] background: Reload when GPU memory is invalidated Fixes corrupt background wallpaper when resuming from suspend on the Nvidia driver. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1084 https://gitlab.gnome.org/GNOME/mutter/merge_requests/600 --- src/compositor/meta-background.c | 46 +++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/compositor/meta-background.c b/src/compositor/meta-background.c index 4efc1ed54..4a1ce0396 100644 --- a/src/compositor/meta-background.c +++ b/src/compositor/meta-background.c @@ -252,12 +252,11 @@ static void set_file (MetaBackground *self, GFile **filep, MetaBackgroundImage **imagep, - GFile *file) + GFile *file, + gboolean force_reload) { - if (!file_equal0 (*filep, file)) + if (force_reload || !file_equal0 (*filep, file)) { - g_clear_object (filep); - if (*imagep) { g_signal_handlers_disconnect_by_func (*imagep, @@ -267,11 +266,12 @@ set_file (MetaBackground *self, *imagep = NULL; } + g_set_object (filep, file); + if (file) { MetaBackgroundImageCache *cache = meta_background_image_cache_get_default (); - *filep = g_object_ref (file); *imagep = meta_background_image_cache_load (cache, file); g_signal_connect (*imagep, "loaded", G_CALLBACK (on_background_loaded), self); @@ -279,6 +279,32 @@ set_file (MetaBackground *self, } } +static void +on_gl_video_memory_purged (MetaBackground *self) +{ + MetaBackgroundImageCache *cache = meta_background_image_cache_get_default (); + + /* The GPU memory that just got invalidated is the texture inside + * self->background_image1,2 and/or its mipmaps. However, to save memory the + * original pixbuf isn't kept in RAM so we can't do a simple re-upload. The + * only copy of the image was the one in texture memory that got invalidated. + * So we need to do a full reload from disk. + */ + if (self->file1) + { + meta_background_image_cache_purge (cache, self->file1); + set_file (self, &self->file1, &self->background_image1, self->file1, TRUE); + } + + if (self->file2) + { + meta_background_image_cache_purge (cache, self->file2); + set_file (self, &self->file2, &self->background_image2, self->file2, TRUE); + } + + mark_changed (self); +} + static void meta_background_dispose (GObject *object) { @@ -287,8 +313,8 @@ meta_background_dispose (GObject *object) free_color_texture (self); free_wallpaper_texture (self); - set_file (self, &self->file1, &self->background_image1, NULL); - set_file (self, &self->file2, &self->background_image2, NULL); + set_file (self, &self->file1, &self->background_image1, NULL, FALSE); + set_file (self, &self->file2, &self->background_image2, NULL, FALSE); set_display (self, NULL); @@ -312,7 +338,7 @@ meta_background_constructed (GObject *object) G_OBJECT_CLASS (meta_background_parent_class)->constructed (object); g_signal_connect_object (self->display, "gl-video-memory-purged", - G_CALLBACK (mark_changed), object, G_CONNECT_SWAPPED); + G_CALLBACK (on_gl_video_memory_purged), object, G_CONNECT_SWAPPED); g_signal_connect_object (monitor_manager, "monitors-changed", G_CALLBACK (on_monitors_changed), self, @@ -937,8 +963,8 @@ meta_background_set_blend (MetaBackground *self, g_return_if_fail (META_IS_BACKGROUND (self)); g_return_if_fail (blend_factor >= 0.0 && blend_factor <= 1.0); - set_file (self, &self->file1, &self->background_image1, file1); - set_file (self, &self->file2, &self->background_image2, file2); + set_file (self, &self->file1, &self->background_image1, file1, FALSE); + set_file (self, &self->file2, &self->background_image2, file2, FALSE); self->blend_factor = blend_factor; self->style = style;