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
qquick3dxrview.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
7#include <QQuickWindow>
8#include <QQuickItem>
9#include <QLoggingCategory>
10
11#include <QtQuick3DUtils/private/qssgassert_p.h>
12
14
16
17Q_DECLARE_LOGGING_CATEGORY(lcQuick3DXr);
18
19/*!
20 \qmltype XrView
21 \inherits Node
22 \inqmlmodule QtQuick3D.Xr
23 \brief Sets up the view for an Xr application.
24
25 An XrView sets up the view for an XR application.
26 The following snippet is from the \l{\qxr Simple Example} and shows
27 how to use the type.
28
29 \quotefromfile xr_simple/main.qml
30 \printto XrOrigin
31
32 \section1 Platform notes
33
34 \section2 Meta Quest Devices
35
36 To \l{XrView::passthroughEnabled}{enable passthrough} you need to add the
37 following permisson your app's \c AndroidManifest.xml file:
38
39 \badcode
40 <uses-feature android:name="com.oculus.feature.PASSTHROUGH" android:required="false"/>
41 \endcode
42
43*/
44
45QQuick3DXrView::QQuick3DXrView()
46 : m_xrRuntimeInfo(&m_xrManager)
47{
48 init();
49}
50
51QQuick3DXrView::~QQuick3DXrView()
52{
53 m_inDestructor = true;
54}
55
56/*!
57 \qmlproperty XrOrigin QtQuick3D.Xr::XrView::xrOrigin
58 \brief Holds the active XR origin.
59
60 The XR origin is the point in the scene that is considered the origin of the
61 XR coordinate system. The XR origin is used to position tracked objects like
62 the camera and controllers in the scene. An application can have multiple XrOrigins
63 but only one can be active at a time.
64
65 \note This property must be set for the scene to be rendered in XR.
66
67 \sa XrOrigin
68*/
69
70QQuick3DXrOrigin *QQuick3DXrView::xrOrigin() const
71{
72 return m_xrOrigin;
73}
74
75/*!
76 \qmlproperty SceneEnvironment QtQuick3D.Xr::XrView::environment
77 \summary Holds the SceneEnvironment for the XR view.
78*/
79
80QQuick3DSceneEnvironment *QQuick3DXrView::environment() const
81{
82 return m_xrManager.m_vrViewport ? m_xrManager.m_vrViewport->environment() : nullptr;
83}
84
85QQuick3DViewport *QQuick3DXrView::view3d() const
86{
87 return m_xrManager.m_vrViewport;
88}
89
90/*!
91 \qmlproperty bool QtQuick3D.Xr::XrView::passthroughEnabled
92 \summary Holds whether passthrough is enabled for the XR view.
93*/
94bool QQuick3DXrView::passthroughEnabled() const
95{
96 return m_xrManager.isPassthroughEnabled();
97}
98
99/*!
100 \qmlproperty QQuick3DXrRuntimeInfo QtQuick3D.Xr::XrView::runtimeInfo
101 \summary Provides information about the XR runtime for the XR view.
102*/
103
104QQuick3DXrRuntimeInfo *QQuick3DXrView::runtimeInfo() const
105{
106 return &m_xrRuntimeInfo;
107}
108
109void QQuick3DXrView::setEnvironment(QQuick3DSceneEnvironment *environment)
110{
111 QQuick3DViewport *view = m_xrManager.m_vrViewport;
112
113 // If the view is not created yet, we can't set the environment which means we need to
114 // set it again once the view is created...
115 if (!view) {
116 m_pendingSceneEnvironment = environment;
117 return;
118 }
119
120 auto oldEnvironment = view->environment();
121 if (oldEnvironment == environment)
122 return;
123
124 if (oldEnvironment)
125 disconnect(oldEnvironment);
126
127 view->setEnvironment(environment);
128
129 // The view will always have an environment, setting the environment to null will just mean the default environment
130 // is used. So querying the environment from the view is always valid (and we should do it here to make sure we're
131 // in sync with the view).
132 environment = view->environment();
133
134 handleClearColorChanged();
135 handleAAChanged();
136
137 connect(environment, &QQuick3DSceneEnvironment::backgroundModeChanged, this, &QQuick3DXrView::handleClearColorChanged);
138 connect(environment, &QQuick3DSceneEnvironment::clearColorChanged, this, &QQuick3DXrView::handleClearColorChanged);
139 connect(environment, &QQuick3DSceneEnvironment::antialiasingModeChanged, this, &QQuick3DXrView::handleAAChanged);
140 connect(environment, &QQuick3DSceneEnvironment::antialiasingQualityChanged, this, &QQuick3DXrView::handleAAChanged);
141
142 emit environmentChanged(environment);
143}
144
145/*!
146 \qmlproperty bool QtQuick3D.Xr::XrView::passthroughSupported
147 \summary Indicates whether passthrough is supported for the XR view.
148*/
149
150bool QQuick3DXrView::passthroughSupported() const
151{
152 if (!m_xrManager.isValid())
153 return false;
154
155 return m_xrManager.supportsPassthrough();
156}
157
158void QQuick3DXrView::setPassthroughEnabled(bool enable)
159{
160 if (!m_xrManager.isValid()) {
161 qWarning("Attempted to set passthrough mode without a valid XR manager");
162 return;
163 }
164
165 const bool orgPassthroughEnabled = m_xrManager.isPassthroughEnabled();
166 // bail if passthrough is not supported
167 if (!m_xrManager.setPassthroughEnabled(enable)) {
168 qWarning("Enabling Passthrough is not supported.");
169 return;
170 }
171
172 if (orgPassthroughEnabled != m_xrManager.isPassthroughEnabled())
173 emit passthroughEnabledChanged();
174}
175
176/*!
177 \qmlproperty enumeration QtQuick3D.Xr::XrView::fixedFoveation
178 \brief Controls the level of fixed foveated rendering for the XrView.
179 \default XrView.HighFoveation
180
181 Foveated rendering reduces GPU load by reducing image quality (resolution)
182 in areas where the difference is less perceptible to the eye. With fixed
183 foveated rendering, the areas with reduced visual fidelity are fixed and do
184 not change. On some platforms, there is no concept of fixed foveated
185 rendering or control over it. For example, VisionOS-based devices perform
186 dynamic, eye-tracked foveation; thus, the value of this property is
187 ignored in practice. Other devices, such as the Meta Quest 3, only
188 support fixed foveation, which makes this property relevant.
189
190 The value can be one of:
191 \value XrView.NoFoveation 0, no foveation.
192 \value XrView.LowFoveation 1, low foveation.
193 \value XrView.MediumFoveation 2, medium foveation.
194 \value XrView.HighFoveation 3, high foveation.
195
196 Where supported, the default is \c HighFoveation. Therefore, changing this
197 value in applications should be rarely needed in practice.
198*/
199
200QQuick3DXrView::FoveationLevel QQuick3DXrView::fixedFoveation() const
201{
202 return FoveationLevel(m_xrManager.getFixedFoveationLevel());
203}
204
205void QQuick3DXrView::setFixedFoveation(FoveationLevel level)
206{
207 const auto orgFoviationLevel = m_xrManager.getFixedFoveationLevel();
208 m_xrManager.setFixedFoveationLevel(QtQuick3DXr::FoveationLevel(level));
209 if (orgFoviationLevel != m_xrManager.getFixedFoveationLevel())
210 emit fixedFoveationChanged();
211}
212
213/*!
214 \qmlproperty bool QtQuick3D.Xr::XrView::isQuitOnSessionEndEnabled
215 \brief Holds whether the application should quit when the XR session ends.
216*/
217
218bool QQuick3DXrView::isQuitOnSessionEndEnabled() const
219{
220 return m_quitOnSessionEnd;
221}
222
223void QQuick3DXrView::setQuitOnSessionEnd(bool enable)
224{
225 if (m_quitOnSessionEnd == enable)
226 return;
227
228 m_quitOnSessionEnd = enable;
229 emit quitOnSessionEndChanged();
230}
231/*!
232 \qmlproperty RenderStats QtQuick3D.Xr::XrView::renderStats
233 \summary Holds rendering statistics for the XR view.
234*/
235
236QQuick3DRenderStats *QQuick3DXrView::renderStats() const
237{
238 return m_xrManager.m_vrViewport ? m_xrManager.m_vrViewport->renderStats() : nullptr;
239}
240
241void QQuick3DXrView::updateViewportGeometry()
242{
243 auto contentItem = m_xrManager.m_quickWindow->contentItem();
244 auto viewport = m_xrManager.m_vrViewport;
245 if (viewport->height() != contentItem->height())
246 viewport->setHeight(contentItem->height());
247 if (viewport->width() != contentItem->width())
248 viewport->setWidth(contentItem->width());
249 if (viewport->x() != contentItem->x())
250 viewport->setX(contentItem->x());
251 if (viewport->y() != contentItem->y())
252 viewport->setY(contentItem->y());
253}
254
255void QQuick3DXrView::handleSessionEnded()
256{
257 emit sessionEnded();
258 if (m_quitOnSessionEnd)
259 QCoreApplication::quit();
260}
261
262void QQuick3DXrView::handleClearColorChanged()
263{
264 auto env = environment();
265
266 if (env) {
267 if (env->backgroundMode() == QQuick3DSceneEnvironment::Color)
268 m_xrManager.m_quickWindow->setColor(env->clearColor());
269 else if (env->backgroundMode() == QQuick3DSceneEnvironment::Transparent)
270 m_xrManager.m_quickWindow->setColor(Qt::transparent);
271 }
272}
273
274void QQuick3DXrView::handleAAChanged()
275{
276 auto env = environment();
277 int samples = 1;
278 if (env && env->antialiasingMode() == QQuick3DSceneEnvironment::MSAA) {
279 switch (env->antialiasingQuality()) {
280 case QQuick3DSceneEnvironment::Medium:
281 samples = 2;
282 break;
283 case QQuick3DSceneEnvironment::High:
284 samples = 4;
285 break;
286 case QQuick3DSceneEnvironment::VeryHigh:
287 samples = 8;
288 break;
289 }
290 }
291 m_xrManager.setSamples(samples);
292}
293
294bool QQuick3DXrView::init()
295{
296 if (m_isInitialized) {
297 qWarning("Already initialized!");
298 return false;
299 }
300
301 connect(&m_xrManager, &QQuick3DXrManager::sessionEnded, this, &QQuick3DXrView::handleSessionEnded);
302 connect(&m_xrManager, &QQuick3DXrManager::frameReady, this, &QQuick3DXrView::frameReady);
303 connect(&m_xrManager, &QQuick3DXrManager::referenceSpaceChanged, this, &QQuick3DXrView::referenceSpaceChanged);
304 connect(&m_xrManager, &QQuick3DXrManager::multiViewRenderingEnabledChanged, this, &QQuick3DXrView::multiViewRenderingEnabledChanged);
305 connect(&m_xrManager, &QQuick3DXrManager::initialized, this, &QQuick3DXrView::init, Qt::UniqueConnection);
306
307 if (!m_xrManager.isReady() && !m_xrManager.initialize()) {
308 qCDebug(lcQuick3DXr, "Waiting for XR platform to be initialized");
309
310 return false;
311 }
312
313 if (!m_xrManager.initialize()) {
314 QString errorString = m_xrManager.errorString();
315 if (errorString.isEmpty())
316 errorString = tr("Failed to initialize XR platform");
317 qWarning("\n%s\n", qPrintable(errorString));
318 QMetaObject::invokeMethod(this, "initializeFailed", Qt::QueuedConnection, errorString);
319 return false;
320 }
321
322 // Create View3D
323 QSSG_CHECK_X(m_xrManager.m_vrViewport == nullptr, "View3D already created!");
324 auto viewport = new QQuick3DViewport(QQuick3DViewport::PrivateInstanceType::XrViewInstance);
325 viewport->setRenderMode(QQuick3DViewport::Underlay);
326 auto contentItem = m_xrManager.m_quickWindow->contentItem();
327 viewport->setParentItem(contentItem);
328 m_xrManager.m_vrViewport = viewport;
329 viewport->setImportScene(this);
330
331 contentItem->forceActiveFocus(Qt::MouseFocusReason);
332
333 connect(contentItem, &QQuickItem::heightChanged, this, &QQuick3DXrView::updateViewportGeometry);
334 connect(contentItem, &QQuickItem::widthChanged, this, &QQuick3DXrView::updateViewportGeometry);
335 connect(contentItem, &QQuickItem::xChanged, this, &QQuick3DXrView::updateViewportGeometry);
336 connect(contentItem, &QQuickItem::yChanged, this, &QQuick3DXrView::updateViewportGeometry);
337
338 QQuick3DSceneEnvironment *env = environment();
339 if (env) {
340 connect(env, &QQuick3DSceneEnvironment::backgroundModeChanged, this, &QQuick3DXrView::handleClearColorChanged);
341 connect(env, &QQuick3DSceneEnvironment::clearColorChanged, this, &QQuick3DXrView::handleClearColorChanged);
342 connect(env, &QQuick3DSceneEnvironment::antialiasingModeChanged, this, &QQuick3DXrView::handleAAChanged);
343 connect(env, &QQuick3DSceneEnvironment::antialiasingQualityChanged, this, &QQuick3DXrView::handleAAChanged);
344 }
345
346 // NOTE: If we've called async, we need to make sure the environment, etc. is set again
347 setEnvironment(m_pendingSceneEnvironment);
348 m_pendingSceneEnvironment = nullptr;
349
350 m_xrManager.update();
351
352 m_isInitialized = true;
353
354 return m_isInitialized;
355}
356
357/*!
358 \qmlmethod pickResult XrView::rayPick(vector3d origin, vector3d direction)
359
360 This method will \e shoot a ray into the scene starting at \a origin and in
361 \a direction and return information about the nearest intersection with an
362 object in the scene.
363
364 For example, pass the position and forward vector of
365 any object in a scene to see what object is in front of an item. This
366 makes it possible to do picking from any point in the scene.
367 */
368QQuick3DPickResult QQuick3DXrView::rayPick(const QVector3D &origin, const QVector3D &direction) const
369{
370 return m_xrManager.m_vrViewport->rayPick(origin, direction);
371}
372
373/*!
374 \qmlmethod List<pickResult> XrView::rayPickAll(vector3d origin, vector3d direction)
375
376 This method will \e shoot a ray into the scene starting at \a origin and in
377 \a direction and return a list of information about the nearest intersections with
378 objects in the scene.
379 The list is presorted by distance from the origin along the direction
380 vector with the nearest intersections appearing first and the furthest
381 appearing last.
382
383 This can, for instance, be called with the position and forward vector of
384 any object in a scene to see what objects are in front of an item. This
385 makes it possible to do picking from any point in the scene.
386 */
387QList<QQuick3DPickResult> QQuick3DXrView::rayPickAll(const QVector3D &origin, const QVector3D &direction) const
388{
389 return m_xrManager.m_vrViewport->rayPickAll(origin, direction);
390}
391
392/*!
393 \qmlmethod pickResult XrView::rayPick(vector3d origin, vector3d direction, Model model)
394
395 This method will "shoot" a ray into the scene starting at \a origin and in
396 \a direction and return information about the intersection between the ray and the specified \a model.
397
398 \since 6.11
399*/
400QQuick3DPickResult QQuick3DXrView::rayPick(const QVector3D &origin, const QVector3D &direction, QQuick3DModel *model) const
401{
402 return m_xrManager.m_vrViewport->rayPick(origin, direction, model);
403}
404
405/*!
406 \qmlmethod XrView::setTouchpoint(Item target, point position, int pointId, bool pressed)
407
408 Sends a synthetic touch event to \a target, moving the touch point with ID \a pointId to \a position,
409 with \a pressed determining if the point is pressed.
410 Also sends the appropriate touch release event if \a pointId was previously active on a different
411 item.
412*/
413
414void QQuick3DXrView::setTouchpoint(QQuickItem *target, const QPointF &position, int pointId, bool pressed)
415{
416 view3d()->setTouchpoint(target, position, pointId, pressed);
417}
418
419// TODO: Maybe do a proper QQuick3DXrViewPrivate instead
420struct QQuick3DXrView::XrTouchState
421{
422 QHash<int, QQuick3DXrItem::TouchState> points;
423};
424
425/*!
426 \qmlmethod vector3d XrView::processTouch(vector3d position, int pointId)
427
428 This method will search for an XrItem near \a position and send a virtual
429 touch event with touch point ID \a pointId if \a position maps to a point
430 on the surface.
431
432 The return value is the offset between \a position and the touched point on
433 the surface. This can be used to prevent a hand model from passing through
434 an XrItem.
435
436 \sa XrHandModel
437
438*/
439
440QVector3D QQuick3DXrView::processTouch(const QVector3D &pos, int pointId)
441{
442 QVector3D offset;
443 if (m_xrItems.isEmpty())
444 return offset;
445
446 if (!m_touchState)
447 m_touchState = new XrTouchState;
448 QQuick3DXrItem::TouchState &state = m_touchState->points[pointId];
449 state.pointId = pointId; // in case it's a new point that was default-constructed
450
451 auto *prevTarget = state.target;
452 bool grabbed = false;
453 if (prevTarget) {
454 grabbed = prevTarget->handleVirtualTouch(this, pos, &state, &offset);
455 }
456 for (auto *item : std::as_const(m_xrItems)) {
457 if (grabbed)
458 break;
459 if (item != prevTarget)
460 grabbed = item->handleVirtualTouch(this, pos, &state, &offset);
461 }
462
463 return offset;
464}
465
466/*!
467 \qmlmethod object XrView::touchpointState(int pointId)
468
469 This method returns the state of the touch point with ID \a pointId.
470 The state is represented by a map from property names to values:
471
472 \table
473 \header
474 \li Key
475 \li Type
476 \li Description
477 \row
478 \li \c grabbed
479 \li \c bool
480 \li Is the point grabbed by an item? If \c false, all other values are \c undefined.
481 \row
482 \li \c target
483 \li XrItem
484 \li The item that is grabbing the touch point.
485 \row
486 \li \c pressed
487 \li \c bool
488 \li Is the touch point pressed?
489 \row
490 \li \c cursorPos
491 \li \c point
492 \li The 2D position of the touch point within \c target
493 \row
494 \li \c touchDistance
495 \li \c real
496 \li The distance from the plane to the touch point. It will be \c 0 if \c pressed is \c true.
497 \endtable
498
499 */
500
501#define Q_TOUCHPOINT_STATE(prop) { QStringLiteral(#prop), QVariant::fromValue(it->prop) }
502QVariantMap QQuick3DXrView::touchpointState(int pointId) const
503{
504 auto constexpr end = QHash<int, QQuick3DXrItem::TouchState>::const_iterator();
505 auto it = m_touchState ? m_touchState->points.constFind(pointId) : end;
506
507 if (it == end)
508 return { { QStringLiteral("grabbed"), QVariant::fromValue(false) } };
509
510 return { Q_TOUCHPOINT_STATE(target),
511 Q_TOUCHPOINT_STATE(grabbed),
512 Q_TOUCHPOINT_STATE(pressed),
513 Q_TOUCHPOINT_STATE(cursorPos),
514 Q_TOUCHPOINT_STATE(touchDistance) };
515}
516#undef Q_TOUCHPOINT_STATE
517
518/*!
519 \qmlproperty enumeration QtQuick3D.Xr::XrView::referenceSpace
520 \brief Gets or sets the reference space for the XR view.
521
522 It can be one of:
523 \value XrView.ReferenceSpaceUnknown
524 \value XrView.ReferenceSpaceLocal Origin is at the default view position (typically defined by a "reset view" operation).
525 \value XrView.ReferenceSpaceStage Origin is at floor height in the center of the user's defined area.
526 \value XrView.ReferenceSpaceLocalFloor Origin is at floor height, below the default view position.
527
528 \c ReferenceSpaceLocal is mainly useful for seated applications where the content is not positioned
529 relative to the floor, for example floating menus. The content will move when the user resets the view.
530
531 \c ReferenceSpaceStage is mainly useful for room-scale applications where the user will move freely within the
532 playing area. The content will not move when the user resets the view.
533
534 \c ReferenceSpaceLocalFloor is mainly useful for stationary applications (seated or standing) where the content is
535 positioned relative to the floor. The content will move when the user resets the view.
536
537 \default XrView.ReferenceSpaceLocal
538*/
539
540QQuick3DXrView::ReferenceSpace QQuick3DXrView::referenceSpace() const
541{
542 return ReferenceSpace(m_xrManager.getReferenceSpace());
543}
544
545void QQuick3DXrView::setReferenceSpace(ReferenceSpace newReferenceSpace)
546{
547 m_xrManager.setReferenceSpace(QtQuick3DXr::ReferenceSpace(newReferenceSpace));
548}
549
550bool QQuick3DXrView::depthSubmissionEnabled() const
551{
552 if (!m_xrManager.isValid()) {
553 qWarning("Attempted to check depth submission mode without a valid XR manager");
554 return false;
555 }
556
557 return m_xrManager.isDepthSubmissionEnabled();
558}
559
560/*!
561 \qmlproperty bool QtQuick3D.Xr::XrView::multiViewRenderingSupported
562
563 \brief This read-only property reports the availability of \l{Multiview Rendering}.
564
565 \sa multiViewRenderingEnabled
566 */
567bool QQuick3DXrView::isMultiViewRenderingSupported() const
568{
569 if (!m_xrManager.isValid())
570 return false;
571
572 return m_xrManager.isMultiViewRenderingSupported();
573}
574
575/*!
576 \qmlproperty bool QtQuick3D.Xr::XrView::multiViewRenderingEnabled
577
578 \brief This is a read-only property that reports if \l{Multiview Rendering} is enabled for the XR view.
579
580 \default true
581
582 This property tells you if multiview rendering is actually in use at run time.
583 When not supported, the value will flip back to \c false.
584
585 Enabling multiview rendering is recommended. It can improve performance and reduce
586 CPU and GPU power usage. It defaults to disabled to ensure maximum
587 compatibility. Developers are encouraged to verify that their application
588 renders as expected with multiViewRenderingEnabled set to \c true and then
589 leave it set afterward.
590
591 \note Certain Qt Quick and Quick 3D features that involve shader code that is
592 provided by the application may need this code to be modified to be multiview
593 compatible. Examples of these are custom 2D and 3D materials and
594 postprocessing effects. The \l {Multiview Rendering} documentation provides
595 more information on this and how to disable multiview rendering.
596
597 \sa multiViewRenderingSupported {Multiview Rendering}
598*/
599bool QQuick3DXrView::multiViewRenderingEnabled() const
600{
601 if (!m_xrManager.isValid())
602 return false;
603
604 return m_xrManager.isMultiViewRenderingEnabled();
605}
606
607void QQuick3DXrView::registerXrItem(QQuick3DXrItem *newXrItem)
608{
609 m_xrItems.append(newXrItem);
610}
611
612void QQuick3DXrView::unregisterXrItem(QQuick3DXrItem *xrItem)
613{
614 m_xrItems.removeAll(xrItem);
615}
616
617/*!
618 \qmlproperty bool QtQuick3D.Xr::XrView::depthSubmissionEnabled
619 \brief Controls whether submitting the depth buffer to the XR compositor
620 is enabled.
621 \default false
622
623 By default, the depth buffer used by the 3D scene in the XrView is not exposed
624 to the XR compositor. However, in some platforms, depth submission is implicit
625 and cannot be disabled or controlled by the application. An example of this is
626 VisionOS. Changing this property has no effect on those platforms. Elsewhere,
627 with OpenXR in particular, support depends on the OpenXR implementation used
628 at run time.
629
630 It is always safe to set depthSubmissionEnabled to \c true. It will just have
631 no effect when not supported by the underlying stack. To be sure, you can
632 inspect the debug output to see if depth submission is in use.
633 Submitting the depth buffer may improve reprojections that the XR compositor
634 may perform. Reprojection could happen, for example, when the system cannot
635 maintain the target frame rate and thus has to resort to predicting frame
636 contents to improve and stabilize the user's perception of the
637 scene and reduce possible motion sickness. However, the application and
638 Qt have no control over data usage. It could also happen that
639 submitting depth data has no practical effects and is ignored by the
640 underlying XR runtime and compositor.
641
642 In practice, submitting the depth buffer implies rendering into a depth
643 texture provided by the XR runtime instead of the intermediate texture/render buffer
644 created and managed by Qt. Rendering into a depth texture has certain lower-level
645 consequences that can have a performance impact:
646
647 When using \l{QtQuick3D::SceneEnvironment::antialiasingMode}{multisample antialiasing}
648 (MSAA), enabling depth submission implies rendering into a multisample depth
649 texture and resolving the samples into the non-multisample depth texture provided by
650 the XR runtime. Without depth submission,
651 the resolve step would not be necessary. In addition, some 3D APIs
652 do not support resolving multisample depth-stencil data (see
653 the \l{QRhi::ResolveDepthStencil} flag for details). Without this support,
654 attempts to enable depth submission in combination with MSAA are gracefully ignored.
655
656 Even when MSAA is not used, enabling depth submission triggers writing out
657 depth data with 3D APIs that have control over this. The store operation for
658 depth/stencil data is typically indicated by Qt as unnecessary, which can
659 have positive performance impacts on tiled GPU architectures. This is not
660 done with depth submission because depth data must always be written out
661 from Qt's perspective.
662
663 \note We recommended that developers test their applications with depth
664 submission enabled, evaluate the advantages and disadvantages, and make a
665 conscious choice based on their testing if they wish to enable it or not.
666*/
667
668void QQuick3DXrView::setDepthSubmissionEnabled(bool enable)
669{
670 if (!m_xrManager.isValid()) {
671 qWarning("Attempted to set depth submission mode without a valid XR manager");
672 return;
673 }
674
675 const bool orgDepthSubmission = m_xrManager.isDepthSubmissionEnabled();
676
677 m_xrManager.setDepthSubmissionEnabled(enable);
678
679 if (orgDepthSubmission != m_xrManager.isDepthSubmissionEnabled())
680 emit depthSubmissionEnabledChanged();
681}
682
683void QQuick3DXrView::setXROrigin(QQuick3DXrOrigin *newXrOrigin)
684{
685 if (m_xrOrigin == newXrOrigin)
686 return;
687
688 QQuick3DObjectPrivate::attachWatcher(this, &QQuick3DXrView::setXROrigin, newXrOrigin, m_xrOrigin);
689
690 m_xrOrigin = newXrOrigin;
691
692 // Make sure the XrOrigin has a parent item, if it hasn't, we're it.
693 if (m_xrOrigin && !m_xrOrigin->parentItem())
694 m_xrOrigin->setParentItem(this);
695
696 m_xrManager.setXROrigin(m_xrOrigin);
697
698 emit xrOriginChanged();
699}
700
701QQuick3DViewport *QQuick3DXrViewPrivate::getView3d(QQuick3DXrView *view)
702{
703 QSSG_ASSERT(view != nullptr, return nullptr);
704 return view->view3d();
705}
706
707/*!
708 \qmlsignal XrView::initializeFailed(const QString &errorString)
709
710 Emitted when initialization fails, and there is a new \a errorString
711 describing the failure.
712 */
713
714/*!
715 \qmlsignal XrView::sessionEnded()
716
717 Emitted when the session ends.
718 */
719
720/*!
721 \qmlsignal XrView::frameReady()
722 \internal
723
724 Emitted when a new frame is ready.
725 */
726
727QT_END_NAMESPACE
#define Q_TOUCHPOINT_STATE(prop)
\qmlmethod object XrView::touchpointState(int pointId)