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:
parent
7f0d0436e9
commit
041be646b5
4 changed files with 63 additions and 0 deletions
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 ®ion)
|
||||||
}
|
}
|
||||||
#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");
|
||||||
|
|
|
@ -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 ®ion, ScreenPaintData &data);
|
virtual void paintDesktop(int desktop, int mask, const QRegion ®ion, 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);
|
||||||
|
|
Loading…
Reference in a new issue