summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Senyk <thomas.senyk@qt.io>2023-07-19 10:46:14 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-09-18 10:45:14 +0000
commit40888d8d94282032400a679cd682f2103f7f3be4 (patch)
tree6f38154a366fbf7f1feee4a8bff3bb309367ebdd
parent74ae723c98d44d8021c1ff6d2171a3caa9e3c5fc (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>
-rw-r--r--src/compositor/CMakeLists.txt1
-rw-r--r--src/compositor/hardware_integration/qwltextureorphanage.cpp108
-rw-r--r--src/compositor/hardware_integration/qwltextureorphanage_p.h64
-rw-r--r--src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.cpp4
-rw-r--r--src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp66
-rw-r--r--src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h7
-rw-r--r--src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp82
-rw-r--r--src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp79
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;