moz_external_vr.h (24989B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef GFX_VR_EXTERNAL_API_H 8 #define GFX_VR_EXTERNAL_API_H 9 10 #define GFX_VR_EIGHTCC(c1, c2, c3, c4, c5, c6, c7, c8) \ 11 ((uint64_t)(c1) << 56 | (uint64_t)(c2) << 48 | (uint64_t)(c3) << 40 | \ 12 (uint64_t)(c4) << 32 | (uint64_t)(c5) << 24 | (uint64_t)(c6) << 16 | \ 13 (uint64_t)(c7) << 8 | (uint64_t)(c8)) 14 15 #ifdef MOZILLA_INTERNAL_API 16 17 // __STDC_WANT_LIB_EXT1__ required for memcpy_s 18 # ifndef __STDC_WANT_LIB_EXT1__ 19 # define __STDC_WANT_LIB_EXT1__ 1 20 # endif // __STDC_WANT_LIB_EXT1__ 21 22 static_assert(__STDC_WANT_LIB_EXT1__ == 1, 23 "__STDC_WANT_LIB_EXT1__ must be set"); 24 25 # include <stdlib.h> 26 # include <string.h> 27 # include "mozilla/TiedFields.h" 28 # include "mozilla/TypedEnumBits.h" 29 # include "mozilla/gfx/2D.h" 30 # include <stddef.h> 31 # include <stdint.h> 32 #endif // MOZILLA_INTERNAL_API 33 34 #if defined(__ANDROID__) 35 # include <pthread.h> 36 #endif // defined(__ANDROID__) 37 38 #include <array> 39 #include <cstdint> 40 #include <type_traits> 41 42 namespace mozilla { 43 #ifdef MOZILLA_INTERNAL_API 44 namespace dom { 45 enum class GamepadHand : uint8_t; 46 enum class GamepadCapabilityFlags : uint16_t; 47 } // namespace dom 48 #endif // MOZILLA_INTERNAL_API 49 namespace gfx { 50 51 // If there is any change of "SHMEM_VERSION" or "kVRExternalVersion", 52 // we need to change both of them at the same time. 53 54 // TODO: we might need to use different names for the mutexes 55 // and mapped files if we have both release and nightlies 56 // running at the same time? Or...what if we have multiple 57 // release builds running on same machine? (Bug 1563232) 58 #define SHMEM_VERSION "0.0.12" 59 static const int32_t kVRExternalVersion = 19; 60 61 // We assign VR presentations to groups with a bitmask. 62 // Currently, we will only display either content or chrome. 63 // Later, we will have more groups to support VR home spaces and 64 // multitasking environments. 65 // These values are not exposed to regular content and only affect 66 // chrome-only API's. They may be changed at any time. 67 static const uint32_t kVRGroupNone = 0; 68 static const uint32_t kVRGroupContent = 1 << 0; 69 static const uint32_t kVRGroupChrome = 1 << 1; 70 static const uint32_t kVRGroupAll = 0xffffffff; 71 72 static const int kVRDisplayNameMaxLen = 256; 73 static const int kVRControllerNameMaxLen = 256; 74 static const int kVRControllerMaxCount = 16; 75 static const int kVRControllerMaxButtons = 64; 76 static const int kVRControllerMaxAxis = 16; 77 static const int kVRLayerMaxCount = 8; 78 static const int kVRHapticsMaxCount = 32; 79 80 #if defined(__ANDROID__) 81 typedef uint64_t VRLayerTextureHandle; 82 #elif defined(XP_MACOSX) 83 typedef uint32_t VRLayerTextureHandle; 84 #else 85 typedef void* VRLayerTextureHandle; 86 #endif 87 88 struct Point3D_POD { 89 float x; 90 float y; 91 float z; 92 93 #ifdef MOZILLA_INTERNAL_API 94 auto MutTiedFields() { return std::tie(x, y, z); } 95 96 bool operator==(const Point3D_POD& other) const { 97 return TiedFields(*this) == TiedFields(other); 98 } 99 #endif 100 }; 101 102 struct IntSize_POD { 103 int32_t width; 104 int32_t height; 105 106 #ifdef MOZILLA_INTERNAL_API 107 auto MutTiedFields() { return std::tie(width, height); } 108 109 bool operator==(const IntSize_POD& other) const { 110 return TiedFields(*this) == TiedFields(other); 111 } 112 #endif 113 }; 114 115 struct FloatSize_POD { 116 float width; 117 float height; 118 119 #ifdef MOZILLA_INTERNAL_API 120 auto MutTiedFields() { return std::tie(width, height); } 121 122 bool operator==(const FloatSize_POD& other) const { 123 return TiedFields(*this) == TiedFields(other); 124 } 125 #endif 126 }; 127 128 #ifndef MOZILLA_INTERNAL_API 129 130 enum class ControllerHand : uint8_t { _empty, Left, Right, EndGuard_ }; 131 132 enum class ControllerCapabilityFlags : uint16_t { 133 Cap_None = 0, 134 /** 135 * Cap_Position is set if the Gamepad is capable of tracking its position. 136 */ 137 Cap_Position = 1 << 1, 138 /** 139 * Cap_Orientation is set if the Gamepad is capable of tracking its 140 * orientation. 141 */ 142 Cap_Orientation = 1 << 2, 143 /** 144 * Cap_AngularAcceleration is set if the Gamepad is capable of tracking its 145 * angular acceleration. 146 */ 147 Cap_AngularAcceleration = 1 << 3, 148 /** 149 * Cap_LinearAcceleration is set if the Gamepad is capable of tracking its 150 * linear acceleration. 151 */ 152 Cap_LinearAcceleration = 1 << 4, 153 /** 154 * Cap_TargetRaySpacePosition is set if the Gamepad has a grip space position. 155 */ 156 Cap_GripSpacePosition = 1 << 5, 157 /** 158 * Cap_PositionEmulated is set if the XRInputSoruce is capable of setting a 159 * emulated position (e.g. neck model) even if still doesn't support 6DOF 160 * tracking. 161 */ 162 Cap_PositionEmulated = 1 << 6, 163 /** 164 * Cap_All used for validity checking during IPC serialization 165 */ 166 Cap_All = (1 << 7) - 1 167 }; 168 169 #endif // ifndef MOZILLA_INTERNAL_API 170 171 enum class VRControllerType : uint8_t { 172 _empty, 173 HTCVive, 174 HTCViveCosmos, 175 HTCViveFocus, 176 HTCViveFocusPlus, 177 MSMR, 178 ValveIndex, 179 OculusGo, 180 OculusTouch, 181 OculusTouch2, 182 OculusTouch3, 183 PicoGaze, 184 PicoG2, 185 PicoNeo2, 186 _end 187 }; 188 189 } // namespace gfx 190 191 template <class T> 192 bool IsEnumCase(T); 193 194 template <> 195 inline constexpr bool IsEnumCase<gfx::VRControllerType>( 196 const gfx::VRControllerType raw) { 197 switch (raw) { 198 case gfx::VRControllerType::_empty: 199 case gfx::VRControllerType::HTCVive: 200 case gfx::VRControllerType::HTCViveCosmos: 201 case gfx::VRControllerType::HTCViveFocus: 202 case gfx::VRControllerType::HTCViveFocusPlus: 203 case gfx::VRControllerType::MSMR: 204 case gfx::VRControllerType::ValveIndex: 205 case gfx::VRControllerType::OculusGo: 206 case gfx::VRControllerType::OculusTouch: 207 case gfx::VRControllerType::OculusTouch2: 208 case gfx::VRControllerType::OculusTouch3: 209 case gfx::VRControllerType::PicoGaze: 210 case gfx::VRControllerType::PicoG2: 211 case gfx::VRControllerType::PicoNeo2: 212 case gfx::VRControllerType::_end: 213 return true; 214 } 215 return false; 216 } 217 namespace gfx { 218 219 // - 220 221 enum class TargetRayMode : uint8_t { Gaze, TrackedPointer, Screen }; 222 223 } // namespace gfx 224 template <> 225 inline constexpr bool IsEnumCase<gfx::TargetRayMode>( 226 const gfx::TargetRayMode raw) { 227 switch (raw) { 228 case gfx::TargetRayMode::Gaze: 229 case gfx::TargetRayMode::TrackedPointer: 230 case gfx::TargetRayMode::Screen: 231 return true; 232 } 233 return false; 234 } 235 namespace gfx { 236 237 // - 238 239 enum class GamepadMappingType : uint8_t { _empty, Standard, XRStandard }; 240 241 } // namespace gfx 242 template <> 243 inline constexpr bool IsEnumCase<gfx::GamepadMappingType>( 244 const gfx::GamepadMappingType raw) { 245 switch (raw) { 246 case gfx::GamepadMappingType::_empty: 247 case gfx::GamepadMappingType::Standard: 248 case gfx::GamepadMappingType::XRStandard: 249 return true; 250 } 251 return false; 252 } 253 namespace gfx { 254 255 // - 256 257 enum class VRDisplayBlendMode : uint8_t { Opaque, Additive, AlphaBlend }; 258 259 } // namespace gfx 260 template <> 261 inline constexpr bool IsEnumCase<gfx::VRDisplayBlendMode>( 262 const gfx::VRDisplayBlendMode raw) { 263 switch (raw) { 264 case gfx::VRDisplayBlendMode::Opaque: 265 case gfx::VRDisplayBlendMode::Additive: 266 case gfx::VRDisplayBlendMode::AlphaBlend: 267 return true; 268 } 269 return false; 270 } 271 namespace gfx { 272 273 // - 274 275 enum class VRDisplayCapabilityFlags : uint16_t { 276 Cap_None = 0, 277 /** 278 * Cap_Position is set if the VRDisplay is capable of tracking its position. 279 */ 280 Cap_Position = 1 << 1, 281 /** 282 * Cap_Orientation is set if the VRDisplay is capable of tracking its 283 * orientation. 284 */ 285 Cap_Orientation = 1 << 2, 286 /** 287 * Cap_Present is set if the VRDisplay is capable of presenting content to an 288 * HMD or similar device. Can be used to indicate "magic window" devices that 289 * are capable of 6DoF tracking but for which requestPresent is not 290 * meaningful. If false then calls to requestPresent should always fail, and 291 * getEyeParameters should return null. 292 */ 293 Cap_Present = 1 << 3, 294 /** 295 * Cap_External is set if the VRDisplay is separate from the device's 296 * primary display. If presenting VR content will obscure 297 * other content on the device, this should be un-set. When 298 * un-set, the application should not attempt to mirror VR content 299 * or update non-VR UI because that content will not be visible. 300 */ 301 Cap_External = 1 << 4, 302 /** 303 * Cap_AngularAcceleration is set if the VRDisplay is capable of tracking its 304 * angular acceleration. 305 */ 306 Cap_AngularAcceleration = 1 << 5, 307 /** 308 * Cap_LinearAcceleration is set if the VRDisplay is capable of tracking its 309 * linear acceleration. 310 */ 311 Cap_LinearAcceleration = 1 << 6, 312 /** 313 * Cap_StageParameters is set if the VRDisplay is capable of room scale VR 314 * and can report the StageParameters to describe the space. 315 */ 316 Cap_StageParameters = 1 << 7, 317 /** 318 * Cap_MountDetection is set if the VRDisplay is capable of sensing when the 319 * user is wearing the device. 320 */ 321 Cap_MountDetection = 1 << 8, 322 /** 323 * Cap_PositionEmulated is set if the VRDisplay is capable of setting a 324 * emulated position (e.g. neck model) even if still doesn't support 6DOF 325 * tracking. 326 */ 327 Cap_PositionEmulated = 1 << 9, 328 /** 329 * Cap_Inline is set if the device can be used for WebXR inline sessions 330 * where the content is displayed within an element on the page. 331 */ 332 Cap_Inline = 1 << 10, 333 /** 334 * Cap_ImmersiveVR is set if the device can give exclusive access to the 335 * XR device display and that content is not intended to be integrated 336 * with the user's environment 337 */ 338 Cap_ImmersiveVR = 1 << 11, 339 /** 340 * Cap_ImmersiveAR is set if the device can give exclusive access to the 341 * XR device display and that content is intended to be integrated with 342 * the user's environment. 343 */ 344 Cap_ImmersiveAR = 1 << 12, 345 /** 346 * Cap_UseDepthValues is set if the device will use the depth values of the 347 * submitted frames if provided. How the depth values are used is determined 348 * by the VR runtime. Often the depth is used for occlusion of system UI 349 * or to enable more effective asynchronous reprojection of frames. 350 */ 351 Cap_UseDepthValues = 1 << 13, 352 /** 353 * Cap_All used for validity checking during IPC serialization 354 */ 355 Cap_All = (1 << 14) - 1 356 }; 357 358 #ifdef MOZILLA_INTERNAL_API 359 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRDisplayCapabilityFlags) 360 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRDisplayBlendMode) 361 #endif // MOZILLA_INTERNAL_API 362 363 struct VRPose { 364 std::array<float, 4> orientation; 365 std::array<float, 3> position; 366 std::array<float, 3> angularVelocity; 367 std::array<float, 3> angularAcceleration; 368 std::array<float, 3> linearVelocity; 369 std::array<float, 3> linearAcceleration; 370 371 #ifdef MOZILLA_INTERNAL_API 372 auto MutTiedFields() { 373 return std::tie(orientation, position, angularVelocity, angularAcceleration, 374 linearVelocity, linearAcceleration); 375 } 376 377 bool operator==(const VRPose& other) const { 378 return TiedFields(*this) == TiedFields(other); 379 } 380 #endif // MOZILLA_INTERNAL_API 381 }; 382 383 struct VRHMDSensorState { 384 uint64_t inputFrameID; 385 double timestamp; 386 VRDisplayCapabilityFlags flags; 387 uint16_t _padding; 388 389 // These members will only change with inputFrameID: 390 VRPose pose; 391 std::array<float, 16> leftViewMatrix; 392 std::array<float, 16> rightViewMatrix; 393 394 #ifdef MOZILLA_INTERNAL_API 395 396 auto MutTiedFields() { 397 return std::tie(inputFrameID, timestamp, flags, _padding, pose, 398 leftViewMatrix, rightViewMatrix); 399 } 400 401 void Clear() { memset(this, 0, sizeof(VRHMDSensorState)); } 402 403 bool operator==(const VRHMDSensorState& other) const { 404 return inputFrameID == other.inputFrameID && timestamp == other.timestamp; 405 } 406 407 bool operator!=(const VRHMDSensorState& other) const { 408 return !(*this == other); 409 } 410 411 void CalcViewMatrices(const gfx::Matrix4x4* aHeadToEyeTransforms); 412 413 #endif // MOZILLA_INTERNAL_API 414 }; 415 416 struct VRFieldOfView { 417 double upDegrees; 418 double rightDegrees; 419 double downDegrees; 420 double leftDegrees; 421 422 #ifdef MOZILLA_INTERNAL_API 423 auto MutTiedFields() { 424 return std::tie(upDegrees, rightDegrees, downDegrees, leftDegrees); 425 } 426 427 bool operator==(const VRFieldOfView& other) const { 428 return TiedFields(*this) == TiedFields(other); 429 } 430 431 VRFieldOfView() = default; 432 VRFieldOfView(double up, double right, double down, double left) 433 : upDegrees(up), 434 rightDegrees(right), 435 downDegrees(down), 436 leftDegrees(left) {} 437 438 void SetFromTanRadians(double up, double right, double down, double left) { 439 upDegrees = atan(up) * 180.0 / M_PI; 440 rightDegrees = atan(right) * 180.0 / M_PI; 441 downDegrees = atan(down) * 180.0 / M_PI; 442 leftDegrees = atan(left) * 180.0 / M_PI; 443 } 444 445 bool operator!=(const VRFieldOfView& other) const { 446 return !(*this == other); 447 } 448 449 bool IsZero() const { 450 return upDegrees == 0.0 || rightDegrees == 0.0 || downDegrees == 0.0 || 451 leftDegrees == 0.0; 452 } 453 454 Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar, 455 bool rightHanded) const; 456 457 #endif // MOZILLA_INTERNAL_API 458 }; 459 460 struct VRDisplayState { 461 enum Eye { Eye_Left, Eye_Right, NumEyes }; 462 463 // When true, indicates that the VR service has shut down 464 bool shutdown; 465 std::array<uint8_t, 3> _padding1; 466 // Minimum number of milliseconds to wait before attempting 467 // to start the VR service again 468 uint32_t minRestartInterval; 469 std::array<char, kVRDisplayNameMaxLen> displayName; 470 // eight byte character code identifier 471 // LSB first, so "ABCDEFGH" -> ('H'<<56) + ('G'<<48) + ('F'<<40) + 472 // ('E'<<32) + ('D'<<24) + ('C'<<16) + 473 // ('B'<<8) + 'A'). 474 uint64_t eightCC; 475 VRDisplayCapabilityFlags capabilityFlags; 476 VRDisplayBlendMode blendMode; 477 std::array<uint8_t, 5> _padding2; 478 std::array<VRFieldOfView, VRDisplayState::NumEyes> eyeFOV; 479 static_assert(std::is_trivial_v<VRFieldOfView>); 480 std::array<Point3D_POD, VRDisplayState::NumEyes> eyeTranslation; 481 static_assert(std::is_trivial_v<Point3D_POD>); 482 IntSize_POD eyeResolution; 483 static_assert(std::is_trivial_v<IntSize_POD>); 484 float nativeFramebufferScaleFactor; 485 bool suppressFrames; 486 bool isConnected; 487 bool isMounted; 488 uint8_t _padding3; 489 FloatSize_POD stageSize; 490 static_assert(std::is_trivial_v<FloatSize_POD>); 491 // We can't use a Matrix4x4 here unless we ensure it's a POD type 492 std::array<float, 16> sittingToStandingTransform; 493 uint64_t lastSubmittedFrameId; 494 bool lastSubmittedFrameSuccessful; 495 std::array<uint8_t, 3> _padding4; 496 uint32_t presentingGeneration; 497 // Telemetry 498 bool reportsDroppedFrames; 499 std::array<uint8_t, 7> _padding5; 500 uint64_t droppedFrameCount; 501 502 #ifdef MOZILLA_INTERNAL_API 503 auto MutTiedFields() { 504 return std::tie(shutdown, _padding1, minRestartInterval, displayName, 505 eightCC, capabilityFlags, blendMode, _padding2, eyeFOV, 506 eyeTranslation, eyeResolution, nativeFramebufferScaleFactor, 507 suppressFrames, isConnected, isMounted, _padding3, 508 stageSize, sittingToStandingTransform, lastSubmittedFrameId, 509 lastSubmittedFrameSuccessful, _padding4, 510 presentingGeneration, reportsDroppedFrames, _padding5, 511 droppedFrameCount); 512 } 513 514 bool operator==(const VRDisplayState& other) const { 515 return TiedFields(*this) == TiedFields(other); 516 } 517 518 void Clear() { memset(this, 0, sizeof(VRDisplayState)); } 519 #endif 520 }; 521 static_assert(std::is_trivial_v<VRDisplayState>); 522 523 struct VRControllerState { 524 std::array<char, kVRControllerNameMaxLen> controllerName; 525 #ifdef MOZILLA_INTERNAL_API 526 dom::GamepadHand hand; 527 #else 528 ControllerHand hand; 529 #endif 530 // For WebXR->WebVR mapping conversion, once we remove WebVR, 531 // we can remove this item. 532 VRControllerType type; 533 // https://immersive-web.github.io/webxr/#enumdef-xrtargetraymode 534 TargetRayMode targetRayMode; 535 536 // https://immersive-web.github.io/webxr-gamepads-module/#enumdef-gamepadmappingtype 537 GamepadMappingType mappingType; 538 539 uint32_t _padding1; 540 541 // Start frame ID of the most recent primary select 542 // action, or 0 if the select action has never occurred. 543 uint64_t selectActionStartFrameId; 544 // End frame Id of the most recent primary select 545 // action, or 0 if action never occurred. 546 // If selectActionStopFrameId is less than 547 // selectActionStartFrameId, then the select 548 // action has not ended yet. 549 uint64_t selectActionStopFrameId; 550 551 // start frame Id of the most recent primary squeeze 552 // action, or 0 if the squeeze action has never occurred. 553 uint64_t squeezeActionStartFrameId; 554 // End frame Id of the most recent primary squeeze 555 // action, or 0 if action never occurred. 556 // If squeezeActionStopFrameId is less than 557 // squeezeActionStartFrameId, then the squeeze 558 // action has not ended yet. 559 uint64_t squeezeActionStopFrameId; 560 561 uint32_t numButtons; 562 uint32_t numAxes; 563 uint32_t numHaptics; 564 uint32_t _padding2; 565 // The current button pressed bit of button mask. 566 uint64_t buttonPressed; 567 // The current button touched bit of button mask. 568 uint64_t buttonTouched; 569 std::array<float, kVRControllerMaxButtons> triggerValue; 570 std::array<float, kVRControllerMaxAxis> axisValue; 571 572 #ifdef MOZILLA_INTERNAL_API 573 dom::GamepadCapabilityFlags flags; 574 #else 575 ControllerCapabilityFlags flags; 576 #endif 577 578 uint16_t _padding3; 579 580 // When Cap_Position is set in flags, pose corresponds 581 // to the controllers' pose in grip space: 582 // https://immersive-web.github.io/webxr/#dom-xrinputsource-gripspace 583 VRPose pose; 584 585 // When Cap_TargetRaySpacePosition is set in flags, targetRayPose corresponds 586 // to the controllers' pose in target ray space: 587 // https://immersive-web.github.io/webxr/#dom-xrinputsource-targetrayspace 588 VRPose targetRayPose; 589 590 bool isPositionValid; 591 bool isOrientationValid; 592 uint16_t _padding4; 593 594 #ifdef MOZILLA_INTERNAL_API 595 auto MutTiedFields() { 596 return std::tie(controllerName, hand, type, targetRayMode, mappingType, 597 _padding1, selectActionStartFrameId, 598 selectActionStopFrameId, squeezeActionStartFrameId, 599 squeezeActionStopFrameId, numButtons, numAxes, numHaptics, 600 _padding2, buttonPressed, buttonTouched, triggerValue, 601 axisValue, flags, _padding3, pose, targetRayPose, 602 isPositionValid, isOrientationValid, _padding4); 603 } 604 605 bool operator==(const VRControllerState& other) const { 606 return TiedFields(*this) == TiedFields(other); 607 } 608 609 void Clear() { memset(this, 0, sizeof(VRControllerState)); } 610 #endif 611 }; 612 613 struct VRLayerEyeRect { 614 float x; 615 float y; 616 float width; 617 float height; 618 }; 619 620 enum class VRLayerType : uint16_t { 621 LayerType_None = 0, 622 LayerType_2D_Content = 1, 623 LayerType_Stereo_Immersive = 2 624 }; 625 626 enum class VRLayerTextureType : uint16_t { 627 LayerTextureType_None = 0, 628 LayerTextureType_D3D10SurfaceDescriptor = 1, 629 LayerTextureType_MacIOSurface = 2, 630 LayerTextureType_GeckoSurfaceTexture = 3 631 }; 632 633 struct VRLayer_2D_Content { 634 VRLayerTextureHandle textureHandle; 635 VRLayerTextureType textureType; 636 uint64_t frameId; 637 }; 638 639 struct VRLayer_Stereo_Immersive { 640 VRLayerTextureHandle textureHandle; 641 VRLayerTextureType textureType; 642 uint64_t frameId; 643 uint64_t inputFrameId; 644 VRLayerEyeRect leftEyeRect; 645 VRLayerEyeRect rightEyeRect; 646 IntSize_POD textureSize; 647 }; 648 649 struct VRLayerState { 650 VRLayerType type; 651 union { 652 VRLayer_2D_Content layer_2d_content; 653 VRLayer_Stereo_Immersive layer_stereo_immersive; 654 }; 655 }; 656 657 struct VRHapticState { 658 // Reference frame for timing. 659 // When 0, this does not represent an active haptic pulse. 660 uint64_t inputFrameID; 661 // Index within VRSystemState.controllerState identifying the controller 662 // to emit the haptic pulse 663 uint32_t controllerIndex; 664 // 0-based index indicating which haptic actuator within the controller 665 uint32_t hapticIndex; 666 // Start time of the haptic feedback pulse, relative to the start of 667 // inputFrameID, in seconds 668 float pulseStart; 669 // Duration of the haptic feedback pulse, in seconds 670 float pulseDuration; 671 // Intensity of the haptic feedback pulse, from 0.0f to 1.0f 672 float pulseIntensity; 673 }; 674 675 struct VRBrowserState { 676 #if defined(__ANDROID__) 677 bool shutdown; 678 #endif // defined(__ANDROID__) 679 /** 680 * In order to support WebXR's navigator.xr.IsSessionSupported call without 681 * displaying any permission dialogue, it is necessary to have a safe way to 682 * detect the capability of running a VR or AR session without activating XR 683 * runtimes or powering on hardware. 684 * 685 * API's such as OpenVR make no guarantee that hardware and software won't be 686 * left activated after enumerating devices, so each backend in gfx/vr/service 687 * must allow for more granular detection of capabilities. 688 * 689 * When detectRuntimesOnly is true, the initialization exits early after 690 * reporting the presence of XR runtime software. 691 * 692 * The result of the runtime detection is reported with the Cap_ImmersiveVR 693 * and Cap_ImmersiveAR bits in VRDisplayState.flags. 694 */ 695 bool detectRuntimesOnly; 696 bool presentationActive; 697 bool navigationTransitionActive; 698 VRLayerState layerState[kVRLayerMaxCount]; 699 VRHapticState hapticState[kVRHapticsMaxCount]; 700 701 #ifdef MOZILLA_INTERNAL_API 702 void Clear() { memset(this, 0, sizeof(VRBrowserState)); } 703 #endif 704 }; 705 706 struct VRSystemState { 707 bool enumerationCompleted; 708 VRDisplayState displayState; 709 VRHMDSensorState sensorState; 710 std::array<VRControllerState, kVRControllerMaxCount> controllerState; 711 }; 712 static_assert(std::is_trivial_v<VRDisplayState>); 713 static_assert(std::is_trivial_v<VRHMDSensorState>); 714 static_assert(std::is_trivial_v<VRControllerState>); 715 static_assert(std::is_trivial_v<VRSystemState>); 716 717 enum class VRFxEventType : uint8_t { 718 NONE = 0, 719 IME, 720 SHUTDOWN, 721 FULLSCREEN, 722 TOTAL 723 }; 724 725 enum class VRFxEventState : uint8_t { 726 NONE = 0, 727 BLUR, 728 FOCUS, 729 FULLSCREEN_ENTER, 730 FULLSCREEN_EXIT, 731 TOTAL 732 }; 733 734 // Data shared via shmem for running Firefox in a VR windowed environment 735 struct VRWindowState { 736 // State from Firefox 737 uint64_t hwndFx; 738 uint32_t widthFx; 739 uint32_t heightFx; 740 VRLayerTextureHandle textureFx; 741 uint32_t windowID; 742 VRFxEventType eventType; 743 VRFxEventState eventState; 744 745 // State from VRHost 746 uint32_t dxgiAdapterHost; 747 uint32_t widthHost; 748 uint32_t heightHost; 749 750 // Name of synchronization primitive to signal change to this struct 751 char signalName[32]; 752 }; 753 754 enum class VRTelemetryId : uint8_t { 755 NONE = 0, 756 INSTALLED_FROM = 1, 757 ENTRY_METHOD = 2, 758 FIRST_RUN = 3, 759 TOTAL = 4, 760 }; 761 762 enum class VRTelemetryInstallFrom : uint8_t { 763 User = 0, 764 FxR = 1, 765 HTC = 2, 766 Valve = 3, 767 TOTAL = 4, 768 }; 769 770 enum class VRTelemetryEntryMethod : uint8_t { 771 SystemBtn = 0, 772 Library = 1, 773 Gaze = 2, 774 TOTAL = 3, 775 }; 776 777 struct VRTelemetryState { 778 uint32_t uid; 779 780 bool installedFrom : 1; 781 bool entryMethod : 1; 782 bool firstRun : 1; 783 784 uint8_t installedFromValue : 3; 785 uint8_t entryMethodValue : 3; 786 bool firstRunValue : 1; 787 }; 788 789 struct VRExternalShmem { 790 int32_t version; 791 int32_t size; 792 #if defined(__ANDROID__) 793 pthread_mutex_t systemMutex; 794 pthread_mutex_t geckoMutex; 795 pthread_mutex_t servoMutex; 796 pthread_cond_t systemCond; 797 pthread_cond_t geckoCond; 798 pthread_cond_t servoCond; 799 #else 800 int64_t generationA; 801 #endif // defined(__ANDROID__) 802 VRSystemState state; 803 #if !defined(__ANDROID__) 804 int64_t generationB; 805 int64_t geckoGenerationA; 806 int64_t servoGenerationA; 807 #endif // !defined(__ANDROID__) 808 VRBrowserState geckoState; 809 VRBrowserState servoState; 810 #if !defined(__ANDROID__) 811 int64_t geckoGenerationB; 812 int64_t servoGenerationB; 813 #endif // !defined(__ANDROID__) 814 #if defined(XP_WIN) 815 VRWindowState windowState; 816 VRTelemetryState telemetryState; 817 #endif 818 #ifdef MOZILLA_INTERNAL_API 819 void Clear() volatile { 820 /** 821 * When possible we do a memset_s, which is explicitly safe for 822 * the volatile, POD struct. A memset may be optimized out by 823 * the compiler and will fail to compile due to volatile keyword 824 * propagation. 825 * 826 * A loop-based fallback is provided in case the toolchain does 827 * not include STDC_LIB_EXT1 for memset_s. 828 */ 829 # ifdef __STDC_LIB_EXT1__ 830 memset_s((void*)this, sizeof(VRExternalShmem), 0, sizeof(VRExternalShmem)); 831 # else 832 size_t remaining = sizeof(VRExternalShmem); 833 volatile unsigned char* d = (volatile unsigned char*)this; 834 while (remaining--) { 835 *d++ = 0; 836 } 837 # endif 838 } 839 #endif 840 }; 841 842 // As we are memcpy'ing VRExternalShmem and its members around, it must be a POD 843 // type 844 static_assert(std::is_trivial_v<VRSystemState>); 845 static_assert(std::is_trivial_v<VRBrowserState>); 846 static_assert(std::is_trivial_v<VRWindowState>); 847 static_assert(std::is_trivial_v<VRTelemetryState>); 848 static_assert(std::is_trivial_v<VRExternalShmem>, 849 "VRExternalShmem must be a trivial type."); 850 851 } // namespace gfx 852 } // namespace mozilla 853 854 #endif /* GFX_VR_EXTERNAL_API_H */