Package: gnome-shell
Version: 3.14.2-3+b1
Severity: normal
Tags: upstream
Dear Maintainer,
The proprietary NVIDIA driver has a bug where it doesn't preserve OpenGL
frame buffer objects (FBOs) across power events (most noticeably across
a suspend/resume cycle). This is reported in Debian as bug
https://bugs.debian.org/761360 (and a couple others that got merged into
that), and upstream as https://bugzilla.gnome.org/739178. GNOME started
storing the backgrounds for the desktop and lock screen in FBOs in 3.14,
which is why the issue didn't show up before 3.14.
This is NVIDIA's problem, of course, and NVIDIA has admitted as much,
but the word from NVIDIA is just that this will be fixed at some
indeterminate point "in the future."
In the meantime, upstream has applied a patch included in the 3.14.4
releases of gnome-shell and mutter, and will also include this fix in
the 3.16.1 release. The patch adds an ability to mutter to redraw all
FBO background instances, and invokes this from gnome-shell during resume.
The upstream patches (reattached here) apply to the gnome-shell and
mutter versions currently in sid/testing. I've rebuilt the packages
locally (on amd64/unstable) with the patches applied, and can confirm
that this does work around the problem with the proprietary NVIDIA driver.
It would be nice for proprietary NVIDIA jessie users if we could get
these patches applied to jessie as well, perhaps for the first jessie
point update, either with a package update to 3.14.4, or by applying
these patches to the current 3.14.2 version: this is going to be an
issue that affects a lot of jessie users, and it doesn't sound as though
NVIDIA is particularly concerned about fixing it in the immediate future.
The upstream patches are attached here for convenience:
background-instance-refresh.patch is the mutter side of the fix,
refresh-bg-after-suspend.patch is the gnome-shell side of the fix.
Thanks,
Jason Rhinelander
From c96f57449f1cdc60162f6bbcc82d504fde5c1f76 Mon Sep 17 00:00:00 2001
From: Rui Matos <tiagoma...@gmail.com>
Date: Thu, 19 Mar 2015 14:58:25 +0100
Subject: [PATCH] meta-background: Add a function to refresh all background
instances
We need to reload the FBOs under some circumstances, this adds a way
to easily do so.
https://bugzilla.gnome.org/show_bug.cgi?id=739178
---
src/compositor/meta-background.c | 14 ++++++++++++++
src/meta/meta-background.h | 2 ++
2 files changed, 16 insertions(+)
diff --git a/src/compositor/meta-background.c b/src/compositor/meta-background.c
index 6284a7a..3f2e23f 100644
--- a/src/compositor/meta-background.c
+++ b/src/compositor/meta-background.c
@@ -71,6 +71,8 @@ enum
G_DEFINE_TYPE (MetaBackground, meta_background, G_TYPE_OBJECT)
+static GSList *all_backgrounds = NULL;
+
static void
free_fbos (MetaBackground *self)
{
@@ -305,6 +307,8 @@ meta_background_dispose (GObject *object)
static void
meta_background_finalize (GObject *object)
{
+ all_backgrounds = g_slist_remove (all_backgrounds, object);
+
G_OBJECT_CLASS (meta_background_parent_class)->finalize (object);
}
@@ -347,6 +351,7 @@ meta_background_init (MetaBackground *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
META_TYPE_BACKGROUND,
MetaBackgroundPrivate);
+ all_backgrounds = g_slist_prepend (all_backgrounds, self);
}
static void
@@ -913,3 +918,12 @@ meta_background_set_blend (MetaBackground *self,
free_wallpaper_texture (self);
mark_changed (self);
}
+
+void
+meta_background_refresh_all (void)
+{
+ GSList *l;
+
+ for (l = all_backgrounds; l; l = l->next)
+ mark_changed (l->data);
+}
diff --git a/src/meta/meta-background.h b/src/meta/meta-background.h
index 822d27b..d48d966 100644
--- a/src/meta/meta-background.h
+++ b/src/meta/meta-background.h
@@ -57,6 +57,8 @@ struct _MetaBackground
MetaBackgroundPrivate *priv;
};
+void meta_background_refresh_all (void);
+
GType meta_background_get_type (void);
MetaBackground *meta_background_new (MetaScreen *screen);
--
2.1.0
From d19e78af2459b1b5165848b643525df29ee20265 Mon Sep 17 00:00:00 2001
From: Rui Matos <tiagoma...@gmail.com>
Date: Thu, 19 Mar 2015 15:46:08 +0100
Subject: [PATCH] Refresh all background instances after suspend if needed
NVIDIA drivers don't preserve FBO contents across suspend / resume
cycles which results in broken backgrounds. We can work around that by
forcing a refresh when coming out of suspend.
https://bugzilla.gnome.org/show_bug.cgi?id=739178
---
js/ui/layout.js | 13 +++++++++++++
src/shell-util.c | 33 +++++++++++++++++++++++++++++++++
src/shell-util.h | 2 ++
3 files changed, 48 insertions(+)
diff --git a/js/ui/layout.js b/js/ui/layout.js
index 9228bd1..e9aab13 100644
--- a/js/ui/layout.js
+++ b/js/ui/layout.js
@@ -11,6 +11,7 @@ const St = imports.gi.St;
const Background = imports.ui.background;
const BackgroundMenu = imports.ui.backgroundMenu;
+const LoginManager = imports.misc.loginManager;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
@@ -248,6 +249,18 @@ const LayoutManager = new Lang.Class({
global.screen.connect('in-fullscreen-changed',
Lang.bind(this, this._updateFullscreen));
this._monitorsChanged();
+
+ // NVIDIA drivers don't preserve FBO contents across
+ // suspend/resume, see
+ // https://bugzilla.gnome.org/show_bug.cgi?id=739178
+ if (Shell.util_need_background_refresh()) {
+ LoginManager.getLoginManager().connect('prepare-for-sleep',
+ function(lm, suspending) {
+ if (suspending)
+ return;
+ Meta.Background.refresh_all();
+ });
+ }
},
// This is called by Main after everything else is constructed
diff --git a/src/shell-util.c b/src/shell-util.c
index 5ae4fdb..8792403 100644
--- a/src/shell-util.c
+++ b/src/shell-util.c
@@ -5,6 +5,9 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include <GL/gl.h>
+#include <cogl/cogl.h>
+
#include "shell-util.h"
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
@@ -330,3 +333,33 @@ shell_util_cursor_tracker_to_clutter (MetaCursorTracker *tracker,
clutter_actor_hide (CLUTTER_ACTOR (texture));
}
}
+
+typedef const gchar *(*ShellGLGetString) (GLenum);
+
+static const gchar *
+get_gl_vendor (void)
+{
+ static const gchar *vendor = NULL;
+
+ if (!vendor)
+ {
+ ShellGLGetString gl_get_string;
+ gl_get_string = (ShellGLGetString) cogl_get_proc_address ("glGetString");
+ if (gl_get_string)
+ vendor = gl_get_string (GL_VENDOR);
+ }
+
+ return vendor;
+}
+
+gboolean
+shell_util_need_background_refresh (void)
+{
+ if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
+ return FALSE;
+
+ if (g_strcmp0 (get_gl_vendor (), "NVIDIA Corporation") == 0)
+ return TRUE;
+
+ return FALSE;
+}
diff --git a/src/shell-util.h b/src/shell-util.h
index d7ab4fd..be20083 100644
--- a/src/shell-util.h
+++ b/src/shell-util.h
@@ -44,6 +44,8 @@ GdkPixbuf *shell_util_create_pixbuf_from_data (const guchar *data,
void shell_util_cursor_tracker_to_clutter (MetaCursorTracker *tracker,
ClutterTexture *texture);
+gboolean shell_util_need_background_refresh (void);
+
G_END_DECLS
#endif /* __SHELL_UTIL_H__ */
--
2.1.0