5#if defined(QGC_HAS_ANY_GPU_PATH)
7#include <QtCore/QMutex>
11QGC_LOGGING_CATEGORY(GstContextBridgeRegistryLog,
"Video.GStreamer.HwBuffers.GstContextBridgeRegistry")
13namespace GstContextBridgeRegistry {
21constexpr int kMaxBridges = 0
22#if defined(QGC_HAS_GST_GLMEMORY_GPU_PATH)
25#if defined(QGC_HAS_GST_D3D11_GPU_PATH)
28#if defined(QGC_HAS_GST_D3D12_GPU_PATH)
31#if defined(QGC_HAS_GST_VULKAN_GPU_PATH)
37constexpr int kMaxCacheResets = 0
38#if defined(QGC_HAS_GST_DMABUF_GPU_PATH)
41#if defined(QGC_HAS_GST_D3D11_GPU_PATH)
44#if defined(QGC_HAS_GST_D3D12_GPU_PATH)
47#if defined(QGC_HAS_GST_IOSURFACE_GPU_PATH)
50#if defined(QGC_HAS_GST_AHARDWAREBUFFER_GPU_PATH)
55std::array<BridgeHandler, kMaxBridges> s_handlers{};
56std::atomic<int> s_handlerCount{0};
57std::array<ResetCallback, kMaxBridges> s_resets{};
58std::atomic<int> s_resetCount{0};
59std::array<ResetCallback, (kMaxCacheResets > 0 ? kMaxCacheResets : 1)> s_cacheResets{};
60std::atomic<int> s_cacheResetCount{0};
64RegistrationHandle registerBridgeHandler(BridgeHandler handler)
66 if (handler ==
nullptr) {
67 return kInvalidHandle;
69 QMutexLocker lock(&s_mutex);
70 const int count = s_handlerCount.load(std::memory_order_relaxed);
71 for (
int i = 0; i < count; ++i) {
72 if (s_handlers[i] == handler)
73 return static_cast<RegistrationHandle
>(i);
75 if (count >= kMaxBridges) {
76 qCWarning(GstContextBridgeRegistryLog) <<
"bridge handler registry full (kMaxBridges=" << kMaxBridges
77 <<
"); handler will not receive GstBus messages";
78 return kInvalidHandle;
80 s_handlers[count] = handler;
81 s_handlerCount.store(count + 1, std::memory_order_release);
82 return static_cast<RegistrationHandle
>(count);
85RegistrationHandle registerResetCallback(ResetCallback callback)
87 if (callback ==
nullptr) {
88 return kInvalidHandle;
90 QMutexLocker lock(&s_mutex);
91 const int count = s_resetCount.load(std::memory_order_relaxed);
92 for (
int i = 0; i < count; ++i) {
93 if (s_resets[i] == callback)
94 return static_cast<RegistrationHandle
>(i);
96 if (count >= kMaxBridges) {
97 qCWarning(GstContextBridgeRegistryLog) <<
"reset callback registry full (kMaxBridges=" << kMaxBridges
98 <<
"); callback will not run on QRhi teardown";
99 return kInvalidHandle;
101 s_resets[count] = callback;
102 s_resetCount.store(count + 1, std::memory_order_release);
103 return static_cast<RegistrationHandle
>(count);
106RegistrationHandle registerCacheReset(ResetCallback callback)
108 if (callback ==
nullptr) {
109 return kInvalidHandle;
111 QMutexLocker lock(&s_mutex);
112 const int count = s_cacheResetCount.load(std::memory_order_relaxed);
113 for (
int i = 0; i < count; ++i) {
114 if (s_cacheResets[i] == callback)
115 return static_cast<RegistrationHandle
>(i);
117 if (count >= kMaxCacheResets) {
118 qCWarning(GstContextBridgeRegistryLog) <<
"cache-reset registry full (kMaxCacheResets=" << kMaxCacheResets
119 <<
"); callback will not run on GPU device-loss";
120 return kInvalidHandle;
122 s_cacheResets[count] = callback;
123 s_cacheResetCount.store(count + 1, std::memory_order_release);
124 return static_cast<RegistrationHandle
>(count);
128GstBusSyncReply dispatchBridges(GstMessage* message)
131 const int count = s_handlerCount.load(std::memory_order_acquire);
132 for (
int i = 0; i < count; ++i) {
133 const BridgeHandler h = s_handlers[i];
134 if (h && (h(message) == GST_BUS_DROP))
140void resetAllBridges()
142 const int count = s_resetCount.load(std::memory_order_acquire);
143 for (
int i = 0; i < count; ++i) {
144 const ResetCallback cb = s_resets[i];
155 const int count = s_cacheResetCount.load(std::memory_order_acquire);
156 for (
int i = 0; i < count; ++i) {
157 const ResetCallback cb = s_cacheResets[i];
163#ifdef QGC_GST_BUILD_TESTING
168 QMutexLocker lock(&s_mutex);
169 s_handlers.fill(
nullptr);
170 s_resets.fill(
nullptr);
171 s_cacheResets.fill(
nullptr);
172 s_handlerCount.store(0, std::memory_order_release);
173 s_resetCount.store(0, std::memory_order_release);
174 s_cacheResetCount.store(0, std::memory_order_release);
#define QGC_LOGGING_CATEGORY(name, categoryStr)