diff options
author | David Edmundson <davidedmundson@kde.org> | 2022-01-28 16:24:32 +0000 |
---|---|---|
committer | David Edmundson <davidedmundson@kde.org> | 2023-03-07 13:26:50 +0000 |
commit | 26d8603b523af973682b7e602f1158ae62f21c9b (patch) | |
tree | cf5223fea624e961af7150fdde44bdf1e9cfa27a /src/hardwareintegration | |
parent | 83599e16789f945ef15954f2a2aabb37b245e596 (diff) | |
download | qtwayland-26d8603b523af973682b7e602f1158ae62f21c9b.tar.gz |
Introduce path for surviving compositor restarts
This patch introduces an optional mechanism for clients to survive a
crash and reconnect seemingly seamlessly.
In the event of a disconnect from the compositor socket we simply try to
reconnect again and replay any data needed so that we maintain a
consistent state to where we left off.
From an application point-of-view any open popups will be dismissed and
we we potentially get a new framecallback, but it will be almost
entirely transparent. Users of custom QWaylandClientExtensions will be
notified via the activeChanged signal and rebuild as though the
compositor had withdrawn and re-announced the global.
OpenGL contexts will be marked as invalid, and handled the same way as a
GPU reset. On the next frame RHI will notice these are invalid and
recreate them, only now against a new wl_display and new EGLDisplay.
Users of low level EGL/native objects might be affected, but the
alternative at this point is being closed anyway. The entire codepath is
only activated via an environment variable.
Change-Id: I6c4acc885540e14cead7640794df86dd974fef4f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Diffstat (limited to 'src/hardwareintegration')
4 files changed, 17 insertions, 0 deletions
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp index 8221d5d9..ca7d58f3 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp @@ -140,6 +140,12 @@ void QWaylandEglWindow::invalidateSurface() m_contentFBO = nullptr; } +void QWaylandEglWindow::reinit() +{ + QWaylandWindow::reinit(); + m_clientBufferIntegration = static_cast<QWaylandEglClientBufferIntegration *>(mDisplay->clientBufferIntegration()); +} + EGLSurface QWaylandEglWindow::eglSurface() const { return m_eglSurface; diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow_p.h b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow_p.h index 5b9aa987..cfcdd577 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow_p.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow_p.h @@ -50,6 +50,7 @@ public: void bindContentFBO(); void invalidateSurface() override; + void reinit() override; private: QWaylandEglClientBufferIntegration *m_clientBufferIntegration = nullptr; diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp index 0b64db5c..050b3eba 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp @@ -195,6 +195,10 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *dis const QSurfaceFormat &fmt, QPlatformOpenGLContext *share) : QEGLPlatformContext(fmt, share, eglDisplay), m_display(display) { + m_reconnectionWatcher = QObject::connect(m_display, &QWaylandDisplay::reconnected, [this]() { + invalidateContext(); + }); + switch (format().renderableType()) { case QSurfaceFormat::OpenVG: m_api = EGL_OPENVG_API; @@ -260,6 +264,7 @@ void QWaylandGLContext::destroyTemporaryOffscreenSurface(EGLSurface eglSurface) QWaylandGLContext::~QWaylandGLContext() { + QObject::disconnect(m_reconnectionWatcher); delete m_blitter; m_blitter = nullptr; if (m_decorationsContext != EGL_NO_CONTEXT) @@ -280,6 +285,10 @@ void QWaylandGLContext::endFrame() bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) { + if (!isValid()) { + return false; + } + // in QWaylandGLContext() we called eglBindAPI with the correct value. However, // eglBindAPI's documentation says: // "eglBindAPI defines the current rendering API for EGL in the thread it is called from" diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext_p.h b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext_p.h index 00ef99b1..b985c667 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext_p.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext_p.h @@ -62,6 +62,7 @@ private: wl_surface *m_wlSurface = nullptr; wl_egl_window *m_eglWindow = nullptr; QWaylandEglWindow *m_currentWindow = nullptr; + QMetaObject::Connection m_reconnectionWatcher; }; } |