Title: [273382] trunk/Source/WebCore
Revision
273382
Author
commit-qu...@webkit.org
Date
2021-02-24 05:13:21 -0800 (Wed, 24 Feb 2021)

Log Message

Refactor OpenXR platform code into different classes and files.
https://bugs.webkit.org/show_bug.cgi?id=222263

Patch by Imanol Fernandez <ifernan...@igalia.com> on 2021-02-24
Reviewed by Sergio Villar Senin.

OpenXR platform code is going to grow with graphics, extensions, swapchains, controllers and more.
This patch splits the code into different files to make it more readable and maintanable.

* Sources.txt:
* platform/xr/openxr/OpenXRExtensions.cpp: Added.
(PlatformXR::OpenXRExtensions::create):
(PlatformXR::OpenXRExtensions::OpenXRExtensions):
(PlatformXR::OpenXRExtensions::isExtensionSupported const):
* platform/xr/openxr/OpenXRExtensions.h: Added.
* platform/xr/openxr/OpenXRInstance.cpp: Added.
(PlatformXR::Instance::Impl::xrInstance const):
(PlatformXR::Instance::Impl::queue const):
(PlatformXR::Instance::Impl::extensions):
(PlatformXR::Instance::Impl::Impl):
(PlatformXR::Instance::Impl::~Impl):
(PlatformXR::Instance::singleton):
(PlatformXR::Instance::Instance):
(PlatformXR::Instance::enumerateImmersiveXRDevices):
* platform/xr/openxr/OpenXRUtils.h: Added.
(PlatformXR::createStructure):
(PlatformXR::resultToString):
(PlatformXR::XrPosefToPose):
(PlatformXR::xrViewToPose):
(PlatformXR::toXrViewConfigurationType):
* platform/xr/openxr/PlatformXROpenXR.cpp:
(PlatformXR::isSessionActive):
(PlatformXR::isSessionReady):
(PlatformXR::OpenXRDevice::OpenXRDevice):
(PlatformXR::OpenXRDevice::recommendedResolution):
(PlatformXR::OpenXRDevice::initializeTrackingAndRendering):
(PlatformXR::OpenXRDevice::shutDownTrackingAndRendering):
(PlatformXR::OpenXRDevice::initializeReferenceSpace):
(PlatformXR::OpenXRDevice::requestFrame):
(PlatformXR::OpenXRDevice::views const):
(PlatformXR::OpenXRDevice::enumerateReferenceSpaces const):
(PlatformXR::OpenXRDevice::createReferenceSpace):
(PlatformXR::OpenXRDevice::resetSession):
(PlatformXR::OpenXRDevice::handleSessionStateChange):
(PlatformXR::OpenXRDevice::waitUntilStopping):
* platform/xr/openxr/PlatformXROpenXR.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (273381 => 273382)


--- trunk/Source/WebCore/ChangeLog	2021-02-24 13:09:49 UTC (rev 273381)
+++ trunk/Source/WebCore/ChangeLog	2021-02-24 13:13:21 UTC (rev 273382)
@@ -1,5 +1,53 @@
 2021-02-24  Imanol Fernandez  <ifernan...@igalia.com>
 
+        Refactor OpenXR platform code into different classes and files.
+        https://bugs.webkit.org/show_bug.cgi?id=222263
+
+        Reviewed by Sergio Villar Senin.
+
+        OpenXR platform code is going to grow with graphics, extensions, swapchains, controllers and more.
+        This patch splits the code into different files to make it more readable and maintanable.
+
+        * Sources.txt:
+        * platform/xr/openxr/OpenXRExtensions.cpp: Added.
+        (PlatformXR::OpenXRExtensions::create):
+        (PlatformXR::OpenXRExtensions::OpenXRExtensions):
+        (PlatformXR::OpenXRExtensions::isExtensionSupported const):
+        * platform/xr/openxr/OpenXRExtensions.h: Added.
+        * platform/xr/openxr/OpenXRInstance.cpp: Added.
+        (PlatformXR::Instance::Impl::xrInstance const):
+        (PlatformXR::Instance::Impl::queue const):
+        (PlatformXR::Instance::Impl::extensions):
+        (PlatformXR::Instance::Impl::Impl):
+        (PlatformXR::Instance::Impl::~Impl):
+        (PlatformXR::Instance::singleton):
+        (PlatformXR::Instance::Instance):
+        (PlatformXR::Instance::enumerateImmersiveXRDevices):
+        * platform/xr/openxr/OpenXRUtils.h: Added.
+        (PlatformXR::createStructure):
+        (PlatformXR::resultToString):
+        (PlatformXR::XrPosefToPose):
+        (PlatformXR::xrViewToPose):
+        (PlatformXR::toXrViewConfigurationType):
+        * platform/xr/openxr/PlatformXROpenXR.cpp:
+        (PlatformXR::isSessionActive):
+        (PlatformXR::isSessionReady):
+        (PlatformXR::OpenXRDevice::OpenXRDevice):
+        (PlatformXR::OpenXRDevice::recommendedResolution):
+        (PlatformXR::OpenXRDevice::initializeTrackingAndRendering):
+        (PlatformXR::OpenXRDevice::shutDownTrackingAndRendering):
+        (PlatformXR::OpenXRDevice::initializeReferenceSpace):
+        (PlatformXR::OpenXRDevice::requestFrame):
+        (PlatformXR::OpenXRDevice::views const):
+        (PlatformXR::OpenXRDevice::enumerateReferenceSpaces const):
+        (PlatformXR::OpenXRDevice::createReferenceSpace):
+        (PlatformXR::OpenXRDevice::resetSession):
+        (PlatformXR::OpenXRDevice::handleSessionStateChange):
+        (PlatformXR::OpenXRDevice::waitUntilStopping):
+        * platform/xr/openxr/PlatformXROpenXR.h:
+
+2021-02-24  Imanol Fernandez  <ifernan...@igalia.com>
+
         Implement WebXR getViewport
         https://bugs.webkit.org/show_bug.cgi?id=222270
 

Modified: trunk/Source/WebCore/Sources.txt (273381 => 273382)


--- trunk/Source/WebCore/Sources.txt	2021-02-24 13:09:49 UTC (rev 273381)
+++ trunk/Source/WebCore/Sources.txt	2021-02-24 13:13:21 UTC (rev 273382)
@@ -2172,6 +2172,8 @@
 platform/text/TextEncoding.cpp
 platform/text/TextEncodingDetectorICU.cpp
 platform/text/TextEncodingRegistry.cpp
+platform/xr/openxr/OpenXRInstance.cpp @no-unify
+platform/xr/openxr/OpenXRExtensions.cpp @no-unify
 platform/xr/openxr/PlatformXROpenXR.cpp @no-unify
 plugins/DOMMimeType.cpp
 plugins/DOMMimeTypeArray.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (273381 => 273382)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-02-24 13:09:49 UTC (rev 273381)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-02-24 13:13:21 UTC (rev 273382)
@@ -393,6 +393,10 @@
 		115CFA86208B9066001E6991 /* FloatingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 115CFA84208B9066001E6991 /* FloatingContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		115CFA97208B952B001E6991 /* LayoutBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 115CFA95208B952B001E6991 /* LayoutBox.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		1163F82424E5D5AE000AB960 /* RenderTreeMutationDisallowedScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 1163F82124E5D59B000AB960 /* RenderTreeMutationDisallowedScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		118B068B25E41E530070BE4B /* OpenXRExtensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 118B068625E41E510070BE4B /* OpenXRExtensions.cpp */; };
