kwin: Detect and handle graphics resets

Reset compositing when the GL context state has been lost as a result
of a graphics reset.
This commit is contained in:
Fredrik Höglund 2013-05-19 16:45:06 +02:00
parent 7f0d0436e9
commit 041be646b5
4 changed files with 63 additions and 0 deletions

View file

@ -198,6 +198,7 @@ void Compositor::slotCompositingOptionsInitialized()
#endif #endif
m_scene = SceneOpenGL::createScene(); m_scene = SceneOpenGL::createScene();
connect(m_scene, SIGNAL(resetCompositing()), SLOT(restart()));
// TODO: Add 30 second delay to protect against screen freezes as well // TODO: Add 30 second delay to protect against screen freezes as well
unsafeConfig.writeEntry(openGLIsUnsafe, false); unsafeConfig.writeEntry(openGLIsUnsafe, false);

View file

@ -194,3 +194,8 @@ Comment[x-test]=xxAnother application has requested to suspend compositing.xx
Comment[zh_CN]=另一个应用程序已经请求中断混成操作。 Comment[zh_CN]=另一个应用程序已经请求中断混成操作。
Comment[zh_TW]=另一個應用程式要求暫停組合效能。 Comment[zh_TW]=另一個應用程式要求暫停組合效能。
Action=Popup Action=Popup
[Event/graphicsreset]
Name=Graphics Reset
Comment=A graphics reset event occurred
Action=Popup

View file

@ -46,6 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "workspace.h" #include "workspace.h"
#include <math.h> #include <math.h>
#include <unistd.h>
// turns on checks for opengl errors in various places (for easier finding of them) // turns on checks for opengl errors in various places (for easier finding of them)
// normally only few of them are enabled // normally only few of them are enabled
@ -64,6 +65,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QMatrix4x4> #include <QMatrix4x4>
#include <KDE/KLocalizedString> #include <KDE/KLocalizedString>
#include <KDE/KNotification>
#include <KProcess> #include <KProcess>
namespace KWin namespace KWin
@ -275,6 +277,48 @@ void SceneOpenGL::copyPixels(const QRegion &region)
} }
#endif #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) qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
{ {
// actually paint the frame, flushed with the NEXT frame // actually paint the frame, flushed with the NEXT frame
@ -285,6 +329,13 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
} }
m_backend->prepareRenderingFrame(); m_backend->prepareRenderingFrame();
const GLenum status = glGetGraphicsResetStatus();
if (status != GL_NO_ERROR) {
handleGraphicsReset(status);
return 0;
}
int mask = 0; int mask = 0;
#ifdef CHECK_GL_ERROR #ifdef CHECK_GL_ERROR
checkGLError("Paint1"); checkGLError("Paint1");

View file

@ -80,8 +80,14 @@ protected:
QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const; QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const;
virtual void paintDesktop(int desktop, int mask, const QRegion &region, ScreenPaintData &data); virtual void paintDesktop(int desktop, int mask, const QRegion &region, ScreenPaintData &data);
void handleGraphicsReset(GLenum status);
virtual void doPaintBackground(const QVector<float> &vertices) = 0; virtual void doPaintBackground(const QVector<float> &vertices) = 0;
virtual SceneOpenGL::Window *createWindow(Toplevel *t) = 0; virtual SceneOpenGL::Window *createWindow(Toplevel *t) = 0;
Q_SIGNALS:
void resetCompositing();
public Q_SLOTS: public Q_SLOTS:
virtual void windowOpacityChanged(KWin::Toplevel* c); virtual void windowOpacityChanged(KWin::Toplevel* c);
virtual void windowGeometryShapeChanged(KWin::Toplevel* c); virtual void windowGeometryShapeChanged(KWin::Toplevel* c);