From 3dfb7d8827acd34fc17617deab68c9f0990782e1 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 15 Jul 2025 15:36:28 -0700 Subject: [PATCH] core/window: handle graphics context loss --- src/window/proxywindow.cpp | 20 ++++++++++++++++++++ src/window/proxywindow.hpp | 8 ++++++-- src/window/windowinterface.cpp | 1 + src/window/windowinterface.hpp | 6 ++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/window/proxywindow.cpp b/src/window/proxywindow.cpp index ac5127bf..618751ae 100644 --- a/src/window/proxywindow.cpp +++ b/src/window/proxywindow.cpp @@ -1,6 +1,7 @@ #include "proxywindow.hpp" #include +#include #include #include #include @@ -112,6 +113,8 @@ void ProxyWindowBase::ensureQWindow() { auto opaque = this->qsSurfaceFormat.opaqueModified ? this->qsSurfaceFormat.opaque : this->mColor.alpha() >= 255; + format.setOption(QSurfaceFormat::ResetNotification); + if (opaque) format.setAlphaBufferSize(0); else format.setAlphaBufferSize(8); @@ -195,6 +198,7 @@ void ProxyWindowBase::connectWindow() { QObject::connect(this->window, &QWindow::heightChanged, this, &ProxyWindowBase::heightChanged); QObject::connect(this->window, &QWindow::screenChanged, this, &ProxyWindowBase::screenChanged); QObject::connect(this->window, &QQuickWindow::colorChanged, this, &ProxyWindowBase::colorChanged); + QObject::connect(this->window, &QQuickWindow::sceneGraphError, this, &ProxyWindowBase::onSceneGraphError); QObject::connect(this->window, &ProxiedWindow::exposed, this, &ProxyWindowBase::onExposed); QObject::connect(this->window, &ProxiedWindow::devicePixelRatioChanged, this, &ProxyWindowBase::devicePixelRatioChanged); // clang-format on @@ -226,6 +230,22 @@ void ProxyWindowBase::completeWindow() { emit this->screenChanged(); } +void ProxyWindowBase::onSceneGraphError( + QQuickWindow::SceneGraphError error, + const QString& message +) { + if (error == QQuickWindow::ContextNotAvailable) { + qCritical().nospace() << "Failed to create graphics context for " << this << ": " << message; + } else { + qCritical().nospace() << "Scene graph error " << error << " occurred for " << this << ": " + << message; + } + + emit this->resourcesLost(); + this->mVisible = false; + this->setVisibleDirect(false); +} + void ProxyWindowBase::onVisibleChanged() { if (this->mVisible && !this->window->isVisible()) { this->mVisible = false; diff --git a/src/window/proxywindow.hpp b/src/window/proxywindow.hpp index ba35d594..025b970a 100644 --- a/src/window/proxywindow.hpp +++ b/src/window/proxywindow.hpp @@ -142,6 +142,7 @@ public: signals: void closed(); + void resourcesLost(); void windowConnected(); void windowDestroyed(); void visibleChanged(); @@ -161,13 +162,16 @@ signals: void polished(); protected slots: - void onVisibleChanged(); virtual void onWidthChanged(); virtual void onHeightChanged(); + virtual void onPolished(); + +private slots: + void onSceneGraphError(QQuickWindow::SceneGraphError error, const QString& message); + void onVisibleChanged(); void onMaskChanged(); void onMaskDestroyed(); void onScreenDestroyed(); - virtual void onPolished(); void onExposed(); protected: diff --git a/src/window/windowinterface.cpp b/src/window/windowinterface.cpp index aac0df34..8917f12d 100644 --- a/src/window/windowinterface.cpp +++ b/src/window/windowinterface.cpp @@ -134,6 +134,7 @@ void WindowInterface::connectSignals() const { auto* window = this->proxyWindow(); // clang-format off QObject::connect(window, &ProxyWindowBase::closed, this, &WindowInterface::closed); + QObject::connect(window, &ProxyWindowBase::resourcesLost, this, &WindowInterface::resourcesLost); QObject::connect(window, &ProxyWindowBase::windowConnected, this, &WindowInterface::windowConnected); QObject::connect(window, &ProxyWindowBase::visibleChanged, this, &WindowInterface::visibleChanged); QObject::connect(window, &ProxyWindowBase::backerVisibilityChanged, this, &WindowInterface::backingWindowVisibleChanged); diff --git a/src/window/windowinterface.hpp b/src/window/windowinterface.hpp index e3ed84a4..9e917b9f 100644 --- a/src/window/windowinterface.hpp +++ b/src/window/windowinterface.hpp @@ -239,6 +239,12 @@ signals: /// This signal is emitted when the window is closed by the user, the display server, /// or an error. It is not emitted when @@visible is set to false. void closed(); + /// This signal is emitted when resources a window depends on to display are lost, + /// or could not be acquired during window creation. The most common trigger for + /// this signal is a lack of VRAM when creating or resizing a window. + /// + /// Following this signal, @@closed(s) will be sent. + void resourcesLost(); void windowConnected(); void visibleChanged(); void backingWindowVisibleChanged();