From 1c5e709e76a0c8e8ac373c75d823b235f9d1ca78 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 22 Apr 2020 17:50:44 +0200 Subject: [PATCH] WIP: Limited workaround for device loss Change-Id: Ia7f7a58ab91eb34cc2cb6283673158e211cadf78 --- .../platforms/windows/qwindowseglcontext.cpp | 40 ++++++++++++++++--- .../platforms/windows/qwindowseglcontext.h | 3 ++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 4ae087dfaa..a6c83b2116 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -461,6 +461,37 @@ QWindowsEGLContext::~QWindowsEGLContext() } } +void QWindowsEGLContext::handleContextLost(QWindowsWindow *window) +{ + // Newer ANGLE requires destroying all existing contexts associated with the + // EGLDisplay before a subsequent eglCreateContext() is allowed to succeed. + QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext); + m_eglContext = EGL_NO_CONTEXT; + + window->invalidateSurface(); + + + + // ### NB! The following is technically incorrect and is almost certainly guaranteed + // to break if more than one QOpenGLContext or window are involved. It does work in a + // single QQuickWindow type of applications but is not suitable otherwise. It is also + // insufficient for QQuickWidget and friends. + // + // Instead, the QWindowsEGLStaticContext would need to implement the proper + // infrastructure for tracking all associated resources (in a thread safe manner!), + // and having a central point of reinitializing which would then invalidate all + // associated handles etc. etc. + + + + // In addition the EGLDisplay needs to be terminated and reinitialized. (why? is this + // a bug in ANGLE?) + EGLint major = 0; + EGLint minor = 0; + QWindowsEGLStaticContext::libEGL.eglTerminate(m_eglDisplay); + QWindowsEGLStaticContext::libEGL.eglInitialize(m_eglDisplay, &major, &minor); +} + bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) { Q_ASSERT(surface->surface()->supportsOpenGL()); @@ -473,8 +504,8 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) auto eglSurface = static_cast(window->surface(m_eglConfig, &err)); if (eglSurface == EGL_NO_SURFACE) { if (err == EGL_CONTEXT_LOST) { - m_eglContext = EGL_NO_CONTEXT; qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this; + handleContextLost(window); } else if (err == EGL_BAD_ACCESS) { // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters. qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this; @@ -505,10 +536,9 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) // EGL_CONTEXT_LOST (loss of the D3D device) is not necessarily fatal. // Qt Quick is able to recover for example. if (err == EGL_CONTEXT_LOST) { - m_eglContext = EGL_NO_CONTEXT; qCDebug(lcQpaGl) << "Got EGL context lost in makeCurrent() for context" << this; // Drop the surface. Will recreate on the next makeCurrent. - window->invalidateSurface(); + handleContextLost(window); } else { qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this); } @@ -534,8 +564,8 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface) auto eglSurface = static_cast(window->surface(m_eglConfig, &err)); if (eglSurface == EGL_NO_SURFACE) { if (err == EGL_CONTEXT_LOST) { - m_eglContext = EGL_NO_CONTEXT; qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this; + handleContextLost(window); } return; } @@ -544,8 +574,8 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface) if (!ok) { err = QWindowsEGLStaticContext::libEGL.eglGetError(); if (err == EGL_CONTEXT_LOST) { - m_eglContext = EGL_NO_CONTEXT; qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()"; + handleContextLost(window); } else { qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this); } diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h index d96e266159..b556d5bd2a 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -46,6 +46,8 @@ QT_BEGIN_NAMESPACE +class QWindowsWindow; + struct QWindowsLibEGL { bool init(); @@ -160,6 +162,7 @@ public: private: EGLConfig chooseConfig(const QSurfaceFormat &format); + void handleContextLost(QWindowsWindow *window); QWindowsEGLStaticContext *m_staticContext; EGLContext m_eglContext; -- 2.23.0.windows.1