Handle context loss in the threaded render loop
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>
Tue, 10 Mar 2015 15:59:08 +0000 (16:59 +0100)
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>
Thu, 12 Mar 2015 09:46:30 +0000 (09:46 +0000)
Change-Id: I3f9219dd2fed15094c2f7d670a981406e601959b
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
src/quick/items/qquickwindow.cpp
src/quick/items/qquickwindow_p.h
src/quick/scenegraph/qsgthreadedrenderloop.cpp

index aabeefb..35f4a84 100644 (file)
@@ -1403,6 +1403,9 @@ bool QQuickWindow::event(QEvent *e)
         break;
     }
 
+    if (e->type() == QEvent::Type(QQuickWindowPrivate::FullUpdateRequest))
+        update();
+
     return QWindow::event(e);
 }
 
index c3ae6c0..a61c0b0 100644 (file)
@@ -101,6 +101,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickWindowPrivate : public QWindowPrivate
 public:
     Q_DECLARE_PUBLIC(QQuickWindow)
 
+    enum CustomEvents {
+        FullUpdateRequest = QEvent::User + 1
+    };
+
     static inline QQuickWindowPrivate *get(QQuickWindow *c) { return c->d_func(); }
 
     QQuickWindowPrivate();
index 6974271..e1a5481 100644 (file)
@@ -490,6 +490,14 @@ void QSGRenderThread::sync(bool inExpose)
     bool current = false;
     if (windowSize.width() > 0 && windowSize.height() > 0)
         current = gl->makeCurrent(window);
+    // Check for context loss.
+    if (!current && !gl->isValid()) {
+        QQuickWindowPrivate::get(window)->cleanupNodesOnShutdown();
+        sgrc->invalidate();
+        current = gl->create() && gl->makeCurrent(window);
+        if (current)
+            sgrc->initialize(gl);
+    }
     if (current) {
         QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
         bool hadRenderer = d->renderer != 0;
@@ -571,6 +579,12 @@ void QSGRenderThread::syncAndRender()
     bool current = false;
     if (d->renderer && windowSize.width() > 0 && windowSize.height() > 0)
         current = gl->makeCurrent(window);
+    // Check for context loss.
+    if (!current && !gl->isValid()) {
+        // Cannot do anything here because gui is not locked. Request a new
+        // sync+render round on the gui thread and let the sync handle it.
+        QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest)));
+    }
     if (current) {
         d->renderSceneGraph(windowSize);
         if (profileFrames)