Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qthreadlocalrhi.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <rhi/qrhi.h>
7#include <QtCore/qcoreapplication.h>
8#include <QtCore/qthreadstorage.h>
9#include <QtGui/qoffscreensurface.h>
10#include <qpa/qplatformintegration.h>
11#include <private/qguiapplication_p.h>
12
13#if defined(Q_OS_ANDROID)
14#include <qmetaobject.h>
15#endif
16
18
19namespace {
20
22{
23public:
24 ~ThreadLocalRhiHolder() { resetRhi(); }
25
26 QRhi *ensureRhi(QRhi *referenceRhi)
27 {
28 if (m_rhi || m_cpuOnly)
29 return m_rhi.get();
30
31 QRhi::Implementation referenceBackend = referenceRhi ? referenceRhi->backend() : QRhi::Null;
32 const QPlatformIntegration *qpa = QGuiApplicationPrivate::platformIntegration();
33
34 if (qpa && qpa->hasCapability(QPlatformIntegration::RhiBasedRendering)) {
35
36#if QT_CONFIG(metal)
37 if (referenceBackend == QRhi::Metal || referenceBackend == QRhi::Null) {
38 QRhiMetalInitParams params;
39 m_rhi.reset(QRhi::create(QRhi::Metal, &params));
40 }
41#endif
42
43#if defined(Q_OS_WIN)
44 if (referenceBackend == QRhi::D3D11 || referenceBackend == QRhi::Null) {
45 QRhiD3D11InitParams params;
46 m_rhi.reset(QRhi::create(QRhi::D3D11, &params));
47 }
48#endif
49
50#if QT_CONFIG(opengl)
51 if (!m_rhi && (referenceBackend == QRhi::OpenGLES2 || referenceBackend == QRhi::Null)) {
52 if (qpa->hasCapability(QPlatformIntegration::OpenGL)
53 && qpa->hasCapability(QPlatformIntegration::RasterGLSurface)
54 && !QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets)) {
55
56 m_fallbackSurface.reset(QRhiGles2InitParams::newFallbackSurface());
57 QRhiGles2InitParams params;
58 params.fallbackSurface = m_fallbackSurface.get();
59 if (referenceBackend == QRhi::OpenGLES2)
60 params.shareContext = static_cast<const QRhiGles2NativeHandles *>(
61 referenceRhi->nativeHandles())
62 ->context;
63 m_rhi.reset(QRhi::create(QRhi::OpenGLES2, &params));
64
65# if defined(Q_OS_ANDROID)
66 // reset RHI state on application suspension, as this will be invalid after
67 // resuming
68 if (!m_appStateChangedConnection) {
69 if (!m_eventsReceiver)
70 m_eventsReceiver = std::make_unique<QObject>();
71
72 auto onStateChanged = [this](auto state) {
73 if (state == Qt::ApplicationSuspended)
74 resetRhi();
75 };
76
77 m_appStateChangedConnection =
78 QObject::connect(qApp, &QGuiApplication::applicationStateChanged,
79 m_eventsReceiver.get(), onStateChanged);
80 }
81# endif
82 }
83 }
84#endif
85 }
86
87 if (!m_rhi) {
88 m_cpuOnly = true;
89 qWarning() << Q_FUNC_INFO << ": No RHI backend. Using CPU conversion.";
90 }
91
92 return m_rhi.get();
93 }
94
95private:
96 void resetRhi()
97 {
98 m_rhi.reset();
99#if QT_CONFIG(opengl)
100 m_fallbackSurface.reset();
101#endif
102 m_cpuOnly = false;
103 }
104
105private:
106 std::unique_ptr<QRhi> m_rhi;
107#if QT_CONFIG(opengl)
109#endif
110 bool m_cpuOnly = false;
111#if defined(Q_OS_ANDROID)
113 // we keep and check QMetaObject::Connection because the sender, qApp,
114 // can be recreated and the connection invalidated.
116#endif
117};
118
120
121}
122
123QRhi *ensureThreadLocalRhi(QRhi* referenceRhi)
124{
125 return g_threadLocalRhiHolder.localData().ensureRhi(referenceRhi);
126}
127
128QT_END_NAMESPACE
Combined button and popup list for selecting options.
QThreadStorage< ThreadLocalRhiHolder > g_threadLocalRhiHolder
QRhi * ensureThreadLocalRhi(QRhi *referenceRhi)