diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-07-27 19:42:27 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-08-02 14:35:33 +0200 |
commit | b594374ba84da986c5ebc93984961040338465d0 (patch) | |
tree | 41880eaf968ce0c5be934612a71edc61b0dbab58 /src/gui/rhi/qrhigles2.cpp | |
parent | ee68257b61268ef8f5f4c9b4090d8a1624cd98ce (diff) |
rhi: Be more graceful when one destroys a resource after the QRhi
One is a bad application or library in this case, but nonetheless
we should handle this more gracefully then just crashing due to
the QRhi already having been destroyed. Mainly because in Qt 5 one
could get away with the same: releasing OpenGL objects underneath,
for example, a QSGPlainTexture with no (or wrong) GL context did
not generate any user visible fatal errors. So we should not crash
in Qt 6 either with these code bases.
In debug builds or when QT_RHI_LEAK_CHECK is set, one will get the
unreleased resources warning printed in Qt 6, which is a step
forward compared to Qt 5. So there is still some indication that
something is badly designed, even if the application survives.
Task-number: QTBUG-95394
Pick-to: 6.2
Change-Id: I944f4f425ff126e7363a82aff926b280ccf1dfc3
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui/rhi/qrhigles2.cpp')
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 76 |
1 files changed, 51 insertions, 25 deletions
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 05465e40cc..7650e852ff 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -4256,10 +4256,12 @@ void QGles2Buffer::destroy() buffer = 0; QRHI_RES_RHI(QRhiGles2); - rhiD->releaseQueue.append(e); - QRHI_PROF; - QRHI_PROF_F(releaseBuffer(this)); - rhiD->unregisterResource(this); + if (rhiD) { + rhiD->releaseQueue.append(e); + QRHI_PROF; + QRHI_PROF_F(releaseBuffer(this)); + rhiD->unregisterResource(this); + } } bool QGles2Buffer::create() @@ -4366,11 +4368,13 @@ void QGles2RenderBuffer::destroy() stencilRenderbuffer = 0; QRHI_RES_RHI(QRhiGles2); - if (owns) - rhiD->releaseQueue.append(e); - QRHI_PROF; - QRHI_PROF_F(releaseRenderBuffer(this)); - rhiD->unregisterResource(this); + if (rhiD) { + if (owns) + rhiD->releaseQueue.append(e); + QRHI_PROF; + QRHI_PROF_F(releaseRenderBuffer(this)); + rhiD->unregisterResource(this); + } } bool QGles2RenderBuffer::create() @@ -4521,11 +4525,13 @@ void QGles2Texture::destroy() zeroInitialized = false; QRHI_RES_RHI(QRhiGles2); - if (owns) - rhiD->releaseQueue.append(e); - QRHI_PROF; - QRHI_PROF_F(releaseTexture(this)); - rhiD->unregisterResource(this); + if (rhiD) { + if (owns) + rhiD->releaseQueue.append(e); + QRHI_PROF; + QRHI_PROF_F(releaseTexture(this)); + rhiD->unregisterResource(this); + } } bool QGles2Texture::prepareCreate(QSize *adjustedSize) @@ -4803,9 +4809,10 @@ void QGles2TextureRenderTarget::destroy() framebuffer = 0; QRHI_RES_RHI(QRhiGles2); - rhiD->releaseQueue.append(e); - - rhiD->unregisterResource(this); + if (rhiD) { + rhiD->releaseQueue.append(e); + rhiD->unregisterResource(this); + } } QRhiRenderPassDescriptor *QGles2TextureRenderTarget::newCompatibleRenderPassDescriptor() @@ -4999,9 +5006,10 @@ void QGles2GraphicsPipeline::destroy() samplers.clear(); QRHI_RES_RHI(QRhiGles2); - rhiD->releaseQueue.append(e); - - rhiD->unregisterResource(this); + if (rhiD) { + rhiD->releaseQueue.append(e); + rhiD->unregisterResource(this); + } } bool QGles2GraphicsPipeline::create() @@ -5135,9 +5143,10 @@ void QGles2ComputePipeline::destroy() samplers.clear(); QRHI_RES_RHI(QRhiGles2); - rhiD->releaseQueue.append(e); - - rhiD->unregisterResource(this); + if (rhiD) { + rhiD->releaseQueue.append(e); + rhiD->unregisterResource(this); + } } bool QGles2ComputePipeline::create() @@ -5231,8 +5240,12 @@ QGles2SwapChain::~QGles2SwapChain() void QGles2SwapChain::destroy() { - QRHI_PROF; - QRHI_PROF_F(releaseSwapChain(this)); + QRHI_RES_RHI(QRhiGles2); + if (rhiD) { + QRHI_PROF; + QRHI_PROF_F(releaseSwapChain(this)); + rhiD->unregisterResource(this); + } } QRhiCommandBuffer *QGles2SwapChain::currentFrameCommandBuffer() @@ -5258,6 +5271,11 @@ QRhiRenderPassDescriptor *QGles2SwapChain::newCompatibleRenderPassDescriptor() bool QGles2SwapChain::createOrResize() { + // can be called multiple times due to window resizes + const bool needsRegistration = !surface || surface != m_window; + if (surface && surface != m_window) + destroy(); + surface = m_window; m_currentPixelSize = surfacePixelSize(); pixelSize = m_currentPixelSize; @@ -5283,6 +5301,14 @@ bool QGles2SwapChain::createOrResize() // make something up QRHI_PROF_F(resizeSwapChain(this, 2, m_sampleCount > 1 ? 2 : 0, m_sampleCount)); + // The only reason to register this fairly fake gl swapchain + // object with no native resources underneath is to be able to + // implement a safe destroy(). + if (needsRegistration) { + QRHI_RES_RHI(QRhiGles2); + rhiD->registerResource(this); + } + return true; } |