diff --git a/.clang-format b/.clang-format index c8c48aa..7899a42 100644 --- a/.clang-format +++ b/.clang-format @@ -5,11 +5,11 @@ ColumnLimit: 80 AlignEscapedNewlines: DontAlign AlignTrailingComments: - Kind: Always - OverEmptyLines: 0 + Kind: Always + OverEmptyLines: 0 BasedOnStyle: WebKit BraceWrapping: - AfterFunction: true + AfterFunction: true BreakBeforeBraces: Custom BreakBeforeInheritanceComma: true BreakConstructorInitializers: BeforeComma @@ -18,8 +18,8 @@ IndentRequiresClause: false InsertNewlineAtEOF: true LineEnding: LF NamespaceIndentation: None -PointerAlignment: Right # east pointer -QualifierAlignment: Right # east const +PointerAlignment: Right # east pointer +QualifierAlignment: Right # east const RemoveSemicolon: true RequiresClausePosition: WithFollowing RequiresExpressionIndentation: OuterScope diff --git a/CMakeLists.txt b/CMakeLists.txt index b4c9d1f..571b72c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ pkg_check_modules(WAYLAND REQUIRED IMPORTED_TARGET GLOBAL wayland-server) pkg_check_modules(EGL REQUIRED IMPORTED_TARGET egl) pkg_check_modules(GLES2 REQUIRED IMPORTED_TARGET glesv2) pkg_check_modules(WLROOTS REQUIRED IMPORTED_TARGET wlroots-0.19) +pkg_check_modules(XKBCOMMON REQUIRED IMPORTED_TARGET xkbcommon) pkg_check_modules(OPENXR REQUIRED IMPORTED_TARGET openxr) include(FetchContent) @@ -45,6 +46,7 @@ target_sources(${PROJECT_NAME} PUBLIC FILE_SET CXX_MODULES FILES src/LunarWM.cppm ) target_link_libraries(${PROJECT_NAME} PUBLIC + PkgConfig::XKBCOMMON PkgConfig::WAYLAND PkgConfig::EGL PkgConfig::GLES2 diff --git a/flake.nix b/flake.nix index 1019b09..ba3a4b6 100644 --- a/flake.nix +++ b/flake.nix @@ -34,6 +34,7 @@ # For wlroots libxkbcommon + libxkbcommon.dev libdrm xorg.libxcb pixman diff --git a/src/LunarWM.cppm b/src/LunarWM.cppm index ce278f6..991d49c 100644 --- a/src/LunarWM.cppm +++ b/src/LunarWM.cppm @@ -20,7 +20,9 @@ extern "C" { #include #include #include +#include #include +#include #include #include } @@ -40,531 +42,688 @@ import LunarWM.Math; using Clock = std::chrono::high_resolution_clock; namespace std { -template <> struct formatter { - template constexpr auto parse(ParseContext &ctx) { - return ctx.begin(); - } +template<> struct formatter { + template constexpr auto parse(ParseContext &ctx) + { + return ctx.begin(); + } - static constexpr std::string_view to_string(XrResult r) { - switch (r) { - case XR_FRAME_DISCARDED: - return "XR_FRAME_DISCARDED"; - case XR_ERROR_VALIDATION_FAILURE: - return "XR_ERROR_VALIDATION_FAILURE: The function usage was invalid in " - "some way."; - case XR_ERROR_RUNTIME_FAILURE: - return "XR_ERROR_RUNTIME_FAILURE: The runtime failed to handle the " - "function in an unexpected way that is not covered by another " - "error result."; - case XR_ERROR_OUT_OF_MEMORY: - return "XR_ERROR_OUT_OF_MEMORY: A memory allocation has failed."; - case XR_ERROR_API_VERSION_UNSUPPORTED: - return "XR_ERROR_API_VERSION_UNSUPPORTED: The runtime does not support " - "the requested API version."; - case XR_ERROR_INITIALIZATION_FAILED: - return "XR_ERROR_INITIALIZATION_FAILED: Initialization of object could " - "not be completed."; - case XR_ERROR_FUNCTION_UNSUPPORTED: - return "XR_ERROR_FUNCTION_UNSUPPORTED: The requested function was not " - "found or is otherwise unsupported."; - case XR_ERROR_FEATURE_UNSUPPORTED: - return "XR_ERROR_FEATURE_UNSUPPORTED: The requested feature is not " - "supported."; - case XR_ERROR_EXTENSION_NOT_PRESENT: - return "XR_ERROR_EXTENSION_NOT_PRESENT: A requested extension is not " - "supported."; - case XR_ERROR_LIMIT_REACHED: - return "XR_ERROR_LIMIT_REACHED: The runtime supports no more of the " - "requested resource."; - case XR_ERROR_SIZE_INSUFFICIENT: - return "XR_ERROR_SIZE_INSUFFICIENT: The supplied size was smaller than " - "required."; - case XR_ERROR_HANDLE_INVALID: - return "XR_ERROR_HANDLE_INVALID: A supplied object handle was invalid."; - case XR_ERROR_INSTANCE_LOST: - return "XR_ERROR_INSTANCE_LOST: The XrInstance was lost or could not be " - "found. It will need to be destroyed and optionally recreated."; - case XR_ERROR_SESSION_RUNNING: - return "XR_ERROR_SESSION_RUNNING: The session is already running."; - case XR_ERROR_SESSION_NOT_RUNNING: - return "XR_ERROR_SESSION_NOT_RUNNING: The session is not yet running."; - case XR_ERROR_SESSION_LOST: - return "XR_ERROR_SESSION_LOST: The XrSession was lost. It will need to " - "be destroyed and optionally recreated."; - case XR_ERROR_SYSTEM_INVALID: - return "XR_ERROR_SYSTEM_INVALID: The provided XrSystemId was invalid."; - case XR_ERROR_PATH_INVALID: - return "XR_ERROR_PATH_INVALID: The provided XrPath was not valid."; - case XR_ERROR_PATH_COUNT_EXCEEDED: - return "XR_ERROR_PATH_COUNT_EXCEEDED: The maximum number of supported " - "semantic paths has been reached."; - case XR_ERROR_PATH_FORMAT_INVALID: - return "XR_ERROR_PATH_FORMAT_INVALID: The semantic path character format " - "is invalid."; - case XR_ERROR_PATH_UNSUPPORTED: - return "XR_ERROR_PATH_UNSUPPORTED: The semantic path is unsupported."; - case XR_ERROR_LAYER_INVALID: - return "XR_ERROR_LAYER_INVALID: The layer was NULL or otherwise invalid."; - case XR_ERROR_LAYER_LIMIT_EXCEEDED: - return "XR_ERROR_LAYER_LIMIT_EXCEEDED: The number of specified layers is " - "greater than the supported number."; - case XR_ERROR_SWAPCHAIN_RECT_INVALID: - return "XR_ERROR_SWAPCHAIN_RECT_INVALID: The image rect was negatively " - "sized or otherwise invalid."; - case XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED: - return "XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED: The image format is not " - "supported by the runtime or platform."; - case XR_ERROR_ACTION_TYPE_MISMATCH: - return "XR_ERROR_ACTION_TYPE_MISMATCH: The API used to retrieve an " - "action’s state does not match the action’s type."; - case XR_ERROR_SESSION_NOT_READY: - return "XR_ERROR_SESSION_NOT_READY: The session is not in the ready " - "state."; - case XR_ERROR_SESSION_NOT_STOPPING: - return "XR_ERROR_SESSION_NOT_STOPPING: The session is not in the " - "stopping state."; - case XR_ERROR_TIME_INVALID: - return "XR_ERROR_TIME_INVALID: The provided XrTime was zero, negative, " - "or out of range."; - case XR_ERROR_REFERENCE_SPACE_UNSUPPORTED: - return "XR_ERROR_REFERENCE_SPACE_UNSUPPORTED: The specified reference " - "space is not supported by the runtime or system."; - case XR_ERROR_FILE_ACCESS_ERROR: - return "XR_ERROR_FILE_ACCESS_ERROR: The file could not be accessed."; - case XR_ERROR_FILE_CONTENTS_INVALID: - return "XR_ERROR_FILE_CONTENTS_INVALID: The file’s contents were " - "invalid."; - case XR_ERROR_FORM_FACTOR_UNSUPPORTED: - return "XR_ERROR_FORM_FACTOR_UNSUPPORTED: The specified form factor is " - "not supported by the current runtime or platform."; - case XR_ERROR_FORM_FACTOR_UNAVAILABLE: - return "XR_ERROR_FORM_FACTOR_UNAVAILABLE: The specified form factor is " - "supported, but the device is currently not available, e.g. not " - "plugged in or powered off."; - case XR_ERROR_API_LAYER_NOT_PRESENT: - return "XR_ERROR_API_LAYER_NOT_PRESENT: A requested API layer is not " - "present or could not be loaded."; - case XR_ERROR_CALL_ORDER_INVALID: - return "XR_ERROR_CALL_ORDER_INVALID: The call was made without having " - "made a previously required call."; - case XR_ERROR_GRAPHICS_DEVICE_INVALID: - return "XR_ERROR_GRAPHICS_DEVICE_INVALID: The given graphics device is " - "not in a valid state. The graphics device could be lost or " - "initialized without meeting graphics requirements."; - case XR_ERROR_POSE_INVALID: - return "XR_ERROR_POSE_INVALID: The supplied pose was invalid with " - "respect to the requirements."; - case XR_ERROR_INDEX_OUT_OF_RANGE: - return "XR_ERROR_INDEX_OUT_OF_RANGE: The supplied index was outside the " - "range of valid indices."; - case XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED: - return "XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED: The specified view " - "configuration type is not supported by the runtime or platform."; - case XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED: - return "XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED: The specified " - "environment blend mode is not supported by the runtime or " - "platform."; - case XR_ERROR_NAME_DUPLICATED: - return "XR_ERROR_NAME_DUPLICATED: The name provided was a duplicate of " - "an already-existing resource."; - case XR_ERROR_NAME_INVALID: - return "XR_ERROR_NAME_INVALID: The name provided was invalid."; - case XR_ERROR_ACTIONSET_NOT_ATTACHED: - return "XR_ERROR_ACTIONSET_NOT_ATTACHED: A referenced action set is not " - "attached to the session."; - case XR_ERROR_ACTIONSETS_ALREADY_ATTACHED: - return "XR_ERROR_ACTIONSETS_ALREADY_ATTACHED: The session already has " - "attached action sets."; - case XR_ERROR_LOCALIZED_NAME_DUPLICATED: - return "XR_ERROR_LOCALIZED_NAME_DUPLICATED: The localized name provided " - "was a duplicate of an already-existing resource."; - case XR_ERROR_LOCALIZED_NAME_INVALID: - return "XR_ERROR_LOCALIZED_NAME_INVALID: The localized name provided was " - "invalid."; - case XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING: - return "XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING: The " - "xrGetGraphicsRequirements* call was not made before calling " - "xrCreateSession."; - case XR_ERROR_RUNTIME_UNAVAILABLE: - return "XR_ERROR_RUNTIME_UNAVAILABLE: The loader was unable to find or " - "load a runtime."; - case XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED: - return "XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED: One or more of the " - "extensions being enabled has dependency on extensions that are " - "not enabled."; - case XR_ERROR_PERMISSION_INSUFFICIENT: - return "XR_ERROR_PERMISSION_INSUFFICIENT: Insufficient permissions. This " - "error is included for use by vendor extensions. The precise " - "definition of XR_ERROR_PERMISSION_INSUFFICIENT and actions " - "possible by the developer or user to resolve it can vary by " - "platform, extension or function. The developer should refer to " - "the documentation of the function that returned the error code " - "and extension it was defined."; - case XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR: - return "XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR: " - "xrSetAndroidApplicationThreadKHR failed as thread id is invalid. " - "(Added by the XR_KHR_android_thread_settings extension)"; - case XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR: - return "XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR: " - "xrSetAndroidApplicationThreadKHR failed setting the thread " - "attributes/priority. (Added by the " - "XR_KHR_android_thread_settings extension)"; - case XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT: - return "XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT: Spatial anchor could " - "not be created at that location. (Added by the " - "XR_MSFT_spatial_anchor extension)"; - case XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT: - return "XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT: The " - "secondary view configuration was not enabled when creating the " - "session. (Added by the XR_MSFT_secondary_view_configuration " - "extension)"; - case XR_ERROR_CONTROLLER_MODEL_KEY_INVALID_MSFT: - return "XR_ERROR_CONTROLLER_MODEL_KEY_INVALID_MSFT: The controller model " - "key is invalid. (Added by the XR_MSFT_controller_model " - "extension)"; - case XR_ERROR_REPROJECTION_MODE_UNSUPPORTED_MSFT: - return "XR_ERROR_REPROJECTION_MODE_UNSUPPORTED_MSFT: The reprojection " - "mode is not supported. (Added by the " - "XR_MSFT_composition_layer_reprojection extension)"; - case XR_ERROR_COMPUTE_NEW_SCENE_NOT_COMPLETED_MSFT: - return "XR_ERROR_COMPUTE_NEW_SCENE_NOT_COMPLETED_MSFT: Compute new scene " - "not completed. (Added by the XR_MSFT_scene_understanding " - "extension)"; - case XR_ERROR_SCENE_COMPONENT_ID_INVALID_MSFT: - return "XR_ERROR_SCENE_COMPONENT_ID_INVALID_MSFT: Scene component id " - "invalid. (Added by the XR_MSFT_scene_understanding extension)"; - case XR_ERROR_SCENE_COMPONENT_TYPE_MISMATCH_MSFT: - return "XR_ERROR_SCENE_COMPONENT_TYPE_MISMATCH_MSFT: Scene component " - "type mismatch. (Added by the XR_MSFT_scene_understanding " - "extension)"; - case XR_ERROR_SCENE_MESH_BUFFER_ID_INVALID_MSFT: - return "XR_ERROR_SCENE_MESH_BUFFER_ID_INVALID_MSFT: Scene mesh buffer id " - "invalid. (Added by the XR_MSFT_scene_understanding extension)"; - case XR_ERROR_SCENE_COMPUTE_FEATURE_INCOMPATIBLE_MSFT: - return "XR_ERROR_SCENE_COMPUTE_FEATURE_INCOMPATIBLE_MSFT: Scene compute " - "feature incompatible. (Added by the XR_MSFT_scene_understanding " - "extension)"; - case XR_ERROR_SCENE_COMPUTE_CONSISTENCY_MISMATCH_MSFT: - return "XR_ERROR_SCENE_COMPUTE_CONSISTENCY_MISMATCH_MSFT: Scene compute " - "consistency mismatch. (Added by the XR_MSFT_scene_understanding " - "extension)"; - case XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB: - return "XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB: The display " - "refresh rate is not supported by the platform. (Added by the " - "XR_FB_display_refresh_rate extension)"; - case XR_ERROR_COLOR_SPACE_UNSUPPORTED_FB: - return "XR_ERROR_COLOR_SPACE_UNSUPPORTED_FB: The color space is not " - "supported by the runtime. (Added by the XR_FB_color_space " - "extension)"; - case XR_ERROR_SPACE_COMPONENT_NOT_SUPPORTED_FB: - return "XR_ERROR_SPACE_COMPONENT_NOT_SUPPORTED_FB: The component type is " - "not supported for this space. (Added by the XR_FB_spatial_entity " - "extension)"; - case XR_ERROR_SPACE_COMPONENT_NOT_ENABLED_FB: - return "XR_ERROR_SPACE_COMPONENT_NOT_ENABLED_FB: The required component " - "is not enabled for this space. (Added by the " - "XR_FB_spatial_entity extension)"; - case XR_ERROR_SPACE_COMPONENT_STATUS_PENDING_FB: - return "XR_ERROR_SPACE_COMPONENT_STATUS_PENDING_FB: A request to set the " - "component’s status is currently pending. (Added by the " - "XR_FB_spatial_entity extension)"; - case XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB: - return "XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB: The component is " - "already set to the requested value. (Added by the " - "XR_FB_spatial_entity extension)"; - case XR_ERROR_UNEXPECTED_STATE_PASSTHROUGH_FB: - return "XR_ERROR_UNEXPECTED_STATE_PASSTHROUGH_FB: The object state is " - "unexpected for the issued command. (Added by the " - "XR_FB_passthrough extension)"; - case XR_ERROR_FEATURE_ALREADY_CREATED_PASSTHROUGH_FB: - return "XR_ERROR_FEATURE_ALREADY_CREATED_PASSTHROUGH_FB: Trying to " - "create an MR feature when one was already created and only one " - "instance is allowed. (Added by the XR_FB_passthrough extension)"; - case XR_ERROR_FEATURE_REQUIRED_PASSTHROUGH_FB: - return "XR_ERROR_FEATURE_REQUIRED_PASSTHROUGH_FB: Requested " - "functionality requires a feature to be created first. (Added by " - "the XR_FB_passthrough extension)"; - case XR_ERROR_NOT_PERMITTED_PASSTHROUGH_FB: - return "XR_ERROR_NOT_PERMITTED_PASSTHROUGH_FB: Requested functionality " - "is not permitted - application is not allowed to perform the " - "requested operation. (Added by the XR_FB_passthrough extension)"; - case XR_ERROR_INSUFFICIENT_RESOURCES_PASSTHROUGH_FB: - return "XR_ERROR_INSUFFICIENT_RESOURCES_PASSTHROUGH_FB: There were " - "insufficient resources available to perform an operation. (Added " - "by the XR_FB_passthrough extension)"; - case XR_ERROR_UNKNOWN_PASSTHROUGH_FB: - return "XR_ERROR_UNKNOWN_PASSTHROUGH_FB: Unknown Passthrough error (no " - "further details provided). (Added by the XR_FB_passthrough " - "extension)"; - case XR_ERROR_RENDER_MODEL_KEY_INVALID_FB: - return "XR_ERROR_RENDER_MODEL_KEY_INVALID_FB: The model key is invalid. " - "(Added by the XR_FB_render_model extension)"; - case XR_ERROR_MARKER_NOT_TRACKED_VARJO: - return "XR_ERROR_MARKER_NOT_TRACKED_VARJO: Marker tracking is disabled " - "or the specified marker is not currently tracked. (Added by the " - "XR_VARJO_marker_tracking extension)"; - case XR_ERROR_MARKER_ID_INVALID_VARJO: - return "XR_ERROR_MARKER_ID_INVALID_VARJO: The specified marker ID is not " - "valid. (Added by the XR_VARJO_marker_tracking extension)"; - case XR_ERROR_MARKER_DETECTOR_PERMISSION_DENIED_ML: - return "XR_ERROR_MARKER_DETECTOR_PERMISSION_DENIED_ML: The " - "com.magicleap.permission.MARKER_TRACKING permission was denied. " - "(Added by the XR_ML_marker_understanding extension)"; - case XR_ERROR_MARKER_DETECTOR_LOCATE_FAILED_ML: - return "XR_ERROR_MARKER_DETECTOR_LOCATE_FAILED_ML: The specified marker " - "could not be located spatially. (Added by the " - "XR_ML_marker_understanding extension)"; - case XR_ERROR_MARKER_DETECTOR_INVALID_DATA_QUERY_ML: - return "XR_ERROR_MARKER_DETECTOR_INVALID_DATA_QUERY_ML: The marker " - "queried does not contain data of the requested type. (Added by " - "the XR_ML_marker_understanding extension)"; - case XR_ERROR_MARKER_DETECTOR_INVALID_CREATE_INFO_ML: - return "XR_ERROR_MARKER_DETECTOR_INVALID_CREATE_INFO_ML: createInfo " - "contains mutually exclusive parameters, such as setting " - "XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_APRIL_TAG_ML with " - "XR_MARKER_TYPE_ARUCO_ML. (Added by the " - "XR_ML_marker_understanding extension)"; - case XR_ERROR_MARKER_INVALID_ML: - return "XR_ERROR_MARKER_INVALID_ML: The marker id passed to the function " - "was invalid. (Added by the XR_ML_marker_understanding extension)"; - case XR_ERROR_LOCALIZATION_MAP_INCOMPATIBLE_ML: - return "XR_ERROR_LOCALIZATION_MAP_INCOMPATIBLE_ML: The localization map " - "being imported is not compatible with current OS or mode. (Added " - "by the XR_ML_localization_map extension)"; - case XR_ERROR_LOCALIZATION_MAP_UNAVAILABLE_ML: - return "XR_ERROR_LOCALIZATION_MAP_UNAVAILABLE_ML: The localization map " - "requested is not available. (Added by the XR_ML_localization_map " - "extension)"; - case XR_ERROR_LOCALIZATION_MAP_FAIL_ML: - return "XR_ERROR_LOCALIZATION_MAP_FAIL_ML: The map localization service " - "failed to fulfill the request, retry later. (Added by the " - "XR_ML_localization_map extension)"; - case XR_ERROR_LOCALIZATION_MAP_IMPORT_EXPORT_PERMISSION_DENIED_ML: - return "XR_ERROR_LOCALIZATION_MAP_IMPORT_EXPORT_PERMISSION_DENIED_ML: " - "The com.magicleap.permission.SPACE_IMPORT_EXPORT permission was " - "denied. (Added by the XR_ML_localization_map extension)"; - case XR_ERROR_LOCALIZATION_MAP_PERMISSION_DENIED_ML: - return "XR_ERROR_LOCALIZATION_MAP_PERMISSION_DENIED_ML: The " - "com.magicleap.permission.SPACE_MANAGER permission was denied. " - "(Added by the XR_ML_localization_map extension)"; - case XR_ERROR_LOCALIZATION_MAP_ALREADY_EXISTS_ML: - return "XR_ERROR_LOCALIZATION_MAP_ALREADY_EXISTS_ML: The map being " - "imported already exists in the system. (Added by the " - "XR_ML_localization_map extension)"; - case XR_ERROR_LOCALIZATION_MAP_CANNOT_EXPORT_CLOUD_MAP_ML: - return "XR_ERROR_LOCALIZATION_MAP_CANNOT_EXPORT_CLOUD_MAP_ML: The map " - "localization service cannot export cloud based maps. (Added by " - "the XR_ML_localization_map extension)"; - case XR_ERROR_SPATIAL_ANCHORS_PERMISSION_DENIED_ML: - return "XR_ERROR_SPATIAL_ANCHORS_PERMISSION_DENIED_ML: The " - "com.magicleap.permission.SPATIAL_ANCHOR permission was not " - "granted. (Added by the XR_ML_spatial_anchors extension)"; - case XR_ERROR_SPATIAL_ANCHORS_NOT_LOCALIZED_ML: - return "XR_ERROR_SPATIAL_ANCHORS_NOT_LOCALIZED_ML: Operation failed " - "because the system is not localized into a localization map. " - "(Added by the XR_ML_spatial_anchors extension)"; - case XR_ERROR_SPATIAL_ANCHORS_OUT_OF_MAP_BOUNDS_ML: - return "XR_ERROR_SPATIAL_ANCHORS_OUT_OF_MAP_BOUNDS_ML: Operation failed " - "because it is performed outside of the localization map. (Added " - "by the XR_ML_spatial_anchors extension)"; - case XR_ERROR_SPATIAL_ANCHORS_SPACE_NOT_LOCATABLE_ML: - return "XR_ERROR_SPATIAL_ANCHORS_SPACE_NOT_LOCATABLE_ML: Operation " - "failed because the space referenced cannot be located. (Added by " - "the XR_ML_spatial_anchors extension)"; - case XR_ERROR_SPATIAL_ANCHORS_ANCHOR_NOT_FOUND_ML: - return "XR_ERROR_SPATIAL_ANCHORS_ANCHOR_NOT_FOUND_ML: The anchor " - "references was not found. (Added by the " - "XR_ML_spatial_anchors_storage extension)"; - case XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT: - return "XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT: A spatial anchor " - "was not found associated with the spatial anchor name provided " - "(Added by the XR_MSFT_spatial_anchor_persistence extension)"; - case XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT: - return "XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT: The spatial anchor " - "name provided was not valid (Added by the " - "XR_MSFT_spatial_anchor_persistence extension)"; - case XR_ERROR_SPACE_MAPPING_INSUFFICIENT_FB: - return "XR_ERROR_SPACE_MAPPING_INSUFFICIENT_FB: Anchor import from cloud " - "or export from device failed. (Added by the " - "XR_FB_spatial_entity_sharing extension)"; - case XR_ERROR_SPACE_LOCALIZATION_FAILED_FB: - return "XR_ERROR_SPACE_LOCALIZATION_FAILED_FB: Anchors were downloaded " - "from the cloud but failed to be imported/aligned on the device. " - "(Added by the XR_FB_spatial_entity_sharing extension)"; - case XR_ERROR_SPACE_NETWORK_TIMEOUT_FB: - return "XR_ERROR_SPACE_NETWORK_TIMEOUT_FB: Timeout occurred while " - "waiting for network request to complete. (Added by the " - "XR_FB_spatial_entity_sharing extension)"; - case XR_ERROR_SPACE_NETWORK_REQUEST_FAILED_FB: - return "XR_ERROR_SPACE_NETWORK_REQUEST_FAILED_FB: The network request " - "failed. (Added by the XR_FB_spatial_entity_sharing extension)"; - case XR_ERROR_SPACE_CLOUD_STORAGE_DISABLED_FB: - return "XR_ERROR_SPACE_CLOUD_STORAGE_DISABLED_FB: Cloud storage is " - "required for this operation but is currently disabled. (Added by " - "the XR_FB_spatial_entity_sharing extension)"; - case XR_ERROR_PASSTHROUGH_COLOR_LUT_BUFFER_SIZE_MISMATCH_META: - return "XR_ERROR_PASSTHROUGH_COLOR_LUT_BUFFER_SIZE_MISMATCH_META: The " - "provided data buffer did not match the required size. (Added by " - "the XR_META_passthrough_color_lut extension)"; - case XR_ERROR_RENDER_MODEL_ID_INVALID_EXT: - return "XR_ERROR_RENDER_MODEL_ID_INVALID_EXT: The render model ID is " - "invalid. (Added by the XR_EXT_render_model extension)"; - case XR_ERROR_RENDER_MODEL_ASSET_UNAVAILABLE_EXT: - return "XR_ERROR_RENDER_MODEL_ASSET_UNAVAILABLE_EXT: The render model " - "asset is unavailable. (Added by the XR_EXT_render_model " - "extension)"; - case XR_ERROR_RENDER_MODEL_GLTF_EXTENSION_REQUIRED_EXT: - return "XR_ERROR_RENDER_MODEL_GLTF_EXTENSION_REQUIRED_EXT: A glTF " - "extension is required. (Added by the XR_EXT_render_model " - "extension)"; - case XR_ERROR_NOT_INTERACTION_RENDER_MODEL_EXT: - return "XR_ERROR_NOT_INTERACTION_RENDER_MODEL_EXT: The provided " - "XrRenderModelEXT was not created from a XrRenderModelIdEXT from " - "[XR_EXT_interaction_render_model] (Added by the " - "XR_EXT_interaction_render_model extension)"; - case XR_ERROR_HINT_ALREADY_SET_QCOM: - return "XR_ERROR_HINT_ALREADY_SET_QCOM: Tracking optimization hint is " - "already set for the domain. (Added by the " - "XR_QCOM_tracking_optimization_settings extension)"; - case XR_ERROR_NOT_AN_ANCHOR_HTC: - return "XR_ERROR_NOT_AN_ANCHOR_HTC: The provided space is valid but not " - "an anchor. (Added by the XR_HTC_anchor extension)"; - case XR_ERROR_SPATIAL_ENTITY_ID_INVALID_BD: - return "XR_ERROR_SPATIAL_ENTITY_ID_INVALID_BD: The spatial entity id is " - "invalid. (Added by the XR_BD_spatial_sensing extension)"; - case XR_ERROR_SPATIAL_SENSING_SERVICE_UNAVAILABLE_BD: - return "XR_ERROR_SPATIAL_SENSING_SERVICE_UNAVAILABLE_BD: The spatial " - "sensing service is unavailable. (Added by the " - "XR_BD_spatial_sensing extension)"; - case XR_ERROR_ANCHOR_NOT_SUPPORTED_FOR_ENTITY_BD: - return "XR_ERROR_ANCHOR_NOT_SUPPORTED_FOR_ENTITY_BD: The spatial entity " - "does not support anchor. (Added by the XR_BD_spatial_sensing " - "extension)"; - case XR_ERROR_SCENE_CAPTURE_FAILURE_BD: - return "XR_ERROR_SCENE_CAPTURE_FAILURE_BD: The scene capture is failed, " - "for example exiting abnormally. (Added by the " - "XR_BD_spatial_scene extension)"; - case XR_ERROR_SPACE_NOT_LOCATABLE_EXT: - return "XR_ERROR_SPACE_NOT_LOCATABLE_EXT: The space passed to the " - "function was not locatable. (Added by the XR_EXT_plane_detection " - "extension)"; - case XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT: - return "XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT: The permission " - "for this resource was not granted. (Added by the " - "XR_EXT_plane_detection extension)"; - case XR_ERROR_FUTURE_PENDING_EXT: - return "XR_ERROR_FUTURE_PENDING_EXT: Returned by completion function to " - "indicate future is not ready. (Added by the XR_EXT_future " - "extension)"; - case XR_ERROR_FUTURE_INVALID_EXT: - return "XR_ERROR_FUTURE_INVALID_EXT: Returned by completion function to " - "indicate future is not valid. (Added by the XR_EXT_future " - "extension)"; - case XR_ERROR_SYSTEM_NOTIFICATION_PERMISSION_DENIED_ML: - return "XR_ERROR_SYSTEM_NOTIFICATION_PERMISSION_DENIED_ML: The " - "com.magicleap.permission.SYSTEM_NOTIFICATION permission was not " - "granted. (Added by the XR_ML_system_notifications extension)"; - case XR_ERROR_SYSTEM_NOTIFICATION_INCOMPATIBLE_SKU_ML: - return "XR_ERROR_SYSTEM_NOTIFICATION_INCOMPATIBLE_SKU_ML: Incompatible " - "SKU detected. (Added by the XR_ML_system_notifications " - "extension)"; - case XR_ERROR_WORLD_MESH_DETECTOR_PERMISSION_DENIED_ML: - return "XR_ERROR_WORLD_MESH_DETECTOR_PERMISSION_DENIED_ML: The world " - "mesh detector permission was not granted. (Added by the " - "XR_ML_world_mesh_detection extension)"; - case XR_ERROR_WORLD_MESH_DETECTOR_SPACE_NOT_LOCATABLE_ML: - return "XR_ERROR_WORLD_MESH_DETECTOR_SPACE_NOT_LOCATABLE_ML: At the time " - "of the call the runtime was unable to locate the space and " - "cannot fulfill your request. (Added by the " - "XR_ML_world_mesh_detection extension)"; - case XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META: - return "XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META: The network " - "request failed. (Added by the XR_META_colocation_discovery " - "extension)"; - case XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META: - return "XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META: The " - "runtime does not have any methods available to perform " - "discovery. (Added by the XR_META_colocation_discovery extension)"; - case XR_ERROR_SPACE_GROUP_NOT_FOUND_META: - return "XR_ERROR_SPACE_GROUP_NOT_FOUND_META: The group UUID was not " - "found within the runtime (Added by the " - "XR_META_spatial_entity_group_sharing extension)"; - case XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT: - return "XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT: The specified " - "spatial capability is not supported by the runtime or the " - "system. (Added by the XR_EXT_spatial_entity extension)"; - case XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT: - return "XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT: The specified spatial " - "entity id is invalid or an entity with that id does not exist in " - "the environment. (Added by the XR_EXT_spatial_entity extension)"; - case XR_ERROR_SPATIAL_BUFFER_ID_INVALID_EXT: - return "XR_ERROR_SPATIAL_BUFFER_ID_INVALID_EXT: The specified spatial " - "buffer id is invalid or does not exist in the spatial snapshot " - "being used to query for the buffer data. (Added by the " - "XR_EXT_spatial_entity extension)"; - case XR_ERROR_SPATIAL_COMPONENT_UNSUPPORTED_FOR_CAPABILITY_EXT: - return "XR_ERROR_SPATIAL_COMPONENT_UNSUPPORTED_FOR_CAPABILITY_EXT: The " - "specified spatial component is not supported by the runtime or " - "the system for the given capability. (Added by the " - "XR_EXT_spatial_entity extension)"; - case XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT: - return "XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT: The " - "specified spatial capability configuration is invalid. (Added by " - "the XR_EXT_spatial_entity extension)"; - case XR_ERROR_SPATIAL_COMPONENT_NOT_ENABLED_EXT: - return "XR_ERROR_SPATIAL_COMPONENT_NOT_ENABLED_EXT: The specified " - "spatial component is not enabled for the spatial context. (Added " - "by the XR_EXT_spatial_entity extension)"; - case XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT: - return "XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT: The " - "specified spatial persistence scope is not supported by the " - "runtime or the system. (Added by the XR_EXT_spatial_persistence " - "extension)"; - case XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_INCOMPATIBLE_EXT: - return "XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_INCOMPATIBLE_EXT: THe scope " - "configured for the persistence context is incompatible for the " - "current spatial entity. (Added by the " - "XR_EXT_spatial_persistence_operations extension)"; - default: - return ""; - } - } + static constexpr std::string_view to_string(XrResult r) + { + switch (r) { + case XR_FRAME_DISCARDED: + return "XR_FRAME_DISCARDED"; + case XR_ERROR_VALIDATION_FAILURE: + return "XR_ERROR_VALIDATION_FAILURE: The function usage was " + "invalid in " + "some way."; + case XR_ERROR_RUNTIME_FAILURE: + return "XR_ERROR_RUNTIME_FAILURE: The runtime failed to handle the " + "function in an unexpected way that is not covered by " + "another " + "error result."; + case XR_ERROR_OUT_OF_MEMORY: + return "XR_ERROR_OUT_OF_MEMORY: A memory allocation has failed."; + case XR_ERROR_API_VERSION_UNSUPPORTED: + return "XR_ERROR_API_VERSION_UNSUPPORTED: The runtime does not " + "support " + "the requested API version."; + case XR_ERROR_INITIALIZATION_FAILED: + return "XR_ERROR_INITIALIZATION_FAILED: Initialization of object " + "could " + "not be completed."; + case XR_ERROR_FUNCTION_UNSUPPORTED: + return "XR_ERROR_FUNCTION_UNSUPPORTED: The requested function was " + "not " + "found or is otherwise unsupported."; + case XR_ERROR_FEATURE_UNSUPPORTED: + return "XR_ERROR_FEATURE_UNSUPPORTED: The requested feature is not " + "supported."; + case XR_ERROR_EXTENSION_NOT_PRESENT: + return "XR_ERROR_EXTENSION_NOT_PRESENT: A requested extension is " + "not " + "supported."; + case XR_ERROR_LIMIT_REACHED: + return "XR_ERROR_LIMIT_REACHED: The runtime supports no more of " + "the " + "requested resource."; + case XR_ERROR_SIZE_INSUFFICIENT: + return "XR_ERROR_SIZE_INSUFFICIENT: The supplied size was smaller " + "than " + "required."; + case XR_ERROR_HANDLE_INVALID: + return "XR_ERROR_HANDLE_INVALID: A supplied object handle was " + "invalid."; + case XR_ERROR_INSTANCE_LOST: + return "XR_ERROR_INSTANCE_LOST: The XrInstance was lost or could " + "not be " + "found. It will need to be destroyed and optionally " + "recreated."; + case XR_ERROR_SESSION_RUNNING: + return "XR_ERROR_SESSION_RUNNING: The session is already running."; + case XR_ERROR_SESSION_NOT_RUNNING: + return "XR_ERROR_SESSION_NOT_RUNNING: The session is not yet " + "running."; + case XR_ERROR_SESSION_LOST: + return "XR_ERROR_SESSION_LOST: The XrSession was lost. It will " + "need to " + "be destroyed and optionally recreated."; + case XR_ERROR_SYSTEM_INVALID: + return "XR_ERROR_SYSTEM_INVALID: The provided XrSystemId was " + "invalid."; + case XR_ERROR_PATH_INVALID: + return "XR_ERROR_PATH_INVALID: The provided XrPath was not valid."; + case XR_ERROR_PATH_COUNT_EXCEEDED: + return "XR_ERROR_PATH_COUNT_EXCEEDED: The maximum number of " + "supported " + "semantic paths has been reached."; + case XR_ERROR_PATH_FORMAT_INVALID: + return "XR_ERROR_PATH_FORMAT_INVALID: The semantic path character " + "format " + "is invalid."; + case XR_ERROR_PATH_UNSUPPORTED: + return "XR_ERROR_PATH_UNSUPPORTED: The semantic path is " + "unsupported."; + case XR_ERROR_LAYER_INVALID: + return "XR_ERROR_LAYER_INVALID: The layer was NULL or otherwise " + "invalid."; + case XR_ERROR_LAYER_LIMIT_EXCEEDED: + return "XR_ERROR_LAYER_LIMIT_EXCEEDED: The number of specified " + "layers is " + "greater than the supported number."; + case XR_ERROR_SWAPCHAIN_RECT_INVALID: + return "XR_ERROR_SWAPCHAIN_RECT_INVALID: The image rect was " + "negatively " + "sized or otherwise invalid."; + case XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED: + return "XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED: The image format is " + "not " + "supported by the runtime or platform."; + case XR_ERROR_ACTION_TYPE_MISMATCH: + return "XR_ERROR_ACTION_TYPE_MISMATCH: The API used to retrieve an " + "action’s state does not match the action’s type."; + case XR_ERROR_SESSION_NOT_READY: + return "XR_ERROR_SESSION_NOT_READY: The session is not in the " + "ready " + "state."; + case XR_ERROR_SESSION_NOT_STOPPING: + return "XR_ERROR_SESSION_NOT_STOPPING: The session is not in the " + "stopping state."; + case XR_ERROR_TIME_INVALID: + return "XR_ERROR_TIME_INVALID: The provided XrTime was zero, " + "negative, " + "or out of range."; + case XR_ERROR_REFERENCE_SPACE_UNSUPPORTED: + return "XR_ERROR_REFERENCE_SPACE_UNSUPPORTED: The specified " + "reference " + "space is not supported by the runtime or system."; + case XR_ERROR_FILE_ACCESS_ERROR: + return "XR_ERROR_FILE_ACCESS_ERROR: The file could not be " + "accessed."; + case XR_ERROR_FILE_CONTENTS_INVALID: + return "XR_ERROR_FILE_CONTENTS_INVALID: The file’s contents were " + "invalid."; + case XR_ERROR_FORM_FACTOR_UNSUPPORTED: + return "XR_ERROR_FORM_FACTOR_UNSUPPORTED: The specified form " + "factor is " + "not supported by the current runtime or platform."; + case XR_ERROR_FORM_FACTOR_UNAVAILABLE: + return "XR_ERROR_FORM_FACTOR_UNAVAILABLE: The specified form " + "factor is " + "supported, but the device is currently not available, e.g. " + "not " + "plugged in or powered off."; + case XR_ERROR_API_LAYER_NOT_PRESENT: + return "XR_ERROR_API_LAYER_NOT_PRESENT: A requested API layer is " + "not " + "present or could not be loaded."; + case XR_ERROR_CALL_ORDER_INVALID: + return "XR_ERROR_CALL_ORDER_INVALID: The call was made without " + "having " + "made a previously required call."; + case XR_ERROR_GRAPHICS_DEVICE_INVALID: + return "XR_ERROR_GRAPHICS_DEVICE_INVALID: The given graphics " + "device is " + "not in a valid state. The graphics device could be lost or " + "initialized without meeting graphics requirements."; + case XR_ERROR_POSE_INVALID: + return "XR_ERROR_POSE_INVALID: The supplied pose was invalid with " + "respect to the requirements."; + case XR_ERROR_INDEX_OUT_OF_RANGE: + return "XR_ERROR_INDEX_OUT_OF_RANGE: The supplied index was " + "outside the " + "range of valid indices."; + case XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED: + return "XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED: The " + "specified view " + "configuration type is not supported by the runtime or " + "platform."; + case XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED: + return "XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED: The specified " + "environment blend mode is not supported by the runtime or " + "platform."; + case XR_ERROR_NAME_DUPLICATED: + return "XR_ERROR_NAME_DUPLICATED: The name provided was a " + "duplicate of " + "an already-existing resource."; + case XR_ERROR_NAME_INVALID: + return "XR_ERROR_NAME_INVALID: The name provided was invalid."; + case XR_ERROR_ACTIONSET_NOT_ATTACHED: + return "XR_ERROR_ACTIONSET_NOT_ATTACHED: A referenced action set " + "is not " + "attached to the session."; + case XR_ERROR_ACTIONSETS_ALREADY_ATTACHED: + return "XR_ERROR_ACTIONSETS_ALREADY_ATTACHED: The session already " + "has " + "attached action sets."; + case XR_ERROR_LOCALIZED_NAME_DUPLICATED: + return "XR_ERROR_LOCALIZED_NAME_DUPLICATED: The localized name " + "provided " + "was a duplicate of an already-existing resource."; + case XR_ERROR_LOCALIZED_NAME_INVALID: + return "XR_ERROR_LOCALIZED_NAME_INVALID: The localized name " + "provided was " + "invalid."; + case XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING: + return "XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING: The " + "xrGetGraphicsRequirements* call was not made before " + "calling " + "xrCreateSession."; + case XR_ERROR_RUNTIME_UNAVAILABLE: + return "XR_ERROR_RUNTIME_UNAVAILABLE: The loader was unable to " + "find or " + "load a runtime."; + case XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED: + return "XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED: One or more of " + "the " + "extensions being enabled has dependency on extensions that " + "are " + "not enabled."; + case XR_ERROR_PERMISSION_INSUFFICIENT: + return "XR_ERROR_PERMISSION_INSUFFICIENT: Insufficient " + "permissions. This " + "error is included for use by vendor extensions. The " + "precise " + "definition of XR_ERROR_PERMISSION_INSUFFICIENT and actions " + "possible by the developer or user to resolve it can vary " + "by " + "platform, extension or function. The developer should " + "refer to " + "the documentation of the function that returned the error " + "code " + "and extension it was defined."; + case XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR: + return "XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR: " + "xrSetAndroidApplicationThreadKHR failed as thread id is " + "invalid. " + "(Added by the XR_KHR_android_thread_settings extension)"; + case XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR: + return "XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR: " + "xrSetAndroidApplicationThreadKHR failed setting the thread " + "attributes/priority. (Added by the " + "XR_KHR_android_thread_settings extension)"; + case XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT: + return "XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT: Spatial anchor " + "could " + "not be created at that location. (Added by the " + "XR_MSFT_spatial_anchor extension)"; + case XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT: + return "XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_" + "MSFT: The " + "secondary view configuration was not enabled when creating " + "the " + "session. (Added by the " + "XR_MSFT_secondary_view_configuration " + "extension)"; + case XR_ERROR_CONTROLLER_MODEL_KEY_INVALID_MSFT: + return "XR_ERROR_CONTROLLER_MODEL_KEY_INVALID_MSFT: The controller " + "model " + "key is invalid. (Added by the XR_MSFT_controller_model " + "extension)"; + case XR_ERROR_REPROJECTION_MODE_UNSUPPORTED_MSFT: + return "XR_ERROR_REPROJECTION_MODE_UNSUPPORTED_MSFT: The " + "reprojection " + "mode is not supported. (Added by the " + "XR_MSFT_composition_layer_reprojection extension)"; + case XR_ERROR_COMPUTE_NEW_SCENE_NOT_COMPLETED_MSFT: + return "XR_ERROR_COMPUTE_NEW_SCENE_NOT_COMPLETED_MSFT: Compute new " + "scene " + "not completed. (Added by the XR_MSFT_scene_understanding " + "extension)"; + case XR_ERROR_SCENE_COMPONENT_ID_INVALID_MSFT: + return "XR_ERROR_SCENE_COMPONENT_ID_INVALID_MSFT: Scene component " + "id " + "invalid. (Added by the XR_MSFT_scene_understanding " + "extension)"; + case XR_ERROR_SCENE_COMPONENT_TYPE_MISMATCH_MSFT: + return "XR_ERROR_SCENE_COMPONENT_TYPE_MISMATCH_MSFT: Scene " + "component " + "type mismatch. (Added by the XR_MSFT_scene_understanding " + "extension)"; + case XR_ERROR_SCENE_MESH_BUFFER_ID_INVALID_MSFT: + return "XR_ERROR_SCENE_MESH_BUFFER_ID_INVALID_MSFT: Scene mesh " + "buffer id " + "invalid. (Added by the XR_MSFT_scene_understanding " + "extension)"; + case XR_ERROR_SCENE_COMPUTE_FEATURE_INCOMPATIBLE_MSFT: + return "XR_ERROR_SCENE_COMPUTE_FEATURE_INCOMPATIBLE_MSFT: Scene " + "compute " + "feature incompatible. (Added by the " + "XR_MSFT_scene_understanding " + "extension)"; + case XR_ERROR_SCENE_COMPUTE_CONSISTENCY_MISMATCH_MSFT: + return "XR_ERROR_SCENE_COMPUTE_CONSISTENCY_MISMATCH_MSFT: Scene " + "compute " + "consistency mismatch. (Added by the " + "XR_MSFT_scene_understanding " + "extension)"; + case XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB: + return "XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB: The display " + "refresh rate is not supported by the platform. (Added by " + "the " + "XR_FB_display_refresh_rate extension)"; + case XR_ERROR_COLOR_SPACE_UNSUPPORTED_FB: + return "XR_ERROR_COLOR_SPACE_UNSUPPORTED_FB: The color space is " + "not " + "supported by the runtime. (Added by the XR_FB_color_space " + "extension)"; + case XR_ERROR_SPACE_COMPONENT_NOT_SUPPORTED_FB: + return "XR_ERROR_SPACE_COMPONENT_NOT_SUPPORTED_FB: The component " + "type is " + "not supported for this space. (Added by the " + "XR_FB_spatial_entity " + "extension)"; + case XR_ERROR_SPACE_COMPONENT_NOT_ENABLED_FB: + return "XR_ERROR_SPACE_COMPONENT_NOT_ENABLED_FB: The required " + "component " + "is not enabled for this space. (Added by the " + "XR_FB_spatial_entity extension)"; + case XR_ERROR_SPACE_COMPONENT_STATUS_PENDING_FB: + return "XR_ERROR_SPACE_COMPONENT_STATUS_PENDING_FB: A request to " + "set the " + "component’s status is currently pending. (Added by the " + "XR_FB_spatial_entity extension)"; + case XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB: + return "XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB: The " + "component is " + "already set to the requested value. (Added by the " + "XR_FB_spatial_entity extension)"; + case XR_ERROR_UNEXPECTED_STATE_PASSTHROUGH_FB: + return "XR_ERROR_UNEXPECTED_STATE_PASSTHROUGH_FB: The object state " + "is " + "unexpected for the issued command. (Added by the " + "XR_FB_passthrough extension)"; + case XR_ERROR_FEATURE_ALREADY_CREATED_PASSTHROUGH_FB: + return "XR_ERROR_FEATURE_ALREADY_CREATED_PASSTHROUGH_FB: Trying to " + "create an MR feature when one was already created and only " + "one " + "instance is allowed. (Added by the XR_FB_passthrough " + "extension)"; + case XR_ERROR_FEATURE_REQUIRED_PASSTHROUGH_FB: + return "XR_ERROR_FEATURE_REQUIRED_PASSTHROUGH_FB: Requested " + "functionality requires a feature to be created first. " + "(Added by " + "the XR_FB_passthrough extension)"; + case XR_ERROR_NOT_PERMITTED_PASSTHROUGH_FB: + return "XR_ERROR_NOT_PERMITTED_PASSTHROUGH_FB: Requested " + "functionality " + "is not permitted - application is not allowed to perform " + "the " + "requested operation. (Added by the XR_FB_passthrough " + "extension)"; + case XR_ERROR_INSUFFICIENT_RESOURCES_PASSTHROUGH_FB: + return "XR_ERROR_INSUFFICIENT_RESOURCES_PASSTHROUGH_FB: There were " + "insufficient resources available to perform an operation. " + "(Added " + "by the XR_FB_passthrough extension)"; + case XR_ERROR_UNKNOWN_PASSTHROUGH_FB: + return "XR_ERROR_UNKNOWN_PASSTHROUGH_FB: Unknown Passthrough error " + "(no " + "further details provided). (Added by the XR_FB_passthrough " + "extension)"; + case XR_ERROR_RENDER_MODEL_KEY_INVALID_FB: + return "XR_ERROR_RENDER_MODEL_KEY_INVALID_FB: The model key is " + "invalid. " + "(Added by the XR_FB_render_model extension)"; + case XR_ERROR_MARKER_NOT_TRACKED_VARJO: + return "XR_ERROR_MARKER_NOT_TRACKED_VARJO: Marker tracking is " + "disabled " + "or the specified marker is not currently tracked. (Added " + "by the " + "XR_VARJO_marker_tracking extension)"; + case XR_ERROR_MARKER_ID_INVALID_VARJO: + return "XR_ERROR_MARKER_ID_INVALID_VARJO: The specified marker ID " + "is not " + "valid. (Added by the XR_VARJO_marker_tracking extension)"; + case XR_ERROR_MARKER_DETECTOR_PERMISSION_DENIED_ML: + return "XR_ERROR_MARKER_DETECTOR_PERMISSION_DENIED_ML: The " + "com.magicleap.permission.MARKER_TRACKING permission was " + "denied. " + "(Added by the XR_ML_marker_understanding extension)"; + case XR_ERROR_MARKER_DETECTOR_LOCATE_FAILED_ML: + return "XR_ERROR_MARKER_DETECTOR_LOCATE_FAILED_ML: The specified " + "marker " + "could not be located spatially. (Added by the " + "XR_ML_marker_understanding extension)"; + case XR_ERROR_MARKER_DETECTOR_INVALID_DATA_QUERY_ML: + return "XR_ERROR_MARKER_DETECTOR_INVALID_DATA_QUERY_ML: The marker " + "queried does not contain data of the requested type. " + "(Added by " + "the XR_ML_marker_understanding extension)"; + case XR_ERROR_MARKER_DETECTOR_INVALID_CREATE_INFO_ML: + return "XR_ERROR_MARKER_DETECTOR_INVALID_CREATE_INFO_ML: " + "createInfo " + "contains mutually exclusive parameters, such as setting " + "XR_MARKER_DETECTOR_CORNER_REFINE_METHOD_APRIL_TAG_ML with " + "XR_MARKER_TYPE_ARUCO_ML. (Added by the " + "XR_ML_marker_understanding extension)"; + case XR_ERROR_MARKER_INVALID_ML: + return "XR_ERROR_MARKER_INVALID_ML: The marker id passed to the " + "function " + "was invalid. (Added by the XR_ML_marker_understanding " + "extension)"; + case XR_ERROR_LOCALIZATION_MAP_INCOMPATIBLE_ML: + return "XR_ERROR_LOCALIZATION_MAP_INCOMPATIBLE_ML: The " + "localization map " + "being imported is not compatible with current OS or mode. " + "(Added " + "by the XR_ML_localization_map extension)"; + case XR_ERROR_LOCALIZATION_MAP_UNAVAILABLE_ML: + return "XR_ERROR_LOCALIZATION_MAP_UNAVAILABLE_ML: The localization " + "map " + "requested is not available. (Added by the " + "XR_ML_localization_map " + "extension)"; + case XR_ERROR_LOCALIZATION_MAP_FAIL_ML: + return "XR_ERROR_LOCALIZATION_MAP_FAIL_ML: The map localization " + "service " + "failed to fulfill the request, retry later. (Added by the " + "XR_ML_localization_map extension)"; + case XR_ERROR_LOCALIZATION_MAP_IMPORT_EXPORT_PERMISSION_DENIED_ML: + return "XR_ERROR_LOCALIZATION_MAP_IMPORT_EXPORT_PERMISSION_DENIED_" + "ML: " + "The com.magicleap.permission.SPACE_IMPORT_EXPORT " + "permission was " + "denied. (Added by the XR_ML_localization_map extension)"; + case XR_ERROR_LOCALIZATION_MAP_PERMISSION_DENIED_ML: + return "XR_ERROR_LOCALIZATION_MAP_PERMISSION_DENIED_ML: The " + "com.magicleap.permission.SPACE_MANAGER permission was " + "denied. " + "(Added by the XR_ML_localization_map extension)"; + case XR_ERROR_LOCALIZATION_MAP_ALREADY_EXISTS_ML: + return "XR_ERROR_LOCALIZATION_MAP_ALREADY_EXISTS_ML: The map being " + "imported already exists in the system. (Added by the " + "XR_ML_localization_map extension)"; + case XR_ERROR_LOCALIZATION_MAP_CANNOT_EXPORT_CLOUD_MAP_ML: + return "XR_ERROR_LOCALIZATION_MAP_CANNOT_EXPORT_CLOUD_MAP_ML: The " + "map " + "localization service cannot export cloud based maps. " + "(Added by " + "the XR_ML_localization_map extension)"; + case XR_ERROR_SPATIAL_ANCHORS_PERMISSION_DENIED_ML: + return "XR_ERROR_SPATIAL_ANCHORS_PERMISSION_DENIED_ML: The " + "com.magicleap.permission.SPATIAL_ANCHOR permission was not " + "granted. (Added by the XR_ML_spatial_anchors extension)"; + case XR_ERROR_SPATIAL_ANCHORS_NOT_LOCALIZED_ML: + return "XR_ERROR_SPATIAL_ANCHORS_NOT_LOCALIZED_ML: Operation " + "failed " + "because the system is not localized into a localization " + "map. " + "(Added by the XR_ML_spatial_anchors extension)"; + case XR_ERROR_SPATIAL_ANCHORS_OUT_OF_MAP_BOUNDS_ML: + return "XR_ERROR_SPATIAL_ANCHORS_OUT_OF_MAP_BOUNDS_ML: Operation " + "failed " + "because it is performed outside of the localization map. " + "(Added " + "by the XR_ML_spatial_anchors extension)"; + case XR_ERROR_SPATIAL_ANCHORS_SPACE_NOT_LOCATABLE_ML: + return "XR_ERROR_SPATIAL_ANCHORS_SPACE_NOT_LOCATABLE_ML: Operation " + "failed because the space referenced cannot be located. " + "(Added by " + "the XR_ML_spatial_anchors extension)"; + case XR_ERROR_SPATIAL_ANCHORS_ANCHOR_NOT_FOUND_ML: + return "XR_ERROR_SPATIAL_ANCHORS_ANCHOR_NOT_FOUND_ML: The anchor " + "references was not found. (Added by the " + "XR_ML_spatial_anchors_storage extension)"; + case XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT: + return "XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT: A spatial " + "anchor " + "was not found associated with the spatial anchor name " + "provided " + "(Added by the XR_MSFT_spatial_anchor_persistence " + "extension)"; + case XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT: + return "XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT: The spatial " + "anchor " + "name provided was not valid (Added by the " + "XR_MSFT_spatial_anchor_persistence extension)"; + case XR_ERROR_SPACE_MAPPING_INSUFFICIENT_FB: + return "XR_ERROR_SPACE_MAPPING_INSUFFICIENT_FB: Anchor import from " + "cloud " + "or export from device failed. (Added by the " + "XR_FB_spatial_entity_sharing extension)"; + case XR_ERROR_SPACE_LOCALIZATION_FAILED_FB: + return "XR_ERROR_SPACE_LOCALIZATION_FAILED_FB: Anchors were " + "downloaded " + "from the cloud but failed to be imported/aligned on the " + "device. " + "(Added by the XR_FB_spatial_entity_sharing extension)"; + case XR_ERROR_SPACE_NETWORK_TIMEOUT_FB: + return "XR_ERROR_SPACE_NETWORK_TIMEOUT_FB: Timeout occurred while " + "waiting for network request to complete. (Added by the " + "XR_FB_spatial_entity_sharing extension)"; + case XR_ERROR_SPACE_NETWORK_REQUEST_FAILED_FB: + return "XR_ERROR_SPACE_NETWORK_REQUEST_FAILED_FB: The network " + "request " + "failed. (Added by the XR_FB_spatial_entity_sharing " + "extension)"; + case XR_ERROR_SPACE_CLOUD_STORAGE_DISABLED_FB: + return "XR_ERROR_SPACE_CLOUD_STORAGE_DISABLED_FB: Cloud storage is " + "required for this operation but is currently disabled. " + "(Added by " + "the XR_FB_spatial_entity_sharing extension)"; + case XR_ERROR_PASSTHROUGH_COLOR_LUT_BUFFER_SIZE_MISMATCH_META: + return "XR_ERROR_PASSTHROUGH_COLOR_LUT_BUFFER_SIZE_MISMATCH_META: " + "The " + "provided data buffer did not match the required size. " + "(Added by " + "the XR_META_passthrough_color_lut extension)"; + case XR_ERROR_RENDER_MODEL_ID_INVALID_EXT: + return "XR_ERROR_RENDER_MODEL_ID_INVALID_EXT: The render model ID " + "is " + "invalid. (Added by the XR_EXT_render_model extension)"; + case XR_ERROR_RENDER_MODEL_ASSET_UNAVAILABLE_EXT: + return "XR_ERROR_RENDER_MODEL_ASSET_UNAVAILABLE_EXT: The render " + "model " + "asset is unavailable. (Added by the XR_EXT_render_model " + "extension)"; + case XR_ERROR_RENDER_MODEL_GLTF_EXTENSION_REQUIRED_EXT: + return "XR_ERROR_RENDER_MODEL_GLTF_EXTENSION_REQUIRED_EXT: A glTF " + "extension is required. (Added by the XR_EXT_render_model " + "extension)"; + case XR_ERROR_NOT_INTERACTION_RENDER_MODEL_EXT: + return "XR_ERROR_NOT_INTERACTION_RENDER_MODEL_EXT: The provided " + "XrRenderModelEXT was not created from a XrRenderModelIdEXT " + "from " + "[XR_EXT_interaction_render_model] (Added by the " + "XR_EXT_interaction_render_model extension)"; + case XR_ERROR_HINT_ALREADY_SET_QCOM: + return "XR_ERROR_HINT_ALREADY_SET_QCOM: Tracking optimization hint " + "is " + "already set for the domain. (Added by the " + "XR_QCOM_tracking_optimization_settings extension)"; + case XR_ERROR_NOT_AN_ANCHOR_HTC: + return "XR_ERROR_NOT_AN_ANCHOR_HTC: The provided space is valid " + "but not " + "an anchor. (Added by the XR_HTC_anchor extension)"; + case XR_ERROR_SPATIAL_ENTITY_ID_INVALID_BD: + return "XR_ERROR_SPATIAL_ENTITY_ID_INVALID_BD: The spatial entity " + "id is " + "invalid. (Added by the XR_BD_spatial_sensing extension)"; + case XR_ERROR_SPATIAL_SENSING_SERVICE_UNAVAILABLE_BD: + return "XR_ERROR_SPATIAL_SENSING_SERVICE_UNAVAILABLE_BD: The " + "spatial " + "sensing service is unavailable. (Added by the " + "XR_BD_spatial_sensing extension)"; + case XR_ERROR_ANCHOR_NOT_SUPPORTED_FOR_ENTITY_BD: + return "XR_ERROR_ANCHOR_NOT_SUPPORTED_FOR_ENTITY_BD: The spatial " + "entity " + "does not support anchor. (Added by the " + "XR_BD_spatial_sensing " + "extension)"; + case XR_ERROR_SCENE_CAPTURE_FAILURE_BD: + return "XR_ERROR_SCENE_CAPTURE_FAILURE_BD: The scene capture is " + "failed, " + "for example exiting abnormally. (Added by the " + "XR_BD_spatial_scene extension)"; + case XR_ERROR_SPACE_NOT_LOCATABLE_EXT: + return "XR_ERROR_SPACE_NOT_LOCATABLE_EXT: The space passed to the " + "function was not locatable. (Added by the " + "XR_EXT_plane_detection " + "extension)"; + case XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT: + return "XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT: The " + "permission " + "for this resource was not granted. (Added by the " + "XR_EXT_plane_detection extension)"; + case XR_ERROR_FUTURE_PENDING_EXT: + return "XR_ERROR_FUTURE_PENDING_EXT: Returned by completion " + "function to " + "indicate future is not ready. (Added by the XR_EXT_future " + "extension)"; + case XR_ERROR_FUTURE_INVALID_EXT: + return "XR_ERROR_FUTURE_INVALID_EXT: Returned by completion " + "function to " + "indicate future is not valid. (Added by the XR_EXT_future " + "extension)"; + case XR_ERROR_SYSTEM_NOTIFICATION_PERMISSION_DENIED_ML: + return "XR_ERROR_SYSTEM_NOTIFICATION_PERMISSION_DENIED_ML: The " + "com.magicleap.permission.SYSTEM_NOTIFICATION permission " + "was not " + "granted. (Added by the XR_ML_system_notifications " + "extension)"; + case XR_ERROR_SYSTEM_NOTIFICATION_INCOMPATIBLE_SKU_ML: + return "XR_ERROR_SYSTEM_NOTIFICATION_INCOMPATIBLE_SKU_ML: " + "Incompatible " + "SKU detected. (Added by the XR_ML_system_notifications " + "extension)"; + case XR_ERROR_WORLD_MESH_DETECTOR_PERMISSION_DENIED_ML: + return "XR_ERROR_WORLD_MESH_DETECTOR_PERMISSION_DENIED_ML: The " + "world " + "mesh detector permission was not granted. (Added by the " + "XR_ML_world_mesh_detection extension)"; + case XR_ERROR_WORLD_MESH_DETECTOR_SPACE_NOT_LOCATABLE_ML: + return "XR_ERROR_WORLD_MESH_DETECTOR_SPACE_NOT_LOCATABLE_ML: At " + "the time " + "of the call the runtime was unable to locate the space and " + "cannot fulfill your request. (Added by the " + "XR_ML_world_mesh_detection extension)"; + case XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META: + return "XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META: The " + "network " + "request failed. (Added by the XR_META_colocation_discovery " + "extension)"; + case XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META: + return "XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META: " + "The " + "runtime does not have any methods available to perform " + "discovery. (Added by the XR_META_colocation_discovery " + "extension)"; + case XR_ERROR_SPACE_GROUP_NOT_FOUND_META: + return "XR_ERROR_SPACE_GROUP_NOT_FOUND_META: The group UUID was " + "not " + "found within the runtime (Added by the " + "XR_META_spatial_entity_group_sharing extension)"; + case XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT: + return "XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT: The specified " + "spatial capability is not supported by the runtime or the " + "system. (Added by the XR_EXT_spatial_entity extension)"; + case XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT: + return "XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT: The specified " + "spatial " + "entity id is invalid or an entity with that id does not " + "exist in " + "the environment. (Added by the XR_EXT_spatial_entity " + "extension)"; + case XR_ERROR_SPATIAL_BUFFER_ID_INVALID_EXT: + return "XR_ERROR_SPATIAL_BUFFER_ID_INVALID_EXT: The specified " + "spatial " + "buffer id is invalid or does not exist in the spatial " + "snapshot " + "being used to query for the buffer data. (Added by the " + "XR_EXT_spatial_entity extension)"; + case XR_ERROR_SPATIAL_COMPONENT_UNSUPPORTED_FOR_CAPABILITY_EXT: + return "XR_ERROR_SPATIAL_COMPONENT_UNSUPPORTED_FOR_CAPABILITY_EXT: " + "The " + "specified spatial component is not supported by the " + "runtime or " + "the system for the given capability. (Added by the " + "XR_EXT_spatial_entity extension)"; + case XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT: + return "XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT: The " + "specified spatial capability configuration is invalid. " + "(Added by " + "the XR_EXT_spatial_entity extension)"; + case XR_ERROR_SPATIAL_COMPONENT_NOT_ENABLED_EXT: + return "XR_ERROR_SPATIAL_COMPONENT_NOT_ENABLED_EXT: The specified " + "spatial component is not enabled for the spatial context. " + "(Added " + "by the XR_EXT_spatial_entity extension)"; + case XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT: + return "XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT: The " + "specified spatial persistence scope is not supported by " + "the " + "runtime or the system. (Added by the " + "XR_EXT_spatial_persistence " + "extension)"; + case XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_INCOMPATIBLE_EXT: + return "XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_INCOMPATIBLE_EXT: THe " + "scope " + "configured for the persistence context is incompatible for " + "the " + "current spatial entity. (Added by the " + "XR_EXT_spatial_persistence_operations extension)"; + default: + return ""; + } + } - template auto format(XrResult r, FmtCtx &ctx) const { - if (spec == 'd') - return format_to(ctx.out(), "{}", static_cast(r)); + template auto format(XrResult r, FmtCtx &ctx) const + { + if (spec == 'd') + return format_to(ctx.out(), "{}", static_cast(r)); - std::string_view str = this->to_string(r); - if (!str.empty()) - return format_to(ctx.out(), "{}", str); + std::string_view str = this->to_string(r); + if (!str.empty()) + return format_to(ctx.out(), "{}", str); - return format_to(ctx.out(), "<0x{:x}>", static_cast(r)); - } + return format_to(ctx.out(), "<0x{:x}>", static_cast(r)); + } private: - char spec{'s'}; + char spec { 's' }; }; } // namespace std namespace LunarWM { -static Matrix xr_projection_matrix(const XrFovf& fov) +static Matrix xr_projection_matrix(XrFovf const &fov) { static_assert(RL_CULL_DISTANCE_FAR > RL_CULL_DISTANCE_NEAR); - Matrix matrix{}; + Matrix matrix {}; - const float near = (float)RL_CULL_DISTANCE_NEAR; - const float far = (float)RL_CULL_DISTANCE_FAR; + float const near = (float)RL_CULL_DISTANCE_NEAR; + float const far = (float)RL_CULL_DISTANCE_FAR; - const float tan_angle_left = tanf(fov.angleLeft); - const float tan_angle_right = tanf(fov.angleRight); + float const tan_angle_left = tanf(fov.angleLeft); + float const tan_angle_right = tanf(fov.angleRight); - const float tan_angle_down = tanf(fov.angleDown); - const float tan_angle_up = tanf(fov.angleUp); + float const tan_angle_down = tanf(fov.angleDown); + float const tan_angle_up = tanf(fov.angleUp); - const float tan_angle_width = tan_angle_right - tan_angle_left; - const float tan_angle_height = tan_angle_up - tan_angle_down; + float const tan_angle_width = tan_angle_right - tan_angle_left; + float const tan_angle_height = tan_angle_up - tan_angle_down; matrix.m0 = 2 / tan_angle_width; matrix.m4 = 0; @@ -589,105 +748,119 @@ static Matrix xr_projection_matrix(const XrFovf& fov) return matrix; } -static Matrix xr_matrix(const XrPosef& pose) +static Matrix xr_matrix(XrPosef const &pose) { - Matrix translation = MatrixTranslate(pose.position.x, pose.position.y, pose.position.z); - Matrix rotation = QuaternionToMatrix(Quaternion{pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w}); + Matrix translation + = MatrixTranslate(pose.position.x, pose.position.y, pose.position.z); + Matrix rotation = QuaternionToMatrix(Quaternion { pose.orientation.x, + pose.orientation.y, pose.orientation.z, pose.orientation.w }); return rotation * translation; } enum class SwapchainType { - Color, - Depth, + Color, + Depth, }; struct SwapchainInfo { - XrSwapchain swapchain{XR_NULL_HANDLE}; - std::int64_t swapchain_format{}; - std::vector image_views; + XrSwapchain swapchain { XR_NULL_HANDLE }; + std::int64_t swapchain_format {}; + std::vector image_views; }; export struct LunarWM { - LunarWM() = default; - ~LunarWM(); + LunarWM() = default; + ~LunarWM(); - void init(); + void init(); - void run(); - void terminate(); + void run(); + void terminate(); private: - struct RenderLayerInfo; + struct RenderLayerInfo; - void init_wayland(); - void init_xr(); + void init_wayland(); + void init_xr(); - void poll_events_xr(); - bool render_layer(RenderLayerInfo &info, float dt); + void poll_events_xr(); + bool render_layer(RenderLayerInfo &info, float dt); void render_3d(float dt); - bool m_initialized{}; + bool m_initialized {}; - struct { - wl_display *display{}; - wl_event_loop *event_loop{}; + struct Keyboard { + struct wl_list link; + struct LunarWM *server; + struct wlr_keyboard *wlr_keyboard; - wlr_backend *backend{}; - wlr_renderer *renderer{}; + struct wl_listener modifiers; + struct wl_listener key; + struct wl_listener destroy; + }; - wlr_egl *egl{}; - EGLDisplay egl_display; - EGLContext egl_context; - EGLConfig egl_config; + struct { + wl_display *display {}; + wl_event_loop *event_loop {}; - wlr_allocator *allocator{}; - wlr_compositor *compositor{}; - wlr_subcompositor *subcompositor{}; - wlr_data_device_manager *data_device_manager{}; + wlr_backend *backend {}; + wlr_renderer *renderer {}; - wlr_seat *seat{}; - wl_list keyboards; - wl_listener new_input_listener{}; - } m_wayland; + wlr_egl *egl {}; + EGLDisplay egl_display; + EGLContext egl_context; + EGLConfig egl_config; - struct { - std::optional instance; - std::optional system_id; - XrSession session{XR_NULL_HANDLE}; - XrSessionState session_state{XR_SESSION_STATE_UNKNOWN}; - struct { - std::vector color; - std::vector depth; - } swapchains; + wlr_allocator *allocator {}; + wlr_compositor *compositor {}; + wlr_subcompositor *subcompositor {}; + wlr_data_device_manager *data_device_manager {}; - std::unordered_map< - XrSwapchain, - std::pair>> - swapchain_images_map; + wlr_seat *seat {}; + wl_list keyboards; + wl_listener new_input_listener {}; - std::vector view_configuration_views; - XrEnvironmentBlendMode environment_blend_mode; + wlr_cursor *cursor {}; + } m_wayland; - XrSpace local_space{XR_NULL_HANDLE}; - XrSpace view_space{XR_NULL_HANDLE}; + struct { + std::optional instance; + std::optional system_id; + XrSession session { XR_NULL_HANDLE }; + XrSessionState session_state { XR_SESSION_STATE_UNKNOWN }; + struct { + std::vector color; + std::vector depth; + } swapchains; - std::uint32_t get_swapchain_image(XrSwapchain swapchain, uint32_t index) { - return swapchain_images_map[swapchain].second[index].image; - } - } m_xr; + std::unordered_map>> + swapchain_images_map; - struct RendererFrame { - GLuint fbo{0}; - uint32_t color_idx{UINT32_MAX}; - uint32_t depth_idx{UINT32_MAX}; - bool has_depth{}; - }; + std::vector view_configuration_views; + XrEnvironmentBlendMode environment_blend_mode; - struct { - GLuint fbo{}; - RenderTexture2D tmp_rt{}; + XrSpace local_space { XR_NULL_HANDLE }; + XrSpace view_space { XR_NULL_HANDLE }; - Camera3D camera{ + std::uint32_t get_swapchain_image(XrSwapchain swapchain, uint32_t index) + { + return swapchain_images_map[swapchain].second[index].image; + } + } m_xr; + + struct RendererFrame { + GLuint fbo { 0 }; + uint32_t color_idx { UINT32_MAX }; + uint32_t depth_idx { UINT32_MAX }; + bool has_depth {}; + }; + + struct { + GLuint fbo {}; + RenderTexture2D tmp_rt {}; + + Camera3D camera { .position = { 0, 0, 0 }, .target = { 0, 0, 1 }, .up = { 0, 1, 0 }, @@ -695,465 +868,567 @@ private: .projection = CAMERA_PERSPECTIVE, }; - bool begin_render(GLuint color_tex, GLuint depth_tex, uint32_t w, uint32_t h, const XrView& view) { - if (!fbo) // create once - glGenFramebuffers(1, &fbo); + bool begin_render(GLuint color_tex, GLuint depth_tex, uint32_t w, + uint32_t h, XrView const &view) + { + if (!fbo) // create once + glGenFramebuffers(1, &fbo); - rlFramebufferAttach(fbo, color_tex, RL_ATTACHMENT_COLOR_CHANNEL0, - RL_ATTACHMENT_TEXTURE2D, 0); + rlFramebufferAttach(fbo, color_tex, RL_ATTACHMENT_COLOR_CHANNEL0, + RL_ATTACHMENT_TEXTURE2D, 0); - assert(rlFramebufferComplete(fbo)); + assert(rlFramebufferComplete(fbo)); glBindFramebuffer(GL_FRAMEBUFFER, fbo); GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if(fbStatus != GL_FRAMEBUFFER_COMPLETE){ + if (fbStatus != GL_FRAMEBUFFER_COMPLETE) { printf("FBO incomplete: 0x%04x\n", fbStatus); return false; } - tmp_rt = {.id = fbo, - .texture = {color_tex, (int)w, (int)h, 1, -1}, - .depth = {depth_tex, (int)w, (int)h, 1, -1}}; + tmp_rt = { .id = fbo, + .texture = { color_tex, (int)w, (int)h, 1, -1 }, + .depth = { depth_tex, (int)w, (int)h, 1, -1 } }; - BeginTextureMode(tmp_rt); - rlEnableStereoRender(); + BeginTextureMode(tmp_rt); + rlEnableStereoRender(); - const XrFovf &fov = view.fov; - Matrix proj = xr_projection_matrix(fov); - Matrix viewM = MatrixInvert(xr_matrix(view.pose)); + XrFovf const &fov = view.fov; + Matrix proj = xr_projection_matrix(fov); + Matrix viewM = MatrixInvert(xr_matrix(view.pose)); - rlSetMatrixProjectionStereo(proj, proj); - rlSetMatrixViewOffsetStereo(viewM, viewM); + rlSetMatrixProjectionStereo(proj, proj); + rlSetMatrixViewOffsetStereo(viewM, viewM); - return true; - } + return true; + } - void end_render(LunarWM &wm, SwapchainInfo &color_sc, - SwapchainInfo *depth_sc) { - rlDisableStereoRender(); - EndTextureMode(); - } + void end_render( + LunarWM &wm, SwapchainInfo &color_sc, SwapchainInfo *depth_sc) + { + rlDisableStereoRender(); + EndTextureMode(); + } void update_camera(LunarWM &wm, Camera3D &camera, RenderLayerInfo &info) { - const XrTime time = info.predicted_display_time; + XrTime const time = info.predicted_display_time; - XrSpaceLocation view_location{ XR_TYPE_SPACE_LOCATION }; - XrResult result = xrLocateSpace(wm.m_xr.view_space, wm.m_xr.local_space, time, &view_location); + XrSpaceLocation view_location { XR_TYPE_SPACE_LOCATION }; + XrResult result = xrLocateSpace( + wm.m_xr.view_space, wm.m_xr.local_space, time, &view_location); if (result != XR_SUCCESS) { return; } - if (view_location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) { - const auto& pos = view_location.pose.position; - camera.position = Vector3{ pos.x, pos.y, pos.z }; + if (view_location.locationFlags + & XR_SPACE_LOCATION_POSITION_VALID_BIT) { + auto const &pos = view_location.pose.position; + camera.position = Vector3 { pos.x, pos.y, pos.z }; } - if (view_location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) { - const auto& rot = view_location.pose.orientation; - const auto forward = Vector3RotateByQuaternion(Vector3{ 0, 0, -1 }, Quaternion{ rot.x, rot.y, rot.z, rot.w }); - const auto up = Vector3RotateByQuaternion(Vector3{ 0, 1, 0 }, Quaternion{ rot.x, rot.y, rot.z, rot.w }); + if (view_location.locationFlags + & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) { + auto const &rot = view_location.pose.orientation; + auto const forward + = Vector3RotateByQuaternion(Vector3 { 0, 0, -1 }, + Quaternion { rot.x, rot.y, rot.z, rot.w }); + auto const up = Vector3RotateByQuaternion(Vector3 { 0, 1, 0 }, + Quaternion { rot.x, rot.y, rot.z, rot.w }); camera.target = camera.position + forward; camera.up = up; } } - } m_renderer; + } m_renderer; - struct RenderLayerInfo { - XrTime predicted_display_time; - std::vector layers; - XrCompositionLayerProjection layer_projection{ - .type = XR_TYPE_COMPOSITION_LAYER_PROJECTION, - .next = nullptr, - }; - std::vector layer_projection_views; - }; + struct RenderLayerInfo { + XrTime predicted_display_time; + std::vector layers; + XrCompositionLayerProjection layer_projection { + .type = XR_TYPE_COMPOSITION_LAYER_PROJECTION, + .next = nullptr, + }; + std::vector layer_projection_views; + }; std::chrono::time_point m_last_tick; - bool m_running{}; - bool m_session_running{}; - bool m_session_state{}; + bool m_running {}; + bool m_session_running {}; + bool m_session_state {}; }; -void LunarWM::init() { - this->init_wayland(); +void LunarWM::init() +{ + this->init_wayland(); wlr_log(WLR_INFO, "0"); auto draw = eglGetCurrentSurface(EGL_DRAW); auto read = eglGetCurrentSurface(EGL_READ); if (eglMakeCurrent(m_wayland.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, - m_wayland.egl_context) == EGL_FALSE) { + m_wayland.egl_context) + == EGL_FALSE) { throw std::runtime_error("Failed to eglMakeCurrent"); } wlr_log(WLR_INFO, "1"); - this->init_xr(); + this->init_xr(); wlr_log(WLR_INFO, "2"); - wlr_log(WLR_INFO, "OpenGL ES version: %s", glGetString(GL_VERSION)); + wlr_log(WLR_INFO, "OpenGL ES version: %s", glGetString(GL_VERSION)); InitWindow(0, 0, ""); wlr_log(WLR_INFO, "3"); - if (eglMakeCurrent(m_wayland.egl_display, read, draw, - m_wayland.egl_context) == EGL_FALSE) { - throw std::runtime_error("Failed to eglMakeCurrent"); - } + if (eglMakeCurrent(m_wayland.egl_display, read, draw, m_wayland.egl_context) + == EGL_FALSE) { + throw std::runtime_error("Failed to eglMakeCurrent"); + } wlr_log(WLR_INFO, "4"); - m_initialized = true; + m_initialized = true; } -void LunarWM::init_wayland() { - wlr_log_init(WLR_DEBUG, NULL); +void LunarWM::init_wayland() +{ + wlr_log_init(WLR_DEBUG, NULL); - m_wayland.display = wl_display_create(); - if (!m_wayland.display) { - throw std::runtime_error("Failed to create wayland display"); - } + m_wayland.display = wl_display_create(); + if (!m_wayland.display) { + throw std::runtime_error("Failed to create wayland display"); + } - m_wayland.event_loop = wl_display_get_event_loop(m_wayland.display); - if (!m_wayland.event_loop) { - throw std::runtime_error("Failed to get wayland event loop"); - } + m_wayland.event_loop = wl_display_get_event_loop(m_wayland.display); + if (!m_wayland.event_loop) { + throw std::runtime_error("Failed to get wayland event loop"); + } - m_wayland.backend = wlr_backend_autocreate(m_wayland.event_loop, nullptr); - if (!m_wayland.backend) { - throw std::runtime_error("Failed to create wlroots backend"); - } + m_wayland.backend = wlr_backend_autocreate(m_wayland.event_loop, nullptr); + if (!m_wayland.backend) { + throw std::runtime_error("Failed to create wlroots backend"); + } - setenv("WLR_RENDERER", "gles2", 1); - m_wayland.renderer = wlr_renderer_autocreate(m_wayland.backend); - if (!m_wayland.renderer) { - throw std::runtime_error("Failed to create wlroots renderer"); - } + setenv("WLR_RENDERER", "gles2", 1); + m_wayland.renderer = wlr_renderer_autocreate(m_wayland.backend); + if (!m_wayland.renderer) { + throw std::runtime_error("Failed to create wlroots renderer"); + } - m_wayland.egl = wlr_gles2_renderer_get_egl(m_wayland.renderer); - if (!m_wayland.egl) { - throw std::runtime_error("Failed to get egl information from renderer"); - } + m_wayland.egl = wlr_gles2_renderer_get_egl(m_wayland.renderer); + if (!m_wayland.egl) { + throw std::runtime_error("Failed to get egl information from renderer"); + } - m_wayland.egl_display = wlr_egl_get_display(m_wayland.egl); - m_wayland.egl_context = wlr_egl_get_context(m_wayland.egl); - m_wayland.egl_config = EGL_NO_CONFIG_KHR; + m_wayland.egl_display = wlr_egl_get_display(m_wayland.egl); + m_wayland.egl_context = wlr_egl_get_context(m_wayland.egl); + m_wayland.egl_config = EGL_NO_CONFIG_KHR; - if (!wlr_renderer_init_wl_display(m_wayland.renderer, m_wayland.display)) { - throw std::runtime_error( - "Failed to initialize renderer with wayland display"); - } + if (!wlr_renderer_init_wl_display(m_wayland.renderer, m_wayland.display)) { + throw std::runtime_error( + "Failed to initialize renderer with wayland display"); + } - m_wayland.allocator = - wlr_allocator_autocreate(m_wayland.backend, m_wayland.renderer); - if (!m_wayland.allocator) { - throw std::runtime_error("Failed to create wlroots allocator"); - } + m_wayland.allocator + = wlr_allocator_autocreate(m_wayland.backend, m_wayland.renderer); + if (!m_wayland.allocator) { + throw std::runtime_error("Failed to create wlroots allocator"); + } - m_wayland.compositor = - wlr_compositor_create(m_wayland.display, 5, m_wayland.renderer); - if (!m_wayland.compositor) { - throw std::runtime_error("Failed to create wlroots compositor"); - } + m_wayland.compositor + = wlr_compositor_create(m_wayland.display, 5, m_wayland.renderer); + if (!m_wayland.compositor) { + throw std::runtime_error("Failed to create wlroots compositor"); + } - m_wayland.subcompositor = wlr_subcompositor_create(m_wayland.display); - if (!m_wayland.subcompositor) { - throw std::runtime_error("Failed to create wlroots subcompositor"); - } + m_wayland.subcompositor = wlr_subcompositor_create(m_wayland.display); + if (!m_wayland.subcompositor) { + throw std::runtime_error("Failed to create wlroots subcompositor"); + } - m_wayland.data_device_manager = - wlr_data_device_manager_create(m_wayland.display); - if (!m_wayland.data_device_manager) { - throw std::runtime_error("Failed to create wlroots data device manager"); - } + m_wayland.data_device_manager + = wlr_data_device_manager_create(m_wayland.display); + if (!m_wayland.data_device_manager) { + throw std::runtime_error( + "Failed to create wlroots data device manager"); + } - wl_list_init(&m_wayland.keyboards); + m_wayland.cursor = wlr_cursor_create(); - m_wayland.new_input_listener.notify = [](wl_listener *listener, void *data) { - auto wm = reinterpret_cast( - wl_container_of(listener, static_cast(nullptr), - m_wayland.new_input_listener)); - auto dev = reinterpret_cast(data); - if (dev->type == WLR_INPUT_DEVICE_KEYBOARD) { - // FIXME: Implement - } else if (dev->type == WLR_INPUT_DEVICE_POINTER) { - // FIXME: Implement - } + wl_list_init(&m_wayland.keyboards); - std::uint32_t caps = WL_SEAT_CAPABILITY_POINTER; - if (!wl_list_empty(&wm->m_wayland.keyboards)) { - caps |= WL_SEAT_CAPABILITY_KEYBOARD; - } - assert(wm->m_wayland.seat); - wlr_seat_set_capabilities(wm->m_wayland.seat, caps); - }; - wl_signal_add(&m_wayland.backend->events.new_input, - &m_wayland.new_input_listener); - m_wayland.seat = wlr_seat_create(m_wayland.display, "seat0"); - if (!m_wayland.seat) { - throw std::runtime_error("Failed to create wlroots seat"); - } + m_wayland.new_input_listener.notify = [](wl_listener *listener, + void *data) { + auto wm = reinterpret_cast(wl_container_of(listener, + static_cast(nullptr), m_wayland.new_input_listener)); + auto dev = reinterpret_cast(data); + if (dev->type == WLR_INPUT_DEVICE_KEYBOARD) { + struct wlr_keyboard *wlr_keyboard + = wlr_keyboard_from_input_device(dev); + + Keyboard *keyboard = new Keyboard; + keyboard->server = wm; + keyboard->wlr_keyboard = wlr_keyboard; + + struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + struct xkb_keymap *keymap = xkb_keymap_new_from_names( + context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS); + + wlr_keyboard_set_keymap(wlr_keyboard, keymap); + xkb_keymap_unref(keymap); + xkb_context_unref(context); + wlr_keyboard_set_repeat_info(wlr_keyboard, 25, 600); + + keyboard->modifiers.notify + = [](struct wl_listener *listener, void *data) { + Keyboard *keyboard + = wl_container_of(listener, keyboard, modifiers); + wlr_seat_set_keyboard(keyboard->server->m_wayland.seat, + keyboard->wlr_keyboard); + wlr_seat_keyboard_notify_modifiers( + keyboard->server->m_wayland.seat, + &keyboard->wlr_keyboard->modifiers); + }; + wl_signal_add( + &wlr_keyboard->events.modifiers, &keyboard->modifiers); + keyboard->key.notify = [](struct wl_listener *listener, + void *data) { + Keyboard *keyboard = wl_container_of(listener, keyboard, key); + auto *server = keyboard->server; + auto *event + = reinterpret_cast(data); + struct wlr_seat *seat = server->m_wayland.seat; + + uint32_t keycode = event->keycode + 8; + xkb_keysym_t const *syms; + int nsyms = xkb_state_key_get_syms( + keyboard->wlr_keyboard->xkb_state, keycode, &syms); + + bool handled = false; + uint32_t modifiers + = wlr_keyboard_get_modifiers(keyboard->wlr_keyboard); + if ((modifiers & WLR_MODIFIER_LOGO) + && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + if (syms[XKB_KEY_Escape]) { + keyboard->server->terminate(); + } + } + + if (!handled) { + wlr_seat_set_keyboard(seat, keyboard->wlr_keyboard); + wlr_seat_keyboard_notify_key( + seat, event->time_msec, event->keycode, event->state); + } + }; + wl_signal_add(&wlr_keyboard->events.key, &keyboard->key); + keyboard->destroy.notify + = [](struct wl_listener *listener, void *data) { + Keyboard *keyboard + = wl_container_of(listener, keyboard, destroy); + wl_list_remove(&keyboard->modifiers.link); + wl_list_remove(&keyboard->key.link); + wl_list_remove(&keyboard->destroy.link); + wl_list_remove(&keyboard->link); + free(keyboard); + }; + wl_signal_add(&dev->events.destroy, &keyboard->destroy); + + wlr_seat_set_keyboard(wm->m_wayland.seat, keyboard->wlr_keyboard); + + wl_list_insert(&wm->m_wayland.keyboards, &keyboard->link); + } else if (dev->type == WLR_INPUT_DEVICE_POINTER) { + wlr_cursor_attach_input_device(wm->m_wayland.cursor, dev); + } + + std::uint32_t caps = WL_SEAT_CAPABILITY_POINTER; + if (!wl_list_empty(&wm->m_wayland.keyboards)) { + caps |= WL_SEAT_CAPABILITY_KEYBOARD; + } + assert(wm->m_wayland.seat); + wlr_seat_set_capabilities(wm->m_wayland.seat, caps); + }; + wl_signal_add( + &m_wayland.backend->events.new_input, &m_wayland.new_input_listener); + m_wayland.seat = wlr_seat_create(m_wayland.display, "seat0"); + if (!m_wayland.seat) { + throw std::runtime_error("Failed to create wlroots seat"); + } } -void LunarWM::init_xr() { - XrApplicationInfo app_info{ - .applicationVersion = 1, - .engineVersion = 1, - .apiVersion = XR_CURRENT_API_VERSION, - }; - strncpy(app_info.applicationName, "LunarWM", XR_MAX_APPLICATION_NAME_SIZE); - strncpy(app_info.engineName, "LunarWM Engine", XR_MAX_ENGINE_NAME_SIZE); +void LunarWM::init_xr() +{ + XrApplicationInfo app_info { + .applicationVersion = 1, + .engineVersion = 1, + .apiVersion = XR_CURRENT_API_VERSION, + }; + strncpy(app_info.applicationName, "LunarWM", XR_MAX_APPLICATION_NAME_SIZE); + strncpy(app_info.engineName, "LunarWM Engine", XR_MAX_ENGINE_NAME_SIZE); - std::vector instance_extensions{ - XR_EXT_DEBUG_UTILS_EXTENSION_NAME, - XR_MNDX_EGL_ENABLE_EXTENSION_NAME, - XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME, - }; - std::vector apiLayers; - std::vector active_instance_extensions; - std::vector activeAPILayers; + std::vector instance_extensions { + XR_EXT_DEBUG_UTILS_EXTENSION_NAME, + XR_MNDX_EGL_ENABLE_EXTENSION_NAME, + XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME, + }; + std::vector apiLayers; + std::vector active_instance_extensions; + std::vector activeAPILayers; - uint32_t apiLayerCount = 0; - std::vector apiLayerProperties; - if (xrEnumerateApiLayerProperties(0, &apiLayerCount, nullptr) != XR_SUCCESS) { - throw std::runtime_error("Failed to enumerate API layer properties"); - } - apiLayerProperties.resize(apiLayerCount, {XR_TYPE_API_LAYER_PROPERTIES}); - if (xrEnumerateApiLayerProperties(apiLayerCount, &apiLayerCount, - apiLayerProperties.data()) != XR_SUCCESS) { - throw std::runtime_error("Failed to enumerate API layer properties"); - } + uint32_t apiLayerCount = 0; + std::vector apiLayerProperties; + if (xrEnumerateApiLayerProperties(0, &apiLayerCount, nullptr) + != XR_SUCCESS) { + throw std::runtime_error("Failed to enumerate API layer properties"); + } + apiLayerProperties.resize(apiLayerCount, { XR_TYPE_API_LAYER_PROPERTIES }); + if (xrEnumerateApiLayerProperties( + apiLayerCount, &apiLayerCount, apiLayerProperties.data()) + != XR_SUCCESS) { + throw std::runtime_error("Failed to enumerate API layer properties"); + } - for (auto &requestLayer : apiLayers) { - for (auto &layerProperty : apiLayerProperties) { - if (strcmp(requestLayer.c_str(), layerProperty.layerName) != 0) { - continue; - } else { - activeAPILayers.push_back(requestLayer.c_str()); - break; - } - } - } + for (auto &requestLayer : apiLayers) { + for (auto &layerProperty : apiLayerProperties) { + if (strcmp(requestLayer.c_str(), layerProperty.layerName) != 0) { + continue; + } else { + activeAPILayers.push_back(requestLayer.c_str()); + break; + } + } + } - uint32_t extensionCount = 0; - std::vector extensionProperties; - if (xrEnumerateInstanceExtensionProperties(nullptr, 0, &extensionCount, - nullptr) != XR_SUCCESS) { - throw std::runtime_error( - "Failed to enumerate OpenXR instance extension properties"); - } - extensionProperties.resize(extensionCount, {XR_TYPE_EXTENSION_PROPERTIES}); - if (xrEnumerateInstanceExtensionProperties( - nullptr, extensionCount, &extensionCount, - extensionProperties.data()) != XR_SUCCESS) { - throw std::runtime_error( - "Failed to enumerate OpenXR instance extension properties"); - } + uint32_t extensionCount = 0; + std::vector extensionProperties; + if (xrEnumerateInstanceExtensionProperties( + nullptr, 0, &extensionCount, nullptr) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to enumerate OpenXR instance extension properties"); + } + extensionProperties.resize( + extensionCount, { XR_TYPE_EXTENSION_PROPERTIES }); + if (xrEnumerateInstanceExtensionProperties(nullptr, extensionCount, + &extensionCount, extensionProperties.data()) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to enumerate OpenXR instance extension properties"); + } - for (auto &requestedInstanceExtension : instance_extensions) { - bool found = false; - for (auto &extensionProperty : extensionProperties) { - if (strcmp(requestedInstanceExtension.c_str(), - extensionProperty.extensionName) != 0) { - continue; - } else { - active_instance_extensions.push_back( - requestedInstanceExtension.c_str()); - found = true; - break; - } - } - if (!found) { - throw std::runtime_error( - std::format("Failed to find OpenXR instance extension: {}", - requestedInstanceExtension)); - } - } + for (auto &requestedInstanceExtension : instance_extensions) { + bool found = false; + for (auto &extensionProperty : extensionProperties) { + if (strcmp(requestedInstanceExtension.c_str(), + extensionProperty.extensionName) + != 0) { + continue; + } else { + active_instance_extensions.push_back( + requestedInstanceExtension.c_str()); + found = true; + break; + } + } + if (!found) { + throw std::runtime_error( + std::format("Failed to find OpenXR instance extension: {}", + requestedInstanceExtension)); + } + } - { - XrInstanceCreateInfo ci{ - .type = XR_TYPE_INSTANCE_CREATE_INFO, - .next = NULL, - .createFlags = 0, - .applicationInfo = app_info, - .enabledApiLayerCount = - static_cast(activeAPILayers.size()), - .enabledApiLayerNames = activeAPILayers.data(), - .enabledExtensionCount = - static_cast(active_instance_extensions.size()), - .enabledExtensionNames = active_instance_extensions.data(), - }; + { + XrInstanceCreateInfo ci { + .type = XR_TYPE_INSTANCE_CREATE_INFO, + .next = NULL, + .createFlags = 0, + .applicationInfo = app_info, + .enabledApiLayerCount + = static_cast(activeAPILayers.size()), + .enabledApiLayerNames = activeAPILayers.data(), + .enabledExtensionCount + = static_cast(active_instance_extensions.size()), + .enabledExtensionNames = active_instance_extensions.data(), + }; - XrInstance instance; - if (xrCreateInstance(&ci, &instance) != XR_SUCCESS) { - throw std::runtime_error("Failed to create OpenXR instance"); - } - m_xr.instance = instance; - } + XrInstance instance; + if (xrCreateInstance(&ci, &instance) != XR_SUCCESS) { + throw std::runtime_error("Failed to create OpenXR instance"); + } + m_xr.instance = instance; + } - { - XrSystemGetInfo gi{ - .type = XR_TYPE_SYSTEM_GET_INFO, - .next = nullptr, - }; + { + XrSystemGetInfo gi { + .type = XR_TYPE_SYSTEM_GET_INFO, + .next = nullptr, + }; - XrFormFactor factors[]{ - XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY, - XR_FORM_FACTOR_HANDHELD_DISPLAY, - }; - for (auto const factor : factors) { - gi.formFactor = factor; - XrSystemId system_id; - if (xrGetSystem(*m_xr.instance, &gi, &system_id) == XR_SUCCESS) { - m_xr.system_id = system_id; - break; - } - } + XrFormFactor factors[] { + XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY, + XR_FORM_FACTOR_HANDHELD_DISPLAY, + }; + for (auto const factor : factors) { + gi.formFactor = factor; + XrSystemId system_id; + if (xrGetSystem(*m_xr.instance, &gi, &system_id) == XR_SUCCESS) { + m_xr.system_id = system_id; + break; + } + } - if (!m_xr.system_id) { - throw std::runtime_error("Failed to find valid form factor"); - } - } + if (!m_xr.system_id) { + throw std::runtime_error("Failed to find valid form factor"); + } + } - XrGraphicsRequirementsOpenGLESKHR reqs{ - .type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR, - .next = nullptr, - }; - PFN_xrGetOpenGLESGraphicsRequirementsKHR xrGetOpenGLESGraphicsRequirementsKHR; - xrGetInstanceProcAddr( - *m_xr.instance, "xrGetOpenGLESGraphicsRequirementsKHR", - (PFN_xrVoidFunction *)&xrGetOpenGLESGraphicsRequirementsKHR); - if (xrGetOpenGLESGraphicsRequirementsKHR(*m_xr.instance, *m_xr.system_id, - &reqs) != XR_SUCCESS) { - throw std::runtime_error("Failed to get GLES graphics requirements"); - } - printf("OpenGL ES range: %d.%d.%d – %d.%d.%d\n", - XR_VERSION_MAJOR(reqs.minApiVersionSupported), - XR_VERSION_MINOR(reqs.minApiVersionSupported), - XR_VERSION_PATCH(reqs.minApiVersionSupported), - XR_VERSION_MAJOR(reqs.maxApiVersionSupported), - XR_VERSION_MINOR(reqs.maxApiVersionSupported), - XR_VERSION_PATCH(reqs.maxApiVersionSupported)); + XrGraphicsRequirementsOpenGLESKHR reqs { + .type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR, + .next = nullptr, + }; + PFN_xrGetOpenGLESGraphicsRequirementsKHR + xrGetOpenGLESGraphicsRequirementsKHR; + xrGetInstanceProcAddr(*m_xr.instance, + "xrGetOpenGLESGraphicsRequirementsKHR", + (PFN_xrVoidFunction *)&xrGetOpenGLESGraphicsRequirementsKHR); + if (xrGetOpenGLESGraphicsRequirementsKHR( + *m_xr.instance, *m_xr.system_id, &reqs) + != XR_SUCCESS) { + throw std::runtime_error("Failed to get GLES graphics requirements"); + } + printf("OpenGL ES range: %d.%d.%d – %d.%d.%d\n", + XR_VERSION_MAJOR(reqs.minApiVersionSupported), + XR_VERSION_MINOR(reqs.minApiVersionSupported), + XR_VERSION_PATCH(reqs.minApiVersionSupported), + XR_VERSION_MAJOR(reqs.maxApiVersionSupported), + XR_VERSION_MINOR(reqs.maxApiVersionSupported), + XR_VERSION_PATCH(reqs.maxApiVersionSupported)); - glEnable(GL_DEBUG_OUTPUT_KHR); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); + glEnable(GL_DEBUG_OUTPUT_KHR); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); - { - glDrawBuffersEXT = (PFNGLDRAWBUFFERSEXTPROC) eglGetProcAddress("glDrawBuffersEXT"); - XrGraphicsBindingEGLMNDX gbind = { - .type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX, - .next = nullptr, - .getProcAddress = eglGetProcAddress, - .display = m_wayland.egl_display, - .config = m_wayland.egl_config, - .context = m_wayland.egl_context, - }; + { + glDrawBuffersEXT + = (PFNGLDRAWBUFFERSEXTPROC)eglGetProcAddress("glDrawBuffersEXT"); + XrGraphicsBindingEGLMNDX gbind = { + .type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX, + .next = nullptr, + .getProcAddress = eglGetProcAddress, + .display = m_wayland.egl_display, + .config = m_wayland.egl_config, + .context = m_wayland.egl_context, + }; - XrSessionCreateInfo ci{ - .type = XR_TYPE_SESSION_CREATE_INFO, - .next = &gbind, - .createFlags = 0, - .systemId = *m_xr.system_id, - }; + XrSessionCreateInfo ci { + .type = XR_TYPE_SESSION_CREATE_INFO, + .next = &gbind, + .createFlags = 0, + .systemId = *m_xr.system_id, + }; - if (xrCreateSession(*m_xr.instance, &ci, &m_xr.session) != XR_SUCCESS) { - throw std::runtime_error("Failed to create OpenXR session"); - } - } + if (xrCreateSession(*m_xr.instance, &ci, &m_xr.session) != XR_SUCCESS) { + throw std::runtime_error("Failed to create OpenXR session"); + } + } - // Swapchain time! - std::vector view_config_types; - { - std::uint32_t count; - if (xrEnumerateViewConfigurations(*m_xr.instance, *m_xr.system_id, 0, - &count, nullptr) != XR_SUCCESS) { - throw std::runtime_error( - "Failed to get amount of OpenXR view configurations"); - } - view_config_types.resize(count); - if (xrEnumerateViewConfigurations(*m_xr.instance, *m_xr.system_id, count, - &count, - view_config_types.data()) != XR_SUCCESS) { - throw std::runtime_error( - "Failed to enumerate OpenXR view configurations"); - } - } + // Swapchain time! + std::vector view_config_types; + { + std::uint32_t count; + if (xrEnumerateViewConfigurations( + *m_xr.instance, *m_xr.system_id, 0, &count, nullptr) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to get amount of OpenXR view configurations"); + } + view_config_types.resize(count); + if (xrEnumerateViewConfigurations(*m_xr.instance, *m_xr.system_id, + count, &count, view_config_types.data()) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to enumerate OpenXR view configurations"); + } + } - if (!std::ranges::contains(view_config_types, - XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO)) { - throw std::runtime_error( - "XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO not present"); - } + if (!std::ranges::contains( + view_config_types, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO)) { + throw std::runtime_error( + "XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO not present"); + } - { - uint32_t count = 0; - if (xrEnumerateViewConfigurationViews( - *m_xr.instance, *m_xr.system_id, - XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 0, &count, - nullptr) != XR_SUCCESS) { - throw std::runtime_error( - "Failed to get amount of OpenXR view configuration views"); - } - m_xr.view_configuration_views.resize(count, - {XR_TYPE_VIEW_CONFIGURATION_VIEW}); - if (xrEnumerateViewConfigurationViews( - *m_xr.instance, *m_xr.system_id, - XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, count, &count, - m_xr.view_configuration_views.data()) != XR_SUCCESS) { - throw std::runtime_error( - "Failed to enumerate OpenXR view configuration views"); - } - } + { + uint32_t count = 0; + if (xrEnumerateViewConfigurationViews(*m_xr.instance, *m_xr.system_id, + XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 0, &count, nullptr) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to get amount of OpenXR view configuration views"); + } + m_xr.view_configuration_views.resize( + count, { XR_TYPE_VIEW_CONFIGURATION_VIEW }); + if (xrEnumerateViewConfigurationViews(*m_xr.instance, *m_xr.system_id, + XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, count, &count, + m_xr.view_configuration_views.data()) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to enumerate OpenXR view configuration views"); + } + } - std::vector swapchain_formats; - { - std::uint32_t count; - if (xrEnumerateSwapchainFormats(m_xr.session, 0, &count, nullptr) != - XR_SUCCESS) { - throw std::runtime_error( - "Failed to get amount of OpenXR swapchain formats"); - } - swapchain_formats.resize(count); - if (xrEnumerateSwapchainFormats(m_xr.session, count, &count, - swapchain_formats.data()) != XR_SUCCESS) { - throw std::runtime_error("Failed to enumerate OpenXR swapchain formats"); - } - } + std::vector swapchain_formats; + { + std::uint32_t count; + if (xrEnumerateSwapchainFormats(m_xr.session, 0, &count, nullptr) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to get amount of OpenXR swapchain formats"); + } + swapchain_formats.resize(count); + if (xrEnumerateSwapchainFormats( + m_xr.session, count, &count, swapchain_formats.data()) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to enumerate OpenXR swapchain formats"); + } + } - std::vector swapchain_format_depth_needles{ - GL_DEPTH_COMPONENT16, - // GL_DEPTH_COMPONENT32F, - // GL_DEPTH_COMPONENT24, - }; - const std::vector::const_iterator &swapchain_format_depth_it = - std::find_first_of(swapchain_formats.begin(), swapchain_formats.end(), - std::begin(swapchain_format_depth_needles), - std::end(swapchain_format_depth_needles)); - if (swapchain_format_depth_it == swapchain_formats.end()) { - throw std::runtime_error( - "Failed to find satisfying depth swapchain format"); - } - auto const swapchain_format_depth = *swapchain_format_depth_it; + std::vector swapchain_format_depth_needles { + GL_DEPTH_COMPONENT16, + // GL_DEPTH_COMPONENT32F, + // GL_DEPTH_COMPONENT24, + }; + std::vector::const_iterator const &swapchain_format_depth_it + = std::find_first_of(swapchain_formats.begin(), swapchain_formats.end(), + std::begin(swapchain_format_depth_needles), + std::end(swapchain_format_depth_needles)); + if (swapchain_format_depth_it == swapchain_formats.end()) { + throw std::runtime_error( + "Failed to find satisfying depth swapchain format"); + } + auto const swapchain_format_depth = *swapchain_format_depth_it; - std::vector swapchain_format_color_needles{GL_SRGB8_ALPHA8}; - const std::vector::const_iterator &swapchain_format_color_it = - std::find_first_of(swapchain_formats.begin(), swapchain_formats.end(), - std::begin(swapchain_format_color_needles), - std::end(swapchain_format_color_needles)); - if (swapchain_format_color_it == swapchain_formats.end()) { - throw std::runtime_error( - "Failed to find satisfying color swapchain format"); - } - auto const swapchain_format_color = *swapchain_format_color_it; + std::vector swapchain_format_color_needles { + GL_SRGB8_ALPHA8 + }; + std::vector::const_iterator const &swapchain_format_color_it + = std::find_first_of(swapchain_formats.begin(), swapchain_formats.end(), + std::begin(swapchain_format_color_needles), + std::end(swapchain_format_color_needles)); + if (swapchain_format_color_it == swapchain_formats.end()) { + throw std::runtime_error( + "Failed to find satisfying color swapchain format"); + } + auto const swapchain_format_color = *swapchain_format_color_it; - auto const AllocateSwapchainImageData = - [&](XrSwapchain swapchain, SwapchainType type, uint32_t count) { - m_xr.swapchain_images_map[swapchain].first = type; - m_xr.swapchain_images_map[swapchain].second.resize( - count, {XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR}); - return reinterpret_cast( - m_xr.swapchain_images_map[swapchain].second.data()); - }; + auto const AllocateSwapchainImageData + = [&](XrSwapchain swapchain, SwapchainType type, uint32_t count) { + m_xr.swapchain_images_map[swapchain].first = type; + m_xr.swapchain_images_map[swapchain].second.resize( + count, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR }); + return reinterpret_cast( + m_xr.swapchain_images_map[swapchain].second.data()); + }; - const uint32_t view_count = (uint32_t)m_xr.view_configuration_views.size(); - const uint32_t eyeW = m_xr.view_configuration_views[0].recommendedImageRectWidth; - const uint32_t eyeH = m_xr.view_configuration_views[0].recommendedImageRectHeight; - const uint32_t bufW = eyeW * view_count; + uint32_t const view_count = (uint32_t)m_xr.view_configuration_views.size(); + uint32_t const eyeW + = m_xr.view_configuration_views[0].recommendedImageRectWidth; + uint32_t const eyeH + = m_xr.view_configuration_views[0].recommendedImageRectHeight; + uint32_t const bufW = eyeW * view_count; m_xr.swapchains.color.resize(1); m_xr.swapchains.depth.resize(1); @@ -1161,353 +1436,369 @@ void LunarWM::init_xr() { { auto &color_sc = m_xr.swapchains.color[0]; auto &depth_sc = m_xr.swapchains.depth[0]; - auto &vcv = m_xr.view_configuration_views[0]; + auto &vcv = m_xr.view_configuration_views[0]; - { // Create color swapchain - XrSwapchainCreateInfo ci{ - .type = XR_TYPE_SWAPCHAIN_CREATE_INFO, - .next = nullptr, - .createFlags = 0, - .usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | - XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, - .format = swapchain_format_color, - .sampleCount = vcv.recommendedSwapchainSampleCount, - .width = bufW, - .height = eyeH, - .faceCount = 1, - .arraySize = 1, - .mipCount = 1, - }; - color_sc.swapchain_format = ci.format; + { // Create color swapchain + XrSwapchainCreateInfo ci { + .type = XR_TYPE_SWAPCHAIN_CREATE_INFO, + .next = nullptr, + .createFlags = 0, + .usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT + | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, + .format = swapchain_format_color, + .sampleCount = vcv.recommendedSwapchainSampleCount, + .width = bufW, + .height = eyeH, + .faceCount = 1, + .arraySize = 1, + .mipCount = 1, + }; + color_sc.swapchain_format = ci.format; - if (xrCreateSwapchain(m_xr.session, &ci, &color_sc.swapchain) != - XR_SUCCESS) { - throw std::runtime_error("Failed to create OpenXR color swapchain"); - } - } + if (xrCreateSwapchain(m_xr.session, &ci, &color_sc.swapchain) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to create OpenXR color swapchain"); + } + } - { // Create depth swapchain - XrSwapchainCreateInfo ci{ - .type = XR_TYPE_SWAPCHAIN_CREATE_INFO, - .next = nullptr, - .createFlags = 0, - .usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | - XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .format = swapchain_format_depth, - .sampleCount = vcv.recommendedSwapchainSampleCount, - .width = bufW, - .height = eyeH, - .faceCount = 1, - .arraySize = 1, - .mipCount = 1, - }; - depth_sc.swapchain_format = ci.format; + { // Create depth swapchain + XrSwapchainCreateInfo ci { + .type = XR_TYPE_SWAPCHAIN_CREATE_INFO, + .next = nullptr, + .createFlags = 0, + .usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT + | XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .format = swapchain_format_depth, + .sampleCount = vcv.recommendedSwapchainSampleCount, + .width = bufW, + .height = eyeH, + .faceCount = 1, + .arraySize = 1, + .mipCount = 1, + }; + depth_sc.swapchain_format = ci.format; - if (xrCreateSwapchain(m_xr.session, &ci, &depth_sc.swapchain) != - XR_SUCCESS) { - throw std::runtime_error("Failed to create OpenXR color swapchain"); - } - } + if (xrCreateSwapchain(m_xr.session, &ci, &depth_sc.swapchain) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to create OpenXR color swapchain"); + } + } - XrResult res; + XrResult res; - // Enumerate swapchain images - uint32_t color_swapchain_image_count = 0; - if (xrEnumerateSwapchainImages(color_sc.swapchain, 0, - &color_swapchain_image_count, - nullptr) != XR_SUCCESS) { - throw std::runtime_error("Failed to get Color Swapchain Images count."); - } - XrSwapchainImageBaseHeader *color_swapchain_images = - AllocateSwapchainImageData(color_sc.swapchain, SwapchainType::Color, - color_swapchain_image_count); - if (xrEnumerateSwapchainImages(color_sc.swapchain, - color_swapchain_image_count, - &color_swapchain_image_count, - color_swapchain_images) != XR_SUCCESS) { - throw std::runtime_error("Failed to enumerate Color Swapchain Images."); - } + // Enumerate swapchain images + uint32_t color_swapchain_image_count = 0; + if (xrEnumerateSwapchainImages( + color_sc.swapchain, 0, &color_swapchain_image_count, nullptr) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to get Color Swapchain Images count."); + } + XrSwapchainImageBaseHeader *color_swapchain_images + = AllocateSwapchainImageData(color_sc.swapchain, + SwapchainType::Color, color_swapchain_image_count); + if (xrEnumerateSwapchainImages(color_sc.swapchain, + color_swapchain_image_count, &color_swapchain_image_count, + color_swapchain_images) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to enumerate Color Swapchain Images."); + } - uint32_t depth_swapchain_image_count = 0; - if ((res = xrEnumerateSwapchainImages(depth_sc.swapchain, 0, - &depth_swapchain_image_count, - nullptr)) != XR_SUCCESS) { - throw std::runtime_error( - std::format("Failed to get Depth Swapchain Images count. {}", res)); - } - XrSwapchainImageBaseHeader *depth_swapchain_images = - AllocateSwapchainImageData(depth_sc.swapchain, SwapchainType::Depth, - depth_swapchain_image_count); - if ((res = xrEnumerateSwapchainImages( - depth_sc.swapchain, depth_swapchain_image_count, - &depth_swapchain_image_count, depth_swapchain_images)) != - XR_SUCCESS) { - throw std::runtime_error("Failed to enumerate Depth Swapchain Images."); - } + uint32_t depth_swapchain_image_count = 0; + if ((res = xrEnumerateSwapchainImages( + depth_sc.swapchain, 0, &depth_swapchain_image_count, nullptr)) + != XR_SUCCESS) { + throw std::runtime_error(std::format( + "Failed to get Depth Swapchain Images count. {}", res)); + } + XrSwapchainImageBaseHeader *depth_swapchain_images + = AllocateSwapchainImageData(depth_sc.swapchain, + SwapchainType::Depth, depth_swapchain_image_count); + if ((res = xrEnumerateSwapchainImages(depth_sc.swapchain, + depth_swapchain_image_count, &depth_swapchain_image_count, + depth_swapchain_images)) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to enumerate Depth Swapchain Images."); + } - // Get image views - for (uint32_t j = 0; j < color_swapchain_image_count; j++) { - GLuint framebuffer = 0; - glGenFramebuffers(1, &framebuffer); + // Get image views + for (uint32_t j = 0; j < color_swapchain_image_count; j++) { + GLuint framebuffer = 0; + glGenFramebuffers(1, &framebuffer); - GLenum attachment = GL_COLOR_ATTACHMENT0; + GLenum attachment = GL_COLOR_ATTACHMENT0; - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, - m_xr.get_swapchain_image(color_sc.swapchain, j), - 0); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, + GL_TEXTURE_2D, m_xr.get_swapchain_image(color_sc.swapchain, j), + 0); - GLenum result = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - if (result != GL_FRAMEBUFFER_COMPLETE) { - throw std::runtime_error("Failed to create color framebuffer"); - } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + GLenum result = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + if (result != GL_FRAMEBUFFER_COMPLETE) { + throw std::runtime_error("Failed to create color framebuffer"); + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); - color_sc.image_views.push_back(framebuffer); - } - for (uint32_t j = 0; j < depth_swapchain_image_count; j++) { - GLuint framebuffer = 0; - glGenFramebuffers(1, &framebuffer); + color_sc.image_views.push_back(framebuffer); + } + for (uint32_t j = 0; j < depth_swapchain_image_count; j++) { + GLuint framebuffer = 0; + glGenFramebuffers(1, &framebuffer); - GLenum attachment = GL_DEPTH_ATTACHMENT; + GLenum attachment = GL_DEPTH_ATTACHMENT; - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, - m_xr.get_swapchain_image(depth_sc.swapchain, j), - 0); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, + GL_TEXTURE_2D, m_xr.get_swapchain_image(depth_sc.swapchain, j), + 0); - GLenum result = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - if (result != GL_FRAMEBUFFER_COMPLETE) { - throw std::runtime_error("Failed to create depth framebuffer"); - } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + GLenum result = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + if (result != GL_FRAMEBUFFER_COMPLETE) { + throw std::runtime_error("Failed to create depth framebuffer"); + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); - depth_sc.image_views.push_back(framebuffer); - } - } + depth_sc.image_views.push_back(framebuffer); + } + } - std::vector environment_blend_modes; - { // Get available blend modes - std::uint32_t count{}; - if (xrEnumerateEnvironmentBlendModes( - *m_xr.instance, *m_xr.system_id, - XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 0, &count, - nullptr) != XR_SUCCESS) { - throw std::runtime_error( - "Failed to get OpenXR environment blend mode count"); - } - environment_blend_modes.resize(count); - if (xrEnumerateEnvironmentBlendModes( - *m_xr.instance, *m_xr.system_id, - XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, count, &count, - environment_blend_modes.data()) != XR_SUCCESS) { - throw std::runtime_error("Failed to get XR environment blend modes"); - } - } - std::vector requested_environment_blend_modes{ - XR_ENVIRONMENT_BLEND_MODE_OPAQUE, - XR_ENVIRONMENT_BLEND_MODE_ADDITIVE, - XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM, - }; + std::vector environment_blend_modes; + { // Get available blend modes + std::uint32_t count {}; + if (xrEnumerateEnvironmentBlendModes(*m_xr.instance, *m_xr.system_id, + XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 0, &count, nullptr) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to get OpenXR environment blend mode count"); + } + environment_blend_modes.resize(count); + if (xrEnumerateEnvironmentBlendModes(*m_xr.instance, *m_xr.system_id, + XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, count, &count, + environment_blend_modes.data()) + != XR_SUCCESS) { + throw std::runtime_error( + "Failed to get XR environment blend modes"); + } + } + std::vector requested_environment_blend_modes { + XR_ENVIRONMENT_BLEND_MODE_OPAQUE, + XR_ENVIRONMENT_BLEND_MODE_ADDITIVE, + XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM, + }; - for (auto const &bm : requested_environment_blend_modes) { - m_xr.environment_blend_mode = bm; - if (std::ranges::contains(environment_blend_modes, bm)) { - break; - } - } - if (m_xr.environment_blend_mode == XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM) { - wlr_log(WLR_INFO, "Failed to find a compatible blend mode. Defaulting to " - "XR_ENVIRONMENT_BLEND_MODE_OPAQUE."); - m_xr.environment_blend_mode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE; - } + for (auto const &bm : requested_environment_blend_modes) { + m_xr.environment_blend_mode = bm; + if (std::ranges::contains(environment_blend_modes, bm)) { + break; + } + } + if (m_xr.environment_blend_mode == XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM) { + wlr_log(WLR_INFO, + "Failed to find a compatible blend mode. Defaulting to " + "XR_ENVIRONMENT_BLEND_MODE_OPAQUE."); + m_xr.environment_blend_mode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE; + } - { // Reference space - XrReferenceSpaceCreateInfo ci{ - .type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO, - .next = nullptr, - .referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE, - .poseInReferenceSpace = {.orientation = {0.0f, 0.0f, 0.0f, 1.0f}, - .position = {0.0f, 0.0f, 0.0f}}, - }; + { // Reference space + XrReferenceSpaceCreateInfo ci { + .type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO, + .next = nullptr, + .referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE, + .poseInReferenceSpace = { .orientation = { 0.0f, 0.0f, 0.0f, 1.0f }, + .position = { 0.0f, 0.0f, 0.0f } }, + }; - if (xrCreateReferenceSpace(m_xr.session, &ci, &m_xr.local_space) != - XR_SUCCESS) { - throw std::runtime_error("Failed to create OpenXR reference space"); - } - } + if (xrCreateReferenceSpace(m_xr.session, &ci, &m_xr.local_space) + != XR_SUCCESS) { + throw std::runtime_error("Failed to create OpenXR reference space"); + } + } - { // View reference space - XrReferenceSpaceCreateInfo ci{ - .type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO, - .next = nullptr, - .referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW, - .poseInReferenceSpace = {.orientation = {0.0f, 0.0f, 0.0f, 1.0f}, - .position = {0.0f, 0.0f, 0.0f}}, - }; + { // View reference space + XrReferenceSpaceCreateInfo ci { + .type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO, + .next = nullptr, + .referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW, + .poseInReferenceSpace = { .orientation = { 0.0f, 0.0f, 0.0f, 1.0f }, + .position = { 0.0f, 0.0f, 0.0f } }, + }; - if (xrCreateReferenceSpace(m_xr.session, &ci, &m_xr.view_space) != - XR_SUCCESS) { - throw std::runtime_error("Failed to create OpenXR reference space"); - } - } + if (xrCreateReferenceSpace(m_xr.session, &ci, &m_xr.view_space) + != XR_SUCCESS) { + throw std::runtime_error("Failed to create OpenXR reference space"); + } + } } -void LunarWM::poll_events_xr() { - XrEventDataBuffer event_data{XR_TYPE_EVENT_DATA_BUFFER}; - auto XrPollEvents = [&]() -> bool { - event_data = {XR_TYPE_EVENT_DATA_BUFFER}; - return xrPollEvent(*m_xr.instance, &event_data) == XR_SUCCESS; - }; +void LunarWM::poll_events_xr() +{ + XrEventDataBuffer event_data { XR_TYPE_EVENT_DATA_BUFFER }; + auto XrPollEvents = [&]() -> bool { + event_data = { XR_TYPE_EVENT_DATA_BUFFER }; + return xrPollEvent(*m_xr.instance, &event_data) == XR_SUCCESS; + }; - while (XrPollEvents()) { - switch (event_data.type) { - case XR_TYPE_EVENT_DATA_EVENTS_LOST: { - XrEventDataEventsLost *el = - reinterpret_cast(&event_data); - wlr_log(WLR_INFO, "OPENXR: Events Lost: %d", el->lostEventCount); - break; - } - case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: { - XrEventDataInstanceLossPending *ilp = - reinterpret_cast(&event_data); - wlr_log(WLR_INFO, "OPENXR: Instance Loss Pending at: %ld", ilp->lossTime); - m_session_running = false; - m_running = false; - break; - } - case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED: { - XrEventDataInteractionProfileChanged *ipc = - reinterpret_cast(&event_data); - wlr_log(WLR_INFO, "OPENXR: Interaction Profile changed for Session: %p", - ipc->session); - if (ipc->session != m_xr.session) { - wlr_log(WLR_ERROR, - "XrEventDataInteractionProfileChanged for unknown Session"); - break; - } - break; - } - case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: { - XrEventDataReferenceSpaceChangePending *scp = - reinterpret_cast( - &event_data); - wlr_log(WLR_INFO, - "OPENXR: Reference Space Change pending for Session: %p", - scp->session); - if (scp->session != m_xr.session) { - wlr_log(WLR_ERROR, - "XrEventDataReferenceSpaceChangePending for unknown Session"); - break; - } - break; - } - case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: { - XrEventDataSessionStateChanged *sc = - reinterpret_cast(&event_data); - if (sc->session != m_xr.session) { - wlr_log(WLR_ERROR, - "XrEventDataSessionStateChanged for unknown Session"); - break; - } + while (XrPollEvents()) { + switch (event_data.type) { + case XR_TYPE_EVENT_DATA_EVENTS_LOST: { + XrEventDataEventsLost *el + = reinterpret_cast(&event_data); + wlr_log(WLR_INFO, "OPENXR: Events Lost: %d", el->lostEventCount); + break; + } + case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: { + XrEventDataInstanceLossPending *ilp + = reinterpret_cast( + &event_data); + wlr_log(WLR_INFO, "OPENXR: Instance Loss Pending at: %ld", + ilp->lossTime); + m_session_running = false; + m_running = false; + break; + } + case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED: { + XrEventDataInteractionProfileChanged *ipc + = reinterpret_cast( + &event_data); + wlr_log(WLR_INFO, + "OPENXR: Interaction Profile changed for Session: %p", + ipc->session); + if (ipc->session != m_xr.session) { + wlr_log(WLR_ERROR, + "XrEventDataInteractionProfileChanged for unknown Session"); + break; + } + break; + } + case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: { + XrEventDataReferenceSpaceChangePending *scp + = reinterpret_cast( + &event_data); + wlr_log(WLR_INFO, + "OPENXR: Reference Space Change pending for Session: %p", + scp->session); + if (scp->session != m_xr.session) { + wlr_log(WLR_ERROR, + "XrEventDataReferenceSpaceChangePending for unknown " + "Session"); + break; + } + break; + } + case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: { + XrEventDataSessionStateChanged *sc + = reinterpret_cast( + &event_data); + if (sc->session != m_xr.session) { + wlr_log(WLR_ERROR, + "XrEventDataSessionStateChanged for unknown Session"); + break; + } - if (sc->state == XR_SESSION_STATE_READY) { - XrSessionBeginInfo bi{XR_TYPE_SESSION_BEGIN_INFO}; - bi.primaryViewConfigurationType = - XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; - bi.primaryViewConfigurationType = - XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; - if (xrBeginSession(m_xr.session, &bi) != XR_SUCCESS) { - throw std::runtime_error("Failed to begin session"); - } - m_session_running = true; - } - if (sc->state == XR_SESSION_STATE_STOPPING) { - if (xrEndSession(m_xr.session) != XR_SUCCESS) { - throw std::runtime_error("Failed to end session"); - } - m_session_running = false; - } - if (sc->state == XR_SESSION_STATE_EXITING) { - m_session_running = false; - m_running = false; - } - if (sc->state == XR_SESSION_STATE_LOSS_PENDING) { - m_session_running = false; - m_running = false; - } - m_xr.session_state = sc->state; - break; - } - default: { - break; - } - } - } + if (sc->state == XR_SESSION_STATE_READY) { + XrSessionBeginInfo bi { XR_TYPE_SESSION_BEGIN_INFO }; + bi.primaryViewConfigurationType + = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; + bi.primaryViewConfigurationType + = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; + if (xrBeginSession(m_xr.session, &bi) != XR_SUCCESS) { + throw std::runtime_error("Failed to begin session"); + } + m_session_running = true; + } + if (sc->state == XR_SESSION_STATE_STOPPING) { + if (xrEndSession(m_xr.session) != XR_SUCCESS) { + throw std::runtime_error("Failed to end session"); + } + m_session_running = false; + } + if (sc->state == XR_SESSION_STATE_EXITING) { + m_session_running = false; + m_running = false; + } + if (sc->state == XR_SESSION_STATE_LOSS_PENDING) { + m_session_running = false; + m_running = false; + } + m_xr.session_state = sc->state; + break; + } + default: { + break; + } + } + } } bool LunarWM::render_layer(RenderLayerInfo &info, float dt) { - const uint32_t view_count = (uint32_t)m_xr.view_configuration_views.size(); + uint32_t const view_count = (uint32_t)m_xr.view_configuration_views.size(); std::vector views(view_count, { XR_TYPE_VIEW }); - XrViewLocateInfo locInfo{ XR_TYPE_VIEW_LOCATE_INFO }; + XrViewLocateInfo locInfo { XR_TYPE_VIEW_LOCATE_INFO }; locInfo.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; - locInfo.displayTime = info.predicted_display_time; - locInfo.space = m_xr.local_space; + locInfo.displayTime = info.predicted_display_time; + locInfo.space = m_xr.local_space; - XrViewState viewState{ XR_TYPE_VIEW_STATE }; - uint32_t located = 0; - if (xrLocateViews(m_xr.session, &locInfo, &viewState, - view_count, &located, views.data()) != XR_SUCCESS || - located != view_count) - { + XrViewState viewState { XR_TYPE_VIEW_STATE }; + uint32_t located = 0; + if (xrLocateViews(m_xr.session, &locInfo, &viewState, view_count, &located, + views.data()) + != XR_SUCCESS + || located != view_count) { wlr_log(WLR_ERROR, "Failed to locate views"); return false; } - auto &color_sc = m_xr.swapchains.color[0]; - auto &depth_sc = m_xr.swapchains.depth[0]; + auto &color_sc = m_xr.swapchains.color[0]; + auto &depth_sc = m_xr.swapchains.depth[0]; - auto acquire_wait = [](XrSwapchain sc, uint32_t &idx)->bool{ - XrSwapchainImageAcquireInfo ai{ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO }; - if (xrAcquireSwapchainImage(sc, &ai, &idx) != XR_SUCCESS) return false; - XrSwapchainImageWaitInfo wi{ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO }; + auto acquire_wait = [](XrSwapchain sc, uint32_t &idx) -> bool { + XrSwapchainImageAcquireInfo ai { XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO }; + if (xrAcquireSwapchainImage(sc, &ai, &idx) != XR_SUCCESS) + return false; + XrSwapchainImageWaitInfo wi { XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO }; wi.timeout = XR_INFINITE_DURATION; return xrWaitSwapchainImage(sc, &wi) == XR_SUCCESS; }; uint32_t colIdx = 0, depIdx = 0; - if (!acquire_wait(color_sc.swapchain, colIdx) || - !acquire_wait(depth_sc.swapchain, depIdx)) - { + if (!acquire_wait(color_sc.swapchain, colIdx) + || !acquire_wait(depth_sc.swapchain, depIdx)) { wlr_log(WLR_ERROR, "Swap-chain acquire failed"); return false; } GLuint color_tex = m_xr.get_swapchain_image(color_sc.swapchain, colIdx); - GLuint depth_tex = m_xr.get_swapchain_image(depth_sc.swapchain, depIdx); + GLuint depth_tex = m_xr.get_swapchain_image(depth_sc.swapchain, depIdx); - if (!m_renderer.fbo) glGenFramebuffers(1, &m_renderer.fbo); + if (!m_renderer.fbo) + glGenFramebuffers(1, &m_renderer.fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_renderer.fbo); rlFramebufferAttach(m_renderer.fbo, color_tex, RL_ATTACHMENT_COLOR_CHANNEL0, - RL_ATTACHMENT_TEXTURE2D, 0); - rlFramebufferAttach(m_renderer.fbo, depth_tex, RL_ATTACHMENT_DEPTH, - RL_ATTACHMENT_TEXTURE2D, 0); + RL_ATTACHMENT_TEXTURE2D, 0); + rlFramebufferAttach(m_renderer.fbo, depth_tex, RL_ATTACHMENT_DEPTH, + RL_ATTACHMENT_TEXTURE2D, 0); assert(rlFramebufferComplete(m_renderer.fbo)); - const uint32_t eyeW = m_xr.view_configuration_views[0].recommendedImageRectWidth; - const uint32_t eyeH = m_xr.view_configuration_views[0].recommendedImageRectHeight; + uint32_t const eyeW + = m_xr.view_configuration_views[0].recommendedImageRectWidth; + uint32_t const eyeH + = m_xr.view_configuration_views[0].recommendedImageRectHeight; m_renderer.tmp_rt = { m_renderer.fbo, - { color_tex, (int)(eyeW*view_count), (int)eyeH, 1, -1 }, - { depth_tex, (int)(eyeW*view_count), (int)eyeH, 1, -1 } }; + { color_tex, (int)(eyeW * view_count), (int)eyeH, 1, -1 }, + { depth_tex, (int)(eyeW * view_count), (int)eyeH, 1, -1 } }; - Matrix projL = xr_projection_matrix(views[0].fov); - Matrix projR = xr_projection_matrix(views[1].fov); - Matrix viewL = MatrixInvert( xr_matrix(views[0].pose) ); - Matrix viewR = MatrixInvert( xr_matrix(views[1].pose) ); + Matrix projL = xr_projection_matrix(views[0].fov); + Matrix projR = xr_projection_matrix(views[1].fov); + Matrix viewL = MatrixInvert(xr_matrix(views[0].pose)); + Matrix viewR = MatrixInvert(xr_matrix(views[1].pose)); BeginTextureMode(m_renderer.tmp_rt); @@ -1515,7 +1806,7 @@ bool LunarWM::render_layer(RenderLayerInfo &info, float dt) rlSetMatrixProjectionStereo(projL, projR); rlSetMatrixViewOffsetStereo(viewL, viewR); - glViewport(0, 0, (GLsizei)(eyeW*view_count), (GLsizei)eyeH); + glViewport(0, 0, (GLsizei)(eyeW * view_count), (GLsizei)eyeH); ClearBackground(RAYWHITE); BeginMode3D(m_renderer.camera); @@ -1527,195 +1818,203 @@ bool LunarWM::render_layer(RenderLayerInfo &info, float dt) rlDisableStereoRender(); EndTextureMode(); - XrSwapchainImageReleaseInfo ri{ XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO }; + XrSwapchainImageReleaseInfo ri { XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO }; xrReleaseSwapchainImage(color_sc.swapchain, &ri); - xrReleaseSwapchainImage(depth_sc.swapchain, &ri); + xrReleaseSwapchainImage(depth_sc.swapchain, &ri); - info.layer_projection_views.resize(view_count, - { XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW }); + info.layer_projection_views.resize( + view_count, { XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW }); - for (uint32_t i = 0; i < view_count; ++i) - { - const int32_t xOff = (int32_t)i * (int32_t)eyeW; + for (uint32_t i = 0; i < view_count; ++i) { + int32_t const xOff = (int32_t)i * (int32_t)eyeW; - auto &pv = info.layer_projection_views[i]; - pv.pose = views[i].pose; - pv.fov = views[i].fov; - pv.subImage.swapchain = color_sc.swapchain; - pv.subImage.imageRect = { { xOff, 0 }, - { (int32_t)eyeW, (int32_t)eyeH } }; + auto &pv = info.layer_projection_views[i]; + pv.pose = views[i].pose; + pv.fov = views[i].fov; + pv.subImage.swapchain = color_sc.swapchain; + pv.subImage.imageRect + = { { xOff, 0 }, { (int32_t)eyeW, (int32_t)eyeH } }; pv.subImage.imageArrayIndex = 0; } - info.layer_projection.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION; - info.layer_projection.space = m_xr.local_space; + info.layer_projection.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION; + info.layer_projection.space = m_xr.local_space; info.layer_projection.viewCount = view_count; - info.layer_projection.views = info.layer_projection_views.data(); - info.layer_projection.layerFlags = - XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT | - XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT; + info.layer_projection.views = info.layer_projection_views.data(); + info.layer_projection.layerFlags + = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT + | XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT; info.layers.clear(); - info.layers.push_back( - reinterpret_cast(&info.layer_projection)); + info.layers.push_back(reinterpret_cast( + &info.layer_projection)); return true; } -void LunarWM::render_3d(float dt) { - static float animT {0.0f}; +void LunarWM::render_3d(float dt) +{ + static float animT { 0.0f }; animT += dt; DrawGrid(10, 1); - Vector3 forward = Vector3Normalize(Vector3Subtract(m_renderer.camera.target, m_renderer.camera.position)); + Vector3 forward = Vector3Normalize( + Vector3Subtract(m_renderer.camera.target, m_renderer.camera.position)); float distance = 5.0f + sinf(animT) * 3.0f; - Vector3 spherePos = Vector3Add(m_renderer.camera.position, Vector3Scale(forward, distance)); + Vector3 spherePos = Vector3Add( + m_renderer.camera.position, Vector3Scale(forward, distance)); DrawSphere(spherePos, 0.5f, YELLOW); } -LunarWM::~LunarWM() { - assert(m_initialized); +LunarWM::~LunarWM() +{ + assert(m_initialized); - if (m_xr.local_space == XR_NULL_HANDLE) { - xrDestroySpace(m_xr.local_space); - } + if (m_xr.local_space == XR_NULL_HANDLE) { + xrDestroySpace(m_xr.local_space); + } - for (size_t i = 0; i < m_xr.swapchains.color.size(); i++) { - auto &color_sc = m_xr.swapchains.color[i]; - auto &depth_sc = m_xr.swapchains.depth[i]; + for (size_t i = 0; i < m_xr.swapchains.color.size(); i++) { + auto &color_sc = m_xr.swapchains.color[i]; + auto &depth_sc = m_xr.swapchains.depth[i]; - for (auto &iv : color_sc.image_views) { - glDeleteFramebuffers(1, &iv); - } - for (auto &iv : depth_sc.image_views) { - glDeleteFramebuffers(1, &iv); - } + for (auto &iv : color_sc.image_views) { + glDeleteFramebuffers(1, &iv); + } + for (auto &iv : depth_sc.image_views) { + glDeleteFramebuffers(1, &iv); + } - xrDestroySwapchain(color_sc.swapchain); - xrDestroySwapchain(depth_sc.swapchain); - } + xrDestroySwapchain(color_sc.swapchain); + xrDestroySwapchain(depth_sc.swapchain); + } - if (m_xr.session != XR_NULL_HANDLE) { - xrDestroySession(m_xr.session); - } + if (m_xr.session != XR_NULL_HANDLE) { + xrDestroySession(m_xr.session); + } - if (m_xr.instance) { - xrDestroyInstance(*m_xr.instance); - } + if (m_xr.instance) { + xrDestroyInstance(*m_xr.instance); + } - wl_list_remove(&m_wayland.keyboards); + wl_list_remove(&m_wayland.keyboards); - wl_display_destroy_clients(m_wayland.display); - if (!m_wayland.allocator) { - wlr_allocator_destroy(m_wayland.allocator); - } - if (!m_wayland.renderer) { - wlr_renderer_destroy(m_wayland.renderer); - } - if (!m_wayland.backend) { - wlr_backend_destroy(m_wayland.backend); - } - if (!m_wayland.display) { - wl_display_destroy(m_wayland.display); - } + wl_display_destroy_clients(m_wayland.display); + if (!m_wayland.allocator) { + wlr_allocator_destroy(m_wayland.allocator); + } + if (!m_wayland.renderer) { + wlr_renderer_destroy(m_wayland.renderer); + } + if (!m_wayland.backend) { + wlr_backend_destroy(m_wayland.backend); + } + if (!m_wayland.display) { + wl_display_destroy(m_wayland.display); + } } -void LunarWM::run() { - if (!wlr_backend_start(m_wayland.backend)) { - throw std::runtime_error("Failed to start backend"); - } +void LunarWM::run() +{ + if (!wlr_backend_start(m_wayland.backend)) { + throw std::runtime_error("Failed to start backend"); + } - auto const *socket = wl_display_add_socket_auto(m_wayland.display); - if (!socket) { - throw std::runtime_error("Failed to add wayland socket to display"); - } + auto const *socket = wl_display_add_socket_auto(m_wayland.display); + if (!socket) { + throw std::runtime_error("Failed to add wayland socket to display"); + } - setenv("WAYLAND_DISPLAY", socket, true); - wlr_log(WLR_INFO, "Running compositor on WAYLAND_DISPLAY=%s", socket); + setenv("WAYLAND_DISPLAY", socket, true); + wlr_log(WLR_INFO, "Running compositor on WAYLAND_DISPLAY=%s", socket); - m_running = true; - while (m_running) { + m_running = true; + while (m_running) { auto now = Clock::now(); float dt = std::chrono::duration(now - m_last_tick).count(); m_last_tick = now; - wl_display_flush_clients(m_wayland.display); - wl_event_loop_dispatch(m_wayland.event_loop, 0); + wl_display_flush_clients(m_wayland.display); + wl_event_loop_dispatch(m_wayland.event_loop, 0); auto draw = eglGetCurrentSurface(EGL_DRAW); auto read = eglGetCurrentSurface(EGL_READ); - if (eglMakeCurrent(m_wayland.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, - m_wayland.egl_context) == EGL_FALSE) { + if (eglMakeCurrent(m_wayland.egl_display, EGL_NO_SURFACE, + EGL_NO_SURFACE, m_wayland.egl_context) + == EGL_FALSE) { throw std::runtime_error("Failed to eglMakeCurrent"); } - poll_events_xr(); + poll_events_xr(); - XrFrameState frame_state{ - .type = XR_TYPE_FRAME_STATE, - }; - XrFrameWaitInfo frame_wait_info{ - .type = XR_TYPE_FRAME_WAIT_INFO, - .next = nullptr, - }; - if (xrWaitFrame(m_xr.session, &frame_wait_info, &frame_state) != - XR_SUCCESS) { - throw std::runtime_error("Failed to wait for OpenXR frame"); - } + XrFrameState frame_state { + .type = XR_TYPE_FRAME_STATE, + }; + XrFrameWaitInfo frame_wait_info { + .type = XR_TYPE_FRAME_WAIT_INFO, + .next = nullptr, + }; + if (xrWaitFrame(m_xr.session, &frame_wait_info, &frame_state) + != XR_SUCCESS) { + throw std::runtime_error("Failed to wait for OpenXR frame"); + } - XrFrameBeginInfo frame_begin_info{ - .type = XR_TYPE_FRAME_BEGIN_INFO, - .next = nullptr, - }; - XrResult res = xrBeginFrame(m_xr.session, &frame_begin_info); - if (res != XR_FRAME_DISCARDED && res != XR_SUCCESS) { - throw std::runtime_error( - std::format("Failed to begin the OpenXR Frame: {}", res)); - } + XrFrameBeginInfo frame_begin_info { + .type = XR_TYPE_FRAME_BEGIN_INFO, + .next = nullptr, + }; + XrResult res = xrBeginFrame(m_xr.session, &frame_begin_info); + if (res != XR_FRAME_DISCARDED && res != XR_SUCCESS) { + throw std::runtime_error( + std::format("Failed to begin the OpenXR Frame: {}", res)); + } WindowShouldClose(); - RenderLayerInfo render_layer_info{ - .predicted_display_time = frame_state.predictedDisplayTime, - }; - bool session_active = - (m_xr.session_state == XR_SESSION_STATE_SYNCHRONIZED || - m_xr.session_state == XR_SESSION_STATE_VISIBLE || - m_xr.session_state == XR_SESSION_STATE_FOCUSED); - if (session_active && frame_state.shouldRender) { - auto rendered = this->render_layer(render_layer_info, dt); - if (rendered) { - render_layer_info.layers.push_back( - reinterpret_cast( - &render_layer_info.layer_projection)); - } - } + RenderLayerInfo render_layer_info { + .predicted_display_time = frame_state.predictedDisplayTime, + }; + bool session_active + = (m_xr.session_state == XR_SESSION_STATE_SYNCHRONIZED + || m_xr.session_state == XR_SESSION_STATE_VISIBLE + || m_xr.session_state == XR_SESSION_STATE_FOCUSED); + if (session_active && frame_state.shouldRender) { + auto rendered = this->render_layer(render_layer_info, dt); + if (rendered) { + render_layer_info.layers.push_back( + reinterpret_cast( + &render_layer_info.layer_projection)); + } + } - XrFrameEndInfo frame_end_info{ - .type = XR_TYPE_FRAME_END_INFO, - .displayTime = frame_state.predictedDisplayTime, - .environmentBlendMode = m_xr.environment_blend_mode, - .layerCount = static_cast(render_layer_info.layers.size()), - .layers = render_layer_info.layers.data(), - }; - if (xrEndFrame(m_xr.session, &frame_end_info) != XR_SUCCESS) { - throw std::runtime_error("Failed to end OpenXR frame"); - } + XrFrameEndInfo frame_end_info { + .type = XR_TYPE_FRAME_END_INFO, + .displayTime = frame_state.predictedDisplayTime, + .environmentBlendMode = m_xr.environment_blend_mode, + .layerCount + = static_cast(render_layer_info.layers.size()), + .layers = render_layer_info.layers.data(), + }; + if (xrEndFrame(m_xr.session, &frame_end_info) != XR_SUCCESS) { + throw std::runtime_error("Failed to end OpenXR frame"); + } BeginDrawing(); EndDrawing(); - if (eglMakeCurrent(m_wayland.egl_display, read, draw, - m_wayland.egl_context) == EGL_FALSE) { + if (eglMakeCurrent( + m_wayland.egl_display, read, draw, m_wayland.egl_context) + == EGL_FALSE) { throw std::runtime_error("Failed to eglMakeCurrent"); } - } + } } -void LunarWM::terminate() { - wlr_log(WLR_INFO, "Stopping compositor"); - m_running = false; +void LunarWM::terminate() +{ + wlr_log(WLR_INFO, "Stopping compositor"); + m_running = false; } } // namespace LunarWM diff --git a/src/Math.cppm b/src/Math.cppm index 9876b35..79041a4 100644 --- a/src/Math.cppm +++ b/src/Math.cppm @@ -7,195 +7,205 @@ export module LunarWM.Math; export namespace LunarWM { namespace Math { -template - requires std::is_arithmetic_v -struct Vec2 { - template - requires std::is_arithmetic_v - Vec2 operator+(Vec2 const &other) { - return {x + other.x, y + other.y}; - } - template - requires std::is_arithmetic_v - Vec2 operator-(Vec2 const &other) { - return {x - other.x, y - other.y}; - } - template - requires std::is_arithmetic_v - Vec2 operator*(Vec2 const &other) { - return {x * other.x, y * other.x}; - } - template - requires std::is_arithmetic_v - Vec2 operator*(T scalar) { - return {x * scalar, y * scalar}; - } - template - requires std::is_arithmetic_v - Vec2 operator/(T scalar) { - return {x / scalar, y / scalar}; - } - template - requires std::is_arithmetic_v - Vec2 operator-() { - return {-x, -y}; - } - T length() const { return std::sqrt(x * x + y * y); } - T lengthSquared() const { return x * x + y * y; } - Vec2 normalized() const { - T len = length(); - if (len == T(0)) - return {T(0), T(0)}; - return *this / len; - } +template +requires std::is_arithmetic_v struct Vec2 { + template + requires std::is_arithmetic_v Vec2 operator+(Vec2 const &other) + { + return { x + other.x, y + other.y }; + } + template + requires std::is_arithmetic_v Vec2 operator-(Vec2 const &other) + { + return { x - other.x, y - other.y }; + } + template + requires std::is_arithmetic_v Vec2 operator*(Vec2 const &other) + { + return { x * other.x, y * other.x }; + } + template + requires std::is_arithmetic_v Vec2 operator*(T scalar) + { + return { x * scalar, y * scalar }; + } + template + requires std::is_arithmetic_v Vec2 operator/(T scalar) + { + return { x / scalar, y / scalar }; + } + template + requires std::is_arithmetic_v Vec2 operator-() + { + return { -x, -y }; + } + T length() const { return std::sqrt(x * x + y * y); } + T lengthSquared() const { return x * x + y * y; } + Vec2 normalized() const + { + T len = length(); + if (len == T(0)) + return { T(0), T(0) }; + return *this / len; + } - T x, y; + T x, y; }; -template - requires std::is_arithmetic_v -Vec2 operator*(T scalar, Vec2 const &v) { - return {v.x * scalar, v.y * scalar}; +template +requires std::is_arithmetic_v Vec2 operator*(T scalar, Vec2 const &v) +{ + return { v.x * scalar, v.y * scalar }; } -template - requires std::is_arithmetic_v -struct Rect { - Rect(Vec2 pos, Vec2 size) : pos(pos), size(size) {} - Rect(T x, T y, T w, T h) : pos({x, y}), size({w, h}) {} +template +requires std::is_arithmetic_v struct Rect { + Rect(Vec2 pos, Vec2 size) + : pos(pos) + , size(size) + { + } + Rect(T x, T y, T w, T h) + : pos({ x, y }) + , size({ w, h }) + { + } - T &x() { return pos.x; } - T &y() { return pos.y; } - T &w() { return size.x; } - T &h() { return size.y; } + T &x() { return pos.x; } + T &y() { return pos.y; } + T &w() { return size.x; } + T &h() { return size.y; } - T x() const { return pos.x; } - T y() const { return pos.y; } - T w() const { return size.x; } - T h() const { return size.y; } + T x() const { return pos.x; } + T y() const { return pos.y; } + T w() const { return size.x; } + T h() const { return size.y; } - T left() const { return x(); } - T right() const { return x() + w(); } - T top() const { return y(); } - T bottom() const { return y() + h(); } + T left() const { return x(); } + T right() const { return x() + w(); } + T top() const { return y(); } + T bottom() const { return y() + h(); } - T &left() { return x(); } - T &top() { return y(); } + T &left() { return x(); } + T &top() { return y(); } - Vec2 pos, size; + Vec2 pos, size; }; -template - requires std::is_arithmetic_v -struct Box { - template - requires std::is_arithmetic_v - Vec2 &operator[](U const index) { - if (index < 0 || index > 1) - throw std::out_of_range("A box only has two points"); - return m_data[index]; - } - Vec2 &first() { return m_data[0]; } - Vec2 &second() { return m_data[1]; } - T &x0() { return m_data[0].x; } - T &y0() { return m_data[0].y; } - T &x1() { return m_data[1].x; } - T &y1() { return m_data[1].y; } - T &left() { - if (x0() < x1()) - return x0(); - return x1(); - } - T &right() { - if (x0() > x1()) - return x0(); - return x1(); - } - T &top() { - if (y0() < y1()) - return y0(); - return y1(); - } - T &bottom() { - if (y0() > y1()) - return y0(); - return y1(); - } +template +requires std::is_arithmetic_v struct Box { + template + requires std::is_arithmetic_v Vec2 &operator[](U const index) + { + if (index < 0 || index > 1) + throw std::out_of_range("A box only has two points"); + return m_data[index]; + } + Vec2 &first() { return m_data[0]; } + Vec2 &second() { return m_data[1]; } + T &x0() { return m_data[0].x; } + T &y0() { return m_data[0].y; } + T &x1() { return m_data[1].x; } + T &y1() { return m_data[1].y; } + T &left() + { + if (x0() < x1()) + return x0(); + return x1(); + } + T &right() + { + if (x0() > x1()) + return x0(); + return x1(); + } + T &top() + { + if (y0() < y1()) + return y0(); + return y1(); + } + T &bottom() + { + if (y0() > y1()) + return y0(); + return y1(); + } - Box() {} - Box(Rect rect) { - this->m_data[0] = rect.pos; - this->m_data[1] = rect.pos + rect.size; - } + Box() { } + Box(Rect rect) + { + this->m_data[0] = rect.pos; + this->m_data[1] = rect.pos + rect.size; + } private: - Vec2 m_data[2] = {}; + Vec2 m_data[2] = {}; }; -template - requires std::is_arithmetic_v -std::vector> subtract_rect(Math::Rect const &src, - Math::Rect const &clip) { - std::vector> result; +template +requires std::is_arithmetic_v std::vector> subtract_rect( + Math::Rect const &src, Math::Rect const &clip) +{ + std::vector> result; - auto sx = src.x(); - auto sy = src.y(); - auto sw = src.w(); - auto sh = src.h(); + auto sx = src.x(); + auto sy = src.y(); + auto sw = src.w(); + auto sh = src.h(); - auto cx = clip.x(); - auto cy = clip.y(); - auto cw = clip.w(); - auto ch = clip.h(); + auto cx = clip.x(); + auto cy = clip.y(); + auto cw = clip.w(); + auto ch = clip.h(); - T s_right = sx + sw; - T s_bottom = sy + sh; + T s_right = sx + sw; + T s_bottom = sy + sh; - T c_right = cx + cw; - T c_bottom = cy + ch; + T c_right = cx + cw; + T c_bottom = cy + ch; - // No overlap → keep src - if (c_right <= sx || cx >= s_right || c_bottom <= sy || cy >= s_bottom) { - result.push_back(src); - return result; - } + // No overlap → keep src + if (c_right <= sx || cx >= s_right || c_bottom <= sy || cy >= s_bottom) { + result.push_back(src); + return result; + } - // Top piece - if (cy > sy) { - result.emplace_back(sx, sy, sw, cy - sy); - } + // Top piece + if (cy > sy) { + result.emplace_back(sx, sy, sw, cy - sy); + } - // Bottom piece - if (c_bottom < s_bottom) { - result.emplace_back(sx, c_bottom, sw, s_bottom - c_bottom); - } + // Bottom piece + if (c_bottom < s_bottom) { + result.emplace_back(sx, c_bottom, sw, s_bottom - c_bottom); + } - // Middle pieces left and right of clip - T middle_top = std::max(sy, cy); - T middle_bottom = std::min(s_bottom, c_bottom); - T middle_height = middle_bottom - middle_top; + // Middle pieces left and right of clip + T middle_top = std::max(sy, cy); + T middle_bottom = std::min(s_bottom, c_bottom); + T middle_height = middle_bottom - middle_top; - if (middle_height > 0) { - // Left piece - if (cx > sx) { - result.emplace_back(sx, middle_top, cx - sx, middle_height); - } + if (middle_height > 0) { + // Left piece + if (cx > sx) { + result.emplace_back(sx, middle_top, cx - sx, middle_height); + } - // Right piece - if (c_right < s_right) { - result.emplace_back(c_right, middle_top, s_right - c_right, - middle_height); - } - } + // Right piece + if (c_right < s_right) { + result.emplace_back( + c_right, middle_top, s_right - c_right, middle_height); + } + } - return result; + return result; } -template - requires std::is_arithmetic_v -struct Viewport { - Rect rect; - Vec2 depth_limits; +template +requires std::is_arithmetic_v struct Viewport { + Rect rect; + Vec2 depth_limits; }; } // namespace Math diff --git a/tools/format.sh b/tools/format.sh new file mode 100755 index 0000000..c12b955 --- /dev/null +++ b/tools/format.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(git rev-parse --show-toplevel)" + +find "$ROOT/src" -type f -name '*.cppm' -print0 | while IFS= read -r -d '' f; do + clang-format -i --style=file "$f" +done