+		118B068C25E41E530070BE4B /* OpenXRExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 118B068825E41E520070BE4B /* OpenXRExtensions.h */; };
+		118B068D25E41E530070BE4B /* OpenXRInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 118B068925E41E520070BE4B /* OpenXRInstance.cpp */; };
+		118B068E25E41E530070BE4B /* OpenXRUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 118B068A25E41E530070BE4B /* OpenXRUtils.h */; };
 		119340791FE8B92300935F1E /* RenderTreeBuilderTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340771FE8B92300935F1E /* RenderTreeBuilderTable.h */; };
 		1193408A1FEB355D00935F1E /* RenderTreeBuilderRuby.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340881FEB355D00935F1E /* RenderTreeBuilderRuby.h */; };
 		119340971FED715500935F1E /* RenderTreeBuilderFormControls.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340951FED715500935F1E /* RenderTreeBuilderFormControls.h */; };
@@ -6319,6 +6323,10 @@
 		115CFA96208B952B001E6991 /* LayoutBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutBox.cpp; sourceTree = "<group>"; };
 		1163F82124E5D59B000AB960 /* RenderTreeMutationDisallowedScope.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeMutationDisallowedScope.h; sourceTree = "<group>"; };
 		1163F82324E5D59B000AB960 /* RenderTreeMutationDisallowedScope.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeMutationDisallowedScope.cpp; sourceTree = "<group>"; };
+		118B068625E41E510070BE4B /* OpenXRExtensions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenXRExtensions.cpp; sourceTree = "<group>"; };
+		118B068825E41E520070BE4B /* OpenXRExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenXRExtensions.h; sourceTree = "<group>"; };
+		118B068925E41E520070BE4B /* OpenXRInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenXRInstance.cpp; sourceTree = "<group>"; };
+		118B068A25E41E530070BE4B /* OpenXRUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenXRUtils.h; sourceTree = "<group>"; };
 		119340761FE8B92300935F1E /* RenderTreeBuilderTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderTable.cpp; sourceTree = "<group>"; };
 		119340771FE8B92300935F1E /* RenderTreeBuilderTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderTable.h; sourceTree = "<group>"; };
 		119340871FEB355D00935F1E /* RenderTreeBuilderRuby.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderRuby.cpp; sourceTree = "<group>"; };
@@ -28924,6 +28932,10 @@
 		E1EE8B6D2412B2A700E794D6 /* openxr */ = {
 			isa = PBXGroup;
 			children = (
+				118B068625E41E510070BE4B /* OpenXRExtensions.cpp */,
+				118B068825E41E520070BE4B /* OpenXRExtensions.h */,
+				118B068925E41E520070BE4B /* OpenXRInstance.cpp */,
+				118B068A25E41E530070BE4B /* OpenXRUtils.h */,
 				E1C1A39B2480080600E0AF66 /* PlatformXROpenXR.cpp */,
 				E1C1A39C2480080700E0AF66 /* PlatformXROpenXR.h */,
 			);
@@ -34062,6 +34074,8 @@
 				B2D3DA650D006CD600EF6F3A /* OpenTypeCG.h in Headers */,
 				B2D3DA650D006CD600EF6F27 /* OpenTypeMathData.h in Headers */,
 				B2D3EA650D006CD600EF6F28 /* OpenTypeTypes.h in Headers */,
+				118B068C25E41E530070BE4B /* OpenXRExtensions.h in Headers */,
+				118B068E25E41E530070BE4B /* OpenXRUtils.h in Headers */,
 				71207340216DFB0000C78329 /* OptionalEffectTiming.h in Headers */,
 				CDE7FC45181904B1002BBB77 /* OrderIterator.h in Headers */,
 				4184F5161EAF05A800F18BF0 /* OrientationNotifier.h in Headers */,
@@ -36229,6 +36243,8 @@
 				1A569D180D7E2B82007C3983 /* objc_runtime.mm in Sources */,
 				1A569D1A0D7E2B82007C3983 /* objc_utility.mm in Sources */,
 				E16982601134636A00894115 /* ObjCRuntimeObject.mm in Sources */,
+				118B068B25E41E530070BE4B /* OpenXRExtensions.cpp in Sources */,
+				118B068D25E41E530070BE4B /* OpenXRInstance.cpp in Sources */,
 				CEA284662141E84900E407E8 /* PlatformEventFactoryIOS.mm in Sources */,
 				AA12DF491743DF83004DAFDF /* PlatformSpeechSynthesizerIOS.mm in Sources */,
 				E1C1A39D2480080800E0AF66 /* PlatformXROpenXR.cpp in Sources */,

Added: trunk/Source/WebCore/platform/xr/openxr/OpenXRExtensions.cpp (0 => 273382)


--- trunk/Source/WebCore/platform/xr/openxr/OpenXRExtensions.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/xr/openxr/OpenXRExtensions.cpp	2021-02-24 13:13:21 UTC (rev 273382)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 Igalia, S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "OpenXRExtensions.h"
+
+#if ENABLE(WEBXR) && USE(OPENXR)
+
+using namespace WebCore;
+
+namespace PlatformXR {
+
+std::unique_ptr<OpenXRExtensions> OpenXRExtensions::create()
+{
+    uint32_t extensionCount { 0 };
+    XrResult result = xrEnumerateInstanceExtensionProperties(nullptr, 0, &extensionCount, nullptr);
+
+    if (XR_FAILED(result) || !extensionCount) {
+        LOG(XR, "xrEnumerateInstanceExtensionProperties(): no extensions\n");
+        return nullptr;
+    }
+
+    Vector<XrExtensionProperties> extensions(extensionCount, [] {
+        return createStructure<XrExtensionProperties, XR_TYPE_EXTENSION_PROPERTIES>();
+    }());
+
+    result = xrEnumerateInstanceExtensionProperties(nullptr, extensionCount, &extensionCount, extensions.data());
+    if (XR_FAILED(result)) {
+        LOG(XR, "xrEnumerateInstanceExtensionProperties() failed: %d\n", result);
+        return nullptr;
+    }
+
+    return makeUnique<OpenXRExtensions>(WTFMove(extensions));
+}
+
+OpenXRExtensions::OpenXRExtensions(Vector<XrExtensionProperties>&& extensions)
+    : m_extensions(WTFMove(extensions))
+{
+}
+
+bool OpenXRExtensions::isExtensionSupported(const char* name) const
+{
+    auto position = m_extensions.findMatching([name](auto& property) {
+        return !strcmp(property.extensionName, name);
+    });
+    return position != notFound;
+}
+
+} // namespace PlatformXR
+
+#endif // ENABLE(WEBXR) && USE(OPENXR)

Added: trunk/Source/WebCore/platform/xr/openxr/OpenXRExtensions.h (0 => 273382)


--- trunk/Source/WebCore/platform/xr/openxr/OpenXRExtensions.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/xr/openxr/OpenXRExtensions.h	2021-02-24 13:13:21 UTC (rev 273382)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 Igalia, S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#if ENABLE(WEBXR) && USE(OPENXR)
+
+#include "OpenXRUtils.h"
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace PlatformXR {
+
+class OpenXRExtensions final {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(OpenXRExtensions);
+public:
+    static std::unique_ptr<OpenXRExtensions> create();
+    OpenXRExtensions(Vector<XrExtensionProperties>&&);
+
+    bool isExtensionSupported(const char*) const;
+
+private:
+    Vector<XrExtensionProperties> m_extensions;
+};
+
+} // namespace PlatformXR
+
+#endif // ENABLE(WEBXR) && USE(OPENXR)

Added: trunk/Source/WebCore/platform/xr/openxr/OpenXRInstance.cpp (0 => 273382)


--- trunk/Source/WebCore/platform/xr/openxr/OpenXRInstance.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/xr/openxr/OpenXRInstance.cpp	2021-02-24 13:13:21 UTC (rev 273382)
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2021 Igalia, S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEBXR) && USE(OPENXR)
+
+#include "OpenXRExtensions.h"
+#include "PlatformXROpenXR.h"
+
+#include <wtf/Scope.h>
+
+using namespace WebCore;
+
+namespace PlatformXR {
+
+struct Instance::Impl {
+    WTF_MAKE_STRUCT_FAST_ALLOCATED;
+
+    Impl();
+    ~Impl();
+
+    XrInstance xrInstance() const { return m_instance; }
+    WorkQueue& queue() const { return m_workQueue; }
+    OpenXRExtensions* extensions() { return m_extensions.get(); }
+
+private:
+    XrInstance m_instance { XR_NULL_HANDLE };
+    Ref<WorkQueue> m_workQueue;
+    std::unique_ptr<OpenXRExtensions> m_extensions;
+};
+
+Instance::Impl::Impl()
+    : m_workQueue(WorkQueue::create("OpenXR queue"))
+{
+    m_workQueue->dispatch([this]() {
+        LOG(XR, "OpenXR: initializing\n");
+
+        m_extensions = OpenXRExtensions::create();
+        if (!m_extensions)
+            return;
+
+        if (!m_extensions->isExtensionSupported(XR_MND_HEADLESS_EXTENSION_NAME)) {
+            LOG(XR, "Required extension %s not supported", XR_MND_HEADLESS_EXTENSION_NAME);
+            return;
+        }
+
+        static const char* s_applicationName = "WebXR (WebKit)";
+        static const uint32_t s_applicationVersion = 1;
+
+        const char* const enabledExtensions[] = {
+            XR_MND_HEADLESS_EXTENSION_NAME
+        };
+
+        auto createInfo = createStructure<XrInstanceCreateInfo, XR_TYPE_INSTANCE_CREATE_INFO>();
+        createInfo.createFlags = 0;
+        std::memcpy(createInfo.applicationInfo.applicationName, s_applicationName, XR_MAX_APPLICATION_NAME_SIZE);
+        createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
+        createInfo.applicationInfo.applicationVersion = s_applicationVersion;
+        createInfo.enabledApiLayerCount = 0;
+        createInfo.enabledExtensionCount = WTF_ARRAY_LENGTH(enabledExtensions);
+        createInfo.enabledExtensionNames = enabledExtensions;
+
+        XrResult result = xrCreateInstance(&createInfo, &m_instance);
+        RETURN_IF_FAILED(result, "xrCreateInstance()", m_instance);
+        if (m_instance == XR_NULL_HANDLE)
+            return;
+
+        LOG(XR, "xrCreateInstance(): using instance %p\n", m_instance);
+    });
+}
+
+Instance::Impl::~Impl()
+{
+    m_workQueue->dispatch([this] {
+        if (m_instance != XR_NULL_HANDLE)
+            xrDestroyInstance(m_instance);
+    });
+}
+
+Instance& Instance::singleton()
+{
+    static LazyNeverDestroyed<Instance> s_instance;
+    static std::once_flag s_onceFlag;
+    std::call_once(s_onceFlag,
+        [&] {
+            s_instance.construct();
+        });
+    return s_instance.get();
+}
+
+Instance::Instance()
+    : m_impl(makeUniqueRef<Impl>())
+{
+}
+
+void Instance::enumerateImmersiveXRDevices(CompletionHandler<void(const DeviceList& devices)>&& callback)
+{
+    m_impl->queue().dispatch([this, callback = WTFMove(callback)]() mutable {
+        auto callbackOnExit = makeScopeExit([&]() {
+            callOnMainThread([callback = WTFMove(callback)]() mutable {
+                callback({ });
+            });
+        });
+
+        if (m_impl->xrInstance() == XR_NULL_HANDLE || !m_impl->extensions()) {
+            LOG(XR, "%s Unable to enumerate XR devices. No XrInstance present\n", __FUNCTION__);
+            return;
+        }
+
+        auto systemGetInfo = createStructure<XrSystemGetInfo, XR_TYPE_SYSTEM_GET_INFO>();
+        systemGetInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
+
+        XrSystemId systemId;
+        XrResult result = xrGetSystem(m_impl->xrInstance(), &systemGetInfo, &systemId);
+        RETURN_IF_FAILED(result, "xrGetSystem", m_impl->xrInstance());
+
+        callbackOnExit.release();
+
+        callOnMainThread([this, callback = WTFMove(callback), systemId]() mutable {
+            m_immersiveXRDevices = DeviceList::from(makeUniqueRef<OpenXRDevice>(m_impl->xrInstance(), systemId, m_impl->queue(), *m_impl->extensions(), [this, callback = WTFMove(callback)]() mutable {
+                ASSERT(isMainThread());
+                callback(m_immersiveXRDevices);
+            }));
+        });
+    });
+}
+
+
+} // namespace PlatformXR
+
+#endif // ENABLE(WEBXR) && USE(OPENXR)

