Fix failing makeCurrent in basic renderloop when closing windows
authorLaszlo Agocs <laszlo.agocs@digia.com>
Mon, 20 Oct 2014 11:46:13 +0000 (13:46 +0200)
committerOleg Shparber <trollixx@gmail.com>
Tue, 21 Oct 2014 01:15:54 +0000 (03:15 +0200)
The makeCurrent() call can fail if there is no underlying platform
window present anymore (due to close()).

Just continuing with the cleanup is wrong: There may be another context
current (from the application or from some other component of Qt) and
there are GL calls issued which would mess up the state in that context.
Therefore we ensure there's a context/surface by using a temporary
QOffscreenSurface.

Task-number: QTBUG-41942
Change-Id: I79f35a1f5bbe7a8a14943e8603764575ed119f93
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
src/quick/scenegraph/qsgrenderloop.cpp

index cd92d12..f2586b1 100644 (file)
@@ -41,6 +41,7 @@
 #include <QtCore/private/qabstractanimation_p.h>
 
 #include <QtGui/QOpenGLContext>
+#include <QtGui/QOffscreenSurface>
 #include <QtGui/private/qguiapplication_p.h>
 #include <qpa/qplatformintegration.h>
 
@@ -274,15 +275,30 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
     m_windows.remove(window);
     hide(window);
     QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
-    if (gl)
-        gl->makeCurrent(window);
+
+    bool current = false;
+    QScopedPointer<QOffscreenSurface> offscreenSurface;
+    if (gl) {
+        QSurface *surface = window;
+        // There may be no platform window if the window got closed.
+        if (!window->handle()) {
+            offscreenSurface.reset(new QOffscreenSurface);
+            offscreenSurface->setFormat(gl->format());
+            offscreenSurface->create();
+            surface = offscreenSurface.data();
+        }
+        current = gl->makeCurrent(surface);
+    }
+    if (Q_UNLIKELY(!current))
+        qCDebug(QSG_LOG_RENDERLOOP) << "cleanup without an OpenGL context";
+
     d->cleanupNodesOnShutdown();
     if (m_windows.size() == 0) {
         rc->invalidate();
         QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
         delete gl;
         gl = 0;
-    } else if (gl && window == gl->surface()) {
+    } else if (gl && window == gl->surface() && current) {
         gl->doneCurrent();
     }
 }