Changeset 273382 in webkit
- Timestamp:
- Feb 24, 2021 5:13:21 AM (3 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r273381 r273382 1 2021-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 1 49 2021-02-24 Imanol Fernandez <ifernandez@igalia.com> 2 50 -
trunk/Source/WebCore/Sources.txt
r273310 r273382 2173 2173 platform/text/TextEncodingDetectorICU.cpp 2174 2174 platform/text/TextEncodingRegistry.cpp 2175 platform/xr/openxr/OpenXRInstance.cpp @no-unify 2176 platform/xr/openxr/OpenXRExtensions.cpp @no-unify 2175 2177 platform/xr/openxr/PlatformXROpenXR.cpp @no-unify 2176 2178 plugins/DOMMimeType.cpp -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r273310 r273382 394 394 115CFA97208B952B001E6991 /* LayoutBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 115CFA95208B952B001E6991 /* LayoutBox.h */; settings = {ATTRIBUTES = (Private, ); }; }; 395 395 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 */; }; 396 400 119340791FE8B92300935F1E /* RenderTreeBuilderTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340771FE8B92300935F1E /* RenderTreeBuilderTable.h */; }; 397 401 1193408A1FEB355D00935F1E /* RenderTreeBuilderRuby.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340881FEB355D00935F1E /* RenderTreeBuilderRuby.h */; }; … … 6320 6324 1163F82124E5D59B000AB960 /* RenderTreeMutationDisallowedScope.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeMutationDisallowedScope.h; sourceTree = "<group>"; }; 6321 6325 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>"; }; 6322 6330 119340761FE8B92300935F1E /* RenderTreeBuilderTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderTable.cpp; sourceTree = "<group>"; }; 6323 6331 119340771FE8B92300935F1E /* RenderTreeBuilderTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderTable.h; sourceTree = "<group>"; }; … … 28925 28933 isa = PBXGroup; 28926 28934 children = ( 28935 118B068625E41E510070BE4B /* OpenXRExtensions.cpp */, 28936 118B068825E41E520070BE4B /* OpenXRExtensions.h */, 28937 118B068925E41E520070BE4B /* OpenXRInstance.cpp */, 28938 118B068A25E41E530070BE4B /* OpenXRUtils.h */, 28927 28939 E1C1A39B2480080600E0AF66 /* PlatformXROpenXR.cpp */, 28928 28940 E1C1A39C2480080700E0AF66 /* PlatformXROpenXR.h */, … … 34063 34075 B2D3DA650D006CD600EF6F27 /* OpenTypeMathData.h in Headers */, 34064 34076 B2D3EA650D006CD600EF6F28 /* OpenTypeTypes.h in Headers */, 34077 118B068C25E41E530070BE4B /* OpenXRExtensions.h in Headers */, 34078 118B068E25E41E530070BE4B /* OpenXRUtils.h in Headers */, 34065 34079 71207340216DFB0000C78329 /* OptionalEffectTiming.h in Headers */, 34066 34080 CDE7FC45181904B1002BBB77 /* OrderIterator.h in Headers */, … … 36230 36244 1A569D1A0D7E2B82007C3983 /* objc_utility.mm in Sources */, 36231 36245 E16982601134636A00894115 /* ObjCRuntimeObject.mm in Sources */, 36246 118B068B25E41E530070BE4B /* OpenXRExtensions.cpp in Sources */, 36247 118B068D25E41E530070BE4B /* OpenXRInstance.cpp in Sources */, 36232 36248 CEA284662141E84900E407E8 /* PlatformEventFactoryIOS.mm in Sources */, 36233 36249 AA12DF491743DF83004DAFDF /* PlatformSpeechSynthesizerIOS.mm in Sources */, -
trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp
r273132 r273382 23 23 #if ENABLE(WEBXR) && USE(OPENXR) 24 24 25 #include " Logging.h"26 #include <openxr/openxr_platform.h> 25 #include "OpenXRExtensions.h" 26 27 27 #include <wtf/NeverDestroyed.h> 28 28 #include <wtf/Optional.h> 29 #include <wtf/Scope.h>30 #include <wtf/text/StringConcatenateNumbers.h>31 #include <wtf/text/WTFString.h>32 29 33 30 using namespace WebCore; … … 35 32 namespace PlatformXR { 36 33 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 35 static bool isSessionActive(XrSessionState state) 36 { 37 return state == XR_SESSION_STATE_VISIBLE || state == XR_SESSION_STATE_FOCUSED; 38 } 39 40 static bool isSessionReady(XrSessionState state) 41 { 42 return state >= XR_SESSION_STATE_READY && state < XR_SESSION_STATE_STOPPING; 43 } 44 45 OpenXRDevice::OpenXRDevice(XrInstance instance, XrSystemId system, WorkQueue& queue, const OpenXRExtensions& extensions, CompletionHandler<void()>&& callback) 46 : m_instance(instance) 47 , m_systemId(system) 242 48 , m_queue(queue) 49 , m_extensions(extensions) 243 50 { 244 51 ASSERT(isMainThread()); … … 261 68 } 262 69 263 Device::ListOfEnabledFeatures OpenXRDevice::enumerateReferenceSpaces(XrSession& session) const 70 WebCore::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 79 void 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 101 void 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 119 void 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 125 void 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 208 Vector<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 223 Device::ListOfEnabledFeatures OpenXRDevice::enumerateReferenceSpaces(XrSession session) const 264 224 { 265 225 uint32_t referenceSpacesCount; … … 298 258 299 259 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;322 260 } 323 261 … … 391 329 } 392 330 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; 331 XrSpace 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 } 401 340 }; 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; 500 351 } 501 352 … … 558 409 } 559 410 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; 411 void 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 421 void 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 434 void 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 }); 669 443 } 670 444 -
trunk/Source/WebCore/platform/xr/openxr/PlatformXROpenXR.h
r273132 r273382 21 21 22 22 #if ENABLE(WEBXR) && USE(OPENXR) 23 24 #include "OpenXRUtils.h" 23 25 #include "PlatformXR.h" 24 26 25 27 #include <wtf/HashMap.h> 26 27 #include <openxr/openxr.h>28 28 #include <wtf/WorkQueue.h> 29 29 30 30 namespace PlatformXR { 31 32 class OpenXRExtensions; 31 33 32 34 // https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#system … … 44 46 class OpenXRDevice final : public Device { 45 47 public: 46 OpenXRDevice(XrSystemId, XrInstance, WorkQueue&, CompletionHandler<void()>&&); 47 XrSystemId xrSystemId() const { return m_systemId; } 48 OpenXRDevice(XrInstance, XrSystemId, WorkQueue&, const OpenXRExtensions&, CompletionHandler<void()>&&); 48 49 49 50 private: 50 void collectSupportedSessionModes(); 51 void collectConfigurationViews(); 52 53 ListOfEnabledFeatures enumerateReferenceSpaces(XrSession&) const; 54 XrSpace createReferenceSpace(XrReferenceSpaceType); 55 51 // PlatformXR::Device 56 52 WebCore::IntSize recommendedResolution(SessionMode) final; 57 58 53 void initializeTrackingAndRendering(SessionMode) final; 59 54 void shutDownTrackingAndRendering() final; 60 55 void initializeReferenceSpace(PlatformXR::ReferenceSpaceType) final; 61 56 bool supportsSessionShutdownNotification() const final { return true; } 62 void waitUntilStopping(); 57 void requestFrame(RequestFrameCallback&&) final; 58 Vector<ViewData> views(SessionMode) const final; 63 59 60 // Custom methods 61 ListOfEnabledFeatures enumerateReferenceSpaces(XrSession) const; 62 void collectSupportedSessionModes(); 63 void collectConfigurationViews(); 64 XrSpace createReferenceSpace(XrReferenceSpaceType); 64 65 void pollEvents(); 65 66 XrResult beginSession(); … … 67 68 void resetSession(); 68 69 void handleSessionStateChange(); 70 void waitUntilStopping(); 69 71 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 }; 73 78 74 79 using ViewConfigurationPropertiesMap = HashMap<XrViewConfigurationType, XrViewConfigurationProperties, IntHash<XrViewConfigurationType>, WTF::StrongEnumHashTraits<XrViewConfigurationType>>; … … 76 81 using ViewConfigurationViewsMap = HashMap<XrViewConfigurationType, Vector<XrViewConfigurationView>, IntHash<XrViewConfigurationType>, WTF::StrongEnumHashTraits<XrViewConfigurationType>>; 77 82 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 86 83 XrViewConfigurationType m_currentViewConfigurationType; 87 84 XrSpace m_localSpace { XR_NULL_HANDLE };
Note: See TracChangeset
for help on using the changeset viewer.