1 | // Copyright (C) 2024 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "qquick3dxrmanager_p.h" |
5 | |
6 | #include <QtCore/QCoreApplication> |
7 | #include <QtCore/QDebug> |
8 | #include <QtCore/qjsonobject.h> |
9 | #include <QtCore/qjsonarray.h> |
10 | |
11 | #include <rhi/qrhi.h> |
12 | |
13 | #include <QtQuick/private/qquickwindow_p.h> |
14 | #include <QtQuick/QQuickRenderControl> |
15 | #include <QtQuick/QQuickRenderTarget> |
16 | #include <QtQuick/QQuickItem> |
17 | |
18 | #include <QtQuick3D/private/qquick3dnode_p.h> |
19 | #include <QtQuick3D/private/qquick3dviewport_p.h> |
20 | |
21 | |
22 | // #include "qquick3dxrcamera_p.h" |
23 | #include "qquick3dxranimationdriver_p.h" |
24 | |
25 | #if defined(Q_OS_VISIONOS) |
26 | # include <QtQuick3DXr/private/qquick3dxrmanager_visionos_p.h> |
27 | #else |
28 | # include "openxr/qquick3dxrmanager_openxr_p.h" |
29 | #endif |
30 | |
31 | #include "qquick3dxrorigin_p.h" |
32 | #include "qquick3dxrinputmanager_p.h" |
33 | |
34 | QT_BEGIN_NAMESPACE |
35 | |
36 | Q_DECLARE_LOGGING_CATEGORY(lcQuick3DXr); |
37 | Q_LOGGING_CATEGORY(lcQuick3DXr, "qt.quick3d.xr"); |
38 | |
39 | QQuick3DXrManager::QQuick3DXrManager(QObject *parent) |
40 | : QObject(parent) |
41 | , d_ptr(new QQuick3DXrManagerPrivate(*this)) |
42 | { |
43 | } |
44 | |
45 | QQuick3DXrManager::~QQuick3DXrManager() |
46 | { |
47 | teardown(); |
48 | |
49 | // maintain the correct order |
50 | delete m_vrViewport; |
51 | delete m_quickWindow; |
52 | delete m_renderControl; |
53 | delete m_animationDriver; |
54 | } |
55 | |
56 | bool QQuick3DXrManager::isReady() const |
57 | { |
58 | Q_D(const QQuick3DXrManager); |
59 | return d->isReady(); |
60 | } |
61 | |
62 | bool QQuick3DXrManager::initialize() |
63 | { |
64 | Q_D(QQuick3DXrManager); |
65 | |
66 | QString m_errorString; |
67 | |
68 | // TODO: Handle visionos being async a bit better |
69 | if (!d->initialize()) { |
70 | if (!d->isReady()) |
71 | m_errorString = QStringLiteral("Waiting for the renderer to start."); |
72 | else |
73 | m_errorString = QStringLiteral("Failed to initialize the XR manager."); |
74 | |
75 | return false; |
76 | } |
77 | |
78 | // Setup Graphics |
79 | return setupGraphics(); |
80 | } |
81 | |
82 | void QQuick3DXrManager::teardown() |
83 | { |
84 | Q_D(QQuick3DXrManager); |
85 | d->teardown(); |
86 | } |
87 | |
88 | bool QQuick3DXrManager::isValid() const |
89 | { |
90 | Q_D(const QQuick3DXrManager); |
91 | return d->isValid(); |
92 | } |
93 | |
94 | void QQuick3DXrManager::setPassthroughEnabled(bool enabled) |
95 | { |
96 | Q_D(QQuick3DXrManager); |
97 | d->setPassthroughEnabled(enabled); |
98 | } |
99 | |
100 | bool QQuick3DXrManager::isPassthroughEnabled() const |
101 | { |
102 | Q_D(const QQuick3DXrManager); |
103 | return d->isPassthroughEnabled(); |
104 | } |
105 | |
106 | void QQuick3DXrManager::setMultiViewRenderingEnabled(bool enable) |
107 | { |
108 | Q_D(QQuick3DXrManager); |
109 | d->setMultiViewRenderingEnabled(enable); |
110 | } |
111 | |
112 | bool QQuick3DXrManager::isMultiViewRenderingEnabled() const |
113 | { |
114 | Q_D(const QQuick3DXrManager); |
115 | return d->isMultiViewRenderingEnabled(); |
116 | } |
117 | |
118 | bool QQuick3DXrManager::isMultiViewRenderingSupported() const |
119 | { |
120 | QRhi *rhi = m_renderControl->rhi(); |
121 | return rhi ? rhi->isFeatureSupported(feature: QRhi::MultiView) : false; |
122 | } |
123 | |
124 | void QQuick3DXrManager::setXROrigin(QQuick3DXrOrigin *origin) |
125 | { |
126 | m_xrOrigin = origin; |
127 | update(); |
128 | } |
129 | |
130 | void QQuick3DXrManager::getDefaultClipDistances(float &nearClip, float &farClip) const |
131 | { |
132 | Q_D(const QQuick3DXrManager); |
133 | d->getDefaultClipDistances(nearClip, farClip); |
134 | } |
135 | |
136 | QtQuick3DXr::FoveationLevel QQuick3DXrManager::getFixedFoveationLevel() const |
137 | { |
138 | #if defined(Q_OS_VISIONOS) |
139 | // Foveation is not configurable on VisionOS |
140 | return QtQuick3DXr::FoveationLevel::HighFoveation; |
141 | #else |
142 | Q_D(const QQuick3DXrManager); |
143 | return QtQuick3DXr::FoveationLevel(d->m_foveationLevel); |
144 | #endif |
145 | } |
146 | |
147 | void QQuick3DXrManager::setFixedFoveationLevel(QtQuick3DXr::FoveationLevel level) |
148 | { |
149 | #if defined(Q_OS_VISIONOS) |
150 | // Foveation is not configurable on VisionOS |
151 | Q_UNUSED(level); |
152 | #else |
153 | Q_D(QQuick3DXrManager); |
154 | const XrFoveationLevelFB xrLevel = XrFoveationLevelFB(level); |
155 | if (d->m_foveationLevel == xrLevel) |
156 | return; |
157 | |
158 | d->m_foveationLevel = xrLevel; |
159 | d->setupMetaQuestFoveation(); |
160 | #endif |
161 | } |
162 | |
163 | QtQuick3DXr::ReferenceSpace QQuick3DXrManager::getReferenceSpace() const |
164 | { |
165 | Q_D(const QQuick3DXrManager); |
166 | return d->getReferenceSpace(); |
167 | } |
168 | |
169 | void QQuick3DXrManager::setReferenceSpace(QtQuick3DXr::ReferenceSpace newReferenceSpace) |
170 | { |
171 | Q_D(QQuick3DXrManager); |
172 | |
173 | d->setReferenceSpace(newReferenceSpace); |
174 | } |
175 | |
176 | bool QQuick3DXrManager::isDepthSubmissionEnabled() const |
177 | { |
178 | Q_D(const QQuick3DXrManager); |
179 | return d->isDepthSubmissionEnabled(); |
180 | } |
181 | |
182 | void QQuick3DXrManager::setDepthSubmissionEnabled(bool enable) |
183 | { |
184 | Q_D(QQuick3DXrManager); |
185 | d->setDepthSubmissionEnabled(enable); |
186 | } |
187 | |
188 | QString QQuick3DXrManager::errorString() const |
189 | { |
190 | Q_D(const QQuick3DXrManager); |
191 | return d->errorString(); |
192 | } |
193 | |
194 | void QQuick3DXrManager::setSamples(int samples) |
195 | { |
196 | Q_D(QQuick3DXrManager); |
197 | d->setSamples(samples); |
198 | } |
199 | |
200 | void QQuick3DXrManager::update() |
201 | { |
202 | Q_D(QQuick3DXrManager); |
203 | d->update(); |
204 | } |
205 | |
206 | bool QQuick3DXrManager::event(QEvent *e) |
207 | { |
208 | Q_D(QQuick3DXrManager); |
209 | |
210 | if (e->type() == QEvent::UpdateRequest) { |
211 | d->processXrEvents(); |
212 | d->update(); |
213 | return true; |
214 | } |
215 | return QObject::event(event: e); |
216 | } |
217 | |
218 | bool QQuick3DXrManager::isMultiviewRenderingDisabled() |
219 | { |
220 | static bool disabled = qEnvironmentVariableIntValue(varName: "QT_QUICK3D_XR_DISABLE_MULTIVIEW") != 0; |
221 | return disabled; |
222 | } |
223 | |
224 | QQuick3DXrInputManager *QQuick3DXrManager::getInputManager() const |
225 | { |
226 | Q_D(const QQuick3DXrManager); |
227 | return d->m_inputManager.data(); |
228 | } |
229 | |
230 | bool QQuick3DXrManager::setupGraphics() |
231 | { |
232 | Q_D(QQuick3DXrManager); |
233 | |
234 | // FIXME: Should probably make sure we don't accidentally get here more then once |
235 | // or if we're re-initializing, in which case: make sure to clean up properly first. |
236 | if (d->isGraphicsInitialized()) |
237 | return true; |
238 | |
239 | preSetupQuickScene(); |
240 | |
241 | if (!d->setupGraphics(m_quickWindow)) |
242 | return false; |
243 | |
244 | if (!setupQuickScene()) |
245 | return false; |
246 | |
247 | QRhi *rhi = m_quickWindow->rhi(); |
248 | QSSG_ASSERT_X(rhi != nullptr, "No RHI handle!", return false); |
249 | |
250 | if (!d->isMultiViewRenderingEnabled()) |
251 | emit multiViewRenderingEnabledChanged(); |
252 | |
253 | return d->finalizeGraphics(rhi); |
254 | } |
255 | |
256 | void QQuick3DXrManager::renderFrame() |
257 | { |
258 | Q_D(QQuick3DXrManager); |
259 | |
260 | if (!m_xrOrigin) { |
261 | if (!m_xrOriginWarningShown) { |
262 | qWarning() << "No XrOrigin found!"; |
263 | m_xrOriginWarningShown = true; |
264 | } |
265 | return; |
266 | } |
267 | |
268 | d->doRenderFrame(); |
269 | } |
270 | |
271 | void QQuick3DXrManager::preSetupQuickScene() |
272 | { |
273 | if (!m_renderControl) |
274 | m_renderControl = new QQuickRenderControl; |
275 | if (!m_quickWindow) |
276 | m_quickWindow = new QQuickWindow(m_renderControl); |
277 | } |
278 | |
279 | bool QQuick3DXrManager::setupQuickScene() |
280 | { |
281 | Q_D(QQuick3DXrManager); |
282 | |
283 | d->setupWindow(m_quickWindow); |
284 | |
285 | if (!m_animationDriver) { |
286 | m_animationDriver = new QQuick3DXrAnimationDriver; |
287 | m_animationDriver->install(); |
288 | } |
289 | |
290 | const bool initSuccess = m_renderControl->initialize(); |
291 | if (!initSuccess) { |
292 | qWarning(msg: "Quick 3D XR: Failed to create renderControl (failed to initialize RHI?)"); |
293 | return false; |
294 | } |
295 | |
296 | QRhi *rhi = m_renderControl->rhi(); |
297 | if (!rhi) { |
298 | qWarning(msg: "Quick3D XR: No QRhi from renderControl. This should not happen."); |
299 | return false; |
300 | } |
301 | |
302 | qCDebug(lcQuick3DXr, "Quick 3D XR: QRhi initialized with backend %s", rhi->backendName()); |
303 | |
304 | return true; |
305 | } |
306 | |
307 | bool QQuick3DXrManager::supportsPassthrough() const |
308 | { |
309 | Q_D(const QQuick3DXrManager); |
310 | return d->supportsPassthrough(); |
311 | } |
312 | |
313 | QT_END_NAMESPACE |
314 |
Definitions
- lcQuick3DXr
- QQuick3DXrManager
- ~QQuick3DXrManager
- isReady
- initialize
- teardown
- isValid
- setPassthroughEnabled
- isPassthroughEnabled
- setMultiViewRenderingEnabled
- isMultiViewRenderingEnabled
- isMultiViewRenderingSupported
- setXROrigin
- getDefaultClipDistances
- getFixedFoveationLevel
- setFixedFoveationLevel
- getReferenceSpace
- setReferenceSpace
- isDepthSubmissionEnabled
- setDepthSubmissionEnabled
- errorString
- setSamples
- update
- event
- isMultiviewRenderingDisabled
- getInputManager
- setupGraphics
- renderFrame
- preSetupQuickScene
- setupQuickScene
Learn Advanced QML with KDAB
Find out more