5#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
7#include <openxr/openxr_reflection.h>
10#include <QtCore/QCoreApplication>
11#include <QtCore/QDebug>
15#include <QtQuick/private/qquickwindow_p.h>
16#include <QtQuick/QQuickRenderControl>
17#include <QtQuick/QQuickRenderTarget>
18#include <QtQuick/QQuickItem>
20#include <QtQuick3D/private/qquick3dnode_p.h>
21#include <QtQuick3D/private/qquick3dviewport_p.h>
25#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
26#ifdef XR_USE_GRAPHICS_API_VULKAN
30#ifdef XR_USE_GRAPHICS_API_D3D11
34#ifdef XR_USE_GRAPHICS_API_D3D12
38#ifdef XR_USE_GRAPHICS_API_OPENGL
42#ifdef XR_USE_PLATFORM_ANDROID
43# include <QtCore/qnativeinterface.h>
44# include <QtCore/QJniEnvironment>
45# include <QtCore/QJniObject>
46# ifdef XR_USE_GRAPHICS_API_OPENGL_ES
60#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
62#define ENUM_CASE_STR(name, val) case name: return #name;
63#define MAKE_TO_STRING_FUNC(enumType) \
64 static inline const char* to_string(enumType e) { \
66 XR_LIST_ENUM_##enumType(ENUM_CASE_STR) \
67 default: return "Unknown " #enumType; \
71MAKE_TO_STRING_FUNC(XrReferenceSpaceType)
72MAKE_TO_STRING_FUNC(XrViewConfigurationType)
73MAKE_TO_STRING_FUNC(XrEnvironmentBlendMode)
74MAKE_TO_STRING_FUNC(XrSessionState)
75MAKE_TO_STRING_FUNC(XrResult)
88#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
91 m_graphics->releaseResources();
97 delete m_renderControl;
98 delete m_animationDriver;
99#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
106#if defined(Q_OS_VISIONOS)
107 return m_visionOSRenderManager->isReady();
113#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
115bool isExtensionSupported(
const char *extensionName,
const QVector<XrExtensionProperties> &instanceExtensionProperties, uint32_t *extensionVersion =
nullptr)
117 for (
const auto &extensionProperty : instanceExtensionProperties) {
118 if (!strcmp(extensionName, extensionProperty.extensionName)) {
119 if (extensionVersion)
120 *extensionVersion = extensionProperty.extensionVersion;
127bool isApiLayerSupported(
const char *layerName,
const QVector<XrApiLayerProperties> &apiLayerProperties)
129 for (
const auto &prop : apiLayerProperties) {
130 if (!strcmp(layerName, prop.layerName))
140#ifdef XR_EXT_debug_utils
141XRAPI_ATTR XrBool32 XRAPI_CALL defaultDebugCallbackFunc(XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
142 XrDebugUtilsMessageTypeFlagsEXT messageType,
143 const XrDebugUtilsMessengerCallbackDataEXT *callbackData,
149 qDebug(
"xrDebug [QOpenXRManager %p] %s", self, callbackData->message);
156void QOpenXRManager::setErrorString(XrResult
result,
const char *callName)
158 m_errorString =
tr(
"%1 for runtime %2 %3 failed with %4.")
163 if (
result == XR_ERROR_FORM_FACTOR_UNAVAILABLE)
164 m_errorString +=
tr(
"\nThe OpenXR runtime has no connection to the headset; check if connection is active and functional.");
170#if defined(Q_OS_VISIONOS)
171 m_errorString.
clear();
173 if (!m_visionOSRenderManager) {
178 if (!m_visionOSRenderManager->initialize()) {
179 if (m_visionOSRenderManager->isReady())
180 m_errorString =
QStringLiteral(
"Waiting for the renderer to start.");
182 m_errorString =
QStringLiteral(
"Failed to initialize CompositorServices (visionOS).");
190#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
197#if QT_CONFIG(graphicsframecapture)
200 qWarning(
"Quick 3D XR: Frame capture was requested, but Qt is built without QGraphicsFrameCapture");
204#ifdef XR_USE_PLATFORM_ANDROID
206 PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
207 xrGetInstanceProcAddr(
208 XR_NULL_HANDLE,
"xrInitializeLoaderKHR", (PFN_xrVoidFunction*)&xrInitializeLoaderKHR);
209 if (xrInitializeLoaderKHR != NULL) {
210 JavaVM *javaVM = QJniEnvironment::javaVM();
211 m_androidActivity = QNativeInterface::QAndroidApplication::context();
213 XrLoaderInitInfoAndroidKHR loaderInitializeInfoAndroid;
214 memset(&loaderInitializeInfoAndroid, 0,
sizeof(loaderInitializeInfoAndroid));
215 loaderInitializeInfoAndroid.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR;
216 loaderInitializeInfoAndroid.next = NULL;
217 loaderInitializeInfoAndroid.applicationVM = javaVM;
218 loaderInitializeInfoAndroid.applicationContext = m_androidActivity.object();
219 XrResult xrResult = xrInitializeLoaderKHR((XrLoaderInitInfoBaseHeaderKHR*)&loaderInitializeInfoAndroid);
220 if (xrResult != XR_SUCCESS) {
229 qDebug(
"Quick3D XR: multiview rendering requested = %s", m_multiviewRendering ?
"yes" :
"no");
232 auto graphicsAPI = QQuickWindow::graphicsApi();
234 m_graphics =
nullptr;
235#ifdef XR_USE_GRAPHICS_API_VULKAN
239#ifdef XR_USE_GRAPHICS_API_D3D11
243#ifdef XR_USE_GRAPHICS_API_D3D12
247#ifdef XR_USE_GRAPHICS_API_OPENGL
251#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
257 qDebug() <<
"The Qt Quick Scenegraph is not using a supported RHI mode:" << graphicsAPI;
262 checkXrExtensions(
nullptr);
268 XrResult
result = createXrInstance();
269 if (
result != XR_SUCCESS) {
270 setErrorString(
result,
"xrCreateInstance");
272 m_graphics =
nullptr;
279 setupDebugMessenger();
282 result = initializeSystem();
283 if (
result != XR_SUCCESS) {
284 setErrorString(
result,
"xrGetSystem");
286 m_graphics =
nullptr;
291 if (!setupGraphics()) {
292 m_errorString =
tr(
"Failed to set up 3D API integration");
294 m_graphics =
nullptr;
299 XrSessionCreateInfo xrSessionInfo{};
300 xrSessionInfo.type = XR_TYPE_SESSION_CREATE_INFO;
301 xrSessionInfo.next = m_graphics->handle();
302 xrSessionInfo.systemId = m_systemId;
305 if (
result != XR_SUCCESS) {
306 setErrorString(
result,
"xrCreateSession");
308 m_graphics =
nullptr;
313 if (m_colorspaceExtensionSupported)
314 setupMetaQuestColorSpaces();
315 if (m_displayRefreshRateExtensionSupported)
316 setupMetaQuestRefreshRates();
317 if (m_spaceExtensionSupported)
318 m_spaceExtension->initialize(m_instance,
m_session);
320 checkReferenceSpaces();
324 m_inputManager->init(m_instance,
m_session);
326 if (!setupAppSpace())
328 if (!setupViewSpace())
339#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
340 if (m_inputManager) {
341 m_inputManager->teardown();
342 m_inputManager =
nullptr;
345 if (m_spaceExtension) {
346 m_spaceExtension->teardown();
347 m_spaceExtension =
nullptr;
350 if (m_passthroughLayer)
351 destroyMetaQuestPassthroughLayer();
352 if (m_passthroughFeature)
353 destroyMetaQuestPassthrough();
357 if (m_appSpace != XR_NULL_HANDLE) {
358 xrDestroySpace(m_appSpace);
361 if (m_viewSpace != XR_NULL_HANDLE)
362 xrDestroySpace(m_viewSpace);
366#ifdef XR_EXT_debug_utils
367 if (m_debugMessenger) {
368 m_xrDestroyDebugUtilsMessengerEXT(m_debugMessenger);
369 m_debugMessenger = XR_NULL_HANDLE;
373 xrDestroyInstance(m_instance);
379#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
380 return m_graphics !=
nullptr;
386#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
387void QOpenXRManager::destroySwapchain()
389 for (
const Swapchain &swapchain : m_swapchains)
390 xrDestroySwapchain(swapchain.
handle);
392 m_swapchains.clear();
393 m_swapchainImages.clear();
395 for (
const Swapchain &swapchain : m_depthSwapchains)
396 xrDestroySwapchain(swapchain.
handle);
398 m_depthSwapchains.clear();
399 m_depthSwapchainImages.clear();
405 if (m_enablePassthrough ==
enabled)
410#if defined(Q_NO_TEMPORARY_DISABLE_XR_API) && !defined(Q_OS_VISIONOS)
411 if (m_passthroughSupported) {
412 if (m_enablePassthrough) {
413 if (m_passthroughFeature == XR_NULL_HANDLE)
414 createMetaQuestPassthrough();
416 startMetaQuestPassthrough();
418 if (m_passthroughLayer == XR_NULL_HANDLE)
419 createMetaQuestPassthroughLayer();
421 resumeMetaQuestPassthroughLayer();
424 if (m_passthroughLayer)
425 pauseMetaQuestPassthroughLayer();
427 if (m_passthroughFeature)
428 pauseMetaQuestPassthrough();
434void QOpenXRManager::update()
449#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
450void QOpenXRManager::checkXrExtensions(
const char *layerName,
int indent)
452 quint32 instanceExtensionCount;
453 checkXrResult(xrEnumerateInstanceExtensionProperties(layerName, 0, &instanceExtensionCount,
nullptr));
455 QVector<XrExtensionProperties> extensions(instanceExtensionCount);
456 for (XrExtensionProperties&
extension : extensions) {
457 extension.type = XR_TYPE_EXTENSION_PROPERTIES;
461 checkXrResult(xrEnumerateInstanceExtensionProperties(layerName,
463 &instanceExtensionCount,
467 qDebug(
"%sAvailable Extensions: (%d)", indentStr.data(), instanceExtensionCount);
468 for (
const XrExtensionProperties&
extension : extensions) {
469 qDebug(
"%s Name=%s Version=%d.%d.%d",
472 XR_VERSION_MAJOR(
extension.extensionVersion),
473 XR_VERSION_MINOR(
extension.extensionVersion),
474 XR_VERSION_PATCH(
extension.extensionVersion));
478void QOpenXRManager::checkXrLayers()
481 checkXrResult(xrEnumerateApiLayerProperties(0, &layerCount,
nullptr));
483 QVector<XrApiLayerProperties>
layers(layerCount);
485 layer.type = XR_TYPE_API_LAYER_PROPERTIES;
486 layer.next =
nullptr;
491 qDebug(
"Available Layers: (%d)", layerCount);
493 qDebug(
" Name=%s SpecVersion=%d.%d.%d LayerVersion=%d.%d.%d Description=%s",
495 XR_VERSION_MAJOR(
layer.specVersion),
496 XR_VERSION_MINOR(
layer.specVersion),
497 XR_VERSION_PATCH(
layer.specVersion),
498 XR_VERSION_MAJOR(
layer.layerVersion),
499 XR_VERSION_MINOR(
layer.layerVersion),
500 XR_VERSION_PATCH(
layer.layerVersion),
502 checkXrExtensions(
layer.layerName, 4);
506XrResult QOpenXRManager::createXrInstance()
509 XrApplicationInfo appInfo;
511 appInfo.applicationVersion = 7;
513 appInfo.engineVersion = 6;
514 appInfo.apiVersion = XR_CURRENT_API_VERSION;
517 uint32_t apiLayerCount = 0;
518 xrEnumerateApiLayerProperties(0, &apiLayerCount,
nullptr);
519 QVector<XrApiLayerProperties> apiLayerProperties(apiLayerCount);
520 for (uint32_t
i = 0;
i < apiLayerCount;
i++) {
521 apiLayerProperties[
i].type = XR_TYPE_API_LAYER_PROPERTIES;
522 apiLayerProperties[
i].next =
nullptr;
524 xrEnumerateApiLayerProperties(apiLayerCount, &apiLayerCount, apiLayerProperties.data());
527 QVector<const char*> enabledApiLayers;
533 if (wantsValidationLayer) {
534 if (isApiLayerSupported(
"XR_APILAYER_LUNARG_core_validation", apiLayerProperties))
535 enabledApiLayers.append(
"XR_APILAYER_LUNARG_core_validation");
537 qDebug(
"OpenXR validation layer requested, but not available");
540 qDebug() <<
"Requesting to enable XR API layers:" << enabledApiLayers;
542 m_enabledApiLayers.clear();
543 for (
const char *
layer : enabledApiLayers)
547 uint32_t extensionCount = 0;
548 xrEnumerateInstanceExtensionProperties(
nullptr, 0, &extensionCount,
nullptr);
549 QVector<XrExtensionProperties> extensionProperties(extensionCount);
550 for (uint32_t
i = 0;
i < extensionCount;
i++) {
553 extensionProperties[
i].type = XR_TYPE_EXTENSION_PROPERTIES;
554 extensionProperties[
i].next =
nullptr;
556 xrEnumerateInstanceExtensionProperties(
nullptr, extensionCount, &extensionCount, extensionProperties.data());
558 QVector<const char*> enabledExtensions;
559 if (m_graphics->isExtensionSupported(extensionProperties))
560 enabledExtensions.append(m_graphics->extensionName());
562 if (isExtensionSupported(
"XR_EXT_debug_utils", extensionProperties))
563 enabledExtensions.append(
"XR_EXT_debug_utils");
565 if (isExtensionSupported(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME, extensionProperties))
566 enabledExtensions.append(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME);
568 m_handtrackingExtensionSupported = isExtensionSupported(XR_EXT_HAND_TRACKING_EXTENSION_NAME, extensionProperties);
569 if (m_handtrackingExtensionSupported)
570 enabledExtensions.append(XR_EXT_HAND_TRACKING_EXTENSION_NAME);
572 m_compositionLayerDepthSupported = isExtensionSupported(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME, extensionProperties);
573 if (m_compositionLayerDepthSupported) {
576 enabledExtensions.append(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME);
578 if (m_submitLayerDepth)
579 qDebug(
"submitLayerDepth defaults to true due to env.var.");
581 m_submitLayerDepth =
false;
586 m_handtrackingAimExtensionSupported = isExtensionSupported(XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME, extensionProperties);
587 if (m_handtrackingAimExtensionSupported)
588 enabledExtensions.append(XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME);
590 if (isExtensionSupported(XR_MSFT_HAND_INTERACTION_EXTENSION_NAME, extensionProperties))
591 enabledExtensions.append(XR_MSFT_HAND_INTERACTION_EXTENSION_NAME);
593 if (isExtensionSupported(XR_FB_HAND_TRACKING_MESH_EXTENSION_NAME, extensionProperties))
594 enabledExtensions.append(XR_FB_HAND_TRACKING_MESH_EXTENSION_NAME);
598 uint32_t passthroughSpecVersion = 0;
599 m_passthroughSupported = isExtensionSupported(XR_FB_PASSTHROUGH_EXTENSION_NAME, extensionProperties, &passthroughSpecVersion);
600 if (m_passthroughSupported) {
601 qDebug(
"Passthrough extension is supported, spec version %u", passthroughSpecVersion);
602 enabledExtensions.append(XR_FB_PASSTHROUGH_EXTENSION_NAME);
604 qDebug(
"Passthrough extension is NOT supported");
607 if (isExtensionSupported(XR_FB_TRIANGLE_MESH_EXTENSION_NAME, extensionProperties))
608 enabledExtensions.append(XR_FB_TRIANGLE_MESH_EXTENSION_NAME);
610 m_displayRefreshRateExtensionSupported = isExtensionSupported(XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME, extensionProperties);
611 if (m_displayRefreshRateExtensionSupported)
612 enabledExtensions.append(XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME);
614 m_colorspaceExtensionSupported = isExtensionSupported(XR_FB_COLOR_SPACE_EXTENSION_NAME, extensionProperties);
615 if (m_colorspaceExtensionSupported)
616 enabledExtensions.append(XR_FB_COLOR_SPACE_EXTENSION_NAME);
618 if (isExtensionSupported(XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME, extensionProperties))
619 enabledExtensions.append(XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME);
621 m_foveationExtensionSupported = isExtensionSupported(XR_FB_FOVEATION_EXTENSION_NAME, extensionProperties);
622 if (m_foveationExtensionSupported)
623 enabledExtensions.append(XR_FB_FOVEATION_EXTENSION_NAME);
625 if (isExtensionSupported(XR_FB_FOVEATION_CONFIGURATION_EXTENSION_NAME, extensionProperties))
626 enabledExtensions.append(XR_FB_FOVEATION_CONFIGURATION_EXTENSION_NAME);
628 if (m_spaceExtension) {
629 const auto requiredExtensions = m_spaceExtension->requiredExtensions();
631 for (
const auto extension : requiredExtensions) {
638 enabledExtensions.append(requiredExtensions);
642 if (isExtensionSupported(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME, extensionProperties))
643 enabledExtensions.append(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME);
645 auto graphicsAPI = QQuickWindow::graphicsApi();
647 if (isExtensionSupported(XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME, extensionProperties))
648 enabledExtensions.append(XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME);
650 if (isExtensionSupported(XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME, extensionProperties))
651 enabledExtensions.append(XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME);
655 qDebug() <<
"Requesting to enable XR extensions:" << enabledExtensions;
657 m_enabledExtensions.clear();
658 for (
const char *
extension : enabledExtensions)
662 XrInstanceCreateInfo xrInstanceInfo{};
663 xrInstanceInfo.type = XR_TYPE_INSTANCE_CREATE_INFO;
664 xrInstanceInfo.next =
nullptr;
665 xrInstanceInfo.createFlags = 0;
666 xrInstanceInfo.applicationInfo = appInfo;
667 xrInstanceInfo.enabledApiLayerCount = enabledApiLayers.count();
668 xrInstanceInfo.enabledApiLayerNames = enabledApiLayers.constData();
669 xrInstanceInfo.enabledExtensionCount = enabledExtensions.count();
670 xrInstanceInfo.enabledExtensionNames = enabledExtensions.constData();
672 return xrCreateInstance(&xrInstanceInfo, &m_instance);
675void QOpenXRManager::checkXrInstance()
677 Q_ASSERT(m_instance != XR_NULL_HANDLE);
678 XrInstanceProperties instanceProperties{};
679 instanceProperties.type = XR_TYPE_INSTANCE_PROPERTIES;
680 checkXrResult(xrGetInstanceProperties(m_instance, &instanceProperties));
683 m_runtimeVersion =
QVersionNumber(XR_VERSION_MAJOR(instanceProperties.runtimeVersion),
684 XR_VERSION_MINOR(instanceProperties.runtimeVersion),
685 XR_VERSION_PATCH(instanceProperties.runtimeVersion));
687 qDebug(
"Instance RuntimeName=%s RuntimeVersion=%d.%d.%d",
694void QOpenXRManager::setupDebugMessenger()
697 qDebug(
"Quick 3D XR: No debug utils extension, message redirection not set up");
701#ifdef XR_EXT_debug_utils
702 PFN_xrCreateDebugUtilsMessengerEXT xrCreateDebugUtilsMessengerEXT =
nullptr;
704 "xrCreateDebugUtilsMessengerEXT",
705 reinterpret_cast<PFN_xrVoidFunction *
>(&xrCreateDebugUtilsMessengerEXT)));
706 if (!xrCreateDebugUtilsMessengerEXT)
710 "xrDestroyDebugUtilsMessengerEXT",
711 reinterpret_cast<PFN_xrVoidFunction *
>(&m_xrDestroyDebugUtilsMessengerEXT)));
713 XrDebugUtilsMessengerCreateInfoEXT messengerInfo = {};
714 messengerInfo.type = XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
715 messengerInfo.messageSeverities = XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
716 | XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
717 messengerInfo.messageTypes = XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
718 | XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
719 | XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
720 | XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT;
721 messengerInfo.userCallback = defaultDebugCallbackFunc;
722 messengerInfo.userData =
this;
724 XrResult err = xrCreateDebugUtilsMessengerEXT(m_instance, &messengerInfo, &m_debugMessenger);
726 qWarning(
"Quick 3D XR: Failed to create debug report callback, OpenXR messages will not get redirected (%d)", err);
730XrResult QOpenXRManager::initializeSystem()
732 Q_ASSERT(m_instance != XR_NULL_HANDLE);
733 Q_ASSERT(m_systemId == XR_NULL_SYSTEM_ID);
735 XrSystemGetInfo hmdInfo{};
736 hmdInfo.type = XR_TYPE_SYSTEM_GET_INFO;
737 hmdInfo.next =
nullptr;
738 hmdInfo.formFactor = m_formFactor;
740 const XrResult
result = xrGetSystem(m_instance, &hmdInfo, &m_systemId);
747 checkViewConfiguration();
752void QOpenXRManager::checkViewConfiguration()
758 &viewConfigTypeCount,
760 QVector<XrViewConfigurationType> viewConfigTypes(viewConfigTypeCount);
764 &viewConfigTypeCount,
765 viewConfigTypes.data()));
767 qDebug(
"Available View Configuration Types: (%d)", viewConfigTypeCount);
768 for (XrViewConfigurationType viewConfigType : viewConfigTypes) {
769 qDebug(
" View Configuration Type: %s %s",
to_string(viewConfigType), viewConfigType == m_viewConfigType ?
"(Selected)" :
"");
770 XrViewConfigurationProperties viewConfigProperties{};
771 viewConfigProperties.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES;
775 &viewConfigProperties));
777 qDebug(
" View configuration FovMutable=%s", viewConfigProperties.fovMutable == XR_TRUE ?
"True" :
"False");
787 QVector<XrViewConfigurationView> views(viewCount, {XR_TYPE_VIEW_CONFIGURATION_VIEW,
nullptr, 0, 0, 0, 0, 0, 0});
794 for (
int i = 0;
i < views.size(); ++
i) {
795 const XrViewConfigurationView&
view = views[
i];
796 qDebug(
" View [%d]: Recommended Width=%d Height=%d SampleCount=%d",
798 view.recommendedImageRectWidth,
799 view.recommendedImageRectHeight,
800 view.recommendedSwapchainSampleCount);
801 qDebug(
" View [%d]: Maximum Width=%d Height=%d SampleCount=%d",
803 view.maxImageRectWidth,
804 view.maxImageRectHeight,
805 view.maxSwapchainSampleCount);
808 qDebug(
"Empty view configuration type");
810 checkEnvironmentBlendMode(viewConfigType);
813bool QOpenXRManager::checkXrResult(
const XrResult &
result)
818void QOpenXRManager::checkEnvironmentBlendMode(XrViewConfigurationType
type)
828 qDebug(
"Available Environment Blend Mode count : (%d)",
count);
830 QVector<XrEnvironmentBlendMode> blendModes(
count);
838 bool blendModeFound =
false;
839 for (XrEnvironmentBlendMode
mode : blendModes) {
840 const bool blendModeMatch = (
mode == m_environmentBlendMode);
841 qDebug(
"Environment Blend Mode (%s) : %s",
to_string(
mode), blendModeMatch ?
"(Selected)" :
"");
842 blendModeFound |= blendModeMatch;
845 qWarning(
"No matching environment blend mode found");
849bool QOpenXRManager::setupGraphics()
851 preSetupQuickScene();
852#if !defined(Q_OS_VISIONOS)
853 if (!m_graphics->setupGraphics(m_instance, m_systemId, m_quickWindow->graphicsConfiguration()))
857 if (!setupQuickScene())
860 QRhi *rhi = m_quickWindow->rhi();
862#if QT_CONFIG(graphicsframecapture)
863 if (m_frameCapture) {
865 m_frameCapture->setCapturePrefix(
QLatin1String(
"quick3dxr"));
866 m_frameCapture->setRhi(rhi);
867 if (!m_frameCapture->isLoaded()) {
868 qWarning(
"Quick 3D XR: Frame capture was requested but QGraphicsFrameCapture is not initialized"
869 " (or has no backends enabled in the Qt build)");
871 qDebug(
"Quick 3D XR: Frame capture initialized");
875#if !defined(Q_OS_VISIONOS)
876 return m_graphics->finializeGraphics(rhi);
878 return m_visionOSRenderManager->finalizeGraphics(rhi);
882#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
883void QOpenXRManager::checkReferenceSpaces()
889 m_availableReferenceSpace.resize(spaceCount);
890 checkXrResult(xrEnumerateReferenceSpaces(
m_session, spaceCount, &spaceCount, m_availableReferenceSpace.data()));
892 qDebug(
"Available reference spaces: %d", spaceCount);
893 for (XrReferenceSpaceType space : m_availableReferenceSpace) {
898bool QOpenXRManager::isReferenceSpaceAvailable(XrReferenceSpaceType
type)
900 return m_availableReferenceSpace.contains(
type);
903bool QOpenXRManager::setupAppSpace()
907 XrPosef identityPose;
908 identityPose.orientation.w = 1;
909 identityPose.orientation.x = 0;
910 identityPose.orientation.y = 0;
911 identityPose.orientation.z = 0;
912 identityPose.position.x = 0;
913 identityPose.position.y = 0;
914 identityPose.position.z = 0;
916 XrReferenceSpaceType newReferenceSpace;
917 XrSpace newAppSpace = XR_NULL_HANDLE;
918 m_isEmulatingLocalFloor =
false;
920 if (isReferenceSpaceAvailable(m_requestedReferenceSpace)) {
921 newReferenceSpace = m_requestedReferenceSpace;
922 }
else if (m_requestedReferenceSpace == XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT &&
923 isReferenceSpaceAvailable(XR_REFERENCE_SPACE_TYPE_STAGE)) {
924 m_isEmulatingLocalFloor =
true;
925 m_isFloorResetPending =
true;
926 newReferenceSpace = XR_REFERENCE_SPACE_TYPE_LOCAL;
928 qWarning(
"Requested reference space is not available");
929 newReferenceSpace = XR_REFERENCE_SPACE_TYPE_LOCAL;
933 qDebug(
"Creating new reference space for app space: %s",
to_string(newReferenceSpace));
934 XrReferenceSpaceCreateInfo referenceSpaceCreateInfo{};
935 referenceSpaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
936 referenceSpaceCreateInfo.poseInReferenceSpace = identityPose;
937 referenceSpaceCreateInfo.referenceSpaceType = newReferenceSpace;
939 qWarning(
"Failed to create app space");
944 xrDestroySpace(m_appSpace);
946 m_appSpace = newAppSpace;
947 m_referenceSpace = newReferenceSpace;
950 if (!m_isFloorResetPending)
957void QOpenXRManager::updateAppSpace(XrTime predictedDisplayTime)
961 if (m_requestedReferenceSpace != m_referenceSpace && !m_isFloorResetPending) {
962 if (!setupAppSpace()) {
964 qWarning(
"Setting requested reference space failed");
965 m_requestedReferenceSpace = m_referenceSpace;
974 if (m_isFloorResetPending) {
975 if (!resetEmulatedFloorHeight(predictedDisplayTime)) {
977 m_requestedReferenceSpace = XR_REFERENCE_SPACE_TYPE_LOCAL;
985bool QOpenXRManager::setupViewSpace()
989 XrPosef identityPose;
990 identityPose.orientation.w = 1;
991 identityPose.orientation.x = 0;
992 identityPose.orientation.y = 0;
993 identityPose.orientation.z = 0;
994 identityPose.position.x = 0;
995 identityPose.position.y = 0;
996 identityPose.position.z = 0;
998 XrSpace newViewSpace = XR_NULL_HANDLE;
1000 XrReferenceSpaceCreateInfo referenceSpaceCreateInfo{};
1001 referenceSpaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
1002 referenceSpaceCreateInfo.poseInReferenceSpace = identityPose;
1003 referenceSpaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
1005 qWarning(
"Failed to create view space");
1009 if (m_viewSpace != XR_NULL_HANDLE)
1010 xrDestroySpace(m_viewSpace);
1012 m_viewSpace = newViewSpace;
1017bool QOpenXRManager::resetEmulatedFloorHeight(XrTime predictedDisplayTime)
1021 m_isFloorResetPending =
false;
1023 XrPosef identityPose;
1024 identityPose.orientation.w = 1;
1025 identityPose.orientation.x = 0;
1026 identityPose.orientation.y = 0;
1027 identityPose.orientation.z = 0;
1028 identityPose.position.x = 0;
1029 identityPose.position.y = 0;
1030 identityPose.position.z = 0;
1032 XrSpace localSpace = XR_NULL_HANDLE;
1033 XrSpace stageSpace = XR_NULL_HANDLE;
1035 XrReferenceSpaceCreateInfo createInfo{};
1036 createInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
1037 createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
1038 createInfo.poseInReferenceSpace = identityPose;
1041 qWarning(
"Failed to create local space (for emulated LOCAL_FLOOR space)");
1045 createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
1047 qWarning(
"Failed to create stage space (for emulated LOCAL_FLOOR space)");
1048 xrDestroySpace(localSpace);
1052 XrSpaceLocation stageLocation{};
1053 stageLocation.type = XR_TYPE_SPACE_LOCATION;
1054 stageLocation.pose = identityPose;
1056 if (!
checkXrResult(xrLocateSpace(stageSpace, localSpace, predictedDisplayTime, &stageLocation))) {
1057 qWarning(
"Failed to locate STAGE space in LOCAL space, in order to emulate LOCAL_FLOOR");
1058 xrDestroySpace(localSpace);
1059 xrDestroySpace(stageSpace);
1063 xrDestroySpace(localSpace);
1064 xrDestroySpace(stageSpace);
1066 XrSpace newAppSpace = XR_NULL_HANDLE;
1067 createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
1068 createInfo.poseInReferenceSpace.position.y = stageLocation.pose.position.y;
1070 qWarning(
"Failed to recreate emulated LOCAL_FLOOR play space with latest floor estimate");
1074 xrDestroySpace(m_appSpace);
1075 m_appSpace = newAppSpace;
1076 m_referenceSpace = XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT;
1082void QOpenXRManager::createSwapchains()
1088 XrSystemProperties systemProperties{};
1089 systemProperties.type = XR_TYPE_SYSTEM_PROPERTIES;
1091 XrSystemHandTrackingPropertiesEXT handTrackingSystemProperties{};
1092 handTrackingSystemProperties.type = XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT;
1093 systemProperties.next = &handTrackingSystemProperties;
1095 checkXrResult(xrGetSystemProperties(m_instance, m_systemId, &systemProperties));
1096 qDebug(
"System Properties: Name=%s VendorId=%d", systemProperties.systemName, systemProperties.vendorId);
1097 qDebug(
"System Graphics Properties: MaxWidth=%d MaxHeight=%d MaxLayers=%d",
1098 systemProperties.graphicsProperties.maxSwapchainImageWidth,
1099 systemProperties.graphicsProperties.maxSwapchainImageHeight,
1100 systemProperties.graphicsProperties.maxLayerCount);
1101 qDebug(
"System Tracking Properties: OrientationTracking=%s PositionTracking=%s",
1102 systemProperties.trackingProperties.orientationTracking == XR_TRUE ?
"True" :
"False",
1103 systemProperties.trackingProperties.positionTracking == XR_TRUE ?
"True" :
"False");
1104 qDebug(
"System Hand Tracking Properties: handTracking=%s",
1105 handTrackingSystemProperties.supportsHandTracking == XR_TRUE ?
"True" :
"False");
1115 m_configViews.resize(viewCount, {XR_TYPE_VIEW_CONFIGURATION_VIEW,
nullptr, 0, 0, 0, 0, 0, 0});
1121 m_configViews.data()));
1122 m_views.resize(viewCount, {XR_TYPE_VIEW,
nullptr, {}, {}});
1123 m_projectionLayerViews.resize(viewCount, {});
1124 m_layerDepthInfos.resize(viewCount, {});
1127 if (viewCount > 0) {
1129 uint32_t swapchainFormatCount;
1131 QVector<int64_t> swapchainFormats(swapchainFormatCount);
1133 swapchainFormats.size(),
1134 &swapchainFormatCount,
1135 swapchainFormats.data()));
1136 Q_ASSERT(swapchainFormatCount == swapchainFormats.size());
1137 m_colorSwapchainFormat = m_graphics->colorSwapchainFormat(swapchainFormats);
1138 if (m_compositionLayerDepthSupported)
1139 m_depthSwapchainFormat = m_graphics->depthSwapchainFormat(swapchainFormats);
1143 QString swapchainFormatsString;
1144 for (int64_t
format : swapchainFormats) {
1145 const bool selectedColor =
format == m_colorSwapchainFormat;
1146 const bool selectedDepth =
format == m_depthSwapchainFormat;
1147 swapchainFormatsString += u
" ";
1149 swapchainFormatsString += u
"[";
1150 else if (selectedDepth)
1151 swapchainFormatsString += u
"<";
1154 swapchainFormatsString += u
"]";
1155 else if (selectedDepth)
1156 swapchainFormatsString += u
">";
1161 const XrViewConfigurationView &vp = m_configViews[0];
1172 if (m_multiviewRendering) {
1174 XrSwapchainCreateInfo swapchainCreateInfo{};
1175 swapchainCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO;
1176 swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT;
1177 swapchainCreateInfo.format = m_colorSwapchainFormat;
1178 swapchainCreateInfo.sampleCount = 1;
1179 swapchainCreateInfo.width = vp.recommendedImageRectWidth;
1180 swapchainCreateInfo.height = vp.recommendedImageRectHeight;
1181 swapchainCreateInfo.faceCount = 1;
1182 swapchainCreateInfo.arraySize = viewCount;
1183 swapchainCreateInfo.mipCount = 1;
1185 qDebug(
"Creating multiview swapchain for %u view(s) with dimensions Width=%d Height=%d SampleCount=%d Format=%llx",
1187 vp.recommendedImageRectWidth,
1188 vp.recommendedImageRectHeight,
1190 static_cast<long long unsigned int>(m_colorSwapchainFormat));
1192 Swapchain swapchain;
1193 swapchain.width = swapchainCreateInfo.width;
1194 swapchain.height = swapchainCreateInfo.height;
1195 swapchain.arraySize = swapchainCreateInfo.arraySize;
1197 m_swapchains.append(swapchain);
1199 uint32_t imageCount = 0;
1200 checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, 0, &imageCount,
nullptr));
1202 auto swapchainImages = m_graphics->allocateSwapchainImages(imageCount, swapchain.handle);
1203 checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, imageCount, &imageCount, swapchainImages[0]));
1205 m_swapchainImages.insert(swapchain.handle, swapchainImages);
1207 qWarning(
"xrCreateSwapchain failed (multiview)");
1214 if (m_compositionLayerDepthSupported && m_depthSwapchainFormat > 0) {
1215 swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1216 swapchainCreateInfo.format = m_depthSwapchainFormat;
1218 m_depthSwapchains.append(swapchain);
1220 uint32_t imageCount = 0;
1221 checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, 0, &imageCount,
nullptr));
1223 auto swapchainImages = m_graphics->allocateSwapchainImages(imageCount, swapchain.handle);
1224 checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, imageCount, &imageCount, swapchainImages[0]));
1226 m_depthSwapchainImages.insert(swapchain.handle, swapchainImages);
1228 qWarning(
"xrCreateSwapchain failed for depth swapchain (multiview)");
1233 for (uint32_t
i = 0;
i < viewCount;
i++) {
1234 qDebug(
"Creating swapchain for view %u with dimensions Width=%d Height=%d SampleCount=%d Format=%llx",
1236 vp.recommendedImageRectWidth,
1237 vp.recommendedImageRectHeight,
1239 static_cast<long long unsigned int>(m_colorSwapchainFormat));
1242 XrSwapchainCreateInfo swapchainCreateInfo{};
1243 swapchainCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO;
1244 swapchainCreateInfo.arraySize = 1;
1245 swapchainCreateInfo.format = m_colorSwapchainFormat;
1246 swapchainCreateInfo.width = vp.recommendedImageRectWidth;
1247 swapchainCreateInfo.height = vp.recommendedImageRectHeight;
1248 swapchainCreateInfo.mipCount = 1;
1249 swapchainCreateInfo.faceCount = 1;
1250 swapchainCreateInfo.sampleCount = 1;
1251 swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;
1252 Swapchain swapchain;
1253 swapchain.width = swapchainCreateInfo.width;
1254 swapchain.height = swapchainCreateInfo.height;
1256 m_swapchains.append(swapchain);
1258 uint32_t imageCount = 0;
1259 checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, 0, &imageCount,
nullptr));
1261 auto swapchainImages = m_graphics->allocateSwapchainImages(imageCount, swapchain.handle);
1262 checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, imageCount, &imageCount, swapchainImages[0]));
1264 m_swapchainImages.insert(swapchain.handle, swapchainImages);
1266 qWarning(
"xrCreateSwapchain failed (view %u)", viewCount);
1269 if (m_compositionLayerDepthSupported && m_depthSwapchainFormat > 0) {
1270 swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1271 swapchainCreateInfo.format = m_depthSwapchainFormat;
1273 m_depthSwapchains.append(swapchain);
1275 uint32_t imageCount = 0;
1276 checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, 0, &imageCount,
nullptr));
1278 auto swapchainImages = m_graphics->allocateSwapchainImages(imageCount, swapchain.handle);
1279 checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, imageCount, &imageCount, swapchainImages[0]));
1281 m_depthSwapchainImages.insert(swapchain.handle, swapchainImages);
1283 qWarning(
"xrCreateSwapchain failed for depth swapchain (view %u)", viewCount);
1289 if (m_multiviewRendering) {
1290 if (m_swapchains.isEmpty())
1292 if (m_compositionLayerDepthSupported && m_depthSwapchains.isEmpty())
1295 if (m_swapchains.count() !=
qsizetype(viewCount))
1297 if (m_compositionLayerDepthSupported && m_depthSwapchains.count() !=
qsizetype(viewCount))
1302 for (uint32_t
i = 0;
i < viewCount; ++
i) {
1303 m_projectionLayerViews[
i].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
1304 m_projectionLayerViews[
i].next =
nullptr;
1305 m_projectionLayerViews[
i].subImage.swapchain = m_swapchains[0].handle;
1306 m_projectionLayerViews[
i].subImage.imageArrayIndex =
i;
1307 m_projectionLayerViews[
i].subImage.imageRect.offset.x = 0;
1308 m_projectionLayerViews[
i].subImage.imageRect.offset.y = 0;
1309 m_projectionLayerViews[
i].subImage.imageRect.extent.width = vp.recommendedImageRectWidth;
1310 m_projectionLayerViews[
i].subImage.imageRect.extent.height = vp.recommendedImageRectHeight;
1312 m_layerDepthInfos[
i].type = XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR;
1313 m_layerDepthInfos[
i].next =
nullptr;
1314 m_layerDepthInfos[
i].subImage.swapchain = m_depthSwapchains[0].handle;
1315 m_layerDepthInfos[
i].subImage.imageArrayIndex =
i;
1316 m_layerDepthInfos[
i].subImage.imageRect.offset.x = 0;
1317 m_layerDepthInfos[
i].subImage.imageRect.offset.y = 0;
1318 m_layerDepthInfos[
i].subImage.imageRect.extent.width = vp.recommendedImageRectWidth;
1319 m_layerDepthInfos[
i].subImage.imageRect.extent.height = vp.recommendedImageRectHeight;
1323 if (m_foveationExtensionSupported)
1324 setupMetaQuestFoveation();
1339void QOpenXRManager::processXrEvents()
1341#if !defined(Q_OS_VISIONOS)
1342 bool exitRenderLoop =
false;
1343 bool requestrestart =
false;
1344 pollEvents(&exitRenderLoop, &requestrestart);
1349 if (m_sessionRunning) {
1350 m_inputManager->pollActions();
1354 enum RenderState :
quint8 {
1359 static bool logOnce[3] = {
false,
false,
false};
1360 auto renderState = m_visionOSRenderManager->getRenderState();
1363 if (!logOnce[RenderState::Paused]) {
1364 qDebug() <<
"-- Wait --";
1365 logOnce[RenderState::Paused] =
true;
1366 logOnce[RenderState::Running] =
false;
1367 logOnce[RenderState::Invalidated] =
false;
1373 if (!logOnce[RenderState::Running]) {
1374 qDebug() <<
"-- Running --";
1375 logOnce[RenderState::Paused] =
false;
1376 logOnce[RenderState::Running] =
true;
1377 logOnce[RenderState::Invalidated] =
false;
1380 if (!logOnce[RenderState::Invalidated]) {
1381 qDebug() <<
"-- Invalidated --";
1382 logOnce[RenderState::Paused] =
false;
1383 logOnce[RenderState::Running] =
false;
1384 logOnce[RenderState::Invalidated] =
true;
1392#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
1393void QOpenXRManager::pollEvents(
bool *exitRenderLoop,
bool *requestRestart) {
1394 *exitRenderLoop =
false;
1395 *requestRestart =
false;
1397 auto readNextEvent = [
this]() {
1400 XrEventDataBaseHeader* baseHeader =
reinterpret_cast<XrEventDataBaseHeader*
>(&m_eventDataBuffer);
1401 *baseHeader = {XR_TYPE_EVENT_DATA_BUFFER,
nullptr};
1402 const XrResult xr = xrPollEvent(m_instance, &m_eventDataBuffer);
1403 if (xr == XR_SUCCESS) {
1404 if (baseHeader->type == XR_TYPE_EVENT_DATA_EVENTS_LOST) {
1405 const XrEventDataEventsLost*
const eventsLost =
reinterpret_cast<const XrEventDataEventsLost*
>(baseHeader);
1406 qDebug(
"%d events lost", eventsLost->lostEventCount);
1412 return static_cast<XrEventDataBaseHeader*
>(
nullptr);
1415 auto handleSessionStateChangedEvent = [
this](
const XrEventDataSessionStateChanged& stateChangedEvent,
1416 bool* exitRenderLoop,
1417 bool* requestRestart) {
1418 const XrSessionState oldState = m_sessionState;
1419 m_sessionState = stateChangedEvent.state;
1421 qDebug(
"XrEventDataSessionStateChanged: state %s->%s time=%lld",
1424 static_cast<long long int>(stateChangedEvent.time));
1426 if ((stateChangedEvent.session != XR_NULL_HANDLE) && (stateChangedEvent.session !=
m_session)) {
1427 qDebug(
"XrEventDataSessionStateChanged for unknown session");
1431 switch (m_sessionState) {
1432 case XR_SESSION_STATE_READY: {
1434 XrSessionBeginInfo sessionBeginInfo{};
1435 sessionBeginInfo.type = XR_TYPE_SESSION_BEGIN_INFO;
1436 sessionBeginInfo.primaryViewConfigurationType = m_viewConfigType;
1438 m_sessionRunning =
true;
1441 case XR_SESSION_STATE_STOPPING: {
1443 m_sessionRunning =
false;
1447 case XR_SESSION_STATE_EXITING: {
1448 *exitRenderLoop =
true;
1450 *requestRestart =
false;
1453 case XR_SESSION_STATE_LOSS_PENDING: {
1454 *exitRenderLoop =
true;
1456 *requestRestart =
true;
1465 while (
const XrEventDataBaseHeader*
event = readNextEvent()) {
1466 switch (
event->type) {
1467 case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: {
1468 const auto& instanceLossPending = *
reinterpret_cast<const XrEventDataInstanceLossPending*
>(
event);
1469 qDebug(
"XrEventDataInstanceLossPending by %lld",
static_cast<long long int>(instanceLossPending.lossTime));
1470 *exitRenderLoop =
true;
1471 *requestRestart =
true;
1474 case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
1475 auto sessionStateChangedEvent = *
reinterpret_cast<const XrEventDataSessionStateChanged*
>(
event);
1476 handleSessionStateChangedEvent(sessionStateChangedEvent, exitRenderLoop, requestRestart);
1479 case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
1481 case XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB:
1482 case XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB:
1483 case XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB:
1484 case XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB:
1486 if (m_spaceExtension)
1487 m_spaceExtension->handleEvent(
event);
1489 case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
1499void QOpenXRManager::renderFrame()
1501#if !defined(Q_OS_VISIONOS)
1504 XrFrameWaitInfo frameWaitInfo{};
1505 frameWaitInfo.type = XR_TYPE_FRAME_WAIT_INFO;
1506 XrFrameState frameState{};
1507 frameState.type = XR_TYPE_FRAME_STATE;
1510 XrFrameBeginInfo frameBeginInfo{};
1511 frameBeginInfo.type = XR_TYPE_FRAME_BEGIN_INFO;
1514 QVector<XrCompositionLayerBaseHeader*>
layers;
1516 XrCompositionLayerPassthroughFB passthroughCompLayer{};
1517 passthroughCompLayer.type = XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB;
1518 if (m_enablePassthrough && m_passthroughSupported) {
1519 if (m_passthroughLayer == XR_NULL_HANDLE)
1520 createMetaQuestPassthroughLayer();
1521 passthroughCompLayer.layerHandle = m_passthroughLayer;
1522 passthroughCompLayer.flags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
1523 passthroughCompLayer.space = XR_NULL_HANDLE;
1524 layers.push_back(
reinterpret_cast<XrCompositionLayerBaseHeader*
>(&passthroughCompLayer));
1527 XrCompositionLayerProjection
layer{};
1528 layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
1529 layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
1530 layer.layerFlags |= XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
1531 layer.layerFlags |= XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
1533 if (frameState.shouldRender == XR_TRUE) {
1534 if (renderLayer(frameState.predictedDisplayTime, frameState.predictedDisplayPeriod,
layer)) {
1535 layers.push_back(
reinterpret_cast<XrCompositionLayerBaseHeader*
>(&
layer));
1539 XrFrameEndInfo frameEndInfo{};
1540 frameEndInfo.type = XR_TYPE_FRAME_END_INFO;
1541 frameEndInfo.displayTime = frameState.predictedDisplayTime;
1542 if (!m_enablePassthrough)
1543 frameEndInfo.environmentBlendMode = m_environmentBlendMode;
1545 frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
1546 frameEndInfo.layerCount = (uint32_t)
layers.size();
1547 frameEndInfo.layers =
layers.data();
1551 m_visionOSRenderManager->renderFrame(m_quickWindow, m_renderControl, m_xrOrigin, m_vrViewport);
1556#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
1557bool QOpenXRManager::renderLayer(XrTime predictedDisplayTime,
1558 XrDuration predictedDisplayPeriod,
1559 XrCompositionLayerProjection &
layer)
1563 XrViewState viewState{};
1564 viewState.type = XR_TYPE_VIEW_STATE;
1565 quint32 viewCapacityInput = m_views.size();
1569 updateAppSpace(predictedDisplayTime);
1571 XrViewLocateInfo viewLocateInfo{};
1572 viewLocateInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
1573 viewLocateInfo.viewConfigurationType = m_viewConfigType;
1574 viewLocateInfo.displayTime = predictedDisplayTime;
1575 viewLocateInfo.space = m_appSpace;
1577 res = xrLocateViews(
m_session, &viewLocateInfo, &viewState, viewCapacityInput, &viewCountOutput, m_views.data());
1579 if (XR_UNQUALIFIED_SUCCESS(
res)) {
1580 Q_ASSERT(viewCountOutput == viewCapacityInput);
1581 Q_ASSERT(viewCountOutput == m_configViews.size());
1582 Q_ASSERT(viewCountOutput == m_projectionLayerViews.size());
1583 Q_ASSERT(m_multiviewRendering ? viewCountOutput == m_swapchains[0].arraySize : viewCountOutput == m_swapchains.
size());
1590 location.type = XR_TYPE_SPACE_LOCATION;
1594 location.pose.position.z) * 100.0f);
1602 m_inputManager->updatePoses(predictedDisplayTime, m_appSpace);
1605 if (m_spaceExtension)
1606 m_spaceExtension->updateAnchors(predictedDisplayTime, m_appSpace);
1608 if (m_handtrackingExtensionSupported)
1609 m_inputManager->updateHandtracking(predictedDisplayTime, m_appSpace, m_handtrackingAimExtensionSupported);
1614 const qint64 displayPeriodMS = predictedDisplayPeriod / 1000000;
1615 const qint64 displayDeltaMS = (predictedDisplayTime - m_previousTime) / 1000000;
1617 if (m_previousTime == 0)
1618 m_animationDriver->
setStep(displayPeriodMS);
1620 if (displayDeltaMS > displayPeriodMS)
1621 m_animationDriver->
setStep(displayPeriodMS);
1623 m_animationDriver->
setStep(displayDeltaMS);
1626 m_previousTime = predictedDisplayTime;
1628#if QT_CONFIG(graphicsframecapture)
1630 m_frameCapture->startCaptureFrame();
1633 if (m_submitLayerDepth && m_samples > 1) {
1635 static bool warned =
false;
1638 qWarning(
"Quick3D XR: Submitting depth buffer with MSAA cannot be enabled"
1639 " when depth-stencil resolve is not supported by the underlying 3D API (%s)",
1642 m_submitLayerDepth =
false;
1646 if (m_multiviewRendering) {
1647 const Swapchain swapchain = m_swapchains[0];
1650 XrSwapchainImageAcquireInfo acquireInfo{};
1651 acquireInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO;
1652 uint32_t swapchainImageIndex;
1653 checkXrResult(xrAcquireSwapchainImage(swapchain.handle, &acquireInfo, &swapchainImageIndex));
1654 XrSwapchainImageWaitInfo waitInfo{};
1655 waitInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO;
1656 waitInfo.timeout = XR_INFINITE_DURATION;
1657 checkXrResult(xrWaitSwapchainImage(swapchain.handle, &waitInfo));
1658 XrSwapchainImageBaseHeader *swapchainImage = m_swapchainImages[swapchain.handle][swapchainImageIndex];
1660 XrSwapchainImageBaseHeader *depthSwapchainImage =
nullptr;
1661 if (m_submitLayerDepth) {
1662 checkXrResult(xrAcquireSwapchainImage(m_depthSwapchains[0].
handle, &acquireInfo, &swapchainImageIndex));
1664 depthSwapchainImage = m_depthSwapchainImages[m_depthSwapchains[0].handle][swapchainImageIndex];
1670 for (uint32_t
i = 0;
i < viewCountOutput;
i++) {
1672 m_projectionLayerViews[
i].pose = m_views[
i].pose;
1673 m_projectionLayerViews[
i].fov = m_views[
i].fov;
1675 updateCameraMultiview(0, viewCountOutput);
1681 doRender(m_projectionLayerViews[0].subImage,
1683 depthSwapchainImage);
1685 for (uint32_t
i = 0;
i < viewCountOutput;
i++) {
1686 if (m_submitLayerDepth) {
1687 m_layerDepthInfos[
i].minDepth = 0;
1688 m_layerDepthInfos[
i].maxDepth = 1;
1690 m_layerDepthInfos[
i].nearZ = cam ? cam->
clipNear() : 1.0f;
1691 m_layerDepthInfos[
i].farZ = cam ? cam->clipFar() : 10000.0f;
1692 m_projectionLayerViews[
i].next = &m_layerDepthInfos[
i];
1694 m_projectionLayerViews[
i].next =
nullptr;
1699 XrSwapchainImageReleaseInfo releaseInfo{};
1700 releaseInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO;
1701 checkXrResult(xrReleaseSwapchainImage(swapchain.handle, &releaseInfo));
1702 if (depthSwapchainImage)
1705 for (uint32_t
i = 0;
i < viewCountOutput;
i++) {
1707 const Swapchain viewSwapchain = m_swapchains[
i];
1710 XrSwapchainImageAcquireInfo acquireInfo{};
1711 acquireInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO;
1712 uint32_t swapchainImageIndex;
1713 checkXrResult(xrAcquireSwapchainImage(viewSwapchain.handle, &acquireInfo, &swapchainImageIndex));
1714 XrSwapchainImageWaitInfo waitInfo{};
1715 waitInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO;
1716 waitInfo.timeout = XR_INFINITE_DURATION;
1717 checkXrResult(xrWaitSwapchainImage(viewSwapchain.handle, &waitInfo));
1718 XrSwapchainImageBaseHeader *swapchainImage = m_swapchainImages[viewSwapchain.handle][swapchainImageIndex];
1720 XrSwapchainImageBaseHeader *depthSwapchainImage =
nullptr;
1721 if (m_submitLayerDepth) {
1722 checkXrResult(xrAcquireSwapchainImage(m_depthSwapchains[
i].
handle, &acquireInfo, &swapchainImageIndex));
1724 depthSwapchainImage = m_depthSwapchainImages[m_depthSwapchains[
i].handle][swapchainImageIndex];
1727 m_projectionLayerViews[
i].subImage.swapchain = viewSwapchain.handle;
1728 m_projectionLayerViews[
i].subImage.imageArrayIndex = 0;
1729 m_projectionLayerViews[
i].pose = m_views[
i].pose;
1730 m_projectionLayerViews[
i].fov = m_views[
i].fov;
1732 updateCameraNonMultiview(
i, m_projectionLayerViews[
i]);
1734 doRender(m_projectionLayerViews[
i].subImage,
1736 depthSwapchainImage);
1738 if (depthSwapchainImage) {
1739 m_layerDepthInfos[
i].subImage.swapchain = m_depthSwapchains[
i].handle;
1740 m_layerDepthInfos[
i].subImage.imageArrayIndex = 0;
1741 m_layerDepthInfos[
i].minDepth = 0;
1742 m_layerDepthInfos[
i].maxDepth = 1;
1744 m_layerDepthInfos[
i].nearZ = cam ? cam->
clipNear() : 1.0f;
1745 m_layerDepthInfos[
i].farZ = cam ? cam->clipFar() : 10000.0f;
1746 m_projectionLayerViews[
i].next = &m_layerDepthInfos[
i];
1748 m_projectionLayerViews[
i].next =
nullptr;
1751 XrSwapchainImageReleaseInfo releaseInfo{};
1752 releaseInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO;
1753 checkXrResult(xrReleaseSwapchainImage(viewSwapchain.handle, &releaseInfo));
1754 if (depthSwapchainImage)
1759#if QT_CONFIG(graphicsframecapture)
1761 m_frameCapture->endCaptureFrame();
1764 layer.space = m_appSpace;
1765 layer.viewCount = (uint32_t)m_projectionLayerViews.size();
1766 layer.views = m_projectionLayerViews.data();
1774void QOpenXRManager::doRender(
const XrSwapchainSubImage &subImage,
1775 const XrSwapchainImageBaseHeader *swapchainImage,
1776 const XrSwapchainImageBaseHeader *depthSwapchainImage)
1778 const int arraySize = m_multiviewRendering ? m_swapchains[0].arraySize : 1;
1779 m_quickWindow->setRenderTarget(m_graphics->renderTarget(subImage,
1781 m_colorSwapchainFormat,
1784 depthSwapchainImage,
1785 m_depthSwapchainFormat));
1789 subImage.imageRect.extent.width,
1790 subImage.imageRect.extent.height);
1792 subImage.imageRect.extent.height));
1796 m_renderControl->
sync();
1797 m_renderControl->
render();
1811void QOpenXRManager::preSetupQuickScene()
1817bool QOpenXRManager::setupQuickScene()
1820#if !defined(Q_OS_VISIONOS)
1821 m_graphics->setupWindow(m_quickWindow);
1823 m_visionOSRenderManager->setupWindow(m_quickWindow);
1829 const bool initSuccess = m_renderControl->
initialize();
1831 qWarning(
"Quick 3D XR: Failed to create renderControl (failed to initialize RHI?)");
1835 QRhi *rhi = m_renderControl->
rhi();
1837 qWarning(
"Quick3D XR: No QRhi from renderControl. This should not happen.");
1844 qWarning(
"Quick 3D XR: Multiview rendering was enabled, but is reported as unsupported from the current QRhi backend (%s)",
1846 m_multiviewRendering =
false;
1849 qDebug(
"Quick3D XR: multiview rendering %s", m_multiviewRendering ?
"enabled" :
"disabled");
1854#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
1855void QOpenXRManager::updateCameraHelper(
QOpenXREyeCamera *
camera,
const XrCompositionLayerProjectionView &layerView)
1857 camera->setLeftTangent(
qTan(layerView.fov.angleLeft));
1858 camera->setRightTangent(
qTan(layerView.fov.angleRight));
1859 camera->setUpTangent(
qTan(layerView.fov.angleUp));
1860 camera->setDownTangent(
qTan(layerView.fov.angleDown));
1863 layerView.pose.position.y,
1864 layerView.pose.position.z) * 100.0f);
1867 layerView.pose.orientation.x,
1868 layerView.pose.orientation.y,
1869 layerView.pose.orientation.z));
1874void QOpenXRManager::updateCameraNonMultiview(
int eye,
const XrCompositionLayerProjectionView &layerView)
1876 QOpenXREyeCamera *eyeCamera = m_xrOrigin ? m_xrOrigin->eyeCamera(eye) :
nullptr;
1879 updateCameraHelper(eyeCamera, layerView);
1885void QOpenXRManager::updateCameraMultiview(
int projectionLayerViewStartIndex,
int count)
1887 QVarLengthArray<QQuick3DCamera *, 4> cameras;
1888 for (
int i = projectionLayerViewStartIndex;
i < projectionLayerViewStartIndex +
count; ++
i) {
1891 updateCameraHelper(eyeCamera, m_projectionLayerViews[
i]);
1892 cameras.append(eyeCamera);
1894 m_vrViewport->setMultiViewCameras(cameras.data(), cameras.count());
1898void QOpenXRManager::checkOrigin()
1906 auto origin = qobject_cast<QOpenXROrigin *>(node);
1909 for (
auto child : node->childItems()) {
1910 origin = findOriginNode(
child);
1916 auto origin = findOriginNode(m_vrViewport->
importScene());
1918 m_xrOrigin = origin;
1921 m_xrOrigin =
nullptr;
1928bool QOpenXRManager::supportsPassthrough()
const
1930 bool supported =
false;
1931#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
1932 XrSystemPassthroughProperties2FB passthroughSystemProperties{};
1933 passthroughSystemProperties.type = XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB;
1935 XrSystemProperties systemProperties{};
1936 systemProperties.type = XR_TYPE_SYSTEM_PROPERTIES;
1937 systemProperties.next = &passthroughSystemProperties;
1939 XrSystemGetInfo systemGetInfo{};
1940 systemGetInfo.type = XR_TYPE_SYSTEM_GET_INFO;
1941 systemGetInfo.formFactor = m_formFactor;
1943 XrSystemId systemId = XR_NULL_SYSTEM_ID;
1944 xrGetSystem(m_instance, &systemGetInfo, &systemId);
1945 xrGetSystemProperties(m_instance, systemId, &systemProperties);
1947 supported = (passthroughSystemProperties.capabilities & XR_PASSTHROUGH_CAPABILITY_BIT_FB) == XR_PASSTHROUGH_CAPABILITY_BIT_FB;
1953 XrSystemPassthroughPropertiesFB oldPassthroughSystemProperties{};
1954 oldPassthroughSystemProperties.type = XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB;
1955 systemProperties.next = &oldPassthroughSystemProperties;
1956 xrGetSystemProperties(m_instance, systemId, &systemProperties);
1957 supported = oldPassthroughSystemProperties.supportsPassthrough;
1963#if defined(Q_NO_TEMPORARY_DISABLE_XR_API)
1964void QOpenXRManager::setupMetaQuestColorSpaces()
1966 PFN_xrEnumerateColorSpacesFB pfnxrEnumerateColorSpacesFB = NULL;
1969 "xrEnumerateColorSpacesFB",
1970 (PFN_xrVoidFunction*)(&pfnxrEnumerateColorSpacesFB)));
1972 if (!pfnxrEnumerateColorSpacesFB)
1975 uint32_t colorSpaceCountOutput = 0;
1978 XrColorSpaceFB* colorSpaces =
1979 (XrColorSpaceFB*)malloc(colorSpaceCountOutput *
sizeof(XrColorSpaceFB));
1982 m_session, colorSpaceCountOutput, &colorSpaceCountOutput, colorSpaces));
1983 qDebug(
"Supported ColorSpaces:");
1985 for (uint32_t
i = 0;
i < colorSpaceCountOutput;
i++) {
1986 qDebug(
"%d:%d",
i, colorSpaces[
i]);
1989 const XrColorSpaceFB requestColorSpace = XR_COLOR_SPACE_QUEST_FB;
1991 PFN_xrSetColorSpaceFB pfnxrSetColorSpaceFB = NULL;
1993 m_instance,
"xrSetColorSpaceFB", (PFN_xrVoidFunction*)(&pfnxrSetColorSpaceFB)));
2000void QOpenXRManager::setupMetaQuestRefreshRates()
2002 PFN_xrEnumerateDisplayRefreshRatesFB pfnxrEnumerateDisplayRefreshRatesFB = NULL;
2005 "xrEnumerateDisplayRefreshRatesFB",
2006 (PFN_xrVoidFunction*)(&pfnxrEnumerateDisplayRefreshRatesFB)));
2008 if (!pfnxrEnumerateDisplayRefreshRatesFB)
2011 uint32_t numSupportedDisplayRefreshRates;
2012 QVector<float> supportedDisplayRefreshRates;
2015 m_session, 0, &numSupportedDisplayRefreshRates, NULL));
2017 supportedDisplayRefreshRates.resize(numSupportedDisplayRefreshRates);
2021 numSupportedDisplayRefreshRates,
2022 &numSupportedDisplayRefreshRates,
2023 supportedDisplayRefreshRates.data()));
2024 qDebug(
"Supported Refresh Rates:");
2025 for (uint32_t
i = 0;
i < numSupportedDisplayRefreshRates;
i++) {
2026 qDebug(
"%d:%f",
i, supportedDisplayRefreshRates[
i]);
2029 PFN_xrGetDisplayRefreshRateFB pfnGetDisplayRefreshRate;
2032 "xrGetDisplayRefreshRateFB",
2033 (PFN_xrVoidFunction*)(&pfnGetDisplayRefreshRate)));
2035 float currentDisplayRefreshRate = 0.0f;
2037 qDebug(
"Current System Display Refresh Rate: %f", currentDisplayRefreshRate);
2039 PFN_xrRequestDisplayRefreshRateFB pfnRequestDisplayRefreshRate;
2042 "xrRequestDisplayRefreshRateFB",
2043 (PFN_xrVoidFunction*)(&pfnRequestDisplayRefreshRate)));
2047 qDebug(
"Requesting system default display refresh rate");
2050void QOpenXRManager::setupMetaQuestFoveation()
2052 PFN_xrCreateFoveationProfileFB pfnCreateFoveationProfileFB;
2055 "xrCreateFoveationProfileFB",
2056 (PFN_xrVoidFunction*)(&pfnCreateFoveationProfileFB)));
2058 if (!pfnCreateFoveationProfileFB)
2061 PFN_xrDestroyFoveationProfileFB pfnDestroyFoveationProfileFB;
2064 "xrDestroyFoveationProfileFB",
2065 (PFN_xrVoidFunction*)(&pfnDestroyFoveationProfileFB)));
2067 PFN_xrUpdateSwapchainFB pfnUpdateSwapchainFB;
2069 m_instance,
"xrUpdateSwapchainFB", (PFN_xrVoidFunction*)(&pfnUpdateSwapchainFB)));
2071 for (
auto swapchain : m_swapchains) {
2072 XrFoveationLevelProfileCreateInfoFB levelProfileCreateInfo = {};
2073 levelProfileCreateInfo.type = XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB;
2074 levelProfileCreateInfo.level = m_foveationLevel;
2075 levelProfileCreateInfo.verticalOffset = 0;
2076 levelProfileCreateInfo.dynamic = XR_FOVEATION_DYNAMIC_DISABLED_FB;
2078 XrFoveationProfileCreateInfoFB profileCreateInfo = {};
2079 profileCreateInfo.type = XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB;
2080 profileCreateInfo.next = &levelProfileCreateInfo;
2082 XrFoveationProfileFB foveationProfile;
2083 pfnCreateFoveationProfileFB(
m_session, &profileCreateInfo, &foveationProfile);
2085 XrSwapchainStateFoveationFB foveationUpdateState = {};
2086 memset(&foveationUpdateState, 0,
sizeof(foveationUpdateState));
2087 foveationUpdateState.type = XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB;
2088 foveationUpdateState.profile = foveationProfile;
2090 pfnUpdateSwapchainFB(
2092 (XrSwapchainStateBaseHeaderFB*)(&foveationUpdateState));
2094 pfnDestroyFoveationProfileFB(foveationProfile);
2096 qDebug(
"Fixed foveated rendering requested with level %d",
int(m_foveationLevel));
2100void QOpenXRManager::createMetaQuestPassthrough()
2105 Q_ASSERT(m_passthroughSupported && m_enablePassthrough);
2108 PFN_xrCreatePassthroughFB pfnXrCreatePassthroughFBX =
nullptr;
2110 "xrCreatePassthroughFB",
2111 (PFN_xrVoidFunction*)(&pfnXrCreatePassthroughFBX)));
2113 XrPassthroughCreateInfoFB passthroughCreateInfo{};
2114 passthroughCreateInfo.type = XR_TYPE_PASSTHROUGH_CREATE_INFO_FB;
2115 passthroughCreateInfo.flags = XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB;
2120void QOpenXRManager::destroyMetaQuestPassthrough()
2123 PFN_xrDestroyPassthroughFB pfnXrDestroyPassthroughFBX =
nullptr;
2125 "xrDestroyPassthroughFB",
2126 (PFN_xrVoidFunction*)(&pfnXrDestroyPassthroughFBX)));
2127 checkXrResult(pfnXrDestroyPassthroughFBX(m_passthroughFeature));
2128 m_passthroughFeature = XR_NULL_HANDLE;
2131void QOpenXRManager::startMetaQuestPassthrough()
2134 PFN_xrPassthroughStartFB pfnXrPassthroughStartFBX =
nullptr;
2136 "xrPassthroughStartFB",
2137 (PFN_xrVoidFunction*)(&pfnXrPassthroughStartFBX)));
2138 checkXrResult(pfnXrPassthroughStartFBX(m_passthroughFeature));
2141void QOpenXRManager::pauseMetaQuestPassthrough()
2144 PFN_xrPassthroughPauseFB pfnXrPassthroughPauseFBX =
nullptr;
2146 "xrPassthroughPauseFB",
2147 (PFN_xrVoidFunction*)(&pfnXrPassthroughPauseFBX)));
2148 checkXrResult(pfnXrPassthroughPauseFBX(m_passthroughFeature));
2151void QOpenXRManager::createMetaQuestPassthroughLayer()
2154 PFN_xrCreatePassthroughLayerFB pfnXrCreatePassthroughLayerFBX =
nullptr;
2156 "xrCreatePassthroughLayerFB",
2157 (PFN_xrVoidFunction*)(&pfnXrCreatePassthroughLayerFBX)));
2159 XrPassthroughLayerCreateInfoFB layerCreateInfo{};
2160 layerCreateInfo.type = XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB;
2161 layerCreateInfo.passthrough = m_passthroughFeature;
2162 layerCreateInfo.purpose = XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB;
2163 if (m_enablePassthrough)
2164 layerCreateInfo.flags = XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB;
2169void QOpenXRManager::destroyMetaQuestPassthroughLayer()
2172 PFN_xrDestroyPassthroughLayerFB pfnXrDestroyPassthroughLayerFBX =
nullptr;
2174 "xrDestroyPassthroughLayerFB",
2175 (PFN_xrVoidFunction*)(&pfnXrDestroyPassthroughLayerFBX)));
2176 checkXrResult(pfnXrDestroyPassthroughLayerFBX(m_passthroughLayer));
2177 m_passthroughLayer = XR_NULL_HANDLE;
2180void QOpenXRManager::pauseMetaQuestPassthroughLayer()
2183 PFN_xrPassthroughLayerPauseFB pfnXrPassthroughLayerPauseFBX =
nullptr;
2185 "xrPassthroughLayerPauseFB",
2186 (PFN_xrVoidFunction*)(&pfnXrPassthroughLayerPauseFBX)));
2187 checkXrResult(pfnXrPassthroughLayerPauseFBX(m_passthroughLayer));
2190void QOpenXRManager::resumeMetaQuestPassthroughLayer()
2193 PFN_xrPassthroughLayerResumeFB pfnXrPassthroughLayerResumeFBX =
nullptr;
2195 "xrPassthroughLayerResumeFB",
2196 (PFN_xrVoidFunction*)(&pfnXrPassthroughLayerResumeFBX)));
2197 checkXrResult(pfnXrPassthroughLayerResumeFBX(m_passthroughLayer));
AVFCameraSession * m_session
void install()
Installs this animation driver.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
QString applicationName
the name of this application
Type type() const
Returns the event type.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
void advance() override
Advances the animation.
void setStep(int stepSize)
void setPassthroughEnabled(bool enabled)
void referenceSpaceChanged()
void setSamples(int samples)
bool event(QEvent *e) override
This virtual function receives events to an object and should return true if the event e was recogniz...
QOpenXRManager(QObject *parent=nullptr)
void frameReady(QRhiTexture *colorBuffer)
static QOpenXRSpaceExtension * instance()
The QQuaternion class represents a quaternion consisting of a vector and scalar.
void setRotation(const QQuaternion &rotation)
void setPosition(const QVector3D &position)
\qmltype Object3D \inqmlmodule QtQuick3D \instantiates QQuick3DObject \inherits QtObject
QQuick3DNode * importScene
void setCamera(QQuick3DCamera *camera)
void setSize(const QSizeF &size)
The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph onto an offs...
bool initialize()
Initializes the scene graph resources.
void endFrame()
Specifies the end of a graphics frame.
void render()
Renders the scenegraph using the current context.
void beginFrame()
Specifies the start of a graphics frame.
void polishItems()
This function should be called as late as possible before sync().
bool sync()
This function is used to synchronize the QML scene with the rendering scene graph.
static QQuickWindowPrivate * get(QQuickWindow *c)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
QQuickItem * contentItem
\qmlattachedproperty Item Window::contentItem
virtual Type resourceType() const =0
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
bool isFeatureSupported(QRhi::Feature feature) const
const char * backendName() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
void clear()
Clears the contents of the string and makes it null.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray toUtf8() const &
The QVector3D class represents a vector or vertex in 3D space.
int minorVersion() const noexcept
Returns the minor version number, that is, the second segment.
int majorVersion() const noexcept
Returns the major version number, that is, the first segment.
Q_CORE_EXPORT QString toString() const
Returns a string with all of the segments delimited by a period ({.}).
int microVersion() const noexcept
Returns the micro version number, that is, the third segment.
void setGeometry(int posx, int posy, int w, int h)
Sets the geometry of the window, excluding its window frame, to a rectangle constructed from posx,...
list append(new Employee("Blackpool", "Stephen"))
bool checkXrResult(XrResult result, XrInstance instance)
QString getXrResultAsString(XrResult result, XrInstance instance)
Combined button and popup list for selecting options.
int toUtf8(char16_t u, OutputPtr &dst, InputPtr &src, InputPtr end)
const EGLAttrib EGLOutputLayerEXT * layers
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei GLsizei GLenum format
Q_ALWAYS_INLINE QString to_string(QLatin1StringView s) noexcept
#define qPrintable(string)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
QNetworkRequest request(url)