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
|
||||
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -46,6 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "workspace.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
|||
#include <QMatrix4x4>
|
||||
|
||||
#include <KDE/KLocalizedString>
|
||||
#include <KDE/KNotification>
|
||||
#include <KProcess>
|
||||
|
||||
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");
|
||||
|
|
|
@ -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<float> &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);
|
||||
|
|
Loading…
Reference in a new issue