Added: trunk/Source/WebCore/platform/xr/openxr/OpenXRUtils.h (0 => 273382)


--- trunk/Source/WebCore/platform/xr/openxr/OpenXRUtils.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/xr/openxr/OpenXRUtils.h	2021-02-24 13:13:21 UTC (rev 273382)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 Igalia, S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#if ENABLE(WEBXR) && USE(OPENXR)
+
+#include "Logging.h"
+#include "PlatformXR.h"
+#include <openxr/openxr.h>
+
+#include <wtf/text/StringConcatenateNumbers.h>
+#include <wtf/text/WTFString.h>
+
+namespace PlatformXR {
+
+template<typename T, XrStructureType StructureType>
+T createStructure()
+{
+    T object;
+    std::memset(&object, 0, sizeof(T));
+    object.type = StructureType;
+    object.next = nullptr;
+    return object;
+}
+
+inline String resultToString(XrResult value, XrInstance instance)
+{
+    char buffer[XR_MAX_RESULT_STRING_SIZE];
+    XrResult result = xrResultToString(instance, value, buffer);
+    if (result == XR_SUCCESS)
+        return String(buffer);
+    return makeString("<unknown ", int(value), ">");
+}
+
+#define RETURN_IF_FAILED(result, call, instance, ...)                                           \
+    if (XR_FAILED(result)) {                                                                    \
+        LOG(XR, "%s %s: %s\n", __func__, call, resultToString(result, instance).utf8().data()); \
+        return __VA_ARGS__;                                                                     \
+    }
+
+inline Device::FrameData::Pose XrPosefToPose(XrPosef pose)
+{
+    Device::FrameData::Pose result;
+    result.orientation = { pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w };
+    result.position = { pose.position.x, pose.position.y, pose.position.z };
+    return result;
+}
+
+inline Device::FrameData::View xrViewToPose(XrView view)
+{
+    Device::FrameData::View pose;
+    pose.projection = Device::FrameData::Fov { view.fov.angleUp, -view.fov.angleDown, -view.fov.angleLeft, view.fov.angleRight };
+    pose.offset = XrPosefToPose(view.pose);
+    return pose;
+}
+
+inline XrViewConfigurationType toXrViewConfigurationType(SessionMode mode)
+{
+    switch (mode) {
+    case SessionMode::ImmersiveVr:
+        return XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
+    case SessionMode::Inline:
+    case SessionMode::ImmersiveAr:
+        return XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO;
+    };
+    ASSERT_NOT_REACHED();
+    return XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO;
+}
+
+} // namespace PlatformXR
+
+#endif // ENABLE(WEBXR) && USE(OPENXR)

