From 367a91d27880408c0924e15c5d1a156fff99a025 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs <laszlo.agocs@theqtcompany.com> Date: Tue, 10 Mar 2015 12:14:03 +0100 Subject: [PATCH] Enhance EGL_CONTEXT_LOST checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently failures can occur not just when doing eglMakeCurrent() but also when creating window surfaces. Change-Id: Ife1210293d5120fd41352164d9c89e83fb5ce468 Reviewed-by: Michael Brüning <michael.bruning@theqtcompany.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> --- .../platforms/windows/qwindowseglcontext.cpp | 33 ++++++++++++++----- .../platforms/windows/qwindowseglcontext.h | 2 +- .../platforms/windows/qwindowsopenglcontext.h | 2 +- .../platforms/windows/qwindowswindow.cpp | 4 +-- .../platforms/windows/qwindowswindow.h | 2 +- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 74efd492177..7db6abd8efd 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -416,12 +416,15 @@ QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *c return new QWindowsEGLContext(this, context->format(), context->shareHandle()); } -void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig) +void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) { + *err = 0; EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, (EGLConfig) nativeConfig, (EGLNativeWindowType) nativeWindow, 0); - if (surface == EGL_NO_SURFACE) - qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, libEGL.eglGetError()); + if (surface == EGL_NO_SURFACE) { + *err = libEGL.eglGetError(); + qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err); + } return surface; } @@ -578,8 +581,15 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) QWindowsWindow *window = static_cast<QWindowsWindow *>(surface); window->aboutToMakeCurrent(); - EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig)); - Q_ASSERT(eglSurface); + int err = 0; + EGLSurface eglSurface = static_cast<EGLSurface>(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; + } + return false; + } // shortcut: on some GPUs, eglMakeCurrent is not a cheap operation if (QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() == m_eglContext && @@ -597,7 +607,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) QWindowsEGLStaticContext::libEGL.eglSwapInterval(m_staticContext->display(), m_swapInterval); } } else { - int err = QWindowsEGLStaticContext::libEGL.eglGetError(); + err = QWindowsEGLStaticContext::libEGL.eglGetError(); // 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) { @@ -625,8 +635,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface) { QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api); QWindowsWindow *window = static_cast<QWindowsWindow *>(surface); - EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig)); - Q_ASSERT(eglSurface); + int err = 0; + EGLSurface eglSurface = static_cast<EGLSurface>(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; + } + return; + } bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface); if (!ok) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h index 55f58fac5f9..2b249348c3c 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -260,7 +260,7 @@ public: void *moduleHandle() const { return libGLESv2.moduleHandle(); } QOpenGLContext::OpenGLModuleType moduleType() const { return QOpenGLContext::LibGLES; } - void *createWindowSurface(void *nativeWindow, void *nativeConfig) Q_DECL_OVERRIDE; + void *createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) Q_DECL_OVERRIDE; void destroyWindowSurface(void *nativeSurface) Q_DECL_OVERRIDE; QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config, const QSurfaceFormat &referenceFormat); diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h index 8ebcb83a089..2c52c58829b 100644 --- a/src/plugins/platforms/windows/qwindowsopenglcontext.h +++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h @@ -56,7 +56,7 @@ public: // If the windowing system interface needs explicitly created window surfaces (like EGL), // reimplement these. - virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/) { return 0; } + virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return 0; } virtual void destroyWindowSurface(void * /*nativeSurface*/) { } private: diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 6b490b9404b..2fd0f12c268 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -2259,14 +2259,14 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins) } } -void *QWindowsWindow::surface(void *nativeConfig) +void *QWindowsWindow::surface(void *nativeConfig, int *err) { #ifdef QT_NO_OPENGL return 0; #else if (!m_surface) { if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) - m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig); + m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err); } return m_surface; diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index f0b04fbc474..0089ad07a09 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -248,7 +248,7 @@ public: bool isEnabled() const; void setWindowIcon(const QIcon &icon); - void *surface(void *nativeConfig); + void *surface(void *nativeConfig, int *err); void invalidateSurface() Q_DECL_OVERRIDE; void aboutToMakeCurrent(); -- GitLab