Multiple QQuickWindows and opengl context persistence
-
Hi everyone,
While trying to integrate custom opengl rendering and Qt Quick, we encountered the following problem.
We create our items with help of QQuickFramebufferObject. And create opengl buffers (glGenBuffer and glBufferData) on the first rendering (QQuickFramebufferObject::Renderer::render()), that means we use opengl context attached to QQuickWindow that renders our scene. Vertex buffers are pretty big, and we create them only once on the first render.There are several QQuickWindow (integrated into widget application). Empirically we found that all those windows are using the same QOpenGLContext object (QQuickWindow::openglContext). If one of the quickwindow is destroyed and all else of quickwindows aren't visible, then that QOpenGLContext object is destroyed. In Qt documentation it is described here http://qt-project.org/doc/qt-5/qquickwindow.html#exposure-and-visibility
When one of those quickwindows gets visible, a new QOpenGLContext object is created and shared between all quickwindows.In documentation http://qt-project.org/doc/qt-5/qquickwindow.html#setPersistentOpenGLContext it is said that we can ask Qt not to destroy QOpenGLContext object in such situations. However, our test case shows that's not true:
@class PersistanceTest : public QObject
{
Q_OBJECTQQuickView * v1; QQuickView * v2; bool m_hidden;
public:
PersistanceTest() { m_hidden = false; // create QQuickViews createV1(); createV2(); // track their contexts QTimer::singleShot(1000, this, SLOT(dumpV1Context())); QTimer::singleShot(1000, this, SLOT(dumpV2Context())); QPushButton *but = new QPushButton("Click ME"); connect(but, &QPushButton::clicked, [this]() { qDebug() << "clicked"; if (!m_hidden) { // hide v2 and destroy v1 -> this will destroy // their opengl context v2->hide(); delete v1; v1 = nullptr; m_hidden = true; } else { // restore inital state => new QOpenGLContext object // will be created and shared between v1 and v2 createV1(); v2->show(); m_hidden = false; } }); but->show(); } void createV1() { v1 = new QQuickView(); // v1 will be bigger, so that we can distinguish // between v1 and v2 v1->resize(300, 300); // just to track v1 was actually destroyed QObject::connect(v1, &QObject::destroyed, []() { qDebug("v1 destroyed"); }); // changing true/false doesn't matter v1->setPersistentOpenGLContext(true); v1->show(); } void createV2() { v2 = new QQuickView(); // changing true/false doesn't matter v2->setPersistentOpenGLContext(true); v2->show(); }
public slots:
void dumpV1Context()
{
if (v1)
qDebug() << "v1.context = " << v1->openglContext();
QTimer::singleShot(1000, this, SLOT(dumpV1Context()));
}void dumpV2Context() { qDebug() << "v2.context = " << v2->openglContext(); QTimer::singleShot(1000, this, SLOT(dumpV2Context())); }
};
@Log of test execution will look smth like this:
v2.context = 0x2edb9b0
v1.context = 0x2edb9b0
v1.context = 0x2edb9b0
v2.context = 0x2edb9b0
clicked
v1 destroyed
v2.context = 0x0 <---- QOpenGLContext object destroyed
v2.context = 0x0
clicked
v2.context = 0x2e64a10 <----- created for both of them
v1.context = 0x2e64a10
v1.context = 0x2e64a10
v2.context = 0x2e64a10
clicked
v1 destroyed
v2.context = 0x0
v2.context = 0x0
clicked
v2.context = 0x2e8d830
v1.context = 0x2e8d830
v1.context = 0x2e8d830
v2.context = 0x2e8d830And here is the problem. When QOpenGLContext object is destroyed, and one of quickwindow gets back to top - everything crashes on the next opengl call (in our implementation of QQuickFramebufferObject::Renderer::render()). The possible reason of that is absence of previously created vertex buffers.
The question is: is a Qt bug, or application should track context destruction and recreate vertex buffers every time new context is created? Or may be there are some known ways to handle such situation?
Thanks in advance
PS: windows 7 x64, Vusial Studio 2012, Qt. 5.2.1 opengl_64
-
I found that turning on threaded render on Window (via QML_FORCE_THREADED_RENDERER=1 env var) forces all instances of QQuickWindow to create their own opengl context.
But still wondering how to overcome application opengl data destruction when Qt kills opengl contexts object.