summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2021-11-26 11:47:23 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-11-30 13:00:35 +0000
commit88b795bf0417daf43674ad2a89293c141b3319bc (patch)
treef907657e658257601b1d1a869587a052bcbf07c6
parent048bf5a5d8fd7999a175de2a1d8ff06187f7395e (diff)
OpenGL renderer: restore surface on context when shutting down
When using a QQuickWidget and Qt3D, on shutdown and assert occurs. This is the result of the QQuickWidget expecting the surface on the context to be its own internal surface after the QQuickRenderControl has been invalidated. This conflict with what Qt3D does on shutdown as it makes the context current on its own internal offscreen surface on shutdown. Therefore, to fix this issue, we record the surface in use before Qt3D shuts down and we make the context current on it after Qt3D has shutdown. Arguably, the fix should really go in QQuickWidgetPrivate::invalidateRenderControl where the QQuickWidget should check that the current surface is indeed the one it expects and set it accordingly. Change-Id: I534dc330a30a2ad5d17a6416715d03206ef4b1c9 Reviewed-by: Mike Krus <mike.krus@kdab.com> (cherry picked from commit 559d77cacf7a3f6a29d3debec6d61a2ef8a59dc9) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/plugins/renderers/opengl/renderer/renderer.cpp66
1 files changed, 39 insertions, 27 deletions
diff --git a/src/plugins/renderers/opengl/renderer/renderer.cpp b/src/plugins/renderers/opengl/renderer/renderer.cpp
index 37a9eafd9..e09423005 100644
--- a/src/plugins/renderers/opengl/renderer/renderer.cpp
+++ b/src/plugins/renderers/opengl/renderer/renderer.cpp
@@ -585,38 +585,50 @@ void Renderer::releaseGraphicsResources()
QOpenGLContext *context = m_submissionContext->openGLContext();
Q_ASSERT(context);
- if (context->thread() == QThread::currentThread() && context->makeCurrent(offscreenSurface)) {
-
- // Clean up the graphics context and any resources
- const std::vector<HGLTexture> &activeTexturesHandles = m_glResourceManagers->glTextureManager()->activeHandles();
- for (const HGLTexture &textureHandle : activeTexturesHandles) {
- GLTexture *tex = m_glResourceManagers->glTextureManager()->data(textureHandle);
- tex->destroy();
- }
+ if (context->thread() == QThread::currentThread()) {
+ QSurface *lastContextSurface = context->surface();
+
+ if (context->makeCurrent(offscreenSurface)) {
+ // Clean up the graphics context and any resources
+ const std::vector<HGLTexture> &activeTexturesHandles = m_glResourceManagers->glTextureManager()->activeHandles();
+ for (const HGLTexture &textureHandle : activeTexturesHandles) {
+ GLTexture *tex = m_glResourceManagers->glTextureManager()->data(textureHandle);
+ tex->destroy();
+ }
- // Do the same thing with buffers
- const std::vector<HGLBuffer> &activeBuffers = m_glResourceManagers->glBufferManager()->activeHandles();
- for (const HGLBuffer &bufferHandle : activeBuffers) {
- GLBuffer *buffer = m_glResourceManagers->glBufferManager()->data(bufferHandle);
- buffer->destroy(m_submissionContext.data());
- }
+ // Do the same thing with buffers
+ const std::vector<HGLBuffer> &activeBuffers = m_glResourceManagers->glBufferManager()->activeHandles();
+ for (const HGLBuffer &bufferHandle : activeBuffers) {
+ GLBuffer *buffer = m_glResourceManagers->glBufferManager()->data(bufferHandle);
+ buffer->destroy(m_submissionContext.data());
+ }
- // Do the same thing with shaders
- const std::vector<GLShader *> shaders = m_glResourceManagers->glShaderManager()->takeActiveResources();
- qDeleteAll(shaders);
+ // Do the same thing with shaders
+ const std::vector<GLShader *> shaders = m_glResourceManagers->glShaderManager()->takeActiveResources();
+ qDeleteAll(shaders);
- // Do the same thing with VAOs
- const std::vector<HVao> &activeVaos = m_glResourceManagers->vaoManager()->activeHandles();
- for (const HVao &vaoHandle : activeVaos) {
- OpenGLVertexArrayObject *vao = m_glResourceManagers->vaoManager()->data(vaoHandle);
- vao->destroy();
- }
+ // Do the same thing with VAOs
+ const std::vector<HVao> &activeVaos = m_glResourceManagers->vaoManager()->activeHandles();
+ for (const HVao &vaoHandle : activeVaos) {
+ OpenGLVertexArrayObject *vao = m_glResourceManagers->vaoManager()->data(vaoHandle);
+ vao->destroy();
+ }
- m_submissionContext->releaseRenderTargets();
+ m_submissionContext->releaseRenderTargets();
- m_frameProfiler.reset();
- if (m_ownedContext)
- context->doneCurrent();
+ m_frameProfiler.reset();
+ if (m_ownedContext) {
+ context->doneCurrent();
+ } else {
+ // Leave the context in the state we found it in by restoring
+ // its last used surface. This satisfies expectations when used
+ // with QQuickWidgets that surface on current context after
+ // QQuickRenderControl cleanup is the same as prior to the
+ // cleanup. Arguably this could also be checked for in
+ // QQuickWidgetPrivate::invalidateRenderControl.
+ context->makeCurrent(lastContextSurface);
+ }
+ }
} else {
qWarning() << "Failed to make context current: OpenGL resources will not be destroyed";
}