diff options
author | Thomas Senyk <thomas.senyk@qt.io> | 2023-07-19 10:46:14 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-09-18 10:45:14 +0000 |
commit | 40888d8d94282032400a679cd682f2103f7f3be4 (patch) | |
tree | 6f38154a366fbf7f1feee4a8bff3bb309367ebdd /src | |
parent | 74ae723c98d44d8021c1ff6d2171a3caa9e3c5fc (diff) |
Reimplement orphaned texture handling
The previous implementation was a bit error prone
(there was a reproducable "dead pointer" issue)
and had duplicated code (dma, egl and eglstream share the same code).
The new implementation fixes both issues (and more):
- no more 'this' capture on a lambda where the 'this' isn't an object
and hence can go out of scope without the lambda knowing.
- no more duplicated code as we now have a singleton as our orphanage:
QWaylandTextureOrphanage
3 (dma, egl, eglstream) HW-integrations use this singleton
- the class itself as well as it's container are thread-safe
by the usage of QMutex/QMutexLocker.
This also includes the deletion code within the orphanage.
As the orphanes are 100% owned by the orphanage,
they are protected from double deletion.
- The cleanup due to QOpenGLContext::aboutToBeDestroyed is
now ctx specific, no more lamdba-per-texture.
Change-Id: I36e82fae796864319bed7ebdb5154e93dbe96394
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
(cherry picked from commit 2cea2d8520af4f3647f2e7aa7444b68c9c1e51cf)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
8 files changed, 186 insertions, 225 deletions
diff --git a/src/compositor/CMakeLists.txt b/src/compositor/CMakeLists.txt index 593d6194c..434411d0e 100644 --- a/src/compositor/CMakeLists.txt +++ b/src/compositor/CMakeLists.txt @@ -150,6 +150,7 @@ qt_internal_extend_target(WaylandCompositor CONDITION QT_FEATURE_opengl hardware_integration/qwlserverbufferintegration.cpp hardware_integration/qwlserverbufferintegration_p.h hardware_integration/qwlserverbufferintegrationfactory.cpp hardware_integration/qwlserverbufferintegrationfactory_p.h hardware_integration/qwlserverbufferintegrationplugin.cpp hardware_integration/qwlserverbufferintegrationplugin_p.h + hardware_integration/qwltextureorphanage.cpp hardware_integration/qwltextureorphanage_p.h PUBLIC_LIBRARIES Qt::OpenGL ) diff --git a/src/compositor/hardware_integration/qwltextureorphanage.cpp b/src/compositor/hardware_integration/qwltextureorphanage.cpp new file mode 100644 index 000000000..c1337190a --- /dev/null +++ b/src/compositor/hardware_integration/qwltextureorphanage.cpp @@ -0,0 +1,108 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qwltextureorphanage_p.h" + +#include <QOpenGLContext> +#include <QOpenGLTexture> +#include <QDebug> +#include <QtTypeTraits> +#include <QMutexLocker> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcWTO, "qt.waylandcompositor.orphanage") + +Q_GLOBAL_STATIC(QtWayland::QWaylandTextureOrphanage, inst) + +namespace QtWayland { + +QWaylandTextureOrphanage::~QWaylandTextureOrphanage() +{ + QMutexLocker locker(&m_containerLock); + if (!m_orphanedTextures.isEmpty()) { + qCWarning(qLcWTO) << Q_FUNC_INFO << "m_orphanedTextures container isn't empty! content:" + << m_orphanedTextures; + } +} + +QWaylandTextureOrphanage *QWaylandTextureOrphanage::instance() +{ + return inst; +} + +void QWaylandTextureOrphanage::admitTexture(QOpenGLTexture *tex, QOpenGLContext *ctx) +{ + qCDebug(qLcWTO) << Q_FUNC_INFO << "got a texture (" << (void *)tex + << ") ready to be deleted! It's ctx:" << ctx; + + { + QMutexLocker locker(&m_containerLock); + m_orphanedTextures.insert(ctx, tex); + } + + connect(ctx, &QOpenGLContext::aboutToBeDestroyed, this, + &QWaylandTextureOrphanage::onContextAboutToBeDestroyed, + Qt::ConnectionType(Qt::DirectConnection | Qt::UniqueConnection)); +} + +void QWaylandTextureOrphanage::deleteTextures() +{ + QOpenGLContext *cCtx = QOpenGLContext::currentContext(); + + if (cCtx == nullptr) { + qCWarning(qLcWTO) << Q_FUNC_INFO << "cannot delete textures without current OpenGL context"; + return; + } + + { + QMutexLocker locker(&m_containerLock); + + for (QOpenGLContext *aCtx : m_orphanedTextures.keys()) { + if (QOpenGLContext::areSharing(cCtx, aCtx)) { + + qCDebug(qLcWTO) << Q_FUNC_INFO << "currentContext (" << cCtx + << ") and ctx of orphane(s) (" << aCtx + << ") are shared! => deleteTexturesByContext"; + + deleteTexturesByContext(aCtx); + } + } + } +} + +void QWaylandTextureOrphanage::onContextAboutToBeDestroyed() +{ + QOpenGLContext *ctx = qobject_cast<QOpenGLContext *>(sender()); + Q_ASSERT(ctx != nullptr); + + qCDebug(qLcWTO) << Q_FUNC_INFO << " ctx (" << ctx + << ") fired aboutToBeDestroyed => deleteTexturesByContext(ctx)"; + + { + QMutexLocker locker(&m_containerLock); + deleteTexturesByContext(ctx); + } +} + +void QWaylandTextureOrphanage::deleteTexturesByContext(QOpenGLContext *ctx) +{ + // NOTE: We are (by class-internal design) locked (m_containerLock) + // when we enter this function! + // So in a debug-build we will fail below: + Q_ASSERT(!m_containerLock.tryLock()); + + QList<QOpenGLTexture *> texturesToDelete = m_orphanedTextures.values(ctx); + m_orphanedTextures.remove(ctx); + + for (QOpenGLTexture *tex : texturesToDelete) { + delete tex; + qCDebug(qLcWTO) << Q_FUNC_INFO << " texture (" << (void *)tex << ") got deleted"; + } +} + +} // namespace QtWayland + +QT_END_NAMESPACE + +#include "moc_qwltextureorphanage_p.cpp" diff --git a/src/compositor/hardware_integration/qwltextureorphanage_p.h b/src/compositor/hardware_integration/qwltextureorphanage_p.h new file mode 100644 index 000000000..d267043e4 --- /dev/null +++ b/src/compositor/hardware_integration/qwltextureorphanage_p.h @@ -0,0 +1,64 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef QWLTEXTUREORPHANAGE_P_H +#define QWLTEXTUREORPHANAGE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QObject> +#include <QMutex> +#include <QLoggingCategory> +#include <QtWaylandCompositor/qtwaylandcompositorglobal.h> + +QT_BEGIN_NAMESPACE + +class QOpenGLContext; +class QOpenGLTexture; + +Q_DECLARE_LOGGING_CATEGORY(qLcWTO) + +namespace QtWayland { + +class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandTextureOrphanage : public QObject +{ + Q_OBJECT + +public: + QWaylandTextureOrphanage(){}; + ~QWaylandTextureOrphanage(); + + static QWaylandTextureOrphanage *instance(); + + // texture that isn't needed anymore will be "take care of" (killed) appropriately + void admitTexture(QOpenGLTexture *tex, QOpenGLContext *ctx); + + // uses QOpenGLContext::currentContext to call deleteTexturesByContext on all shared ctx + void deleteTextures(); + +public slots: + // uses sender() to call deleteTexturesByContext + void onContextAboutToBeDestroyed(); + +private: + void deleteTexturesByContext(QOpenGLContext *ctx); + + // tracks all the orphanes that need to be deleted + QMultiHash<QOpenGLContext *, QOpenGLTexture *> m_orphanedTextures; + + QMutex m_containerLock; +}; + +} // namespace QtWayland + +QT_END_NAMESPACE +#endif diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.cpp b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.cpp index c09496985..a608b9c4d 100644 --- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.cpp +++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.cpp @@ -5,6 +5,7 @@ #include "linuxdmabufclientbufferintegration.h" #include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/private/qwltextureorphanage_p.h> #include <drm_fourcc.h> #include <drm_mode.h> @@ -262,7 +263,8 @@ void LinuxDmabufWlBuffer::buffer_destroy(Resource *resource) for (uint32_t i = 0; i < m_planesNumber; ++i) { if (m_textures[i] != nullptr) { - m_clientBufferIntegration->deleteGLTextureWhenPossible(m_textures[i], m_texturesContext[i]); + QtWayland::QWaylandTextureOrphanage::instance()->admitTexture(m_textures[i], + m_texturesContext[i]); m_textures[i] = nullptr; m_texturesContext[i] = nullptr; QObject::disconnect(m_texturesAboutToBeDestroyedConnection[i]); diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp index 960ec461f..205f25d1f 100644 --- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp +++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp @@ -6,6 +6,7 @@ #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/private/qwayland-server-wayland.h> +#include <QtWaylandCompositor/private/qwltextureorphanage_p.h> #include <qpa/qplatformnativeinterface.h> #include <QtOpenGL/QOpenGLTexture> #include <QtCore/QVarLengthArray> @@ -350,69 +351,6 @@ QList<uint64_t> LinuxDmabufClientBufferIntegration::supportedDrmModifiers(uint32 return QList<uint64_t>(); } - -void LinuxDmabufClientBufferIntegration::deleteGLTextureWhenPossible(QOpenGLTexture *texture, QOpenGLContext *ctx) { - QMutexLocker locker(&m_orphanedTexturesLock); - - Q_ASSERT(m_orphanedTextures.size() == m_orphanedTexturesAboutToBeDestroyedConnection.size()); - - m_orphanedTextures << texture; - m_orphanedTexturesAboutToBeDestroyedConnection << QObject::connect(ctx, &QOpenGLContext::aboutToBeDestroyed, - ctx, [this, texture]() { - this->deleteSpecificOrphanedTexture(texture); - }, Qt::DirectConnection); -} - - -void LinuxDmabufClientBufferIntegration::deleteOrphanedTextures() -{ - Q_ASSERT(QOpenGLContext::currentContext()); - - QMutexLocker locker(&m_orphanedTexturesLock); - - if (!m_orphanedTextures.isEmpty()) - qCDebug(qLcWaylandCompositorHardwareIntegration) << "About to delete some textures: " - << m_orphanedTextures; - - qDeleteAll(m_orphanedTextures); - - for (QMetaObject::Connection con : m_orphanedTexturesAboutToBeDestroyedConnection) - QObject::disconnect(con); - - m_orphanedTexturesAboutToBeDestroyedConnection.clear(); - m_orphanedTextures.clear(); -} - -void LinuxDmabufClientBufferIntegration::deleteSpecificOrphanedTexture(QOpenGLTexture *texture) -{ - Q_ASSERT(m_orphanedTextures.size() == m_orphanedTexturesAboutToBeDestroyedConnection.size()); - - QMutexLocker locker(&m_orphanedTexturesLock); - - // In this case, deleteOrphanedTextures was called while we entered (see lock!) this function! - if (m_orphanedTextures.length()==0) { - qCWarning(qLcWaylandCompositorHardwareIntegration) - << Q_FUNC_INFO - << "Looks like deleteOrphanedTextures() and this function where called simultaneously!" - << "This might cause issues!"; - return; - } - - int i = m_orphanedTextures.indexOf(texture); - Q_ASSERT(i!=-1); // If it isn't empty (see above if), then it should be guaranteed to still contain this texture - - m_orphanedTextures.removeAt(i); - QMetaObject::Connection con = m_orphanedTexturesAboutToBeDestroyedConnection.takeAt(i); - - QObject::disconnect(con); - delete texture; - - qCDebug(qLcWaylandCompositorHardwareIntegration) - << Q_FUNC_INFO - << "texture deleted due to QOpenGLContext::aboutToBeDestroyed!" - << "Pointer (now dead) was:" << (void*)texture; -} - void LinuxDmabufClientBufferIntegration::deleteImage(EGLImageKHR image) { egl_destroy_image(m_eglDisplay, image); @@ -459,7 +397,7 @@ LinuxDmabufClientBuffer::LinuxDmabufClientBuffer(LinuxDmabufClientBufferIntegrat QOpenGLTexture *LinuxDmabufClientBuffer::toOpenGlTexture(int plane) { // At this point we should have a valid OpenGL context, so it's safe to destroy textures - m_integration->deleteOrphanedTextures(); + QtWayland::QWaylandTextureOrphanage::instance()->deleteTextures(); if (!m_buffer) return nullptr; diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h index 3749d88ea..b72a24d5d 100644 --- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h +++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h @@ -46,10 +46,7 @@ public: QtWayland::ClientBuffer *createBufferFor(wl_resource *resource) override; bool importBuffer(wl_resource *resource, LinuxDmabufWlBuffer *linuxDmabufBuffer); void removeBuffer(wl_resource *resource); - void deleteOrphanedTextures(); - void deleteSpecificOrphanedTexture(QOpenGLTexture *texture); void deleteImage(EGLImageKHR image); - void deleteGLTextureWhenPossible(QOpenGLTexture *texture, QOpenGLContext* ctx); PFNGLEGLIMAGETARGETTEXTURE2DOESPROC gl_egl_image_target_texture_2d = nullptr; private: @@ -71,10 +68,6 @@ private: ::wl_display *m_wlDisplay = nullptr; bool m_displayBound = false; - QMutex m_orphanedTexturesLock; - QList<QOpenGLTexture *> m_orphanedTextures; - QList<QMetaObject::Connection> m_orphanedTexturesAboutToBeDestroyedConnection; - QHash<EGLint, YuvFormatConversion> m_yuvFormats; bool m_supportsDmabufModifiers = false; QHash<struct ::wl_resource *, LinuxDmabufWlBuffer *> m_importedBuffers; diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp index b8a5b2466..38b0e0c4b 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp @@ -4,6 +4,7 @@ #include "waylandeglclientbufferintegration_p.h" #include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/private/qwltextureorphanage_p.h> #include <qpa/qplatformnativeinterface.h> #include <QtOpenGL/QOpenGLTexture> #include <QtGui/QGuiApplication> @@ -150,9 +151,6 @@ public: void setupBufferAndCleanup(BufferState *bs, QOpenGLTexture *texture, int plane); void handleEglstreamTexture(WaylandEglClientBuffer *buffer, wl_resource *bufferHandle); void registerBuffer(struct ::wl_resource *buffer, BufferState state); - void deleteGLTextureWhenPossible(QOpenGLTexture *texture, QOpenGLContext *ctx); - void deleteOrphanedTextures(); - void deleteSpecificOrphanedTexture(QOpenGLTexture *texture); EGLDisplay egl_display = EGL_NO_DISPLAY; bool display_bound = false; @@ -160,11 +158,6 @@ public: QOffscreenSurface *offscreenSurface = nullptr; QOpenGLContext *localContext = nullptr; - QMutex orphanedTexturesLock; - QList<QOpenGLTexture *> orphanedTextures; - QList<QMetaObject::Connection> orphanedTexturesAboutToBeDestroyedConnection; - - PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display = nullptr; PFNEGLUNBINDWAYLANDDISPLAYWL egl_unbind_wayland_display = nullptr; PFNEGLQUERYWAYLANDBUFFERWL_compat egl_query_wayland_buffer = nullptr; @@ -417,74 +410,6 @@ void WaylandEglClientBufferIntegrationPrivate::handleEglstreamTexture(WaylandEgl localContext->doneCurrent(); } -void WaylandEglClientBufferIntegrationPrivate::deleteGLTextureWhenPossible(QOpenGLTexture *texture, QOpenGLContext *ctx) { - QMutexLocker locker(&orphanedTexturesLock); - - Q_ASSERT(ctx != nullptr); - Q_ASSERT(orphanedTextures.size() == orphanedTexturesAboutToBeDestroyedConnection.size()); - - qCDebug(qLcWaylandCompositorHardwareIntegration) - << Q_FUNC_INFO << " got texture and ctx to be deleted!" - << (void*)texture << "; " << (void*)ctx; - - orphanedTextures << texture; - orphanedTexturesAboutToBeDestroyedConnection << QObject::connect(ctx, &QOpenGLContext::aboutToBeDestroyed, - ctx, [this, texture]() { - this->deleteSpecificOrphanedTexture(texture); - }, Qt::DirectConnection); -} - -void WaylandEglClientBufferIntegrationPrivate::deleteOrphanedTextures() -{ - Q_ASSERT(QOpenGLContext::currentContext()); - - QMutexLocker locker(&orphanedTexturesLock); - - for (int i=0; i < orphanedTextures.size(); i++) { - qCDebug(qLcWaylandCompositorHardwareIntegration) - << Q_FUNC_INFO << " about to delete a texture: " - << (void*)orphanedTextures[i]; - } - - qDeleteAll(orphanedTextures); - - for (QMetaObject::Connection con : orphanedTexturesAboutToBeDestroyedConnection) - QObject::disconnect(con); - - orphanedTexturesAboutToBeDestroyedConnection.clear(); - orphanedTextures.clear(); -} - -void WaylandEglClientBufferIntegrationPrivate::deleteSpecificOrphanedTexture(QOpenGLTexture *texture) -{ - Q_ASSERT(orphanedTextures.size() == orphanedTexturesAboutToBeDestroyedConnection.size()); - - QMutexLocker locker(&orphanedTexturesLock); - - // In this case, deleteOrphanedTextures was called while we entered (see lock!) this function! - if (orphanedTextures.length()==0) { - qCWarning(qLcWaylandCompositorHardwareIntegration) - << Q_FUNC_INFO - << "Looks like deleteOrphanedTextures() and this function where called simultaneously!" - << "This might cause issues!"; - return; - } - - int i = orphanedTextures.indexOf(texture); - Q_ASSERT(i!=-1); // If it isn't empty (see above if), then it should be guaranteed to still contain this texture - - orphanedTextures.removeAt(i); - QMetaObject::Connection con = orphanedTexturesAboutToBeDestroyedConnection.takeAt(i); - - QObject::disconnect(con); - delete texture; - - qCDebug(qLcWaylandCompositorHardwareIntegration) - << Q_FUNC_INFO - << "texture deleted due to QOpenGLContext::aboutToBeDestroyed!" - << "Pointer (now dead) was:" << (void*)texture; -} - WaylandEglClientBufferIntegration::WaylandEglClientBufferIntegration() : d_ptr(new WaylandEglClientBufferIntegrationPrivate) { @@ -611,7 +536,8 @@ WaylandEglClientBuffer::~WaylandEglClientBuffer() << (void*)d->textures[i] << "; " << (void*)d->texturesContext[i] << " ... current context might be the same: " << QOpenGLContext::currentContext(); - p->deleteGLTextureWhenPossible(d->textures[i], d->texturesContext[i]); + QtWayland::QWaylandTextureOrphanage::instance()->admitTexture( + d->textures[i], d->texturesContext[i]); d->textures[i] = nullptr; // in case the aboutToBeDestroyed lambda is called while we where here d->texturesContext[i] = nullptr; QObject::disconnect(d->texturesAboutToBeDestroyedConnection[i]); @@ -662,7 +588,7 @@ QOpenGLTexture *WaylandEglClientBuffer::toOpenGlTexture(int plane) { auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration); // At this point we should have a valid OpenGL context, so it's safe to destroy textures - p->deleteOrphanedTextures(); + QtWayland::QWaylandTextureOrphanage::instance()->deleteTextures(); if (!m_buffer) return nullptr; diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp index 23883a2a7..02d289ce0 100644 --- a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp @@ -16,6 +16,7 @@ #include <QtWaylandCompositor/private/qwaylandcompositor_p.h> #include <QtWaylandCompositor/private/qwlbuffermanager_p.h> +#include <QtWaylandCompositor/private/qwltextureorphanage_p.h> #include <EGL/egl.h> #include <EGL/eglext.h> @@ -130,9 +131,6 @@ public: bool initEglStream(WaylandEglStreamClientBuffer *buffer, struct ::wl_resource *bufferHandle); void setupBufferAndCleanup(BufferState *bs, QOpenGLTexture *texture, int plane); void handleEglstreamTexture(WaylandEglStreamClientBuffer *buffer); - void deleteGLTextureWhenPossible(QOpenGLTexture *texture, QOpenGLContext *ctx); - void deleteOrphanedTextures(); - void deleteSpecificOrphanedTexture(QOpenGLTexture *texture); EGLDisplay egl_display = EGL_NO_DISPLAY; bool display_bound = false; @@ -140,10 +138,6 @@ public: QOffscreenSurface *offscreenSurface = nullptr; QOpenGLContext *localContext = nullptr; - QMutex orphanedTexturesLock; - QList<QOpenGLTexture *> orphanedTextures; - QList<QMetaObject::Connection> orphanedTexturesAboutToBeDestroyedConnection; - WaylandEglStreamController *eglStreamController = nullptr; PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display = nullptr; @@ -160,71 +154,6 @@ public: bool WaylandEglStreamClientBufferIntegrationPrivate::shuttingDown = false; - -void WaylandEglStreamClientBufferIntegrationPrivate::deleteGLTextureWhenPossible(QOpenGLTexture *texture, QOpenGLContext *ctx) { - - QMutexLocker locker(&orphanedTexturesLock); - - Q_ASSERT(orphanedTextures.size() == orphanedTexturesAboutToBeDestroyedConnection.size()); - - orphanedTextures << texture; - orphanedTexturesAboutToBeDestroyedConnection << QObject::connect(ctx, &QOpenGLContext::aboutToBeDestroyed, - ctx, [this, texture]() { - this->deleteSpecificOrphanedTexture(texture); - }, Qt::DirectConnection); -} - -void WaylandEglStreamClientBufferIntegrationPrivate::deleteOrphanedTextures() -{ - Q_ASSERT(QOpenGLContext::currentContext()); - - QMutexLocker locker(&orphanedTexturesLock); - - for (int i=0; i < orphanedTextures.size(); i++) { - qCDebug(qLcWaylandCompositorHardwareIntegration) - << Q_FUNC_INFO << " about to delete a texture: " - << (void*)orphanedTextures[i]; - } - - qDeleteAll(orphanedTextures); - - for (QMetaObject::Connection con : orphanedTexturesAboutToBeDestroyedConnection) - QObject::disconnect(con); - - orphanedTexturesAboutToBeDestroyedConnection.clear(); - orphanedTextures.clear(); -} - -void WaylandEglStreamClientBufferIntegrationPrivate::deleteSpecificOrphanedTexture(QOpenGLTexture *texture) -{ - Q_ASSERT(orphanedTextures.size() == orphanedTexturesAboutToBeDestroyedConnection.size()); - - QMutexLocker locker(&orphanedTexturesLock); - - // In this case, deleteOrphanedTextures was called while we entered (see lock!) this function! - if (orphanedTextures.length()==0) { - qCWarning(qLcWaylandCompositorHardwareIntegration) - << Q_FUNC_INFO - << "Looks like deleteOrphanedTextures() and this function where called simultaneously!" - << "This might cause issues!"; - return; - } - - int i = orphanedTextures.indexOf(texture); - Q_ASSERT(i!=-1); // If it isn't empty (see above if), then it should be guaranteed to still contain this texture - - orphanedTextures.removeAt(i); - QMetaObject::Connection con = orphanedTexturesAboutToBeDestroyedConnection.takeAt(i); - - QObject::disconnect(con); - delete texture; - - qCDebug(qLcWaylandCompositorHardwareIntegration) - << Q_FUNC_INFO - << "texture deleted due to QOpenGLContext::aboutToBeDestroyed!" - << "Pointer (now dead) was:" << (void*)texture; -} - bool WaylandEglStreamClientBufferIntegrationPrivate::ensureContext() { bool localContextNeeded = false; @@ -481,7 +410,8 @@ WaylandEglStreamClientBuffer::~WaylandEglStreamClientBuffer() << (void*)d->textures[i] << "; " << (void*)d->texturesContext[i] << " ... current context might be the same: " << QOpenGLContext::currentContext(); - p->deleteGLTextureWhenPossible(d->textures[i], d->texturesContext[i]); + QtWayland::QWaylandTextureOrphanage::instance()->admitTexture( + d->textures[i], d->texturesContext[i]); d->textures[i] = nullptr; // in case the aboutToBeDestroyed lambda is called while we where here d->texturesContext[i] = nullptr; QObject::disconnect(d->texturesAboutToBeDestroyedConnection[i]); @@ -512,9 +442,8 @@ QWaylandSurface::Origin WaylandEglStreamClientBuffer::origin() const QOpenGLTexture *WaylandEglStreamClientBuffer::toOpenGlTexture(int plane) { - auto *p = WaylandEglStreamClientBufferIntegrationPrivate::get(m_integration); // At this point we should have a valid OpenGL context, so it's safe to destroy textures - p->deleteOrphanedTextures(); + QtWayland::QWaylandTextureOrphanage::instance()->deleteTextures(); if (!m_buffer) return nullptr; |