Modified: trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp (273381 => 273382)


--- trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp	2021-02-24 13:09:49 UTC (rev 273381)
+++ trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp	2021-02-24 13:13:21 UTC (rev 273382)
@@ -22,245 +22,205 @@
 
 #if ENABLE(WEBXR) && USE(OPENXR)
 
-#include "Logging.h"
-#include <openxr/openxr_platform.h>
+#include "OpenXRExtensions.h"
+
 #include <wtf/NeverDestroyed.h>
 #include <wtf/Optional.h>
-#include <wtf/Scope.h>
-#include <wtf/text/StringConcatenateNumbers.h>
-#include <wtf/text/WTFString.h>
 
 using namespace WebCore;
 
 namespace PlatformXR {
 
-template<typename T, XrStructureType StructureType>
-T createStructure()
+
+static bool isSessionActive(XrSessionState state)
 {
-    T object;
-    std::memset(&object, 0, sizeof(T));
-    object.type = StructureType;
-    object.next = nullptr;
-    return object;
+    return state == XR_SESSION_STATE_VISIBLE || state == XR_SESSION_STATE_FOCUSED;
 }
 
-String resultToString(XrResult value, XrInstance instance)
+static bool isSessionReady(XrSessionState state)
 {
-    char buffer[XR_MAX_RESULT_STRING_SIZE];
-    XrResult result = xrResultToString(instance, value, buffer);
-    if (result == XR_SUCCESS)
-        return String(buffer);
-    return makeString("<unknown ", int(value), ">");
+    return state >= XR_SESSION_STATE_READY  && state < XR_SESSION_STATE_STOPPING;
 }
 
-#define RETURN_IF_FAILED(result, call, instance, ...)                                           \
-    if (XR_FAILED(result)) {                                                                    \
-        LOG(XR, "%s %s: %s\n", __func__, call, resultToString(result, instance).utf8().data()); \
-        return __VA_ARGS__;                                                                     \
-    }
-
-struct Instance::Impl {
-    WTF_MAKE_STRUCT_FAST_ALLOCATED;
-
-    Impl();
-    ~Impl();
-
-    XrInstance xrInstance() const { return m_instance; }
-    WorkQueue& queue() const { return m_workQueue; }
-
-private:
-    void enumerateApiLayerProperties() const;
-    bool checkInstanceExtensionProperties() const;
-
-    XrInstance m_instance { XR_NULL_HANDLE };
-    Ref<WorkQueue> m_workQueue;
-};
-
-void Instance::Impl::enumerateApiLayerProperties() const
+OpenXRDevice::OpenXRDevice(XrInstance instance, XrSystemId system, WorkQueue& queue, const OpenXRExtensions& extensions, CompletionHandler<void()>&& callback)
+    : m_instance(instance)
+    , m_systemId(system)
+    , m_queue(queue)
+    , m_extensions(extensions)
 {
-    ASSERT(&RunLoop::current() == &m_workQueue->runLoop());
-    uint32_t propertyCountOutput { 0 };
-    XrResult result = xrEnumerateApiLayerProperties(0, &propertyCountOutput, nullptr);
-    RETURN_IF_FAILED(result, "xrEnumerateApiLayerProperties()", m_instance);
+    ASSERT(isMainThread());
+    m_queue.dispatch([this, callback = WTFMove(callback)]() mutable {
+        auto systemProperties = createStructure<XrSystemProperties, XR_TYPE_SYSTEM_PROPERTIES>();
+        auto result = xrGetSystemProperties(m_instance, m_systemId, &systemProperties);
+        if (XR_SUCCEEDED(result))
+            m_supportsOrientationTracking = systemProperties.trackingProperties.orientationTracking == XR_TRUE;
+#if !LOG_DISABLED
+        else
+            LOG(XR, "xrGetSystemProperties(): error %s\n", resultToString(result, m_instance).utf8().data());
+        LOG(XR, "Found XRSystem %lu: \"%s\", vendor ID %d\n", systemProperties.systemId, systemProperties.systemName, systemProperties.vendorId);
+#endif
 
-    if (!propertyCountOutput) {
-        LOG(XR, "xrEnumerateApiLayerProperties(): no properties\n");
-        return;
-    }
+        collectSupportedSessionModes();
+        collectConfigurationViews();
 
-    Vector<XrApiLayerProperties> properties(propertyCountOutput,
-        [] {
-            XrApiLayerProperties object;
-            std::memset(&object, 0, sizeof(XrApiLayerProperties));
-            object.type = XR_TYPE_API_LAYER_PROPERTIES;
-            return object;
-        }());
-    result = xrEnumerateApiLayerProperties(propertyCountOutput, &propertyCountOutput, properties.data());
-
-    RETURN_IF_FAILED(result, "xrEnumerateApiLayerProperties()", m_instance);
-    LOG(XR, "xrEnumerateApiLayerProperties(): %zu properties\n", properties.size());
+        callOnMainThread(WTFMove(callback));
+    });
 }
 
-static bool isExtensionSupported(const char* extensionName, Vector<XrExtensionProperties>& instanceExtensionProperties)
+WebCore::IntSize OpenXRDevice::recommendedResolution(SessionMode mode)
 {
-    auto position = instanceExtensionProperties.findMatching([extensionName](auto& property) {
-        return !strcmp(property.extensionName, extensionName);
-    });
-    return position != notFound;
+    auto configType = toXrViewConfigurationType(mode);
+    auto viewsIterator = m_configurationViews.find(configType);
+    if (viewsIterator != m_configurationViews.end())
+        return { static_cast<int>(viewsIterator->value[0].recommendedImageRectWidth), static_cast<int>(viewsIterator->value[0].recommendedImageRectHeight) };
+    return Device::recommendedResolution(mode);
 }
 
-bool Instance::Impl::checkInstanceExtensionProperties() const
+void OpenXRDevice::initializeTrackingAndRendering(SessionMode mode)
 {
-    ASSERT(&RunLoop::current() == &m_workQueue->runLoop());
-    uint32_t propertyCountOutput { 0 };
-    XrResult result = xrEnumerateInstanceExtensionProperties(nullptr, 0, &propertyCountOutput, nullptr);
-    RETURN_IF_FAILED(result, "xrEnumerateInstanceExtensionProperties", m_instance, false);
+    m_queue.dispatch([this, mode]() {
+        ASSERT(m_instance != XR_NULL_HANDLE);
+        ASSERT(m_session == XR_NULL_HANDLE);
 
-    if (!propertyCountOutput) {
-        LOG(XR, "xrEnumerateInstanceExtensionProperties(): no properties\n");
-        return false;
-    }
+        m_currentViewConfigurationType = toXrViewConfigurationType(mode);
+        ASSERT(m_configurationViews.contains(m_currentViewConfigurationType));
 
-    Vector<XrExtensionProperties> properties(propertyCountOutput,
-        [] {
-            XrExtensionProperties object;
-            std::memset(&object, 0, sizeof(XrExtensionProperties));
-            object.type = XR_TYPE_EXTENSION_PROPERTIES;
-            return object;
-        }());
+        // Create the session.
+        auto sessionCreateInfo = createStructure<XrSessionCreateInfo, XR_TYPE_SESSION_CREATE_INFO>();
+        sessionCreateInfo.systemId = m_systemId;
 
-    uint32_t propertyCountWritten { 0 };
-    result = xrEnumerateInstanceExtensionProperties(nullptr, propertyCountOutput, &propertyCountWritten, properties.data());
-    RETURN_IF_FAILED(result, "xrEnumerateInstanceExtensionProperties", m_instance, false);
-#if !LOG_DISABLED
-    LOG(XR, "xrEnumerateInstanceExtensionProperties(): %zu extension properties\n", properties.size());
-    for (auto& property : properties)
-        LOG(XR, "  extension '%s', version %u\n", property.extensionName, property.extensionVersion);
-#endif
-    if (!isExtensionSupported(XR_MND_HEADLESS_EXTENSION_NAME, properties)) {
-        LOG(XR, "Required extension %s not supported", XR_MND_HEADLESS_EXTENSION_NAME);
-        return false;
-    }
+        auto result = xrCreateSession(m_instance, &sessionCreateInfo, &m_session);
+        RETURN_IF_FAILED(result, "xrEnumerateInstanceExtensionProperties", m_instance);
 
-    return true;
+        // Create the default reference spaces
+        m_localSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_LOCAL);
+        m_viewSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_VIEW);
+    });
 }
 
