From a1d63a2d0f0415e20fac9f663ac358b1227d24f2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 19 Jul 2023 11:18:57 +0200 Subject: [PATCH] rhi: Enable registering cleanup callbacks with a key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And the ability to deregister. Going to be required by QRhiWidget. Task-number: QTBUG-119760 Change-Id: If185cbed2faa042098ac1f6bb1d6daaffd834377 Reviewed-by: Andy Nichols (cherry picked from commit 84873c898cb4cc433f05d3161cad1e458d26c2e9) Reviewed-by: Christian Strømme (cherry picked from commit 075dc6d6f93729f4d72efad467d0df1115cccfc6) --- src/gui/rhi/qrhi.cpp | 32 ++++++++++++++++++++++++++++++++ src/gui/rhi/qrhi_p.h | 2 ++ src/gui/rhi/qrhi_p_p.h | 11 +++++++++++ 3 files changed, 45 insertions(+) diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index caa1ee17d18..1832c23f636 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -5826,6 +5826,33 @@ void QRhi::addCleanupCallback(const CleanupCallback &callback) d->addCleanupCallback(callback); } +/*! + \overload + + Registers \a callback to be invoked either when the QRhi is destroyed or + when runCleanup() is called. This overload takes an opaque pointer, \a key, + that is used to ensure that a given callback is registered (and so called) + only once. + + \sa removeCleanupCallback() + */ +void QRhi::addCleanupCallback(const void *key, const CleanupCallback &callback) +{ + d->addCleanupCallback(key, callback); +} + +/*! + Deregisters the callback with \a key. If no cleanup callback was registered + with \a key, the function does nothing. Callbacks registered without a key + cannot be removed. + + \sa addCleanupCallback() + */ +void QRhi::removeCleanupCallback(const void *key) +{ + d->removeCleanupCallback(key); +} + /*! Invokes all registered cleanup functions. The list of cleanup callbacks it then cleared. Normally destroying the QRhi does this automatically, but @@ -5840,6 +5867,11 @@ void QRhi::runCleanup() f(this); d->cleanupCallbacks.clear(); + + for (auto it = d->keyedCleanupCallbacks.cbegin(), end = d->keyedCleanupCallbacks.cend(); it != end; ++it) + it.value()(this); + + d->keyedCleanupCallbacks.clear(); } /*! diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index de322d37891..233895405a7 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -1729,6 +1729,8 @@ class Q_GUI_EXPORT QRhi using CleanupCallback = std::function; void addCleanupCallback(const CleanupCallback &callback); + void addCleanupCallback(const void *key, const CleanupCallback &callback); + void removeCleanupCallback(const void *key); void runCleanup(); using GpuFrameTimeCallback = std::function; diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h index da29a24df25..714262e4037 100644 --- a/src/gui/rhi/qrhi_p_p.h +++ b/src/gui/rhi/qrhi_p_p.h @@ -175,6 +175,16 @@ class QRhiImplementation cleanupCallbacks.append(callback); } + void addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback) + { + keyedCleanupCallbacks[key] = callback; + } + + void removeCleanupCallback(const void *key) + { + keyedCleanupCallbacks.remove(key); + } + void addGpuFrameTimeCallback(const QRhi::GpuFrameTimeCallback &callback) { gpuFrameTimeCallbacks.append(callback); @@ -236,6 +246,7 @@ class QRhiImplementation QHash resources; QSet pendingDeleteResources; QVarLengthArray cleanupCallbacks; + QHash keyedCleanupCallbacks; QVarLengthArray gpuFrameTimeCallbacks; QElapsedTimer pipelineCreationTimer; qint64 accumulatedPipelineCreationTime = 0;