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