-Instance::Impl::Impl()
-    : m_workQueue(WorkQueue::create("OpenXR queue"))
+void OpenXRDevice::shutDownTrackingAndRendering()
 {
-    m_workQueue->dispatch([this]() {
-        LOG(XR, "OpenXR: initializing\n");
+    m_queue.dispatch([this]() {
+        if (m_session == XR_NULL_HANDLE)
+            return;
 
-        enumerateApiLayerProperties();
-
-        if (!checkInstanceExtensionProperties())
+        // xrRequestExitSession() will transition the session to STOPPED state.
+        // If the session was not running we have to reset the session ourselves.
+        if (XR_FAILED(xrRequestExitSession(m_session))) {
+            resetSession();
             return;
+        }
 
-        static const char* s_applicationName = "WebXR (WebKit)";
-        static const uint32_t s_applicationVersion = 1;
-
-        const char* const enabledExtensions[] = {
-            XR_MND_HEADLESS_EXTENSION_NAME,
-        };
-
-        auto createInfo = createStructure<XrInstanceCreateInfo, XR_TYPE_INSTANCE_CREATE_INFO>();
-        createInfo.createFlags = 0;
-        std::memcpy(createInfo.applicationInfo.applicationName, s_applicationName, XR_MAX_APPLICATION_NAME_SIZE);
-        createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
-        createInfo.applicationInfo.applicationVersion = s_applicationVersion;
-        createInfo.enabledApiLayerCount = 0;
-        createInfo.enabledExtensionCount = WTF_ARRAY_LENGTH(enabledExtensions);
-        createInfo.enabledExtensionNames = enabledExtensions;
-
-        XrInstance instance;
-        XrResult result = xrCreateInstance(&createInfo, &instance);
-        RETURN_IF_FAILED(result, "xrCreateInstance()", m_instance);
-        m_instance = instance;
-        LOG(XR, "xrCreateInstance(): using instance %p\n", m_instance);
+        // OpenXR needs to wait for the XR_SESSION_STATE_STOPPING state to properly end the session.
+        waitUntilStopping();
     });
 }
 
-Instance::Impl::~Impl()
+void OpenXRDevice::initializeReferenceSpace(PlatformXR::ReferenceSpaceType spaceType)
 {
-    m_workQueue->dispatch([this] {
-        if (m_instance != XR_NULL_HANDLE)
-            xrDestroyInstance(m_instance);
-    });
+    if ((spaceType == ReferenceSpaceType::LocalFloor || spaceType == ReferenceSpaceType::BoundedFloor) && m_stageSpace == XR_NULL_HANDLE)
+        m_stageSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_STAGE);
 }
 
-Instance& Instance::singleton()
+void OpenXRDevice::requestFrame(RequestFrameCallback&& callback)
 {
-    static LazyNeverDestroyed<Instance> s_instance;
-    static std::once_flag s_onceFlag;
-    std::call_once(s_onceFlag,
-        [&] {
-            s_instance.construct();
-        });
-    return s_instance.get();
-}
-
-Instance::Instance()
-    : m_impl(makeUniqueRef<Impl>())
-{
-}
-
-void Instance::enumerateImmersiveXRDevices(CompletionHandler<void(const DeviceList& devices)>&& callback)
-{
-    m_impl->queue().dispatch([this, callback = WTFMove(callback)]() mutable {
-        auto callbackOnExit = makeScopeExit([&]() {
+    m_queue.dispatch([this, callback = WTFMove(callback)]() mutable {
+        pollEvents();
+        if (!isSessionReady(m_sessionState)) {
             callOnMainThread([callback = WTFMove(callback)]() mutable {
+                // Device not ready or stopping. Report frameData with invalid tracking.
                 callback({ });
             });
-        });
-
-        if (m_impl->xrInstance() == XR_NULL_HANDLE) {
-            LOG(XR, "%s Unable to enumerate XR devices. No XrInstance present\n", __FUNCTION__);
             return;
         }
 
-        auto systemGetInfo = createStructure<XrSystemGetInfo, XR_TYPE_SYSTEM_GET_INFO>();
-        systemGetInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
+        auto frameState = createStructure<XrFrameState, XR_TYPE_FRAME_STATE>();
+        auto frameWaitInfo = createStructure<XrFrameWaitInfo, XR_TYPE_FRAME_WAIT_INFO>();
+        auto result = xrWaitFrame(m_session, &frameWaitInfo, &frameState);
+        RETURN_IF_FAILED(result, "xrWaitFrame", m_instance);
+        XrTime predictedTime = frameState.predictedDisplayTime;
 
-        XrSystemId systemId;
-        XrResult result = xrGetSystem(m_impl->xrInstance(), &systemGetInfo, &systemId);
-        RETURN_IF_FAILED(result, "xrGetSystem", m_impl->xrInstance());
+        auto frameBeginInfo = createStructure<XrFrameBeginInfo, XR_TYPE_FRAME_BEGIN_INFO>();
+        result = xrBeginFrame(m_session, &frameBeginInfo);
+        RETURN_IF_FAILED(result, "xrBeginFrame", m_instance);
 
-        callbackOnExit.release();
+        Device::FrameData frameData;
+        frameData.predictedDisplayTime = frameState.predictedDisplayTime;
 
-        callOnMainThread([this, callback = WTFMove(callback), systemId]() mutable {
-            m_immersiveXRDevices = DeviceList::from(makeUniqueRef<OpenXRDevice>(systemId, m_impl->xrInstance(), m_impl->queue(), [this, callback = WTFMove(callback)]() mutable {
-                ASSERT(isMainThread());
-                callback(m_immersiveXRDevices);
-            }));
+
+        ASSERT(m_configurationViews.contains(m_currentViewConfigurationType));
+        const auto& configurationView = m_configurationViews.get(m_currentViewConfigurationType);
+
+        uint32_t viewCount = configurationView.size();
+        Vector<XrView> views(viewCount, [] {
+            return createStructure<XrView, XR_TYPE_VIEW>();
+        }());
+
+
+        if (isSessionActive(m_sessionState)) {
+            // Query head location
+            auto location = createStructure<XrSpaceLocation, XR_TYPE_SPACE_LOCATION>();
+            xrLocateSpace(m_viewSpace, m_localSpace, frameState.predictedDisplayTime, &location);
+            frameData.isTrackingValid = location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT;
+            frameData.isPositionValid = location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT;
+            frameData.isPositionEmulated = location.locationFlags & XR_SPACE_LOCATION_POSITION_TRACKED_BIT;
+
+            if (frameData.isTrackingValid)
+                frameData.origin = XrPosefToPose(location.pose);
+            
+
+            auto viewLocateInfo = createStructure<XrViewLocateInfo, XR_TYPE_VIEW_LOCATE_INFO>();
+            viewLocateInfo.displayTime = predictedTime;
+            viewLocateInfo.space = m_localSpace;
+
+            auto viewState = createStructure<XrViewState, XR_TYPE_VIEW_STATE>();
+            uint32_t viewCountOutput;
+            result = xrLocateViews(m_session, &viewLocateInfo, &viewState, viewCount, &viewCountOutput, views.data());
+            if (!XR_FAILED(result)) {
+                for (auto& view : views)
+                    frameData.views.append(xrViewToPose(view));
+            }
+
+            // Query floor transform
+            if (m_stageSpace != XR_NULL_HANDLE) {
+                auto floorLocation = createStructure<XrSpaceLocation, XR_TYPE_SPACE_LOCATION>();
+                xrLocateSpace(m_stageSpace, m_localSpace, frameState.predictedDisplayTime, &floorLocation);
+                frameData.floorTransform = { XrPosefToPose(floorLocation.pose) };
+            }
+        }
+
+        callOnMainThread([frameData = WTFMove(frameData), callback = WTFMove(callback)]() mutable {
+            callback(WTFMove(frameData));
         });
+
+
+        Vector<const XrCompositionLayerBaseHeader*> layers;
+
+        auto frameEndInfo = createStructure<XrFrameEndInfo, XR_TYPE_FRAME_END_INFO>();
+        frameEndInfo.displayTime = predictedTime;
+        frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
+        frameEndInfo.layerCount = layers.size();
+        result = xrEndFrame(m_session, &frameEndInfo);
+        RETURN_IF_FAILED(result, "xrEndFrame", m_instance);
     });
 }
 
-OpenXRDevice::OpenXRDevice(XrSystemId id, XrInstance instance, WorkQueue& queue, CompletionHandler<void()>&& callback)
-    : m_systemId(id)
-    , m_instance(instance)
-    , m_queue(queue)
+Vector<Device::ViewData> OpenXRDevice::views(SessionMode mode) const
 {
-    ASSERT(isMainThread());
-    m_queue.dispatch([this, callback = WTFMove(callback)]() mutable {
-        auto systemProperties = createStructure<XrSystemProperties, XR_TYPE_SYSTEM_PROPERTIES>();
-        auto result = xrGetSystemProperties(m_instance, m_systemId, &systemProperties);
-        if (XR_SUCCEEDED(result))
-            m_supportsOrientationTracking = systemProperties.trackingProperties.orientationTracking == XR_TRUE;
-#if !LOG_DISABLED
-        else
-            LOG(XR, "xrGetSystemProperties(): error %s\n", resultToString(result, m_instance).utf8().data());
-        LOG(XR, "Found XRSystem %lu: \"%s\", vendor ID %d\n", systemProperties.systemId, systemProperties.systemName, systemProperties.vendorId);
-#endif
+    Vector<Device::ViewData> views;
+    auto configurationType = toXrViewConfigurationType(mode);
 
-        collectSupportedSessionModes();
-        collectConfigurationViews();
-
-        callOnMainThread(WTFMove(callback));
-    });
+    if (configurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO)
+        views.append({ .active = true, .eye = Eye::None });
+    else {
+        ASSERT(configurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO);
+        views.append({ .active = true, Eye::Left });
+        views.append({ .active = true, Eye::Right });
+    }
+    return views;
 }
 
-Device::ListOfEnabledFeatures OpenXRDevice::enumerateReferenceSpaces(XrSession& session) const
+Device::ListOfEnabledFeatures OpenXRDevice::enumerateReferenceSpaces(XrSession session) const
 {
     uint32_t referenceSpacesCount;
     auto result = xrEnumerateReferenceSpaces(session, 0, &referenceSpacesCount, nullptr);
@@ -299,28 +259,6 @@
     return enabledFeatures;
 }
 
-XrSpace OpenXRDevice::createReferenceSpace(XrReferenceSpaceType type)
-{
-    ASSERT(&RunLoop::current() == &m_queue.runLoop());
-    ASSERT(m_session != XR_NULL_HANDLE);
-    ASSERT(m_instance != XR_NULL_HANDLE);
-
-    XrPosef identityPose {
-        .orientation = { .x = 0, .y = 0, .z = 0, .w = 1.0 },
-        .position = { .x = 0, .y = 0, .z = 0 }
-    };
-
-    auto spaceCreateInfo = createStructure<XrReferenceSpaceCreateInfo, XR_TYPE_REFERENCE_SPACE_CREATE_INFO>();
-    spaceCreateInfo.referenceSpaceType = type;
-    spaceCreateInfo.poseInReferenceSpace = identityPose;
-
-    XrSpace space;
-    auto result = xrCreateReferenceSpace(m_session, &spaceCreateInfo, &space);
-    RETURN_IF_FAILED(result, "xrCreateReferenceSpace", m_instance, XR_NULL_HANDLE);
-
-    return space;
-}
-
 void OpenXRDevice::collectSupportedSessionModes()
 {
     ASSERT(&RunLoop::current() == &m_queue.runLoop());
@@ -390,115 +328,28 @@
     }
 }
 
-XrViewConfigurationType toXrViewConfigurationType(SessionMode mode)
+XrSpace OpenXRDevice::createReferenceSpace(XrReferenceSpaceType type)
 {
-    switch (mode) {
-    case SessionMode::ImmersiveVr:
-        return XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
-    case SessionMode::Inline:
-    case SessionMode::ImmersiveAr:
-        return XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO;
-    };
-    ASSERT_NOT_REACHED();
-    return XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO;
-}
-
-static bool isSessionActive(XrSessionState state)
-{
-    return state == XR_SESSION_STATE_VISIBLE || state == XR_SESSION_STATE_FOCUSED;
-}
-
-static bool isSessionReady(XrSessionState state)
-{
-    return state >= XR_SESSION_STATE_READY  && state < XR_SESSION_STATE_STOPPING;
-}
-
-WebCore::IntSize OpenXRDevice::recommendedResolution(SessionMode mode)
-{
-    auto configType = toXrViewConfigurationType(mode);
-    auto viewsIterator = m_configurationViews.find(configType);
-    if (viewsIterator != m_configurationViews.end())
-        return { static_cast<int>(viewsIterator->value[0].recommendedImageRectWidth), static_cast<int>(viewsIterator->value[0].recommendedImageRectHeight) };
-    return Device::recommendedResolution(mode);
-}
-
-void OpenXRDevice::initializeTrackingAndRendering(SessionMode mode)
-{
-    m_queue.dispatch([this, mode]() {
-        ASSERT(m_instance != XR_NULL_HANDLE);
-        ASSERT(m_session == XR_NULL_HANDLE);
-
-        m_currentViewConfigurationType = toXrViewConfigurationType(mode);
-        ASSERT(m_configurationViews.contains(m_currentViewConfigurationType));
-
-        // Create the session.
-        auto sessionCreateInfo = createStructure<XrSessionCreateInfo, XR_TYPE_SESSION_CREATE_INFO>();
-        sessionCreateInfo.systemId = m_systemId;
-        auto result = xrCreateSession(m_instance, &sessionCreateInfo, &m_session);
-        RETURN_IF_FAILED(result, "xrEnumerateInstanceExtensionProperties", m_instance);
-
-        m_localSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_LOCAL);
-        m_viewSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_VIEW);
-    });
-}
-
-void OpenXRDevice::resetSession()
-{
     ASSERT(&RunLoop::current() == &m_queue.runLoop());
-    if (m_session != XR_NULL_HANDLE) {
-        xrDestroySession(m_session);
-        m_session = XR_NULL_HANDLE;
-    }
-    m_sessionState = XR_SESSION_STATE_UNKNOWN;
-}
+    ASSERT(m_session != XR_NULL_HANDLE);
+    ASSERT(m_instance != XR_NULL_HANDLE);
 
-void OpenXRDevice::handleSessionStateChange()
-{
-    ASSERT(&RunLoop::current() == &m_queue.runLoop());
-    if (m_sessionState == XR_SESSION_STATE_STOPPING) {
-        // The application should exit the render loop and call xrEndSession
-        endSession();
-    } else if (m_sessionState == XR_SESSION_STATE_READY) {
-        // The application is ready to call xrBeginSession.
-        beginSession();
-    }
-}
+    XrPosef identityPose {
+        .orientation = { .x = 0, .y = 0, .z = 0, .w = 1.0 },
+        .position = { .x = 0, .y = 0, .z = 0 }
+    };
 
-void OpenXRDevice::shutDownTrackingAndRendering()
-{
-    m_queue.dispatch([this]() {
-        if (m_session == XR_NULL_HANDLE)
-            return;
+    auto spaceCreateInfo = createStructure<XrReferenceSpaceCreateInfo, XR_TYPE_REFERENCE_SPACE_CREATE_INFO>();
+    spaceCreateInfo.referenceSpaceType = type;
+    spaceCreateInfo.poseInReferenceSpace = identityPose;
 
-        // xrRequestExitSession() will transition the session to STOPPED state.
-        // If the session was not running we have to reset the session ourselves.
-        if (XR_FAILED(xrRequestExitSession(m_session))) {
-            resetSession();
-            return;
-        }
+    XrSpace space;
+    auto result = xrCreateReferenceSpace(m_session, &spaceCreateInfo, &space);
+    RETURN_IF_FAILED(result, "xrCreateReferenceSpace", m_instance, XR_NULL_HANDLE);
 
-        // OpenXR needs to wait for the XR_SESSION_STATE_STOPPING state to properly end the session.
-        waitUntilStopping();
-    });
+    return space;
 }
 
-void OpenXRDevice::initializeReferenceSpace(PlatformXR::ReferenceSpaceType spaceType)
-{
-    if ((spaceType == ReferenceSpaceType::LocalFloor || spaceType == ReferenceSpaceType::BoundedFloor) && m_stageSpace == XR_NULL_HANDLE)
-        m_stageSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_STAGE);
-}
-
-void OpenXRDevice::waitUntilStopping()
-{
-    ASSERT(&RunLoop::current() == &m_queue.runLoop());
-    pollEvents();
-    if (m_sessionState >= XR_SESSION_STATE_STOPPING)
-        return;
-    m_queue.dispatch([this]() {
-        waitUntilStopping();
-    });
-}
-
 void OpenXRDevice::pollEvents()
 {
     ASSERT(!isMainThread());
@@ -557,117 +408,40 @@
     });
 }
 
