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
qquick3dxrmanager.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
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"
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
33
35
36Q_DECLARE_LOGGING_CATEGORY(lcQuick3DXr);
37Q_LOGGING_CATEGORY(lcQuick3DXr, "qt.quick3d.xr");
38
39QQuick3DXrManager::QQuick3DXrManager(QObject *parent)
40 : QObject(parent)
41 , d_ptr(new QQuick3DXrManagerPrivate(*this))
42{
43}
44
46{
48
49 // maintain the correct order
50 delete m_vrViewport;
51 delete m_quickWindow;
52 delete m_renderControl;
53 delete m_animationDriver;
54}
55
57{
58 Q_D(const QQuick3DXrManager);
59 return d->isReady();
60}
61
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
83{
84 Q_D(QQuick3DXrManager);
85 d->teardown();
86}
87
89{
90 Q_D(const QQuick3DXrManager);
91 return d->isValid();
92}
93
95{
96 Q_D(QQuick3DXrManager);
97 // Returns true if passthrough is supported
98 return d->setPassthroughEnabled(enabled);
99}
100
102{
103 Q_D(const QQuick3DXrManager);
104 return d->isPassthroughEnabled();
105}
106
108{
109 Q_D(QQuick3DXrManager);
110 d->setMultiViewRenderingEnabled(enable);
111}
112
114{
115 Q_D(const QQuick3DXrManager);
116 return d->isMultiViewRenderingEnabled();
117}
118
120{
121 QRhi *rhi = m_renderControl->rhi();
122 return rhi ? rhi->isFeatureSupported(QRhi::MultiView) : false;
123}
124
125void QQuick3DXrManager::setXROrigin(QQuick3DXrOrigin *origin)
126{
127 m_xrOrigin = origin;
128 update();
129}
130
131void QQuick3DXrManager::getDefaultClipDistances(float &nearClip, float &farClip) const
132{
133 Q_D(const QQuick3DXrManager);
134 d->getDefaultClipDistances(nearClip, farClip);
135}
136
138{
139#if defined(Q_OS_VISIONOS)
140 // Foveation is not configurable on VisionOS
141 return QtQuick3DXr::FoveationLevel::HighFoveation;
142#else
143 Q_D(const QQuick3DXrManager);
144 return QtQuick3DXr::FoveationLevel(d->m_foveationLevel);
145#endif
146}
147
148void QQuick3DXrManager::setFixedFoveationLevel(QtQuick3DXr::FoveationLevel level)
149{
150#if defined(Q_OS_VISIONOS)
151 // Foveation is not configurable on VisionOS
152 Q_UNUSED(level);
153#else
154 Q_D(QQuick3DXrManager);
155 const XrFoveationLevelFB xrLevel = XrFoveationLevelFB(level);
156 if (d->m_foveationLevel == xrLevel)
157 return;
158
159 d->m_foveationLevel = xrLevel;
160 d->setupMetaQuestFoveation();
161#endif
162}
163
165{
166 Q_D(const QQuick3DXrManager);
167 return d->getReferenceSpace();
168}
169
170void QQuick3DXrManager::setReferenceSpace(QtQuick3DXr::ReferenceSpace newReferenceSpace)
171{
172 Q_D(QQuick3DXrManager);
173
174 d->setReferenceSpace(newReferenceSpace);
175}
176
178{
179 Q_D(const QQuick3DXrManager);
180 return d->isDepthSubmissionEnabled();
181}
182
184{
185 Q_D(QQuick3DXrManager);
186 d->setDepthSubmissionEnabled(enable);
187}
188
190{
191 Q_D(const QQuick3DXrManager);
192 return d->errorString();
193}
194
196{
197 Q_D(QQuick3DXrManager);
198 d->setSamples(samples);
199}
200
201void QQuick3DXrManager::update()
202{
203 Q_D(QQuick3DXrManager);
204 d->update();
205}
206
207bool QQuick3DXrManager::event(QEvent *e)
208{
209 Q_D(QQuick3DXrManager);
210
211 if (e->type() == QEvent::UpdateRequest) {
212 d->processXrEvents();
213 d->update();
214 return true;
215 }
216 return QObject::event(e);
217}
218
220{
221 static bool disabled = qEnvironmentVariableIntValue("QT_QUICK3D_XR_DISABLE_MULTIVIEW") != 0;
222 return disabled;
223}
224
225QQuick3DXrInputManager *QQuick3DXrManager::getInputManager() const
226{
227 Q_D(const QQuick3DXrManager);
228 return d->m_inputManager.data();
229}
230
231bool QQuick3DXrManager::setupGraphics()
232{
233 Q_D(QQuick3DXrManager);
234
235 // FIXME: Should probably make sure we don't accidentally get here more then once
236 // or if we're re-initializing, in which case: make sure to clean up properly first.
237 if (d->isGraphicsInitialized())
238 return true;
239
240 preSetupQuickScene();
241
242 if (!d->setupGraphics(m_quickWindow))
243 return false;
244
245 if (!setupQuickScene())
246 return false;
247
248 QRhi *rhi = m_quickWindow->rhi();
249 QSSG_ASSERT_X(rhi != nullptr, "No RHI handle!", return false);
250
251 if (!d->isMultiViewRenderingEnabled())
252 emit multiViewRenderingEnabledChanged();
253
254 return d->finalizeGraphics(rhi);
255}
256
257void QQuick3DXrManager::renderFrame()
258{
259 Q_D(QQuick3DXrManager);
260
261 if (!m_xrOrigin) {
262 if (!m_xrOriginWarningShown) {
263 qWarning() << "No XrOrigin found!";
264 m_xrOriginWarningShown = true;
265 }
266 return;
267 }
268
269 d->doRenderFrame();
270}
271
272void QQuick3DXrManager::preSetupQuickScene()
273{
274 if (!m_renderControl)
275 m_renderControl = new QQuickRenderControl;
276 if (!m_quickWindow)
277 m_quickWindow = new QQuickWindow(m_renderControl);
278}
279
280bool QQuick3DXrManager::setupQuickScene()
281{
282 Q_D(QQuick3DXrManager);
283
284 d->setupWindow(m_quickWindow);
285
286 if (!m_animationDriver) {
287 m_animationDriver = new QQuick3DXrAnimationDriver;
288 m_animationDriver->install();
289 }
290
291 const bool initSuccess = m_renderControl->initialize();
292 if (!initSuccess) {
293 qWarning("Quick 3D XR: Failed to create renderControl (failed to initialize RHI?)");
294 return false;
295 }
296
297 QRhi *rhi = m_renderControl->rhi();
298 if (!rhi) {
299 qWarning("Quick3D XR: No QRhi from renderControl. This should not happen.");
300 return false;
301 }
302
303 qCDebug(lcQuick3DXr, "Quick 3D XR: QRhi initialized with backend %s", rhi->backendName());
304
305 return true;
306}
307
308bool QQuick3DXrManager::supportsPassthrough() const
309{
310 Q_D(const QQuick3DXrManager);
311 return d->supportsPassthrough();
312}
313
314QT_END_NAMESPACE
void setDepthSubmissionEnabled(bool enable)
bool isPassthroughEnabled() const
void setFixedFoveationLevel(QtQuick3DXr::FoveationLevel level)
bool isMultiViewRenderingSupported() const
QString errorString() const
QtQuick3DXr::FoveationLevel getFixedFoveationLevel() const
bool isDepthSubmissionEnabled() const
void setMultiViewRenderingEnabled(bool enable)
void setSamples(int samples)
void setXROrigin(QQuick3DXrOrigin *origin)
bool isMultiViewRenderingEnabled() const
void getDefaultClipDistances(float &nearClip, float &farClip) const
void setReferenceSpace(QtQuick3DXr::ReferenceSpace newReferenceSpace)
bool setPassthroughEnabled(bool enabled)
bool event(QEvent *e) override
This virtual function receives events to an object and should return true if the event e was recogniz...
QtQuick3DXr::ReferenceSpace getReferenceSpace() const
static bool isMultiviewRenderingDisabled()
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")