QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GstD3DContextBridgeCommon.cc
Go to the documentation of this file.
2
3#if defined(Q_OS_WIN) && (defined(QGC_HAS_GST_D3D11_GPU_PATH) || defined(QGC_HAS_GST_D3D12_GPU_PATH))
4
5#include "QGCRhiCapture.h"
6
7#include <rhi/qrhi.h>
8#include <glib-object.h>
9
10namespace GstD3DContextBridgeCommon {
11
12// Caller must hold state.mutex — warnedWrongBackend is a plain bool, not atomic.
13// Also called from the bus-sync thread; backend()/backendName() are read-only enum/string
14// accessors on QRhi and don't touch GPU state, but QRhi is documented single-thread so this
15// is "safe by inspection" rather than by API contract — keep the calls limited to these.
16QRhi *checkRhiBackend(BridgeState &state,
17 const QLoggingCategory &cat,
18 int expectedBackend,
19 const char *backendName)
20{
21 QRhi *rhi = QGCRhiCapture::cachedRhi();
22 if (!rhi) {
23 qCDebug(cat) << "QRhi not yet available; will retry on next NEED_CONTEXT";
24 return nullptr;
25 }
26 if (static_cast<int>(rhi->backend()) != expectedBackend) {
27 if (!state.warnedWrongBackend) {
28 qCInfo(cat) << "QRhi backend is" << rhi->backendName()
29 << "(not" << backendName << "); bridge inactive";
30 state.warnedWrongBackend = true;
31 }
32 return nullptr;
33 }
34 return rhi;
35}
36
37GstElement *matchNeedContext(GstMessage *message, const char *expectedContextType)
38{
39 if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_NEED_CONTEXT) {
40 return nullptr;
41 }
42 const gchar *contextType = nullptr;
43 if (!gst_message_parse_context_type(message, &contextType) || !contextType) {
44 return nullptr;
45 }
46 if (g_strcmp0(contextType, expectedContextType) != 0) {
47 return nullptr;
48 }
49 return GST_ELEMENT(GST_MESSAGE_SRC(message));
50}
51
52void logHandoff(BridgeState &state,
53 const QLoggingCategory &cat,
54 GstElement *element,
55 const char *apiName)
56{
57 if (!state.loggedFirstHandoff.exchange(true, std::memory_order_relaxed)) {
58 qCInfo(cat) << "First" << apiName << "device handoff to element"
59 << GST_ELEMENT_NAME(element);
60 } else {
61 qCDebug(cat) << "Provided" << apiName << "device context to" << GST_ELEMENT_NAME(element);
62 }
63}
64
65gint64 readAdapterLuid(gpointer device)
66{
67 if (!device || !G_IS_OBJECT(device)) return 0;
68 gint64 luid = 0;
69 g_object_get(G_OBJECT(device), "adapter-luid", &luid, nullptr);
70 return luid;
71}
72
73void logAdapterMatch(QRhi *rhi, gint64 expectedLuid, gpointer gstDevice,
74 const QLoggingCategory &cat, const char *apiName)
75{
76 const gint64 actualLuid = readAdapterLuid(gstDevice);
77 if (actualLuid != expectedLuid) {
78 qCWarning(cat).noquote()
79 << apiName << "bridge: gst device LUID mismatch — QRhi LUID="
80 << expectedLuid << "but wrapped device LUID=" << actualLuid
81 << "(zero-copy will appear corrupt; check NEED_CONTEXT race)";
82 return;
83 }
84 if (!rhi) return;
85 const QRhiDriverInfo info = rhi->driverInfo();
86 qCInfo(cat).noquote()
87 << apiName << "bridge adapter:" << info.deviceName
88 << QString::asprintf("(vendorId=0x%04X deviceId=0x%04X type=%d luid=%lld)",
89 unsigned(info.vendorId), unsigned(info.deviceId),
90 int(info.deviceType), static_cast<long long>(expectedLuid));
91}
92
93} // namespace GstD3DContextBridgeCommon
94
95#endif // Q_OS_WIN && (QGC_HAS_GST_D3D11_GPU_PATH || QGC_HAS_GST_D3D12_GPU_PATH)
struct _GstElement GstElement
QRhi * cachedRhi() noexcept