-static Device::FrameData::Pose XrPosefToPose(XrPosef pose)
+void OpenXRDevice::resetSession()
 {
-    Device::FrameData::Pose result;
-    result.orientation = { pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w };
-    result.position = { pose.position.x, pose.position.y, pose.position.z };
-    return result;
+    ASSERT(&RunLoop::current() == &m_queue.runLoop());
+    if (m_session != XR_NULL_HANDLE) {
+        xrDestroySession(m_session);
+        m_session = XR_NULL_HANDLE;
+    }
+    m_sessionState = XR_SESSION_STATE_UNKNOWN;
 }
 
-static Device::FrameData::View xrViewToPose(XrView view)
+void OpenXRDevice::handleSessionStateChange()
 {
-    Device::FrameData::View pose;
-    pose.projection = Device::FrameData::Fov { view.fov.angleUp, view.fov.angleDown, view.fov.angleLeft, view.fov.angleRight };
-    pose.offset = XrPosefToPose(view.pose);
-    return pose;
+    ASSERT(&RunLoop::current() == &m_queue.runLoop());
+    if (m_sessionState == XR_SESSION_STATE_STOPPING) {
+        // The application should exit the render loop and call xrEndSession
+        endSession();
+    } else if (m_sessionState == XR_SESSION_STATE_READY) {
+        // The application is ready to call xrBeginSession.
+        beginSession();
+    }
 }
 
