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
34QT_BEGIN_NAMESPACE
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
45QQuick3DXrManager::~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
56bool QQuick3DXrManager::isReady() const
57{
58 Q_D(const QQuick3DXrManager);
59 return d->isReady();
60}
61
62bool 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
82void QQuick3DXrManager::teardown()
83{
84 Q_D(QQuick3DXrManager);
85 d->teardown();
86}
87
88bool QQuick3DXrManager::isValid() const
89{
90 Q_D(const QQuick3DXrManager);
91 return d->isValid();
92}
93
94void QQuick3DXrManager::setPassthroughEnabled(bool enabled)
95{
96 Q_D(QQuick3DXrManager);
97 d->setPassthroughEnabled(enabled);
98}
99
100bool QQuick3DXrManager::isPassthroughEnabled() const
101{
102 Q_D(const QQuick3DXrManager);
103 return d->isPassthroughEnabled();
104}
105
106void QQuick3DXrManager::setMultiViewRenderingEnabled(bool enable)
107{
108 Q_D(QQuick3DXrManager);
109 d->setMultiViewRenderingEnabled(enable);
110}
111
112bool QQuick3DXrManager::isMultiViewRenderingEnabled() const
113{
114 Q_D(const QQuick3DXrManager);
115 return d->isMultiViewRenderingEnabled();
116}
117
118bool QQuick3DXrManager::isMultiViewRenderingSupported() const
119{
120 QRhi *rhi = m_renderControl->rhi();
121 return rhi ? rhi->isFeatureSupported(feature: QRhi::MultiView) : false;
122}
123
124void QQuick3DXrManager::setXROrigin(QQuick3DXrOrigin *origin)
125{
126 m_xrOrigin = origin;
127 update();
128}
129
130void QQuick3DXrManager::getDefaultClipDistances(float &nearClip, float &farClip) const
131{
132 Q_D(const QQuick3DXrManager);
133 d->getDefaultClipDistances(nearClip, farClip);
134}
135
136QtQuick3DXr::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
147void 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
163QtQuick3DXr::ReferenceSpace QQuick3DXrManager::getReferenceSpace() const
164{
165 Q_D(const QQuick3DXrManager);
166 return d->getReferenceSpace();
167}
168
169void QQuick3DXrManager::setReferenceSpace(QtQuick3DXr::ReferenceSpace newReferenceSpace)
170{
171 Q_D(QQuick3DXrManager);
172
173 d->setReferenceSpace(newReferenceSpace);
174}
175
176bool QQuick3DXrManager::isDepthSubmissionEnabled() const
177{
178 Q_D(const QQuick3DXrManager);
179 return d->isDepthSubmissionEnabled();
180}
181
182void QQuick3DXrManager::setDepthSubmissionEnabled(bool enable)
183{
184 Q_D(QQuick3DXrManager);
185 d->setDepthSubmissionEnabled(enable);
186}
187
188QString QQuick3DXrManager::errorString() const
189{
190 Q_D(const QQuick3DXrManager);
191 return d->errorString();
192}
193
194void QQuick3DXrManager::setSamples(int samples)
195{
196 Q_D(QQuick3DXrManager);
197 d->setSamples(samples);
198}
199
200void QQuick3DXrManager::update()
201{
202 Q_D(QQuick3DXrManager);
203 d->update();
204}
205
206bool 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
218bool QQuick3DXrManager::isMultiviewRenderingDisabled()
219{
220 static bool disabled = qEnvironmentVariableIntValue(varName: "QT_QUICK3D_XR_DISABLE_MULTIVIEW") != 0;
221 return disabled;
222}
223
224QQuick3DXrInputManager *QQuick3DXrManager::getInputManager() const
225{
226 Q_D(const QQuick3DXrManager);
227 return d->m_inputManager.data();
228}
229
230bool 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
256void 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
271void 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
279bool 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
307bool QQuick3DXrManager::supportsPassthrough() const
308{
309 Q_D(const QQuick3DXrManager);
310 return d->supportsPassthrough();
311}
312
313QT_END_NAMESPACE
314

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtquick3d/src/xr/quick3dxr/qquick3dxrmanager.cpp