QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GstD3D12ContextBridge.cc
Go to the documentation of this file.
4
5#if defined(Q_OS_WIN) && defined(QGC_HAS_GST_D3D12_GPU_PATH)
6
8
9#include <QtCore/QMutexLocker>
10
11#include <QtGui/rhi/qrhi.h>
12#include <QtGui/rhi/qrhi_platform.h>
13
14#include <gst/d3d12/gstd3d12.h>
15
16QGC_LOGGING_CATEGORY(GstD3D12BridgeLog, "Video.GStreamer.HwBuffers.GstD3D12Bridge")
17
18namespace GstD3D12ContextBridge {
19namespace {
20
21GstD3DContextBridgeCommon::BridgeState s_state;
22GstD3D12Device *s_device = nullptr;
23
24bool primeLocked()
25{
26 if (s_state.primed) return true;
27
28 QRhi *rhi = GstD3DContextBridgeCommon::checkRhiBackend(
29 s_state, GstD3D12BridgeLog(), int(QRhi::D3D12), "D3D12");
30 if (!rhi) return false;
31
32 auto *handles = static_cast<const QRhiD3D12NativeHandles *>(rhi->nativeHandles());
33 if (!handles || !handles->dev) {
34 qCWarning(GstD3D12BridgeLog) << "QRhiD3D12NativeHandles missing ID3D12Device*";
35 return false;
36 }
37
38 // Compose the adapter LUID from the two halves Qt exposes, then let gst-d3d12
39 // create (or retrieve from cache) a GstD3D12Device on that adapter.
40 // HighPart is qint32 (signed, mirrors LARGE_INTEGER::HighPart=LONG); sign-extend
41 // before the shift so negative HighPart matches LARGE_INTEGER::QuadPart bit-for-bit.
42 const gint64 luid = (static_cast<gint64>(handles->adapterLuidHigh) << 32)
43 | static_cast<gint64>(handles->adapterLuidLow);
44
45 s_device = gst_d3d12_device_new_for_adapter_luid(luid);
46 if (!s_device) {
47 qCWarning(GstD3D12BridgeLog) << "gst_d3d12_device_new_for_adapter_luid failed (luid=" << luid << ")";
48 return false;
49 }
50 s_state.primed = true;
51 qCInfo(GstD3D12BridgeLog) << "D3D12 bridge primed: shared device =" << s_device
52 << "luid=" << luid;
53 GstD3DContextBridgeCommon::logAdapterMatch(rhi, luid, s_device,
54 GstD3D12BridgeLog(), "D3D12");
55 return true;
56}
57
58} // namespace
59
60bool prime()
61{
62 QMutexLocker lock(&s_state.mutex);
63 return primeLocked();
64}
65
66GstD3D12Device *currentDevice()
67{
68 QMutexLocker lock(&s_state.mutex);
69 if (!s_device) return nullptr;
70 return GST_D3D12_DEVICE_CAST(gst_object_ref(s_device));
71}
72
73GstBusSyncReply handleSyncMessage(GstMessage *message)
74{
75 GstElement *element = GstD3DContextBridgeCommon::matchNeedContext(
76 message, GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE);
77 if (!element) {
78 return GST_BUS_PASS;
79 }
80
81 QMutexLocker lock(&s_state.mutex);
82 if (!primeLocked() || !s_device) {
83 return GST_BUS_PASS;
84 }
85
86 // gst_d3d12_context_new internally gst_object_ref's s_device; caller retains ownership.
87 GstContext *ctx = gst_d3d12_context_new(s_device);
88 if (!ctx) {
89 qCWarning(GstD3D12BridgeLog) << "gst_d3d12_context_new failed for element"
90 << GST_ELEMENT_NAME(element);
91 return GST_BUS_PASS;
92 }
93 gst_element_set_context(element, ctx);
94 gst_context_unref(ctx);
95 gst_message_unref(message);
96
97 GstD3DContextBridgeCommon::logHandoff(s_state, GstD3D12BridgeLog(), element, "D3D12");
98 return GST_BUS_DROP;
99}
100
101void reset()
102{
103 QMutexLocker lock(&s_state.mutex);
104 gst_clear_object(&s_device);
105 s_state.primed = false;
106 s_state.warnedWrongBackend = false;
107 qCDebug(GstD3D12BridgeLog) << "D3D12 bridge reset";
108}
109
110namespace {
111struct D3D12BridgeRegistrar {
112 D3D12BridgeRegistrar() {
113 GstContextBridgeRegistry::registerBridgeHandler(&GstD3D12ContextBridge::handleSyncMessage);
114 GstContextBridgeRegistry::registerResetCallback(&GstD3D12ContextBridge::reset);
115 }
116};
117static D3D12BridgeRegistrar s_d3d12BridgeRegistrar;
118} // namespace
119
120} // namespace GstD3D12ContextBridge
121
122#endif // Q_OS_WIN && QGC_HAS_GST_D3D12_GPU_PATH
struct _GstElement GstElement
#define QGC_LOGGING_CATEGORY(name, categoryStr)