Changeset 273382 in webkit


Ignore:
Timestamp:
Feb 24, 2021 5:13:21 AM (3 years ago)
Author:
commit-queue@webkit.org
Message:

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

Patch by Imanol Fernandez <imanol> 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:
Location:
trunk/Source/WebCore
Files:
4 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r273381 r273382  
     12021-02-24  Imanol Fernandez  <ifernandez@igalia.com>
     2
     3        Refactor OpenXR platform code into different classes and files.
     4        https://bugs.webkit.org/show_bug.cgi?id=222263
     5
     6        Reviewed by Sergio Villar Senin.
     7
     8        OpenXR platform code is going to grow with graphics, extensions, swapchains, controllers and more.
     9        This patch splits the code into different files to make it more readable and maintanable.
     10
     11        * Sources.txt:
     12        * platform/xr/openxr/OpenXRExtensions.cpp: Added.
     13        (PlatformXR::OpenXRExtensions::create):
     14        (PlatformXR::OpenXRExtensions::OpenXRExtensions):
     15        (PlatformXR::OpenXRExtensions::isExtensionSupported const):
     16        * platform/xr/openxr/OpenXRExtensions.h: Added.
     17        * platform/xr/openxr/OpenXRInstance.cpp: Added.
     18        (PlatformXR::Instance::Impl::xrInstance const):
     19        (PlatformXR::Instance::Impl::queue const):
     20        (PlatformXR::Instance::Impl::extensions):
     21        (PlatformXR::Instance::Impl::Impl):
     22        (PlatformXR::Instance::Impl::~Impl):
     23        (PlatformXR::Instance::singleton):
     24        (PlatformXR::Instance::Instance):
     25        (PlatformXR::Instance::enumerateImmersiveXRDevices):
     26        * platform/xr/openxr/OpenXRUtils.h: Added.
     27        (PlatformXR::createStructure):
     28        (PlatformXR::resultToString):
     29        (PlatformXR::XrPosefToPose):
     30        (PlatformXR::xrViewToPose):
     31        (PlatformXR::toXrViewConfigurationType):
     32        * platform/xr/openxr/PlatformXROpenXR.cpp:
     33        (PlatformXR::isSessionActive):
     34        (PlatformXR::isSessionReady):
     35        (PlatformXR::OpenXRDevice::OpenXRDevice):
     36        (PlatformXR::OpenXRDevice::recommendedResolution):
     37        (PlatformXR::OpenXRDevice::initializeTrackingAndRendering):
     38        (PlatformXR::OpenXRDevice::shutDownTrackingAndRendering):
     39        (PlatformXR::OpenXRDevice::initializeReferenceSpace):
     40        (PlatformXR::OpenXRDevice::requestFrame):
     41        (PlatformXR::OpenXRDevice::views const):
     42        (PlatformXR::OpenXRDevice::enumerateReferenceSpaces const):
     43        (PlatformXR::OpenXRDevice::createReferenceSpace):
     44        (PlatformXR::OpenXRDevice::resetSession):
     45        (PlatformXR::OpenXRDevice::handleSessionStateChange):
     46        (PlatformXR::OpenXRDevice::waitUntilStopping):
     47        * platform/xr/openxr/PlatformXROpenXR.h:
     48
    1492021-02-24  Imanol Fernandez  <ifernandez@igalia.com>
    250
  • trunk/Source/WebCore/Sources.txt

    r273310 r273382  
    21732173platform/text/TextEncodingDetectorICU.cpp
    21742174platform/text/TextEncodingRegistry.cpp
     2175platform/xr/openxr/OpenXRInstance.cpp @no-unify
     2176platform/xr/openxr/OpenXRExtensions.cpp @no-unify
    21752177platform/xr/openxr/PlatformXROpenXR.cpp @no-unify
    21762178plugins/DOMMimeType.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r273310 r273382  
    394394                115CFA97208B952B001E6991 /* LayoutBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 115CFA95208B952B001E6991 /* LayoutBox.h */; settings = {ATTRIBUTES = (Private, ); }; };
    395395                1163F82424E5D5AE000AB960 /* RenderTreeMutationDisallowedScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 1163F82124E5D59B000AB960 /* RenderTreeMutationDisallowedScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
     396                118B068B25E41E530070BE4B /* OpenXRExtensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 118B068625E41E510070BE4B /* OpenXRExtensions.cpp */; };
     397                118B068C25E41E530070BE4B /* OpenXRExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 118B068825E41E520070BE4B /* OpenXRExtensions.h */; };
     398                118B068D25E41E530070BE4B /* OpenXRInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 118B068925E41E520070BE4B /* OpenXRInstance.cpp */; };
     399                118B068E25E41E530070BE4B /* OpenXRUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 118B068A25E41E530070BE4B /* OpenXRUtils.h */; };
    396400                119340791FE8B92300935F1E /* RenderTreeBuilderTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340771FE8B92300935F1E /* RenderTreeBuilderTable.h */; };
    397401                1193408A1FEB355D00935F1E /* RenderTreeBuilderRuby.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340881FEB355D00935F1E /* RenderTreeBuilderRuby.h */; };
     
    63206324                1163F82124E5D59B000AB960 /* RenderTreeMutationDisallowedScope.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeMutationDisallowedScope.h; sourceTree = "<group>"; };
    63216325                1163F82324E5D59B000AB960 /* RenderTreeMutationDisallowedScope.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeMutationDisallowedScope.cpp; sourceTree = "<group>"; };
     6326                118B068625E41E510070BE4B /* OpenXRExtensions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenXRExtensions.cpp; sourceTree = "<group>"; };
     6327                118B068825E41E520070BE4B /* OpenXRExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenXRExtensions.h; sourceTree = "<group>"; };
     6328                118B068925E41E520070BE4B /* OpenXRInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpenXRInstance.cpp; sourceTree = "<group>"; };
     6329                118B068A25E41E530070BE4B /* OpenXRUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenXRUtils.h; sourceTree = "<group>"; };
    63226330                119340761FE8B92300935F1E /* RenderTreeBuilderTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderTable.cpp; sourceTree = "<group>"; };
    63236331                119340771FE8B92300935F1E /* RenderTreeBuilderTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderTable.h; sourceTree = "<group>"; };
     
    2892528933                        isa = PBXGroup;
    2892628934                        children = (
     28935                                118B068625E41E510070BE4B /* OpenXRExtensions.cpp */,
     28936                                118B068825E41E520070BE4B /* OpenXRExtensions.h */,
     28937                                118B068925E41E520070BE4B /* OpenXRInstance.cpp */,
     28938                                118B068A25E41E530070BE4B /* OpenXRUtils.h */,
    2892728939                                E1C1A39B2480080600E0AF66 /* PlatformXROpenXR.cpp */,
    2892828940                                E1C1A39C2480080700E0AF66 /* PlatformXROpenXR.h */,
     
    3406334075                                B2D3DA650D006CD600EF6F27 /* OpenTypeMathData.h in Headers */,
    3406434076                                B2D3EA650D006CD600EF6F28 /* OpenTypeTypes.h in Headers */,
     34077                                118B068C25E41E530070BE4B /* OpenXRExtensions.h in Headers */,
     34078                                118B068E25E41E530070BE4B /* OpenXRUtils.h in Headers */,
    3406534079                                71207340216DFB0000C78329 /* OptionalEffectTiming.h in Headers */,
    3406634080                                CDE7FC45181904B1002BBB77 /* OrderIterator.h in Headers */,
     
    3623036244                                1A569D1A0D7E2B82007C3983 /* objc_utility.mm in Sources */,
    3623136245                                E16982601134636A00894115 /* ObjCRuntimeObject.mm in Sources */,
     36246                                118B068B25E41E530070BE4B /* OpenXRExtensions.cpp in Sources */,
     36247                                118B068D25E41E530070BE4B /* OpenXRInstance.cpp in Sources */,
    3623236248                                CEA284662141E84900E407E8 /* PlatformEventFactoryIOS.mm in Sources */,
    3623336249                                AA12DF491743DF83004DAFDF /* PlatformSpeechSynthesizerIOS.mm in Sources */,
  • trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp

    r273132 r273382  
    2323#if ENABLE(WEBXR) && USE(OPENXR)
    2424
    25 #include "Logging.h"
    26 #include <openxr/openxr_platform.h>
     25#include "OpenXRExtensions.h"
     26
    2727#include <wtf/NeverDestroyed.h>
    2828#include <wtf/Optional.h>
    29 #include <wtf/Scope.h>
    30 #include <wtf/text/StringConcatenateNumbers.h>
    31 #include <wtf/text/WTFString.h>
    3229
    3330using namespace WebCore;
     
    3532namespace PlatformXR {
    3633
    37 template<typename T, XrStructureType StructureType>
    38 T createStructure()
    39 {
    40     T object;
    41     std::memset(&object, 0, sizeof(T));
    42     object.type = StructureType;
    43     object.next = nullptr;
    44     return object;
    45 }
    46 
    47 String resultToString(XrResult value, XrInstance instance)
    48 {
    49     char buffer[XR_MAX_RESULT_STRING_SIZE];
    50     XrResult result = xrResultToString(instance, value, buffer);
    51     if (result == XR_SUCCESS)
    52         return String(buffer);
    53     return makeString("<unknown ", int(value), ">");
    54 }
    55 
    56 #define RETURN_IF_FAILED(result, call, instance, ...)                                           \
    57     if (XR_FAILED(result)) {                                                                    \
    58         LOG(XR, "%s %s: %s\n", __func__, call, resultToString(result, instance).utf8().data()); \
    59         return __VA_ARGS__;                                                                     \
    60     }
    61 
    62 struct Instance::Impl {
    63     WTF_MAKE_STRUCT_FAST_ALLOCATED;
    64 
    65     Impl();
    66     ~Impl();
    67 
    68     XrInstance xrInstance() const { return m_instance; }
    69     WorkQueue& queue() const { return m_workQueue; }
    70 
    71 private:
    72     void enumerateApiLayerProperties() const;
    73     bool checkInstanceExtensionProperties() const;
    74 
    75     XrInstance m_instance { XR_NULL_HANDLE };
    76     Ref<WorkQueue> m_workQueue;
    77 };
    78 
    79 void Instance::Impl::enumerateApiLayerProperties() const
    80 {
    81     ASSERT(&RunLoop::current() == &m_workQueue->runLoop());
    82     uint32_t propertyCountOutput { 0 };
    83     XrResult result = xrEnumerateApiLayerProperties(0, &propertyCountOutput, nullptr);
    84     RETURN_IF_FAILED(result, "xrEnumerateApiLayerProperties()", m_instance);
    85 
    86     if (!propertyCountOutput) {
    87         LOG(XR, "xrEnumerateApiLayerProperties(): no properties\n");
    88         return;
    89     }
    90 
    91     Vector<XrApiLayerProperties> properties(propertyCountOutput,
    92         [] {
    93             XrApiLayerProperties object;
    94             std::memset(&object, 0, sizeof(XrApiLayerProperties));
    95             object.type = XR_TYPE_API_LAYER_PROPERTIES;
    96             return object;
    97         }());
    98     result = xrEnumerateApiLayerProperties(propertyCountOutput, &propertyCountOutput, properties.data());
    99 
    100     RETURN_IF_FAILED(result, "xrEnumerateApiLayerProperties()", m_instance);
    101     LOG(XR, "xrEnumerateApiLayerProperties(): %zu properties\n", properties.size());
    102 }
    103 
    104 static bool isExtensionSupported(const char* extensionName, Vector<XrExtensionProperties>& instanceExtensionProperties)
    105 {
    106     auto position = instanceExtensionProperties.findMatching([extensionName](auto& property) {
    107         return !strcmp(property.extensionName, extensionName);
    108     });
    109     return position != notFound;
    110 }
    111 
    112 bool Instance::Impl::checkInstanceExtensionProperties() const
    113 {
    114     ASSERT(&RunLoop::current() == &m_workQueue->runLoop());
    115     uint32_t propertyCountOutput { 0 };
    116     XrResult result = xrEnumerateInstanceExtensionProperties(nullptr, 0, &propertyCountOutput, nullptr);
    117     RETURN_IF_FAILED(result, "xrEnumerateInstanceExtensionProperties", m_instance, false);
    118 
    119     if (!propertyCountOutput) {
    120         LOG(XR, "xrEnumerateInstanceExtensionProperties(): no properties\n");
    121         return false;
    122     }
    123 
    124     Vector<XrExtensionProperties> properties(propertyCountOutput,
    125         [] {
    126             XrExtensionProperties object;
    127             std::memset(&object, 0, sizeof(XrExtensionProperties));
    128             object.type = XR_TYPE_EXTENSION_PROPERTIES;
    129             return object;
    130         }());
    131 
    132     uint32_t propertyCountWritten { 0 };
    133     result = xrEnumerateInstanceExtensionProperties(nullptr, propertyCountOutput, &propertyCountWritten, properties.data());
    134     RETURN_IF_FAILED(result, "xrEnumerateInstanceExtensionProperties", m_instance, false);
    135 #if !LOG_DISABLED
    136     LOG(XR, "xrEnumerateInstanceExtensionProperties(): %zu extension properties\n", properties.size());
    137     for (auto& property : properties)
    138         LOG(XR, "  extension '%s', version %u\n", property.extensionName, property.extensionVersion);
    139 #endif
    140     if (!isExtensionSupported(XR_MND_HEADLESS_EXTENSION_NAME, properties)) {
    141         LOG(XR, "Required extension %s not supported", XR_MND_HEADLESS_EXTENSION_NAME);
    142         return false;
    143     }
    144 
    145     return true;
    146 }
    147 
    148 Instance::Impl::Impl()
    149     : m_workQueue(WorkQueue::create("OpenXR queue"))
    150 {
    151     m_workQueue->dispatch([this]() {
    152         LOG(XR, "OpenXR: initializing\n");
    153 
    154         enumerateApiLayerProperties();
    155 
    156         if (!checkInstanceExtensionProperties())
    157             return;
    158 
    159         static const char* s_applicationName = "WebXR (WebKit)";
    160         static const uint32_t s_applicationVersion = 1;
    161 
    162         const char* const enabledExtensions[] = {
    163             XR_MND_HEADLESS_EXTENSION_NAME,
    164         };
    165 
    166         auto createInfo = createStructure<XrInstanceCreateInfo, XR_TYPE_INSTANCE_CREATE_INFO>();
    167         createInfo.createFlags = 0;
    168         std::memcpy(createInfo.applicationInfo.applicationName, s_applicationName, XR_MAX_APPLICATION_NAME_SIZE);
    169         createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
    170         createInfo.applicationInfo.applicationVersion = s_applicationVersion;
    171         createInfo.enabledApiLayerCount = 0;
    172         createInfo.enabledExtensionCount = WTF_ARRAY_LENGTH(enabledExtensions);
    173         createInfo.enabledExtensionNames = enabledExtensions;
    174 
    175         XrInstance instance;
    176         XrResult result = xrCreateInstance(&createInfo, &instance);
    177         RETURN_IF_FAILED(result, "xrCreateInstance()", m_instance);
    178         m_instance = instance;
    179         LOG(XR, "xrCreateInstance(): using instance %p\n", m_instance);
    180     });
    181 }
    182 
    183 Instance::Impl::~Impl()
    184 {
    185     m_workQueue->dispatch([this] {
    186         if (m_instance != XR_NULL_HANDLE)
    187             xrDestroyInstance(m_instance);
    188     });
    189 }
    190 
    191 Instance& Instance::singleton()
    192 {
    193     static LazyNeverDestroyed<Instance> s_instance;
    194     static std::once_flag s_onceFlag;
    195     std::call_once(s_onceFlag,
    196         [&] {
    197             s_instance.construct();
    198         });
    199     return s_instance.get();
    200 }
    201 
    202 Instance::Instance()
    203     : m_impl(makeUniqueRef<Impl>())
    204 {
    205 }
    206 
    207 void Instance::enumerateImmersiveXRDevices(CompletionHandler<void(const DeviceList& devices)>&& callback)
    208 {
    209     m_impl->queue().dispatch([this, callback = WTFMove(callback)]() mutable {
    210         auto callbackOnExit = makeScopeExit([&]() {
    211             callOnMainThread([callback = WTFMove(callback)]() mutable {
    212                 callback({ });
    213             });
    214         });
    215 
    216         if (m_impl->xrInstance() == XR_NULL_HANDLE) {
    217             LOG(XR, "%s Unable to enumerate XR devices. No XrInstance present\n", __FUNCTION__);
    218             return;
    219         }
    220 
    221         auto systemGetInfo = createStructure<XrSystemGetInfo, XR_TYPE_SYSTEM_GET_INFO>();
    222         systemGetInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
    223 
    224         XrSystemId systemId;
    225         XrResult result = xrGetSystem(m_impl->xrInstance(), &systemGetInfo, &systemId);
    226         RETURN_IF_FAILED(result, "xrGetSystem", m_impl->xrInstance());
    227 
    228         callbackOnExit.release();
    229 
    230         callOnMainThread([this, callback = WTFMove(callback), systemId]() mutable {
    231             m_immersiveXRDevices = DeviceList::from(makeUniqueRef<OpenXRDevice>(systemId, m_impl->xrInstance(), m_impl->queue(), [this, callback = WTFMove(callback)]() mutable {
    232                 ASSERT(isMainThread());
    233                 callback(m_immersiveXRDevices);
    234             }));
    235         });
    236     });
    237 }
    238 
    239 OpenXRDevice::OpenXRDevice(XrSystemId id, XrInstance instance, WorkQueue& queue, CompletionHandler<void()>&& callback)
    240     : m_systemId(id)
    241     , m_instance(instance)
     34
     35static bool isSessionActive(XrSessionState state)
     36{
     37    return state == XR_SESSION_STATE_VISIBLE || state == XR_SESSION_STATE_FOCUSED;
     38}
     39
     40static bool isSessionReady(XrSessionState state)
     41{
     42    return state >= XR_SESSION_STATE_READY  && state < XR_SESSION_STATE_STOPPING;
     43}
     44
     45OpenXRDevice::OpenXRDevice(XrInstance instance, XrSystemId system, WorkQueue& queue, const OpenXRExtensions& extensions, CompletionHandler<void()>&& callback)
     46    : m_instance(instance)
     47    , m_systemId(system)
    24248    , m_queue(queue)
     49    , m_extensions(extensions)
    24350{
    24451    ASSERT(isMainThread());
     
    26168}
    26269
    263 Device::ListOfEnabledFeatures OpenXRDevice::enumerateReferenceSpaces(XrSession& session) const
     70WebCore::IntSize OpenXRDevice::recommendedResolution(SessionMode mode)
     71{
     72    auto configType = toXrViewConfigurationType(mode);
     73    auto viewsIterator = m_configurationViews.find(configType);
     74    if (viewsIterator != m_configurationViews.end())
     75        return { static_cast<int>(viewsIterator->value[0].recommendedImageRectWidth), static_cast<int>(viewsIterator->value[0].recommendedImageRectHeight) };
     76    return Device::recommendedResolution(mode);
     77}
     78
     79void OpenXRDevice::initializeTrackingAndRendering(SessionMode mode)
     80{
     81    m_queue.dispatch([this, mode]() {
     82        ASSERT(m_instance != XR_NULL_HANDLE);
     83        ASSERT(m_session == XR_NULL_HANDLE);
     84
     85        m_currentViewConfigurationType = toXrViewConfigurationType(mode);
     86        ASSERT(m_configurationViews.contains(m_currentViewConfigurationType));
     87
     88        // Create the session.
     89        auto sessionCreateInfo = createStructure<XrSessionCreateInfo, XR_TYPE_SESSION_CREATE_INFO>();
     90        sessionCreateInfo.systemId = m_systemId;
     91
     92        auto result = xrCreateSession(m_instance, &sessionCreateInfo, &m_session);
     93        RETURN_IF_FAILED(result, "xrEnumerateInstanceExtensionProperties", m_instance);
     94
     95        // Create the default reference spaces
     96        m_localSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_LOCAL);
     97        m_viewSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_VIEW);
     98    });
     99}
     100
     101void OpenXRDevice::shutDownTrackingAndRendering()
     102{
     103    m_queue.dispatch([this]() {
     104        if (m_session == XR_NULL_HANDLE)
     105            return;
     106
     107        // xrRequestExitSession() will transition the session to STOPPED state.
     108        // If the session was not running we have to reset the session ourselves.
     109        if (XR_FAILED(xrRequestExitSession(m_session))) {
     110            resetSession();
     111            return;
     112        }
     113
     114        // OpenXR needs to wait for the XR_SESSION_STATE_STOPPING state to properly end the session.
     115        waitUntilStopping();
     116    });
     117}
     118
     119void OpenXRDevice::initializeReferenceSpace(PlatformXR::ReferenceSpaceType spaceType)
     120{
     121    if ((spaceType == ReferenceSpaceType::LocalFloor || spaceType == ReferenceSpaceType::BoundedFloor) && m_stageSpace == XR_NULL_HANDLE)
     122        m_stageSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_STAGE);
     123}
     124
     125void OpenXRDevice::requestFrame(RequestFrameCallback&& callback)
     126{
     127    m_queue.dispatch([this, callback = WTFMove(callback)]() mutable {
     128        pollEvents();
     129        if (!isSessionReady(m_sessionState)) {
     130            callOnMainThread([callback = WTFMove(callback)]() mutable {
     131                // Device not ready or stopping. Report frameData with invalid tracking.
     132                callback({ });
     133            });
     134            return;
     135        }
     136
     137        auto frameState = createStructure<XrFrameState, XR_TYPE_FRAME_STATE>();
     138        auto frameWaitInfo = createStructure<XrFrameWaitInfo, XR_TYPE_FRAME_WAIT_INFO>();
     139        auto result = xrWaitFrame(m_session, &frameWaitInfo, &frameState);
     140        RETURN_IF_FAILED(result, "xrWaitFrame", m_instance);
     141        XrTime predictedTime = frameState.predictedDisplayTime;
     142
     143        auto frameBeginInfo = createStructure<XrFrameBeginInfo, XR_TYPE_FRAME_BEGIN_INFO>();
     144        result = xrBeginFrame(m_session, &frameBeginInfo);
     145        RETURN_IF_FAILED(result, "xrBeginFrame", m_instance);
     146
     147        Device::FrameData frameData;
     148        frameData.predictedDisplayTime = frameState.predictedDisplayTime;
     149
     150
     151        ASSERT(m_configurationViews.contains(m_currentViewConfigurationType));
     152        const auto& configurationView = m_configurationViews.get(m_currentViewConfigurationType);
     153
     154        uint32_t viewCount = configurationView.size();
     155        Vector<XrView> views(viewCount, [] {
     156            return createStructure<XrView, XR_TYPE_VIEW>();
     157        }());
     158
     159
     160        if (isSessionActive(m_sessionState)) {
     161            // Query head location
     162            auto location = createStructure<XrSpaceLocation, XR_TYPE_SPACE_LOCATION>();
     163            xrLocateSpace(m_viewSpace, m_localSpace, frameState.predictedDisplayTime, &location);
     164            frameData.isTrackingValid = location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT;
     165            frameData.isPositionValid = location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT;
     166            frameData.isPositionEmulated = location.locationFlags & XR_SPACE_LOCATION_POSITION_TRACKED_BIT;
     167
     168            if (frameData.isTrackingValid)
     169                frameData.origin = XrPosefToPose(location.pose);
     170           
     171
     172            auto viewLocateInfo = createStructure<XrViewLocateInfo, XR_TYPE_VIEW_LOCATE_INFO>();
     173            viewLocateInfo.displayTime = predictedTime;
     174            viewLocateInfo.space = m_localSpace;
     175
     176            auto viewState = createStructure<XrViewState, XR_TYPE_VIEW_STATE>();
     177            uint32_t viewCountOutput;
     178            result = xrLocateViews(m_session, &viewLocateInfo, &viewState, viewCount, &viewCountOutput, views.data());
     179            if (!XR_FAILED(result)) {
     180                for (auto& view : views)
     181                    frameData.views.append(xrViewToPose(view));
     182            }
     183
     184            // Query floor transform
     185            if (m_stageSpace != XR_NULL_HANDLE) {
     186                auto floorLocation = createStructure<XrSpaceLocation, XR_TYPE_SPACE_LOCATION>();
     187                xrLocateSpace(m_stageSpace, m_localSpace, frameState.predictedDisplayTime, &floorLocation);
     188                frameData.floorTransform = { XrPosefToPose(floorLocation.pose) };
     189            }
     190        }
     191
     192        callOnMainThread([frameData = WTFMove(frameData), callback = WTFMove(callback)]() mutable {
     193            callback(WTFMove(frameData));
     194        });
     195
     196
     197        Vector<const XrCompositionLayerBaseHeader*> layers;
     198
     199        auto frameEndInfo = createStructure<XrFrameEndInfo, XR_TYPE_FRAME_END_INFO>();
     200        frameEndInfo.displayTime = predictedTime;
     201        frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
     202        frameEndInfo.layerCount = layers.size();
     203        result = xrEndFrame(m_session, &frameEndInfo);
     204        RETURN_IF_FAILED(result, "xrEndFrame", m_instance);
     205    });
     206}
     207
     208Vector<Device::ViewData> OpenXRDevice::views(SessionMode mode) const
     209{
     210    Vector<Device::ViewData> views;
     211    auto configurationType = toXrViewConfigurationType(mode);
     212
     213    if (configurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO)
     214        views.append({ .active = true, .eye = Eye::None });
     215    else {
     216        ASSERT(configurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO);
     217        views.append({ .active = true, Eye::Left });
     218        views.append({ .active = true, Eye::Right });
     219    }
     220    return views;
     221}
     222
     223Device::ListOfEnabledFeatures OpenXRDevice::enumerateReferenceSpaces(XrSession session) const
    264224{
    265225    uint32_t referenceSpacesCount;
     
    298258
    299259    return enabledFeatures;
    300 }
    301 
    302 XrSpace OpenXRDevice::createReferenceSpace(XrReferenceSpaceType type)
    303 {
    304     ASSERT(&RunLoop::current() == &m_queue.runLoop());
    305     ASSERT(m_session != XR_NULL_HANDLE);
    306     ASSERT(m_instance != XR_NULL_HANDLE);
    307 
    308     XrPosef identityPose {
    309         .orientation = { .x = 0, .y = 0, .z = 0, .w = 1.0 },
    310         .position = { .x = 0, .y = 0, .z = 0 }
    311     };
    312 
    313     auto spaceCreateInfo = createStructure<XrReferenceSpaceCreateInfo, XR_TYPE_REFERENCE_SPACE_CREATE_INFO>();
    314     spaceCreateInfo.referenceSpaceType = type;
    315     spaceCreateInfo.poseInReferenceSpace = identityPose;
    316 
    317     XrSpace space;
    318     auto result = xrCreateReferenceSpace(m_session, &spaceCreateInfo, &space);
    319     RETURN_IF_FAILED(result, "xrCreateReferenceSpace", m_instance, XR_NULL_HANDLE);
    320 
    321     return space;
    322260}
    323261
     
    391329}
    392330
    393 XrViewConfigurationType toXrViewConfigurationType(SessionMode mode)
    394 {
    395     switch (mode) {
    396     case SessionMode::ImmersiveVr:
    397         return XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
    398     case SessionMode::Inline:
    399     case SessionMode::ImmersiveAr:
    400         return XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO;
     331XrSpace OpenXRDevice::createReferenceSpace(XrReferenceSpaceType type)
     332{
     333    ASSERT(&RunLoop::current() == &m_queue.runLoop());
     334    ASSERT(m_session != XR_NULL_HANDLE);
     335    ASSERT(m_instance != XR_NULL_HANDLE);
     336
     337    XrPosef identityPose {
     338        .orientation = { .x = 0, .y = 0, .z = 0, .w = 1.0 },
     339        .position = { .x = 0, .y = 0, .z = 0 }
    401340    };
    402     ASSERT_NOT_REACHED();
    403     return XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO;
    404 }
    405 
    406 static bool isSessionActive(XrSessionState state)
    407 {
    408     return state == XR_SESSION_STATE_VISIBLE || state == XR_SESSION_STATE_FOCUSED;
    409 }
    410 
    411 static bool isSessionReady(XrSessionState state)
    412 {
    413     return state >= XR_SESSION_STATE_READY  && state < XR_SESSION_STATE_STOPPING;
    414 }
    415 
    416 WebCore::IntSize OpenXRDevice::recommendedResolution(SessionMode mode)
    417 {
    418     auto configType = toXrViewConfigurationType(mode);
    419     auto viewsIterator = m_configurationViews.find(configType);
    420     if (viewsIterator != m_configurationViews.end())
    421         return { static_cast<int>(viewsIterator->value[0].recommendedImageRectWidth), static_cast<int>(viewsIterator->value[0].recommendedImageRectHeight) };
    422     return Device::recommendedResolution(mode);
    423 }
    424 
    425 void OpenXRDevice::initializeTrackingAndRendering(SessionMode mode)
    426 {
    427     m_queue.dispatch([this, mode]() {
    428         ASSERT(m_instance != XR_NULL_HANDLE);
    429         ASSERT(m_session == XR_NULL_HANDLE);
    430 
    431         m_currentViewConfigurationType = toXrViewConfigurationType(mode);
    432         ASSERT(m_configurationViews.contains(m_currentViewConfigurationType));
    433 
    434         // Create the session.
    435         auto sessionCreateInfo = createStructure<XrSessionCreateInfo, XR_TYPE_SESSION_CREATE_INFO>();
    436         sessionCreateInfo.systemId = m_systemId;
    437         auto result = xrCreateSession(m_instance, &sessionCreateInfo, &m_session);
    438         RETURN_IF_FAILED(result, "xrEnumerateInstanceExtensionProperties", m_instance);
    439 
    440         m_localSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_LOCAL);
    441         m_viewSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_VIEW);
    442     });
    443 }
    444 
    445 void OpenXRDevice::resetSession()
    446 {
    447     ASSERT(&RunLoop::current() == &m_queue.runLoop());
    448     if (m_session != XR_NULL_HANDLE) {
    449         xrDestroySession(m_session);
    450         m_session = XR_NULL_HANDLE;
    451     }
    452     m_sessionState = XR_SESSION_STATE_UNKNOWN;
    453 }
    454 
    455 void OpenXRDevice::handleSessionStateChange()
    456 {
    457     ASSERT(&RunLoop::current() == &m_queue.runLoop());
    458     if (m_sessionState == XR_SESSION_STATE_STOPPING) {
    459         // The application should exit the render loop and call xrEndSession
    460         endSession();
    461     } else if (m_sessionState == XR_SESSION_STATE_READY) {
    462         // The application is ready to call xrBeginSession.
    463         beginSession();
    464     }
    465 }
    466 
    467 void OpenXRDevice::shutDownTrackingAndRendering()
    468 {
    469     m_queue.dispatch([this]() {
    470         if (m_session == XR_NULL_HANDLE)
    471             return;
    472 
    473         // xrRequestExitSession() will transition the session to STOPPED state.
    474         // If the session was not running we have to reset the session ourselves.
    475         if (XR_FAILED(xrRequestExitSession(m_session))) {
    476             resetSession();
    477             return;
    478         }
    479 
    480         // OpenXR needs to wait for the XR_SESSION_STATE_STOPPING state to properly end the session.
    481         waitUntilStopping();
    482     });
    483 }
    484 
    485 void OpenXRDevice::initializeReferenceSpace(PlatformXR::ReferenceSpaceType spaceType)
    486 {
    487     if ((spaceType == ReferenceSpaceType::LocalFloor || spaceType == ReferenceSpaceType::BoundedFloor) && m_stageSpace == XR_NULL_HANDLE)
    488         m_stageSpace = createReferenceSpace(XR_REFERENCE_SPACE_TYPE_STAGE);
    489 }
    490 
    491 void OpenXRDevice::waitUntilStopping()
    492 {
    493     ASSERT(&RunLoop::current() == &m_queue.runLoop());
    494     pollEvents();
    495     if (m_sessionState >= XR_SESSION_STATE_STOPPING)
    496         return;
    497     m_queue.dispatch([this]() {
    498         waitUntilStopping();
    499     });
     341
     342    auto spaceCreateInfo = createStructure<XrReferenceSpaceCreateInfo, XR_TYPE_REFERENCE_SPACE_CREATE_INFO>();
     343    spaceCreateInfo.referenceSpaceType = type;
     344    spaceCreateInfo.poseInReferenceSpace = identityPose;
     345
     346    XrSpace space;
     347    auto result = xrCreateReferenceSpace(m_session, &spaceCreateInfo, &space);
     348    RETURN_IF_FAILED(result, "xrCreateReferenceSpace", m_instance, XR_NULL_HANDLE);
     349
     350    return space;
    500351}
    501352
     
    558409}
    559410
    560 static Device::FrameData::Pose XrPosefToPose(XrPosef pose)
    561 {
    562     Device::FrameData::Pose result;
    563     result.orientation = { pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w };
    564     result.position = { pose.position.x, pose.position.y, pose.position.z };
    565     return result;
    566 }
    567 
    568 static Device::FrameData::View xrViewToPose(XrView view)
    569 {
    570     Device::FrameData::View pose;
    571     pose.projection = Device::FrameData::Fov { view.fov.angleUp, view.fov.angleDown, view.fov.angleLeft, view.fov.angleRight };
    572     pose.offset = XrPosefToPose(view.pose);
    573     return pose;
    574 }
    575 
    576 void OpenXRDevice::requestFrame(RequestFrameCallback&& callback)
    577 {
    578     m_queue.dispatch([this, callback = WTFMove(callback)]() mutable {
    579         pollEvents();
    580         if (!isSessionReady(m_sessionState)) {
    581             callOnMainThread([callback = WTFMove(callback)]() mutable {
    582                 // Device not ready or stopping. Report frameData with invalid tracking.
    583                 callback({ });
    584             });
    585             return;
    586         }
    587 
    588         auto frameState = createStructure<XrFrameState, XR_TYPE_FRAME_STATE>();
    589         auto frameWaitInfo = createStructure<XrFrameWaitInfo, XR_TYPE_FRAME_WAIT_INFO>();
    590         auto result = xrWaitFrame(m_session, &frameWaitInfo, &frameState);
    591         RETURN_IF_FAILED(result, "xrWaitFrame", m_instance);
    592         XrTime predictedTime = frameState.predictedDisplayTime;
    593 
    594         auto frameBeginInfo = createStructure<XrFrameBeginInfo, XR_TYPE_FRAME_BEGIN_INFO>();
    595         result = xrBeginFrame(m_session, &frameBeginInfo);
    596         RETURN_IF_FAILED(result, "xrBeginFrame", m_instance);
    597 
    598         Device::FrameData frameData;
    599         frameData.predictedDisplayTime = frameState.predictedDisplayTime;
    600 
    601         if (isSessionActive(m_sessionState)) {
    602             // Query head location
    603             auto location = createStructure<XrSpaceLocation, XR_TYPE_SPACE_LOCATION>();
    604             xrLocateSpace(m_viewSpace, m_localSpace, frameState.predictedDisplayTime, &location);
    605             frameData.isTrackingValid = location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT;
    606             frameData.isPositionValid = location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT;
    607             frameData.isPositionEmulated = location.locationFlags & XR_SPACE_LOCATION_POSITION_TRACKED_BIT;
    608 
    609             if (frameData.isTrackingValid)
    610                 frameData.origin = XrPosefToPose(location.pose);
    611            
    612             ASSERT(m_configurationViews.contains(m_currentViewConfigurationType));
    613             const auto& configurationView = m_configurationViews.get(m_currentViewConfigurationType);
    614 
    615             auto viewLocateInfo = createStructure<XrViewLocateInfo, XR_TYPE_VIEW_LOCATE_INFO>();
    616             viewLocateInfo.displayTime = predictedTime;
    617             viewLocateInfo.space = m_localSpace;
    618 
    619             uint32_t viewCount = configurationView.size();
    620             Vector<XrView> views(viewCount, [] {
    621                 XrView object;
    622                 std::memset(&object, 0, sizeof(XrView));
    623                 object.type = XR_TYPE_VIEW;
    624                 return object;
    625             }());
    626 
    627             auto viewState = createStructure<XrViewState, XR_TYPE_VIEW_STATE>();
    628             uint32_t viewCountOutput;
    629             result = xrLocateViews(m_session, &viewLocateInfo, &viewState, viewCount, &viewCountOutput, views.data());
    630             if (!XR_FAILED(result)) {
    631                 for (auto& view : views)
    632                     frameData.views.append(xrViewToPose(view));
    633             }
    634 
    635             // Query floor transform
    636             if (m_stageSpace != XR_NULL_HANDLE) {
    637                 auto floorLocation = createStructure<XrSpaceLocation, XR_TYPE_SPACE_LOCATION>();
    638                 xrLocateSpace(m_stageSpace, m_localSpace, frameState.predictedDisplayTime, &floorLocation);
    639                 frameData.floorTransform = { XrPosefToPose(floorLocation.pose) };
    640             }
    641         }
    642 
    643         callOnMainThread([frameData = WTFMove(frameData), callback = WTFMove(callback)]() mutable {
    644             callback(WTFMove(frameData));
    645         });
    646 
    647         auto frameEndInfo = createStructure<XrFrameEndInfo, XR_TYPE_FRAME_END_INFO>();
    648         frameEndInfo.displayTime = predictedTime;
    649         frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
    650         frameEndInfo.layerCount = 0;
    651         result = xrEndFrame(m_session, &frameEndInfo);
    652         RETURN_IF_FAILED(result, "xrEndFrame", m_instance);
    653     });
    654 }
    655 
    656 Vector<Device::ViewData> OpenXRDevice::views(SessionMode mode) const
    657 {
    658     Vector<Device::ViewData> views;
    659     auto configurationType = toXrViewConfigurationType(mode);
    660 
    661     if (configurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO)
    662         views.append({ .active = true, .eye = Eye::None });
    663     else {
    664         ASSERT(configurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO);
    665         views.append({ .active = true, Eye::Left });
    666         views.append({ .active = true, Eye::Right });
    667     }
    668     return views;
     411void OpenXRDevice::resetSession()
     412{
     413    ASSERT(&RunLoop::current() == &m_queue.runLoop());
     414    if (m_session != XR_NULL_HANDLE) {
     415        xrDestroySession(m_session);
     416        m_session = XR_NULL_HANDLE;
     417    }
     418    m_sessionState = XR_SESSION_STATE_UNKNOWN;
     419}
     420
     421void OpenXRDevice::handleSessionStateChange()
     422{
     423    ASSERT(&RunLoop::current() == &m_queue.runLoop());
     424    if (m_sessionState == XR_SESSION_STATE_STOPPING) {
     425        // The application should exit the render loop and call xrEndSession
     426        endSession();
     427    } else if (m_sessionState == XR_SESSION_STATE_READY) {
     428        // The application is ready to call xrBeginSession.
     429        beginSession();
     430    }
     431}
     432
     433
     434void OpenXRDevice::waitUntilStopping()
     435{
     436    ASSERT(&RunLoop::current() == &m_queue.runLoop());
     437    pollEvents();
     438    if (m_sessionState >= XR_SESSION_STATE_STOPPING)
     439        return;
     440    m_queue.dispatch([this]() {
     441        waitUntilStopping();
     442    });
    669443}
    670444
  • trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.h

    r273132 r273382  
    2121
    2222#if ENABLE(WEBXR) && USE(OPENXR)
     23
     24#include "OpenXRUtils.h"
    2325#include "PlatformXR.h"
    2426
    2527#include <wtf/HashMap.h>
    26 
    27 #include <openxr/openxr.h>
    2828#include <wtf/WorkQueue.h>
    2929
    3030namespace PlatformXR {
     31
     32class OpenXRExtensions;
    3133
    3234// https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#system
     
    4446class OpenXRDevice final : public Device {
    4547public:
    46     OpenXRDevice(XrSystemId, XrInstance, WorkQueue&, CompletionHandler<void()>&&);
    47     XrSystemId xrSystemId() const { return m_systemId; }
     48    OpenXRDevice(XrInstance, XrSystemId, WorkQueue&, const OpenXRExtensions&, CompletionHandler<void()>&&);
    4849
    4950private:
    50     void collectSupportedSessionModes();
    51     void collectConfigurationViews();
    52 
    53     ListOfEnabledFeatures enumerateReferenceSpaces(XrSession&) const;
    54     XrSpace createReferenceSpace(XrReferenceSpaceType);
    55 
     51    // PlatformXR::Device
    5652    WebCore::IntSize recommendedResolution(SessionMode) final;
    57 
    5853    void initializeTrackingAndRendering(SessionMode) final;
    5954    void shutDownTrackingAndRendering() final;
    6055    void initializeReferenceSpace(PlatformXR::ReferenceSpaceType) final;
    6156    bool supportsSessionShutdownNotification() const final { return true; }
    62     void waitUntilStopping();
     57    void requestFrame(RequestFrameCallback&&) final;
     58    Vector<ViewData> views(SessionMode) const final;
    6359
     60    // Custom methods
     61    ListOfEnabledFeatures enumerateReferenceSpaces(XrSession) const;
     62    void collectSupportedSessionModes();
     63    void collectConfigurationViews();
     64    XrSpace createReferenceSpace(XrReferenceSpaceType);
    6465    void pollEvents();
    6566    XrResult beginSession();
     
    6768    void resetSession();
    6869    void handleSessionStateChange();
     70    void waitUntilStopping();
    6971
    70     void requestFrame(RequestFrameCallback&&) final;
    71 
    72     Vector<ViewData> views(SessionMode) const final;
     72    XrInstance m_instance;
     73    XrSystemId m_systemId;
     74    WorkQueue& m_queue;
     75    const OpenXRExtensions& m_extensions;
     76    XrSession m_session { XR_NULL_HANDLE };
     77    XrSessionState m_sessionState { XR_SESSION_STATE_UNKNOWN };
    7378
    7479    using ViewConfigurationPropertiesMap = HashMap<XrViewConfigurationType, XrViewConfigurationProperties, IntHash<XrViewConfigurationType>, WTF::StrongEnumHashTraits<XrViewConfigurationType>>;
     
    7681    using ViewConfigurationViewsMap = HashMap<XrViewConfigurationType, Vector<XrViewConfigurationView>, IntHash<XrViewConfigurationType>, WTF::StrongEnumHashTraits<XrViewConfigurationType>>;
    7782    ViewConfigurationViewsMap m_configurationViews;
    78 
    79     XrSystemId m_systemId;
    80     XrInstance m_instance;
    81     XrSession m_session { XR_NULL_HANDLE };
    82     XrSessionState m_sessionState { XR_SESSION_STATE_UNKNOWN };
    83 
    84     WorkQueue& m_queue;
    85 
    8683    XrViewConfigurationType m_currentViewConfigurationType;
    8784    XrSpace m_localSpace { XR_NULL_HANDLE };
Note: See TracChangeset for help on using the changeset viewer.