QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GstD3D11ContextBridge.cc
Go to the documentation of this file.
2
4
5#if defined(Q_OS_WIN) && defined(QGC_HAS_GST_D3D11_GPU_PATH)
6
7#include <d3d11.h>
8#include <d3d11_4.h> // ID3D11Multithread
9#include <gst/d3d11/gstd3d11.h>
10#include <rhi/qrhi.h> // QRhi::Implementation enum only; no runtime use across threads
11
12#include "QGCLoggingCategory.h"
13#include "QGCRhiCapture.h"
14
15QGC_LOGGING_CATEGORY(GstD3D11BridgeLog, "Video.GStreamer.HwBuffers.GstD3D11Bridge")
16
17namespace GstD3D11ContextBridge {
18namespace {
19
20GstD3DContextBridgeCommon::BridgeState s_state;
21
22GstObject* createDevice(const QLoggingCategory& cat)
23{
24 // Snapshot populated on the render thread (sceneGraphInitialized); only atomic loads here.
25 auto* dev = static_cast<ID3D11Device*>(QGCRhiCapture::deviceSnapshot().d3d11Device.load(std::memory_order_acquire));
26 if (!dev) {
27 qCWarning(cat) << "QRhi D3D11 snapshot missing ID3D11Device*";
28 return nullptr;
29 }
30
31 // QRhi creates this device with devFlags=0 (qrhid3d11.cpp) — no multithread protection. GStreamer's streaming
32 // thread and the QRhi render thread share its immediate context, so guard it explicitly. Idempotent: a no-op if
33 // GStreamer or a future QRhi already enabled it.
34 ID3D11DeviceContext* immediate = nullptr;
35 dev->GetImmediateContext(&immediate);
36 if (immediate) {
37 ID3D11Multithread* multithread = nullptr;
38 if (SUCCEEDED(immediate->QueryInterface(__uuidof(ID3D11Multithread), reinterpret_cast<void**>(&multithread))) &&
39 multithread) {
40 multithread->SetMultithreadProtected(TRUE);
41 multithread->Release();
42 }
43 immediate->Release();
44 }
45
46 // gst_d3d11_device_new_wrapped: shared device keeps textures QRhi-sampleable without keyed-mutex transfer.
47 GstD3D11Device* device = gst_d3d11_device_new_wrapped(dev);
48 if (!device) {
49 qCWarning(cat) << "gst_d3d11_device_new_wrapped failed";
50 return nullptr;
51 }
52
53 const gint64 expectedLuid = QGCRhiCapture::deviceSnapshot().adapterLuid.load(std::memory_order_acquire);
54 GstD3DContextBridgeCommon::logAdapterMatch(expectedLuid, device, cat, "D3D11");
55 return GST_OBJECT(device);
56}
57
58GstContext* makeContext(GstObject* device)
59{
60 // gst_d3d11_context_new gst_object_ref's the device internally; caller retains ownership.
61 return gst_d3d11_context_new(GST_D3D11_DEVICE_CAST(device));
62}
63
64const GstD3DContextBridgeCommon::BridgeOps s_ops = {
65 "D3D11", GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE, &GstD3D11BridgeLog, int(QRhi::D3D11), &createDevice, &makeContext,
66};
67
68struct D3D11BridgeRegistrar
69{
70 D3D11BridgeRegistrar() { GstD3DContextBridgeCommon::registerBridge(GstD3D11BridgeLog(), &handleSyncMessage, &reset); }
71};
72
73static D3D11BridgeRegistrar s_d3d11BridgeRegistrar;
74
75} // namespace
76
77bool prime()
78{
79 return GstD3DContextBridgeCommon::prime(s_state, s_ops);
80}
81
82GstD3D11Device* currentDevice()
83{
84 return GST_D3D11_DEVICE_CAST(GstD3DContextBridgeCommon::currentDevice(s_state));
85}
86
87GstBusSyncReply handleSyncMessage(GstMessage* message)
88{
89 return GstD3DContextBridgeCommon::handleSyncMessage(s_state, s_ops, message);
90}
91
92bool answerContextQuery(GstQuery* query)
93{
94 return GstD3DContextBridgeCommon::answerContextQuery(s_state, s_ops, query);
95}
96
97void reset()
98{
99 GstD3DContextBridgeCommon::reset(s_state, s_ops);
100}
101
102} // namespace GstD3D11ContextBridge
103
104#endif // Q_OS_WIN && QGC_HAS_GST_D3D11_GPU_PATH
#define QGC_LOGGING_CATEGORY(name, categoryStr)
DeviceSnapshot & deviceSnapshot() noexcept
Returns the global snapshot. Atomic fields make individual reads thread-safe.
std::atomic< void * > d3d11Device
ID3D11Device* (Windows only)
std::atomic< qint64 > adapterLuid
Composed (high<<32)|low LUID, 0 if unknown.