Fix QQuickWidget cleanup and invalidation sequence
authorLaszlo Agocs <laszlo.agocs@digia.com>
Fri, 30 May 2014 11:53:25 +0000 (13:53 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 3 Jun 2014 08:34:29 +0000 (10:34 +0200)
Make sure the context/surface are still alive and current while destroying
the render control.

Task-number: QTBUG-39034
Change-Id: I6ff0069985a9121a63025bfb165493b3f003391d
Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
src/quick/items/qquickrendercontrol.cpp
src/quickwidgets/qquickwidget.cpp
src/quickwidgets/qquickwidget_p.h

index e2a26836cf29cdc686ea798812fd4f3c683c1dbe..87a60b5cce0aaae237c352a1fae9539b10e76166 100644 (file)
@@ -120,13 +120,13 @@ void QQuickRenderControl::initialize(QOpenGLContext *gl)
     // surface belonging to window. In fact window may not have a native
     // window/surface at all.
 
-    QQuickWindowPrivate::get(d->window)->context->initialize(gl);
+    d->rc->initialize(gl);
 }
 
 void QQuickRenderControl::invalidate()
 {
     Q_D(QQuickRenderControl);
-    QQuickWindowPrivate::get(d->window)->context->invalidate();
+    d->rc->invalidate();
 }
 
 /*!
index b25912a1de168f1f18bab7f99f5b0e757ec2a4cd..aea21af3a03363ed545c52b0b405c837de47a4ab 100644 (file)
@@ -117,9 +117,23 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
     QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate()));
 }
 
-void QQuickWidgetPrivate::handleWindowChange()
+void QQuickWidgetPrivate::stopRenderControl()
 {
+    if (!context) // this is not an error, could be called before creating the context, or multiple times
+        return;
+
+    bool success = context->makeCurrent(offscreenSurface);
+    if (!success) {
+        qWarning("QQuickWidget::stopRenderControl could not make context current");
+        return;
+    }
+
     renderControl->stop();
+}
+
+void QQuickWidgetPrivate::handleWindowChange()
+{
+    stopRenderControl();
     destroyContext();
 }
 
@@ -143,10 +157,17 @@ QQuickWidgetPrivate::~QQuickWidgetPrivate()
 {
     if (QQmlDebugService::isDebuggingEnabled())
         QQmlInspectorService::instance()->removeView(q_func());
-    delete offscreenSurface;
+
+    stopRenderControl();
+
+    // context and offscreenSurface are current at this stage, if the context was created.
+    Q_ASSERT(!context || (QOpenGLContext::currentContext() == context && context->surface() == offscreenSurface));
     delete offscreenWindow;
     delete renderControl;
     delete fbo;
+
+    delete offscreenSurface;
+    destroyContext();
 }
 
 void QQuickWidgetPrivate::createOffscreenSurface()
@@ -628,9 +649,6 @@ void QQuickWidgetPrivate::createContext()
 
 void QQuickWidgetPrivate::destroyContext()
 {
-    if (!context)
-        return;
-    renderControl->invalidate();
     delete context;
     context = 0;
 }
@@ -906,17 +924,7 @@ void QQuickWidget::showEvent(QShowEvent *)
 void QQuickWidget::hideEvent(QHideEvent *)
 {
     Q_D(QQuickWidget);
-
-    if (!d->context) {
-        qWarning("QQuickWidget::hideEvent with no context");
-        return;
-    }
-    bool success = d->context->makeCurrent(d->offscreenSurface);
-    if (!success) {
-        qWarning("QQuickWidget::hideEvent could not make context current");
-        return;
-    }
-    d->renderControl->stop();
+    d->stopRenderControl();
 }
 
 /*! \reimp */
index 5cf2bfbf1d3f4196b64885cfa56f3be808891f9c..8efe32b3ce0a237925053c4351177f22d2631aa6 100644 (file)
@@ -93,6 +93,7 @@ public:
 
     void init(QQmlEngine* e = 0);
     void handleWindowChange();
+    void stopRenderControl();
 
     QSize rootObjectSize() const;