-void OpenXRDevice::requestFrame(RequestFrameCallback&& callback)
+
+void OpenXRDevice::waitUntilStopping()
 {
-    m_queue.dispatch([this, callback = WTFMove(callback)]() mutable {
-        pollEvents();
-        if (!isSessionReady(m_sessionState)) {
-            callOnMainThread([callback = WTFMove(callback)]() mutable {
-                // Device not ready or stopping. Report frameData with invalid tracking.
-                callback({ });
-            });
-            return;
-        }
-
-        auto frameState = createStructure<XrFrameState, XR_TYPE_FRAME_STATE>();
-        auto frameWaitInfo = createStructure<XrFrameWaitInfo, XR_TYPE_FRAME_WAIT_INFO>();
-        auto result = xrWaitFrame(m_session, &frameWaitInfo, &frameState);
-        RETURN_IF_FAILED(result, "xrWaitFrame", m_instance);
-        XrTime predictedTime = frameState.predictedDisplayTime;
-
-        auto frameBeginInfo = createStructure<XrFrameBeginInfo, XR_TYPE_FRAME_BEGIN_INFO>();
-        result = xrBeginFrame(m_session, &frameBeginInfo);
-        RETURN_IF_FAILED(result, "xrBeginFrame", m_instance);
-
-        Device::FrameData frameData;
-        frameData.predictedDisplayTime = frameState.predictedDisplayTime;
-
-        if (isSessionActive(m_sessionState)) {
-            // Query head location
-            auto location = createStructure<XrSpaceLocation, XR_TYPE_SPACE_LOCATION>();
-            xrLocateSpace(m_viewSpace, m_localSpace, frameState.predictedDisplayTime, &location);
-            frameData.isTrackingValid = location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT;
-            frameData.isPositionValid = location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT;
-            frameData.isPositionEmulated = location.locationFlags & XR_SPACE_LOCATION_POSITION_TRACKED_BIT;
-
-            if (frameData.isTrackingValid)
-                frameData.origin = XrPosefToPose(location.pose);
-            
-            ASSERT(m_configurationViews.contains(m_currentViewConfigurationType));
-            const auto& configurationView = m_configurationViews.get(m_currentViewConfigurationType);
-
-            auto viewLocateInfo = createStructure<XrViewLocateInfo, XR_TYPE_VIEW_LOCATE_INFO>();
-            viewLocateInfo.displayTime = predictedTime;
-            viewLocateInfo.space = m_localSpace;
-
-            uint32_t viewCount = configurationView.size();
-            Vector<XrView> views(viewCount, [] {
-                XrView object;
-                std::memset(&object, 0, sizeof(XrView));
-                object.type = XR_TYPE_VIEW;
-                return object;
-            }());
-
-            auto viewState = createStructure<XrViewState, XR_TYPE_VIEW_STATE>();
-            uint32_t viewCountOutput;
-            result = xrLocateViews(m_session, &viewLocateInfo, &viewState, viewCount, &viewCountOutput, views.data());
-            if (!XR_FAILED(result)) {
-                for (auto& view : views)
-                    frameData.views.append(xrViewToPose(view));
-            }
-
-            // Query floor transform
-            if (m_stageSpace != XR_NULL_HANDLE) {
-                auto floorLocation = createStructure<XrSpaceLocation, XR_TYPE_SPACE_LOCATION>();
-                xrLocateSpace(m_stageSpace, m_localSpace, frameState.predictedDisplayTime, &floorLocation);
-                frameData.floorTransform = { XrPosefToPose(floorLocation.pose) };
-            }
-        }
-
-        callOnMainThread([frameData = WTFMove(frameData), callback = WTFMove(callback)]() mutable {
-            callback(WTFMove(frameData));
-        });
-
-        auto frameEndInfo = createStructure<XrFrameEndInfo, XR_TYPE_FRAME_END_INFO>();
-        frameEndInfo.displayTime = predictedTime;
-        frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
-        frameEndInfo.layerCount = 0;
-        result = xrEndFrame(m_session, &frameEndInfo);
-        RETURN_IF_FAILED(result, "xrEndFrame", m_instance);
+    ASSERT(&RunLoop::current() == &m_queue.runLoop());
+    pollEvents();
+    if (m_sessionState >= XR_SESSION_STATE_STOPPING)
+        return;
+    m_queue.dispatch([this]() {
+        waitUntilStopping();
     });
 }
 
-Vector<Device::ViewData> OpenXRDevice::views(SessionMode mode) const
-{
-    Vector<Device::ViewData> views;
-    auto configurationType = toXrViewConfigurationType(mode);
-
-    if (configurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO)
-        views.append({ .active = true, .eye = Eye::None });
-    else {
-        ASSERT(configurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO);
-        views.append({ .active = true, Eye::Left });
-        views.append({ .active = true, Eye::Right });
-    }
-    return views;
-}
-
 } // namespace PlatformXR
 
 #endif // ENABLE(WEBXR) && USE(OPENXR)

Modified: trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.h (273381 => 273382)


--- trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.h	2021-02-24 13:09:49 UTC (rev 273381)
+++ trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.h	2021-02-24 13:13:21 UTC (rev 273382)
@@ -20,15 +20,17 @@
 #pragma once
 
 #if ENABLE(WEBXR) && USE(OPENXR)
+
+#include "OpenXRUtils.h"
 #include "PlatformXR.h"
 
 #include <wtf/HashMap.h>
-
-#include <openxr/openxr.h>
 #include <wtf/WorkQueue.h>
 
 namespace PlatformXR {
 
+class OpenXRExtensions;
+
 // https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#system
 // A system represents a collection of related devices in the runtime, often made up of several individual
 // hardware components working together to enable XR experiences.
@@ -43,46 +45,41 @@
 // the XRSystem is basically the entry point for the WebXR API available via the Navigator object.
 class OpenXRDevice final : public Device {
 public:
-    OpenXRDevice(XrSystemId, XrInstance, WorkQueue&, CompletionHandler<void()>&&);
-    XrSystemId xrSystemId() const { return m_systemId; }
+    OpenXRDevice(XrInstance, XrSystemId, WorkQueue&, const OpenXRExtensions&, CompletionHandler<void()>&&);
 
 private:
-    void collectSupportedSessionModes();
-    void collectConfigurationViews();
-
-    ListOfEnabledFeatures enumerateReferenceSpaces(XrSession&) const;
-    XrSpace createReferenceSpace(XrReferenceSpaceType);
-
+    // PlatformXR::Device
     WebCore::IntSize recommendedResolution(SessionMode) final;
-
     void initializeTrackingAndRendering(SessionMode) final;
     void shutDownTrackingAndRendering() final;
     void initializeReferenceSpace(PlatformXR::ReferenceSpaceType) final;
     bool supportsSessionShutdownNotification() const final { return true; }
-    void waitUntilStopping();
+    void requestFrame(RequestFrameCallback&&) final;
+    Vector<ViewData> views(SessionMode) const final;
 
+    // Custom methods
+    ListOfEnabledFeatures enumerateReferenceSpaces(XrSession) const;
+    void collectSupportedSessionModes();
+    void collectConfigurationViews();
+    XrSpace createReferenceSpace(XrReferenceSpaceType);
     void pollEvents();
     XrResult beginSession();
     void endSession();
     void resetSession();
     void handleSessionStateChange();
+    void waitUntilStopping();
 
-    void requestFrame(RequestFrameCallback&&) final;
+    XrInstance m_instance;
+    XrSystemId m_systemId;
+    WorkQueue& m_queue;
+    const OpenXRExtensions& m_extensions;
+    XrSession m_session { XR_NULL_HANDLE };
+    XrSessionState m_sessionState { XR_SESSION_STATE_UNKNOWN };
 
-    Vector<ViewData> views(SessionMode) const final;
-
     using ViewConfigurationPropertiesMap = HashMap<XrViewConfigurationType, XrViewConfigurationProperties, IntHash<XrViewConfigurationType>, WTF::StrongEnumHashTraits<XrViewConfigurationType>>;
     ViewConfigurationPropertiesMap m_viewConfigurationProperties;
     using ViewConfigurationViewsMap = HashMap<XrViewConfigurationType, Vector<XrViewConfigurationView>, IntHash<XrViewConfigurationType>, WTF::StrongEnumHashTraits<XrViewConfigurationType>>;
     ViewConfigurationViewsMap m_configurationViews;
-
-    XrSystemId m_systemId;
-    XrInstance m_instance;
-    XrSession m_session { XR_NULL_HANDLE };
-    XrSessionState m_sessionState { XR_SESSION_STATE_UNKNOWN };
-
-    WorkQueue& m_queue;
-
     XrViewConfigurationType m_currentViewConfigurationType;
     XrSpace m_localSpace { XR_NULL_HANDLE };
     XrSpace m_viewSpace { XR_NULL_HANDLE };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to