Don't create an offscreen surface when not on the GUI thread

When we try to gracefully destroy a QOpenGLVertexArrayObject it is not
possible to create an QOffscreenSurface from a thread that is not the
GUI thread. In this case we just need to bail out instead.

The side effect that was seen previously was that there would be a
warning and a deadlock on Windows when closing QQuickWindows that
contained a QQuickPaintedItem backed by a FrameBufferObject render
target (which would be using the OpenGL paint engine) when using the
threaded render loop.

Task-number: QTBUG-70148
Change-Id: I4a20d74d9af850bb90d243212ad9f65c3fc9e616
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Andy Nichols 2018-10-23 11:41:19 +02:00 committed by Fredrik Orderud
parent 3b8075de3b
commit 1b9af84c1b

View File

@ -40,8 +40,10 @@
#include "qopenglvertexarrayobject.h"
#include <QtCore/private/qobject_p.h>
#include <QtCore/qthread.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/qoffscreensurface.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qopenglfunctions_3_0.h>
#include <QtGui/qopenglfunctions_3_2_core.h>
@ -204,18 +206,25 @@ void QOpenGLVertexArrayObjectPrivate::destroy()
if (context && context != ctx) {
oldContext = ctx;
oldContextSurface = ctx ? ctx->surface() : 0;
// Cannot just make the current surface current again with another context.
// The format may be incompatible and some platforms (iOS) may impose
// restrictions on using a window with different contexts. Create an
// offscreen surface (a pbuffer or a hidden window) instead to be safe.
offscreenSurface.reset(new QOffscreenSurface);
offscreenSurface->setFormat(context->format());
offscreenSurface->create();
if (context->makeCurrent(offscreenSurface.data())) {
ctx = context;
} else {
qWarning("QOpenGLVertexArrayObject::destroy() failed to make VAO's context current");
// Before going through the effort of creating an offscreen surface
// check that we are on the GUI thread because otherwise many platforms
// will not able to create that offscreen surface.
if (QThread::currentThread() != qGuiApp->thread()) {
ctx = 0;
} else {
// Cannot just make the current surface current again with another context.
// The format may be incompatible and some platforms (iOS) may impose
// restrictions on using a window with different contexts. Create an
// offscreen surface (a pbuffer or a hidden window) instead to be safe.
offscreenSurface.reset(new QOffscreenSurface);
offscreenSurface->setFormat(context->format());
offscreenSurface->create();
if (context->makeCurrent(offscreenSurface.data())) {
ctx = context;
} else {
qWarning("QOpenGLVertexArrayObject::destroy() failed to make VAO's context current");
ctx = 0;
}
}
}
@ -224,7 +233,7 @@ void QOpenGLVertexArrayObjectPrivate::destroy()
context = 0;
}
if (vao) {
if (vao && ctx) {
switch (vaoFuncsType) {
#ifndef QT_OPENGL_ES_2
case Core_3_2: