diff --git a/composite.cpp b/composite.cpp
index d82be84d5b..eddd663c96 100644
--- a/composite.cpp
+++ b/composite.cpp
@@ -198,6 +198,7 @@ void Compositor::slotCompositingOptionsInitialized()
#endif
m_scene = SceneOpenGL::createScene();
+ connect(m_scene, SIGNAL(resetCompositing()), SLOT(restart()));
// TODO: Add 30 second delay to protect against screen freezes as well
unsafeConfig.writeEntry(openGLIsUnsafe, false);
diff --git a/kwin.notifyrc b/kwin.notifyrc
index eda3fc2cf5..fa0b779f5d 100644
--- a/kwin.notifyrc
+++ b/kwin.notifyrc
@@ -194,3 +194,8 @@ Comment[x-test]=xxAnother application has requested to suspend compositing.xx
Comment[zh_CN]=另一个应用程序已经请求中断混成操作。
Comment[zh_TW]=另一個應用程式要求暫停組合效能。
Action=Popup
+
+[Event/graphicsreset]
+Name=Graphics Reset
+Comment=A graphics reset event occurred
+Action=Popup
diff --git a/scene_opengl.cpp b/scene_opengl.cpp
index 8ea91aadf4..b79bad60b9 100644
--- a/scene_opengl.cpp
+++ b/scene_opengl.cpp
@@ -46,6 +46,7 @@ along with this program. If not, see .
#include "workspace.h"
#include
+#include
// turns on checks for opengl errors in various places (for easier finding of them)
// normally only few of them are enabled
@@ -64,6 +65,7 @@ along with this program. If not, see .
#include
#include
+#include
#include
namespace KWin
@@ -275,6 +277,48 @@ void SceneOpenGL::copyPixels(const QRegion ®ion)
}
#endif
+#ifndef KWIN_HAVE_OPENGLES
+# define GL_GUILTY_CONTEXT_RESET_KWIN GL_GUILTY_CONTEXT_RESET_ARB
+# define GL_INNOCENT_CONTEXT_RESET_KWIN GL_INNOCENT_CONTEXT_RESET_ARB
+# define GL_UNKNOWN_CONTEXT_RESET_KWIN GL_UNKNOWN_CONTEXT_RESET_ARB
+#else
+# define GL_GUILTY_CONTEXT_RESET_KWIN GL_GUILTY_CONTEXT_RESET_EXT
+# define GL_INNOCENT_CONTEXT_RESET_KWIN GL_INNOCENT_CONTEXT_RESET_EXT
+# define GL_UNKNOWN_CONTEXT_RESET_KWIN GL_UNKNOWN_CONTEXT_RESET_EXT
+#endif
+
+void SceneOpenGL::handleGraphicsReset(GLenum status)
+{
+ switch (status) {
+ case GL_GUILTY_CONTEXT_RESET_KWIN:
+ kDebug(1212) << "A graphics reset attributable to the current GL context occurred.";
+ break;
+
+ case GL_INNOCENT_CONTEXT_RESET_KWIN:
+ kDebug(1212) << "A graphics reset not attributable to the current GL context occurred.";
+ break;
+
+ case GL_UNKNOWN_CONTEXT_RESET_KWIN:
+ kDebug(1212) << "A graphics reset of an unknown cause occurred.";
+ break;
+
+ default:
+ break;
+ }
+
+ QElapsedTimer timer;
+ timer.start();
+
+ // Wait until the reset is completed or max 10 seconds
+ while (timer.elapsed() < 10000 && glGetGraphicsResetStatus() != GL_NO_ERROR)
+ usleep(50);
+
+ kDebug(1212) << "Attempting to reset compositing.";
+ QMetaObject::invokeMethod(this, "resetCompositing", Qt::QueuedConnection);
+
+ KNotification::event("graphicsreset", i18n("Desktop effects were restarted due to a graphics reset"));
+}
+
qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
{
// actually paint the frame, flushed with the NEXT frame
@@ -285,6 +329,13 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
}
m_backend->prepareRenderingFrame();
+
+ const GLenum status = glGetGraphicsResetStatus();
+ if (status != GL_NO_ERROR) {
+ handleGraphicsReset(status);
+ return 0;
+ }
+
int mask = 0;
#ifdef CHECK_GL_ERROR
checkGLError("Paint1");
diff --git a/scene_opengl.h b/scene_opengl.h
index 439414bd48..b8a998358b 100644
--- a/scene_opengl.h
+++ b/scene_opengl.h
@@ -80,8 +80,14 @@ protected:
QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const;
virtual void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data);
+ void handleGraphicsReset(GLenum status);
+
virtual void doPaintBackground(const QVector &vertices) = 0;
virtual SceneOpenGL::Window *createWindow(Toplevel *t) = 0;
+
+Q_SIGNALS:
+ void resetCompositing();
+
public Q_SLOTS:
virtual void windowOpacityChanged(KWin::Toplevel* c);
virtual void windowGeometryShapeChanged(KWin::Toplevel* c);