[
  {
    "path": ".fpm",
    "content": "--name xr-driver \n--description \"Linux service for interacting with XR devices\"\n--iteration 1\n--url https://github.com/wheaney/XRLinuxDriver\n--maintainer \"Wayne Heaney <wayne at xronlinux dot com>\"\n--license mit \n-s dir \n-f\n--before-install ./fpm/preinstall\n--after-install ./fpm/postinstall\n--after-upgrade ./fpm/postupgrade\n--before-remove ./fpm/preuninstall\n--chdir build/xr_driver\nbin/xrDriver=/usr/bin/xrDriver\nbin/xr_driver_cli=/usr/bin/xr_driver_cli\nsystemd/xr-driver.service=/usr/lib/systemd/user/xr-driver.service"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: wheaney\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: wheaney\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\nlfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry\ncustom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  workflow_dispatch:\n    inputs:\n      force_release:\n        description: 'Run release even if version did not change'\n        type: boolean\n        required: false\n        default: false\n  push:\n    branches:\n      - main\n    paths:\n      - 'CMakeLists.txt'\n\npermissions:\n  contents: write\n\njobs:\n  check-version-change:\n    runs-on: ubuntu-latest\n    outputs:\n      version-changed: ${{ steps.check.outputs.changed }}\n      version: ${{ steps.get-version.outputs.version }}\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 2\n      \n      - name: Check if version changed\n        id: check\n        env:\n          FORCE_RELEASE: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.force_release == 'true' }}\n        run: |\n          # Get the current version\n          CURRENT_VERSION=$(grep -oP 'project\\(xrDriver VERSION \\K[0-9]+\\.[0-9]+\\.[0-9]+' CMakeLists.txt)\n          echo \"Current version: ${CURRENT_VERSION}\"\n          \n          # Get the previous version (from previous commit)\n          if git rev-parse HEAD~1 >/dev/null 2>&1; then\n            git show HEAD~1:CMakeLists.txt > /tmp/prev_cmakelists.txt\n            PREVIOUS_VERSION=$(grep -oP 'project\\(xrDriver VERSION \\K[0-9]+\\.[0-9]+\\.[0-9]+' /tmp/prev_cmakelists.txt 2>/dev/null || echo \"none\")\n            rm /tmp/prev_cmakelists.txt\n          else\n            # This is the first commit\n            PREVIOUS_VERSION=\"none\"\n          fi\n          echo \"Previous version: ${PREVIOUS_VERSION}\"\n\n          if [ \"${FORCE_RELEASE}\" = \"true\" ]; then\n            echo \"Force release enabled; proceeding regardless of version change\"\n            echo \"changed=true\" >> $GITHUB_OUTPUT\n            exit 0\n          fi\n          \n          if [ \"${CURRENT_VERSION}\" != \"${PREVIOUS_VERSION}\" ]; then\n            echo \"Version changed from ${PREVIOUS_VERSION} to ${CURRENT_VERSION}\"\n            echo \"changed=true\" >> $GITHUB_OUTPUT\n          else\n            echo \"Version unchanged\"\n            echo \"changed=false\" >> $GITHUB_OUTPUT\n          fi\n      \n      - name: Get version\n        id: get-version\n        run: |\n          VERSION=$(grep -oP 'project\\(xrDriver VERSION \\K[0-9]+\\.[0-9]+\\.[0-9]+' CMakeLists.txt)\n          echo \"version=${VERSION}\" >> $GITHUB_OUTPUT\n          echo \"Version: ${VERSION}\"\n\n  build-x86_64:\n    needs: check-version-change\n    if: needs.check-version-change.outputs.version-changed == 'true'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          submodules: recursive\n      \n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      \n      - name: Build Docker image for x86_64\n        run: |\n          docker buildx build --platform linux/amd64 --load -f ./docker-build/Dockerfile -t \"xr-driver:amd64\" .\n      \n      - name: Build x86_64 binary package\n        run: |\n          docker run --rm -t -v ./:/source --platform linux/amd64 -e UA_API_SECRET_INTENTIONALLY_EMPTY=1 \"xr-driver:amd64\"\n          sudo chown -R \"${USER}\":\"${USER}\" out/\n      \n      - name: Build x86_64 lib package\n        run: |\n          ./bin/package_libs\n      \n      - name: Upload x86_64 artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: xrDriver-x86_64\n          path: |\n            out/xrDriver-x86_64.tar.gz\n            out/xrDriver-libs-x86_64.tar.gz\n\n  build-aarch64:\n    needs: check-version-change\n    if: needs.check-version-change.outputs.version-changed == 'true'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          submodules: recursive\n      \n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@v3\n      \n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      \n      - name: Build Docker image for aarch64\n        run: |\n          docker buildx build --platform linux/arm64 --load -f ./docker-build/Dockerfile.aarch64 -t \"xr-driver:arm64\" .\n      \n      - name: Build aarch64 binary package\n        run: |\n          docker run --rm -t -v ./:/source --platform linux/arm64 -e UA_API_SECRET_INTENTIONALLY_EMPTY=1 \"xr-driver:arm64\"\n          sudo chown -R \"${USER}\":\"${USER}\" out/\n      \n      - name: Build aarch64 lib package\n        run: |\n          ./bin/package_libs\n      \n      - name: Upload aarch64 artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: xrDriver-aarch64\n          path: |\n            out/xrDriver-aarch64.tar.gz\n            out/xrDriver-libs-aarch64.tar.gz\n\n  create-release:\n    needs: [check-version-change, build-x86_64, build-aarch64]\n    if: needs.check-version-change.outputs.version-changed == 'true'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      \n      - name: Download x86_64 artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: xrDriver-x86_64\n          path: ./artifacts\n      \n      - name: Download aarch64 artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: xrDriver-aarch64\n          path: ./artifacts\n      \n      - name: Create Release\n        uses: softprops/action-gh-release@v2\n        with:\n          tag_name: v${{ needs.check-version-change.outputs.version }}\n          name: Release v${{ needs.check-version-change.outputs.version }}\n          draft: false\n          prerelease: false\n          files: |\n            artifacts/xrDriver-x86_64.tar.gz\n            artifacts/xrDriver-libs-x86_64.tar.gz\n            artifacts/xrDriver-aarch64.tar.gz\n            artifacts/xrDriver-libs-aarch64.tar.gz\n            bin/xr_driver_setup\n            bin/xr_driver_ot_profile_setup\n"
  },
  {
    "path": ".gitignore",
    "content": ".idea/\n.cache/\n\ncmake-build-debug/\ncmake-build-release/\n\nbuild/\nout/\n\nxrDriver\n\n/include/custom_banner_config.h\n/custom_banner_config.yml\n\n# Packaging artifacts\nxr_driver/\nxr_driver_lib/\n*.tar.gz\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"modules/xrealInterfaceLibrary\"]\n\tpath = modules/xrealInterfaceLibrary\n\turl = https://gitlab.com/wheaney/nrealAirLinuxDriver.git\n"
  },
  {
    "path": ".readthedocs.yaml",
    "content": "# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\n# Required\nversion: 2\n\n# Set the OS, Python version, and other tools you might need\nbuild:\n  os: ubuntu-24.04\n  tools:\n    python: \"3.13\"\n\n# Install MkDocs and theme/plugins needed for building.\npython:\n  install:\n    - requirements: docs/requirements.txt\n\n# Build documentation with Mkdocs\nmkdocs:\n  configuration: mkdocs.yml\n"
  },
  {
    "path": ".vscode/tasks.json",
    "content": "{\n\t\"version\": \"2.0.0\",\n\t\"tasks\": [\n\t\t{\n\t\t\t\"label\": \"build XRLinuxDriver (cmake)\",\n\t\t\t\"type\": \"shell\",\n\t\t\t\"command\": \"bash -lc 'set -euo pipefail; if [ -d build ]; then cmake --build build -j$(nproc); else cmake -S . -B build && cmake --build build -j$(nproc); fi'\",\n\t\t\t\"problemMatcher\": [\n\t\t\t\t\"$gcc\"\n\t\t\t],\n\t\t\t\"group\": \"build\"\n\t\t}\n\t]\n}"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.16)\nproject(xrDriver VERSION 2.9.4 LANGUAGES C)\n\n# Emit compile_commands.json for IDEs (VS Code IntelliSense)\nset(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n\nconfigure_file(include/version.h.in version.h)\ninclude_directories(${PROJECT_BINARY_DIR})\n\n# Build type: default to RelWithDebInfo for useful backtraces unless caller overrides\nif(NOT CMAKE_BUILD_TYPE)\n    set(CMAKE_BUILD_TYPE Release CACHE STRING \"Choose the type of build.\" FORCE)\nendif()\nset_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel)\nset(CMAKE_C_STANDARD 17)\nset(THREADS_PREFER_PTHREAD_FLAG ON)\n\nfind_package(PkgConfig REQUIRED)\nfind_package(Python3 REQUIRED COMPONENTS Interpreter)\nset (py_cmd \"${CMAKE_SOURCE_DIR}/bin/build_custom_banner_config.py\")\nset (custom_banner_header_file \"${CMAKE_SOURCE_DIR}/include/custom_banner_config.h\")\nset (custom_banner_yaml_file \"${CMAKE_SOURCE_DIR}/custom_banner_config.yml\")\n\nadd_custom_target(run_python_script ALL\n    COMMAND ${Python3_EXECUTABLE} ${py_cmd} ${custom_banner_yaml_file} ${custom_banner_header_file}\n)\n\nif(DEFINED ENV{UA_API_SECRET})\n  set(UA_API_SECRET $ENV{UA_API_SECRET})\n  message(STATUS \"Using UA_API_SECRET from environment\")\n  add_definitions(-DUA_API_SECRET=\"${UA_API_SECRET}\")\nelse()\n  set(UA_API_SECRET \"\")\n  message(STATUS \"!!! UA_API_SECRET is NOT set\")\nendif()\n\nfile(READ ${CMAKE_CURRENT_SOURCE_DIR}/license_public_key.pem DEVICE_LICENSE_PUBLIC_KEY_RAW)\nstring(REPLACE \"\\n\" \"\\\\n\" DEVICE_LICENSE_PUBLIC_KEY_ESCAPED ${DEVICE_LICENSE_PUBLIC_KEY_RAW})\nadd_definitions(-DDEVICE_LICENSE_PUBLIC_KEY=\"${DEVICE_LICENSE_PUBLIC_KEY_ESCAPED}\")\n\nfind_package(Threads REQUIRED)\n\npkg_check_modules(LIBUSB REQUIRED libusb-1.0)\npkg_check_modules(LIBEVDEV REQUIRED libevdev)\npkg_check_modules(OPENSSL REQUIRED openssl)\npkg_check_modules(JSONC REQUIRED json-c)\npkg_check_modules(CURL REQUIRED libcurl)\npkg_check_modules(LIBWAYLAND_CLIENT REQUIRED wayland-client)\n\nexecute_process(COMMAND git submodule update --init --recursive\n                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})\nadd_subdirectory(modules/xrealInterfaceLibrary/interface_lib)\n\n# Set the library directory based on architecture\nset(LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/${CMAKE_SYSTEM_PROCESSOR})\nset(VITURE_LIB_DIR ${LIB_DIR}/viture)\nmessage(STATUS \"LIB_DIR: ${LIB_DIR}\")\nif(EXISTS ${VITURE_LIB_DIR})\n    message(STATUS \"VITURE_LIB_DIR: ${VITURE_LIB_DIR}\")\nendif()\n\n# Find all .a files in the library directory\nfile(GLOB STATIC_LIBS ${LIB_DIR}/*.a)\nif(EXISTS ${VITURE_LIB_DIR})\n    file(GLOB VITURE_STATIC_LIBS ${VITURE_LIB_DIR}/*.a)\n    list(APPEND STATIC_LIBS ${VITURE_STATIC_LIBS})\nendif()\nmessage(STATUS \"STATIC_LIBS: ${STATIC_LIBS}\")\n\n# Add all static libraries\nforeach(LIB ${STATIC_LIBS})\n    get_filename_component(LIB_NAME ${LIB} NAME_WE)\n    string(REPLACE \"lib\" \"\" LIB_NAME ${LIB_NAME})\n    \n    add_library(${LIB_NAME} STATIC IMPORTED)\n    set_target_properties(${LIB_NAME} PROPERTIES\n        IMPORTED_LOCATION ${LIB}\n    )\nendforeach()\n\n# Find all .so files in the library directory\nfile(GLOB SHARED_LIBS ${LIB_DIR}/*.so)\nif(EXISTS ${VITURE_LIB_DIR})\n    file(GLOB VITURE_SHARED_LIBS ${VITURE_LIB_DIR}/*.so)\n    list(APPEND SHARED_LIBS ${VITURE_SHARED_LIBS})\nendif()\nmessage(STATUS \"SHARED_LIBS: ${SHARED_LIBS}\")\n\n# Add all shared libraries\nforeach(LIB ${SHARED_LIBS})\n    get_filename_component(LIB_NAME ${LIB} NAME_WE)\n    string(REPLACE \"lib\" \"\" LIB_NAME ${LIB_NAME})\n    \n    add_library(${LIB_NAME} SHARED IMPORTED)\n    set_target_properties(${LIB_NAME} PROPERTIES\n        IMPORTED_LOCATION ${LIB}\n        IMPORTED_SONAME ${LIB_NAME}.so\n    )\nendforeach()\n\n# Define the mapping of binary names to source files\nset(DEVICE_MAPPINGS\n    \"libRayNeoXRMiniSDK.so:src/devices/rayneo.c\"\n    \"libGlassSDK.so:src/devices/rokid.c\"\n)\n\nset(SOURCES\n    src/buffer.c\n    src/config.c\n    src/connection_pool.c\n    src/curl.c\n    src/devices/xreal.c\n    src/devices.c\n    src/driver.c\n    src/epoch.c\n    src/features/breezy_desktop.c\n    src/features/smooth_follow.c\n    src/features/sbs.c\n    src/files.c\n    src/logging.c\n    src/imu.c\n    src/ipc.c\n    src/multitap.c\n    src/outputs.c\n    src/plugins.c\n    src/plugins/breezy_desktop.c\n    src/plugins/custom_banner.c\n    src/plugins/device_license.c\n    src/plugins/gamescope_reshade_wayland.c\n    src/plugins/metrics.c\n    src/plugins/sideview.c\n    src/plugins/smooth_follow.c\n    src/plugins/virtual_display.c\n    src/plugins/neck_saver.c\n    src/plugins/opentrack_source.c\n    src/plugins/opentrack_listener.c\n    src/runtime_context.c\n    src/state.c\n    src/strings.c\n    src/system.c\n    src/wl_client/gamescope_reshade.c\n)\n\n# Function to get the source file from a mapping\nfunction(get_source_file BINARY_NAME RESULT_VAR)\n    foreach(MAPPING ${DEVICE_MAPPINGS})\n        string(REPLACE \":\" \";\" MAPPING_LIST ${MAPPING})\n        list(GET MAPPING_LIST 0 MAPPED_BINARY)\n        list(GET MAPPING_LIST 1 MAPPED_SOURCE)\n        if(${BINARY_NAME} STREQUAL ${MAPPED_BINARY})\n            set(${RESULT_VAR} ${MAPPED_SOURCE} PARENT_SCOPE)\n            return()\n        endif()\n    endforeach()\n    set(${RESULT_VAR} \"\" PARENT_SCOPE)\nendfunction()\n\n# Get all targets in the current directory\nget_property(ALL_TARGETS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY IMPORTED_TARGETS)\n\n# Iterate over all targets\nforeach(TARGET ${ALL_TARGETS})\n    get_target_property(LIB_TYPE ${TARGET} TYPE)\n    if(LIB_TYPE STREQUAL \"STATIC_LIBRARY\" OR LIB_TYPE STREQUAL \"SHARED_LIBRARY\")\n        get_target_property(LIB_LOCATION ${TARGET} IMPORTED_LOCATION)\n        if(LIB_LOCATION)\n            get_filename_component(LIB_NAME ${LIB_LOCATION} NAME)\n            get_source_file(${LIB_NAME} SOURCE_FILE)\n            if(SOURCE_FILE)\n                list(APPEND SOURCES ${SOURCE_FILE})\n                string(TOUPPER ${TARGET} TARGET_UPPER)\n                add_definitions(-D${TARGET_UPPER}_SUPPORTED)\n                message(STATUS \"${TARGET} support enabled, added ${SOURCE_FILE}\")\n            endif()\n        endif()\n    endif()\nendforeach()\n\nif(EXISTS ${VITURE_LIB_DIR})\n    list(APPEND SOURCES src/devices/viture.c)\n    add_definitions(-DVITURE_SUPPORTED)\n    message(STATUS \"VITURE support enabled, added src/devices/viture.c\")\nendif()\n\nadd_executable(xrDriver ${SOURCES})\n\n# Improve crash backtraces and line number resolution\nif(CMAKE_C_COMPILER_ID MATCHES \"GNU|Clang\")\n    # Per-config compile options\n    target_compile_options(xrDriver PRIVATE\n        $<$<CONFIG:Debug>:-g3>\n        $<$<CONFIG:Debug>:-O0>\n        $<$<CONFIG:Debug>:-fno-omit-frame-pointer>\n        $<$<CONFIG:RelWithDebInfo>:-g>\n        $<$<CONFIG:RelWithDebInfo>:-fno-omit-frame-pointer>\n    )\n    # Export symbol table for better backtrace_symbols() resolution\n    target_link_options(xrDriver PRIVATE\n        $<$<CONFIG:Debug>:-rdynamic>\n        $<$<CONFIG:RelWithDebInfo>:-rdynamic>\n    )\nendif()\n\n# Optional: AddressSanitizer for clearer reports on memory errors\noption(ENABLE_ASAN \"Build with AddressSanitizer\" OFF)\nif(ENABLE_ASAN AND CMAKE_C_COMPILER_ID MATCHES \"GNU|Clang\")\n    target_compile_options(xrDriver PRIVATE -fsanitize=address -fno-omit-frame-pointer -g)\n    target_link_options(xrDriver PRIVATE -fsanitize=address)\nendif()\n\ntarget_include_directories(xrDriver\n\t\tSYSTEM BEFORE PRIVATE\n\t\t${LIBEVDEV_INCLUDE_DIRS}\n\t\t${JSONC_INCLUDE_DIRS}\n\t\t${CMAKE_CURRENT_SOURCE_DIR}/include\n\t\t${CMAKE_CURRENT_SOURCE_DIR}/modules/rayneoSDKHeaders\n\t\t${CMAKE_CURRENT_SOURCE_DIR}/modules/xrealInterfaceLibrary/interface_lib/include\n\t\t${LIBUSB_INCLUDE_DIRS}\n\t\t${LIBCURL_INCLUDE_DIRS}\n\t\t${OPENSSL_INCLUDE_DIRS}\n\t\t${LIBWAYLAND_CLIENT_INCLUDE_DIRS}\n)\n\nset(ALL_IMPORTED_LIBS)\nget_property(ALL_TARGETS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY IMPORTED_TARGETS)\nforeach(TARGET ${ALL_TARGETS})\n    get_target_property(LIB_TYPE ${TARGET} TYPE)\n    if(LIB_TYPE STREQUAL \"STATIC_LIBRARY\" OR LIB_TYPE STREQUAL \"SHARED_LIBRARY\")\n        list(APPEND ALL_IMPORTED_LIBS ${TARGET})\n    endif()\nendforeach()\n\ntarget_link_libraries(xrDriver\n    PRIVATE\n        ${LIBEVDEV_LIBRARIES}\n        ${JSONC_LIBRARIES}\n        xrealAirLibrary\n        Threads::Threads\n        m\n        ${CURL_LIBRARIES}\n        ${OPENSSL_LIBRARIES}\n        ${ALL_IMPORTED_LIBS}\n        ${LIBUSB_LIBRARIES}\n        ${LIBWAYLAND_CLIENT_LIBRARIES}\n)\nadd_dependencies(xrDriver run_python_script)\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "# XR Linux Driver\n\n[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/U7U8OVC0L)\n\n[![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg)](https://discord.gg/azSBTXNXMt)\n\n[![Documentation Status](https://readthedocs.org/projects/xrlinuxdriver/badge/?version=latest)](https://xrlinuxdriver.readthedocs.io/en/latest/?badge=latest)\n\n## What is this?\n\nThis driver allows your Linux device (including Steam Deck) to automatically recognize supported XR glasses (see [Supported Devices](#supported-devices)) when they're plugged in, and convert the movements of the glasses into mouse movements and an external broadcast that games or any application can utilize.\n\nIf you're looking for a 3DoF virtual display, this driver by itself does not provide that functionality; instead, see [Breezy Desktop](https://github.com/wheaney/breezy-desktop) or [use the Steam Deck plugin](#steam-deck-via-decky-loader).\n\n## Supported Devices\nCheck below to see if your device is supported. **Note: be sure you're on the latest firmware for your device.**\n\n| Brand    | Model             | Support?            | Recommend?   | x86_64 (AMD64) | AARCH64 (ARM64) | Firmware updates                                          | Notes                                                                                                                                   |\n| -------- | ----------------- | -----------------   | ------------ | -------------- | --------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |\n| VITURE   | One<br/>One&nbsp;Lite<br/>Pro&nbsp;XR<br/>Luma<br/>Luma&nbsp;Pro | :heavy_check_mark: | :+1: | :heavy_check_mark: | :heavy_check_mark: | [Official update site](https://static.viture.com/dfu-util/). Requires Chrome on Windows/Mac. | Official collaboration. [Closed source SDK](https://www.viture.com/developer/viture-one-sdk-for-linux). |\n| VITURE   | Luma&nbsp;Ultra | :heavy_check_mark: | :+1: | :heavy_check_mark: | :heavy_check_mark: | [Official update site](https://static.viture.com/dfu-util/). Requires Chrome on Windows/Mac. | Official collaboration. [Closed source SDK](https://www.viture.com/developer/viture-one-sdk-for-linux). |\n| VITURE   | Beast | :clock4: Coming soon... |  |  |  |  | Support requires updates to the official SDK. |\n| TCL/RayNeo | NXTWEAR&nbsp;S/S+<br/>Air&nbsp;2<br/>2s<br/>3s/Pro | :heavy_check_mark: | :+1: | :heavy_check_mark: |             |                                                       | Official collaboration, closed source SDK.                                                                                              |\n| Rokid    | Max<br/>Air          | :heavy_check_mark: | :+1: | :heavy_check_mark:              |             |                                                       | Official collaboration, closed source SDK.                                                                                              |\n| XREAL    | Air<br/>Air&nbsp;2<br/>Air&nbsp;2&nbsp;Pro<br/>Air&nbsp;2&nbsp;Ultra  | :heavy_check_mark: | :-1: | :heavy_check_mark: | :heavy_check_mark: | [Official update site](https://www.xreal.com/support/update/). Requires Chrome. | Unwilling to collaborate. [Unofficial, open-source SDK](https://gitlab.com/TheJackiMonster/nrealAirLinuxDriver). Exhibits drift. |\n| XREAL    | One<br/>One&nbsp;Pro | :heavy_check_mark:<br/><br/>**See notes before use** | :-1: | :heavy_check_mark: | :heavy_check_mark: | [Official update site](https://www.xreal.com/support/update/). Requires Chrome. | **Important** - Disable stabilizer/anchor features on glasses. Must be on latest firmware. |\n| XREAL    | 1S | :heavy_check_mark:&nbsp;XR&nbsp;driver&nbsp;v2.8.x<br/><br/>:heavy_check_mark:&nbsp;Breezy&nbsp;Desktop&nbsp;v2.8.x<br/><br/>:heavy_check_mark:&nbsp;Decky XR Gaming v1.5.x<br/><br/>**See notes before use** | :-1: | :heavy_check_mark: | :heavy_check_mark: | [Official update site](https://www.xreal.com/support/update/). Requires Chrome. | **Important** - Disable stabilizer/anchor features on glasses. Must be on latest firmware. |\n\n## Setup\n\n### Manual installation\n\n*Note: this installation is for just the base driver with mouse/joystick support. If you're looking for virtual display or workspace tools, check out [Breezy Desktop](https://github.com/wheaney/breezy-desktop).*\n\n1. [Download the setup script](https://github.com/wheaney/XRLinuxDriver/releases/latest/download/xr_driver_setup) and set the execute flag (e.g. from the terminal: `chmod +x ~/Downloads/xr_driver_setup`)\n2. Run the setup script as root (e.g. `sudo ~/Downloads/xr_driver_setup`)\n  \nYour device should now automatically recognize when your glasses are plugged in and translate their movements to mouse movements. If you're not seeing this, check the log at `$XDG_STATE_HOME/xr_driver/driver.log` and report an Issue here with its contents.\n\n#### Turning automatic driver usage on or off\n\nTo disable the driver and turn off mouse movements without completely removing it, you can use the config script (e.g. `xr_driver_cli -d` to disable, and `-e` to re-enable). Run this script without arguments to see its usage. Configs are stored in the file `$XDG_CONFIG_HOME/xr_driver/config.ini`.\n\n### Updating\n\nIf using Decky, updates are installed through Decky.\n\nOtherwise, just rerun the `xr_driver_setup` file. No need to redownload this script, as it will automatically download the latest installation binary for you.\n\n### Uninstalling\n\nIf you wish to completely remove the installation, run the following script as root: `~/.local/bin/xr_driver_uninstall`. For Steam Deck users, you can uninstall the plugin via the Decky interface.\n\n## Data Privacy Notice\n\nYour right to privacy and the protection of your personal data are baked into every decision around how your personal data is collected, handled and stored. Your personal data will never be shared, sold, or distributed in any form.\n\n### Data Collected\n\nIn order to provide you with Supporter Tier features, this application and its backend services have to collect the following pieces of personal information:\n\n* Your email address is sent to this application's backend server from either the payment vendor (Ko-fi) or from your device (at your request). Your email address may be used immediately upon receipt in its unaltered form to send you a transactional email, but it is then hashed prior to storage. The unaltered form of your email address is never stored and can no longer be referenced. The hashed value is stored for later reference.\n  * Other personal data may be sent from the payment vendor, but is never utilized nor stored. \n* Your device's MAC address is hashed on your device. It never leaves your device in its original, unaltered form. The hashed value is sent to this application's backend server and stored for later reference.\n* Metrics are collected using Google Analytics. No personal information is explicitly collected, and Google Analytics will anonymize the IP address that's sent as part of the HTTP request. You can disable metrics collection using `xr_driver_cli --no-metrics`.\n\nHashing functions are a one-way process that serve to anonymize your personal data by irreversibly changing them. Once hashed, they can never be unhashed or traced back to their original values.\n\n### Contact\n\nFor inquires about data privacy or any related concerns, please contact:\n\nWayne Heaney - **wayne@xronlinux.com**\n\n## Credits\n\nThis driver wouldn't have been possible without the work of Tobias Frisch for his [base Linux driver](https://gitlab.com/TheJackiMonster/nrealAirLinuxDriver) that this uses under the hood, Matt Smith for his [Windows driver](https://github.com/MSmithDev/AirAPI_Windows/), and others that worked to [reverse engineer the glasses](https://github.com/edwatt/real_utilities/).\n"
  },
  {
    "path": "bin/build_custom_banner_config.py",
    "content": "import sys\nimport os\nimport yaml\n\nstart_date = 0\nend_date = 0\ntarget_device_vendor_id = 0\ntarget_device_product_id = 0\n\nyaml_file_path = sys.argv[1]\noutput_file_path = sys.argv[2]\nif os.path.isfile(yaml_file_path):\n    with open(yaml_file_path, 'r') as stream:\n        try:\n            yaml_data = yaml.safe_load(stream)\n        except yaml.YAMLError as exc:\n            print(exc)\n            sys.exit(1)\n\n    try:\n        start_date = int(yaml_data.get(\"start_date\", 0))\n    except ValueError:\n        print(\"ERROR: start_date is not an int\")\n        sys.exit(1)\n\n    try:\n        end_date = int(yaml_data.get(\"end_date\", 0))\n    except ValueError:\n        print(\"ERROR: end_date is not an int\")\n        sys.exit(1)\n\n    try:\n        target_device_vendor_id = int(yaml_data.get(\"target_device_vendor_id\", 0))\n        if target_device_vendor_id != 0:\n            try:\n                target_device_product_id = int(yaml_data.get(\"target_device_product_id\", 0))\n            except ValueError:\n                print(\"ERROR: target_device_product_id is not an int\")\n                sys.exit(1)\n    except ValueError:\n        print(\"ERROR: target_device_vendor_id is not an int\")\n        sys.exit(1)\n\n    if end_date != 0 and start_date != 0 and start_date > end_date:\n        print(\"ERROR: start_date is after end_date\")\n        sys.exit(1)\n\nwith open(output_file_path, \"w\") as f:\n    f.write(\"#pragma once\\n\")\n    f.write(\"// This file is autogenerated by bin/custom_banner_build.py\\n\")\n    f.write(\"// Do not edit this file directly\\n\")\n    f.write(\"#define CUSTOM_BANNER_START_DATE {}\\n\".format(start_date))\n    f.write(\"#define CUSTOM_BANNER_END_DATE {}\\n\".format(end_date))\n    f.write(\"#define CUSTOM_BANNER_TARGET_DEVICE_VENDOR_ID {}\\n\".format(target_device_vendor_id))\n    f.write(\"#define CUSTOM_BANNER_TARGET_DEVICE_PRODUCT_ID {}\\n\".format(target_device_product_id))"
  },
  {
    "path": "bin/inject_ua",
    "content": "#!/bin/bash\n\n# Function to copy and replace code in scripts. Allows for code reuse without needing multiple bash files.\ncopy_and_inject_ua() {\n  # Source file containing the code to be injected\n  local source_file=$1\n\n  # Directory where the scripts will be copied to\n  local copy_to_dir=$2\n\n  # Keyword in the destination file where the code will be injected\n  local keyword=\"#INJECT_UA_CALL\"\n\n  # List of scripts to be copied and modified\n  local scripts=(\"${@:3}\")\n\n  for script in \"${scripts[@]}\"; do\n    # Copy the script to the package directory\n    cp -p $script $copy_to_dir\n\n    # Get the filename of the script\n    local filename=$(basename $script)\n\n    # Destination file where the code will be injected\n    local destination_file=\"$copy_to_dir/$filename\"\n\n    # Replace the keyword with the content of the source file\n    sed -i -e \"/$keyword/r $source_file\" -e \"s/$keyword/UA_API_SECRET=\\\"${UA_API_SECRET}\\\"/g\" $destination_file\n  done\n}\n"
  },
  {
    "path": "bin/package",
    "content": "#!/usr/bin/env bash\n\n# exit when any command fails\nset -e\n\nUSER=${SUDO_USER:-$USER}\nGROUP=$(id -gn $USER)\n\nsource bin/inject_ua\n\nif [ -z \"$UA_API_SECRET\" ] && [ -z \"$UA_API_SECRET_INTENTIONALLY_EMPTY\" ]; then\n  echo \"UA_API_SECRET isn't set. If this is intentional, set UA_API_SECRET_INTENTIONALLY_EMPTY to a non-empty value.\"\n  exit 1\nfi\n\nARCH=$(uname -m)\necho \"Building for $ARCH\"\n\n# build the driver\nBUILD_PATH=build\nif [ ! -d \"$BUILD_PATH\" ]; then\n  mkdir $BUILD_PATH\nfi\n\npushd $BUILD_PATH\ncmake ..\nmake\n\n# create package\nPACKAGE_DIR=xr_driver\nPACKAGE_BIN_DIR=$PACKAGE_DIR/bin\nPACKAGE_USER_BIN_DIR=$PACKAGE_BIN_DIR/user\nmkdir -p $PACKAGE_USER_BIN_DIR\n\nmv xrDriver $PACKAGE_BIN_DIR\n\n# copy setup and user-relevant scripts\ncopy_and_inject_ua \"../bin/ua.sh\" \"$PACKAGE_DIR\" \"../bin/setup\"\ncopy_and_inject_ua \"../bin/ua.sh\" \"$PACKAGE_BIN_DIR\" \"../bin/xr_driver_verify\" \"../bin/xr_driver_cli\" \"../bin/xr_driver_uninstall\" \"../bin/xr_driver_logs\"\ncopy_and_inject_ua \"../bin/ua.sh\" \"$PACKAGE_USER_BIN_DIR\" \"../bin/user/install\" \"../bin/user/systemd_start\"\n\n# copy the systemd files needed to run our service\ncp -r ../systemd $PACKAGE_DIR\ncp -r ../udev $PACKAGE_DIR\n\n# create manifest file for verifying installed file checksums against the originally packaged versions\n# include any file that doesn't get modified during setup (e.g. the systemd service file)\npushd $PACKAGE_BIN_DIR\nBIN_MANIFEST=$(sha256sum xrDriver xr_driver_cli xr_driver_uninstall xr_driver_logs)\npopd\necho $BIN_MANIFEST > $PACKAGE_DIR/manifest\n\n# bundle up the driver directory (without lib files)\nBUILD_ARTIFACT_NAME=\"xrDriver-$ARCH.tar.gz\"\ntar -zcvf $BUILD_ARTIFACT_NAME $PACKAGE_DIR\n\npopd\n\nmkdir -p out\ncp $BUILD_PATH/$BUILD_ARTIFACT_NAME out/\n\nrm -rf $BUILD_PATH"
  },
  {
    "path": "bin/package_libs",
    "content": "#!/usr/bin/env bash\n\n# exit when any command fails\nset -e\n\n# Package libraries for both architectures\nARCHITECTURES=(\"x86_64\" \"aarch64\")\n\necho \"Building lib packages for all architectures\"\n\n# build the lib package\nBUILD_PATH=build\nif [ ! -d \"$BUILD_PATH\" ]; then\n  mkdir $BUILD_PATH\nfi\n\npushd $BUILD_PATH > /dev/null\n\nfor ARCH in \"${ARCHITECTURES[@]}\"; do\n  echo \"Packaging libraries for $ARCH\"\n  \n  # create separate lib package\n  PACKAGE_LIB_DIR=xr_driver_lib\n  mkdir -p $PACKAGE_LIB_DIR\n  cp ../lib/$ARCH/*.so* $PACKAGE_LIB_DIR || true\n  cp ../lib/$ARCH/viture/*.so* $PACKAGE_LIB_DIR || true\n\n  LIB_ARTIFACT_NAME=\"xrDriver-libs-$ARCH.tar.gz\"\n  tar -zcvf $LIB_ARTIFACT_NAME $PACKAGE_LIB_DIR\n\n  # Clean up for next iteration\n  rm -rf $PACKAGE_LIB_DIR\ndone\n\npopd > /dev/null\n\nmkdir -p out\ncp $BUILD_PATH/*.tar.gz out/\n\nrm -rf $BUILD_PATH\n"
  },
  {
    "path": "bin/setup",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# This script gets packaged with the release and should do the bulk of the setup work. This allows this setup to be tied\n# to a specific release of the code, and guarantees it will never run along-side newer or older binaries.\n\n# Make sure only root can run our script\nif [ \"$(id -u)\" != \"0\" ]; then\n   echo \"This script must be run as root\" 1>&2\n   exit 1\nfi\n\n# some distros don't have systemd enabled by default.\nif [[ -z \"${SKIP_SYSTEMD:-}\" ]]; then\n  if [[ $(ps -p 1 -o comm=) != \"systemd\" ]]; then\n    echo \"systemd is required for this installation. Please enable it, then rerun the setup.\"\n    exit 1\n  fi\nelse\n  if [[ $(ps -p 1 -o comm=) != \"systemd\" ]]; then\n    echo \"SKIP_SYSTEMD is set and systemd is not detected as PID 1; continuing without systemd integration.\"\n  fi\nfi\n\nif ! find /usr/lib* -name 'libcurl.so*' -print -quit | grep -q .; then\n  echo \"The libcurl library is not found. It's typically provided by the package libcurl4 (Debian/Ubuntu), libcurl (Fedora), or curl (Arch). \\\n        Please install it and rerun setup.\"\n  exit 1\nfi\n\nif ! find /usr/lib* -name 'libwayland-client.so*' -print -quit | grep -q .; then\n  echo -e \"\\n\\n!!! WARNING: The Wayland client library was not found, which will disable the gamescope integration. \\\nTo enable this, install the appropriate library. It's typically provided by the package libwayland-client0 \\\n(Debian/Ubuntu), wayland (Fedora), or wayland (Arch).\\n\\n\"\nfi\n\nUSER=${SUDO_USER:-$USER}\nGROUP=$(id -g $USER)\nUSER_HOME=$(getent passwd $USER | cut -d: -f6)\n\nfunction create_and_chown() {\n  if [ ! -d \"$1\" ]; then\n    mkdir -p $1\n  fi\n\n  # XDG dir can be provided as the second argument, we want to make sure it's owned by the user\n  # but don't recursively chown it since other programs may put files in there\n  if [ -n \"$2\" ]; then\n    chown $USER:$GROUP $2\n  fi\n\n  # only recursively chown the directory if it's not an XDG dir\n  if [ -z \"$2\" ] || [ \"$1\" != \"$2\" ]; then\n    chown -R $USER:$GROUP $1\n  fi\n}\n\nif [ -z \"$XDG_DATA_HOME\" ]; then\n  XDG_DATA_HOME=\"$USER_HOME/.local/share\"\nfi\nSYSTEMD_DATA_DIR=\"$XDG_DATA_HOME/systemd\"\nSYSTEMD_USER_DIR=\"$SYSTEMD_DATA_DIR/user\"\nmkdir -p $SYSTEMD_USER_DIR # this will get chowned by the recursive call triggered next\ncreate_and_chown $SYSTEMD_DATA_DIR $XDG_DATA_HOME\n\nDATA_DIR=\"$XDG_DATA_HOME/xr_driver\"\ncreate_and_chown $DATA_DIR $XDG_DATA_HOME\n\nif [ -z \"$XDG_CONFIG_HOME\" ]; then\n  XDG_CONFIG_HOME=\"$USER_HOME/.config\"\nfi\nCONFIG_DIR=\"$XDG_CONFIG_HOME/xr_driver\"\ncreate_and_chown $CONFIG_DIR $XDG_CONFIG_HOME\n\nif [ -z \"$XDG_BIN_HOME\" ]; then\n  XDG_BIN_HOME=\"$USER_HOME/.local/bin\"\nfi\nOLD_BIN_DIR=\"$USER_HOME/bin\"\nBIN_DIR=\"$XDG_BIN_HOME\"\ncreate_and_chown $OLD_BIN_DIR\ncreate_and_chown $BIN_DIR $XDG_BIN_HOME\n\nif [ -z \"$XDG_STATE_HOME\" ]; then\n  XDG_STATE_HOME=\"$USER_HOME/.local/state\"\nfi\nSTATE_DIR=\"$XDG_STATE_HOME/xr_driver\"\ncreate_and_chown $STATE_DIR $XDG_STATE_HOME\n\nif [ -e \"$OLD_BIN_DIR/xreal_driver_uninstall\" ]; then\n  echo \"Cleaning up the previous installation\"\n\n  # ` || true` will ensure that this can't cause a failure, even with `set -e`\n  $OLD_BIN_DIR/xreal_driver_uninstall --for-install || true\n\n  UA_EVENT_NAME=\"update\"\nfi\n\nif [ -e \"$BIN_DIR/xr_driver_uninstall\" ]; then\n  echo \"Cleaning up the previous installation\"\n\n  # ` || true` will ensure that this can't cause a failure, even with `set -e`\n  $BIN_DIR/xr_driver_uninstall --for-install || true\n\n  UA_EVENT_NAME=\"update\"\nfi\n\nif command -v jq >/dev/null 2>&1 && [ -e \"$STATE_DIR/license.json\" ]; then\n  HWID=$(jq -r '.license | fromjson | .hardwareId' \"$STATE_DIR/license.json\" | cut -c 1-8)\n  if [ \"$HWID\" != \"null\" ]; then\n    echo \"Moving your license file to $STATE_DIR/${HWID}_license.json\"\n    mv \"$STATE_DIR/license.json\" \"$STATE_DIR/${HWID}_license.json\"\n  fi\nfi\n\ncurrent_path=$(pwd)\nif [[ \"$current_path\" == /tmp/* ]]; then\n  target_dir=$(echo \"$current_path\" | sed -E 's|^(/tmp/[^/]+).*|\\1|')\n  echo \"Changing ownership of $target_dir to $USER:$GROUP\"\n  chown -R $USER:$GROUP \"$target_dir\"\nfi\n\n# this part of the setup should be run as the user, not root\nXDG_RUNTIME_DIR=\"/run/user/$(id -u $USER)\"\nif [ ! -d \"$XDG_RUNTIME_DIR\" ]; then\n  # On non-systemd systems /run/user/<uid> may not exist. Fall back to a private runtime dir in /tmp.\n  XDG_RUNTIME_DIR=\"/tmp/xr_driver_runtime_$(id -u $USER)\"\n  mkdir -p \"$XDG_RUNTIME_DIR\"\n  chown \"$USER:$GROUP\" \"$XDG_RUNTIME_DIR\"\n  chmod 700 \"$XDG_RUNTIME_DIR\"\nfi\nexport XDG_RUNTIME_DIR\nsu -c \"XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR $(realpath bin/user/install)\" $USER\n\n###############################\n### BEGIN sudo required section\n\nif ! { lsmod | grep -q uinput || [[ -c /dev/uinput ]]; }; then\n  echo \"Setting up uinput kernel module\"\n  modprobe uinput\nfi\n\n# if steamos is detected, we need to install the udev rules to /etc since /usr is on the readonly FS\nUDEV_RULES_DIR=\"/usr/lib/udev/rules.d\"\nUDEV_RULES_DIR_CHANGED=0\nif [ -f /etc/os-release ]; then\n  . /etc/os-release\n  if [ \"$ID\" == \"steamos\" ]; then\n    UDEV_RULES_DIR=\"/etc/udev/rules.d\"\n    UDEV_RULES_DIR_CHANGED=1\n  fi\nfi\n\nif [ $UDEV_RULES_DIR_CHANGED -eq 0 ]; then\n  if touch \"$UDEV_RULES_DIR/100-xr-driver-test-rule\" 2>/dev/null; then\n    rm \"$UDEV_RULES_DIR/100-xr-driver-test-rule\"\n  else \n    UDEV_RULES_DIR=\"/etc/udev/rules.d\"\n  fi\nfi\n\nmkdir -p $UDEV_RULES_DIR\n\necho \"Copying the udev rules to ${UDEV_RULES_DIR}\"\ncp udev/* $UDEV_RULES_DIR\n\nudevadm control --reload-rules >/dev/null 2>&1\nfor subsystem in usb hidraw input; do\n  udevadm trigger --action=add --subsystem-match=\"$subsystem\" >/dev/null 2>&1 || true\ndone\nudevadm settle >/dev/null 2>&1 || true\n\n# remove temporary files that may be left behind, sometimes they cause problems\nrm -f /tmp/shader_runtime_*\nrm -f /dev/shm/xr_*\nrm -f /dev/shm/breezy_desktop_imu\n\n### END sudo required section\n###############################\n\nif [ -n \"$SKIP_SYSTEMD\" ]; then\n  printf \"\\n\\033[1;33m!!! IMPORTANT !!!\\033[0m\\n\"\n  echo \"SKIP_SYSTEMD set; skipping systemd service startup.\"\n  echo \"You are responsible for starting the driver manually when needed:\"\n  printf \"\\tLD_LIBRARY_PATH=\\\"${DATA_DIR}/lib\\\" ${BIN_DIR}/xrDriver\\n\\n\"\nelse\n  # this part of the setup should be run as the user, not root\n  su -l -c \"XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR $(realpath bin/user/systemd_start)\" $USER\n\n  ###############################\n  ### BEGIN sudo required section\n\n  # Ensure the user service persists after logout\n  loginctl enable-linger $USER\n\n  ### END sudo required section\n  ###############################\nfi\n"
  },
  {
    "path": "bin/ua.sh",
    "content": "MEASUREMENT_ID=\"G-Z94MXP18T6\"\n\n# if UA_EVENT_VERSION is set, copy its value and replace any dots in the value with underscores, then append it to UA_EVENT_NAME\nif [ -n \"$UA_EVENT_VERSION\" ]; then\n  UA_EVENT_NAME=\"$(echo $UA_EVENT_NAME)_$(echo $UA_EVENT_VERSION | sed 's/\\./_/g')\"\nfi\n\nPOST_DATA=$(cat <<EOF\n{\n  \"client_id\": \"$UA_CLIENT_ID\",\n  \"events\": [\n    {\n      \"name\": \"$UA_EVENT_NAME\"\n    }\n  ]\n}\nEOF\n)\n\n# make sure this is always silent and can't cause failures\ncurl -X POST -H \"Content-Type: application/json\" -d \"$POST_DATA\" \"https://www.google-analytics.com/mp/collect?api_secret=$UA_API_SECRET&measurement_id=$MEASUREMENT_ID\" >/dev/null 2>&1 || true\n\n"
  },
  {
    "path": "bin/user/install",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# this part of the setup should be run as the user, not root\nif [ \"$(id -u)\" == \"0\" ]; then\n   echo \"This script must NOT be run as root\" 1>&2\n   exit 1\nfi\n\nGROUP=$(id -gn $USER)\nUSER_HOME=$(getent passwd $USER | cut -d: -f6)\nUA_EVENT_NAME=\"install\"\n\nif [ -z \"$XDG_DATA_HOME\" ]; then\n  XDG_DATA_HOME=\"$USER_HOME/.local/share\"\nfi\nSYSTEMD_USER_DIR=\"$XDG_DATA_HOME/systemd/user\"\nDATA_DIR=\"$XDG_DATA_HOME/xr_driver\"\n\nif [ -z \"$XDG_CONFIG_HOME\" ]; then\n  XDG_CONFIG_HOME=\"$USER_HOME/.config\"\nfi\nCONFIG_DIR=\"$XDG_CONFIG_HOME/xr_driver\"\n\nif [ -z \"$XDG_BIN_HOME\" ]; then\n  XDG_BIN_HOME=\"$USER_HOME/.local/bin\"\nfi\nOLD_BIN_DIR=\"$USER_HOME/bin\"\nBIN_DIR=\"$XDG_BIN_HOME\"\n\nif [ -z \"$XDG_STATE_HOME\" ]; then\n  XDG_STATE_HOME=\"$USER_HOME/.local/state\"\nfi\nSTATE_DIR=\"$XDG_STATE_HOME/xr_driver\"\n\nif [ -e \"$OLD_BIN_DIR/xreal_driver_uninstall\" ]; then\n  echo \"Cleaning up the previous installation\"\n\n  # ` || true` will ensure that this can't cause a failure, even with `set -e`\n  $OLD_BIN_DIR/xreal_driver_uninstall --for-install || true\n\n  UA_EVENT_NAME=\"update\"\nfi\n\nif [ -e \"$BIN_DIR/xr_driver_uninstall\" ]; then\n  echo \"Cleaning up the previous installation\"\n\n  # ` || true` will ensure that this can't cause a failure, even with `set -e`\n  $BIN_DIR/xr_driver_uninstall --for-install || true\n\n  UA_EVENT_NAME=\"update\"\nfi\n\nUA_CLIENT_ID=\"ARLinuxDriver\"\nUA_EVENT_VERSION=\"$1\"\n#INJECT_UA_CALL\n\n# make sure the systemd service isn't already running from a previous install\nsystemctl --user is-active --quiet xr-driver && systemctl --user stop xr-driver\n\necho \"Copying shared libraries to ${DATA_DIR}/lib\"\nmkdir -p $DATA_DIR/lib\ncp lib/* \"$DATA_DIR/lib\" 2>/dev/null || true\n\nif [ -e \"$USER_HOME/.xreal_driver_config\" ]; then\n  echo \"Migrating config file to ${CONFIG_DIR}/config.ini\"\n  mv $USER_HOME/.xreal_driver_config $CONFIG_DIR/config.ini\nfi\n\nif [ -e \"$USER_HOME/.xreal_driver_log\" ]; then\n  echo \"Migrating log file to ${STATE_DIR}/driver.log\"\n  mv $USER_HOME/.xreal_driver_log ${STATE_DIR}/driver.log\nfi\n\nif [ -e \"/var/lib/xr_driver/device_license\" ]; then\n  echo \"Migrating device license to ${STATE_DIR}/license.json\"\n  pushd /var/lib/xr_driver > /dev/null\n\n  # since the file has root ownership, rename it before moving to a user directory\n  mv \"device_license\" \"license.json\"\n  mv \"license.json\" \"${STATE_DIR}/license.json\"\n\n  popd > /dev/null\nfi\n\n# escaping sed replace: https://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern\nESCAPED_USER_HOME=$(printf '%s\\n' \"$USER_HOME\" | sed -e 's/[\\/&]/\\\\&/g')\nESCAPED_LD_LIBRARY_PATH=$(printf '%s\\n' \"$DATA_DIR/lib\" | sed -e 's/[\\/&]/\\\\&/g')\nESCAPED_BIN_DIR=$(printf '%s\\n' \"$BIN_DIR\" | sed -e 's/[\\/&]/\\\\&/g')\n\necho \"Copying driver binary and scripts to ${BIN_DIR} and ${DATA_DIR}\"\npushd bin > /dev/null\nsed -i -e \"s/{bin_dir}/$ESCAPED_BIN_DIR/g\" xr_driver_verify\ncp xrDriver $BIN_DIR\ncp xr_driver_cli $BIN_DIR\ncp xr_driver_uninstall $BIN_DIR\ncp xr_driver_logs $BIN_DIR\ncp xr_driver_verify $BIN_DIR\n\n# keep putting this in the old location in case an older version of the script tries to find it\ncp xr_driver_uninstall $OLD_BIN_DIR/xreal_driver_uninstall\npopd > /dev/null\n\ncp manifest $DATA_DIR\n\necho \"Copying the systemd service to ${SYSTEMD_USER_DIR}\"\nsed -i -e \"s/{user_home}/$ESCAPED_USER_HOME/g\" \\\n  -e \"s/{user}/$USER/g\" \\\n  -e \"s/{ld_library_path}/$ESCAPED_LD_LIBRARY_PATH/g\" \\\n  -e \"s/{bin_dir}/$ESCAPED_BIN_DIR/g\" systemd/xr-driver.service\ncp systemd/xr-driver.service $SYSTEMD_USER_DIR\n\n# clear bash's cache of executable locations, so it can find the newly installed scripts\nhash -r"
  },
  {
    "path": "bin/user/systemd_start",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# this part of the setup should be run as the user, not root\nif [ \"$(id -u)\" == \"0\" ]; then\n   echo \"This script must NOT be run as root\" 1>&2\n   exit 1\nfi\n\nif ! command -v systemctl >/dev/null 2>&1; then\n  printf '\\n\\033[31mERROR\\033[0m systemd was not found on this system. If you would still like to proceed without the background service, rerun this script with SKIP_SYSTEMD=1.\\n'\n  exit 1\nfi\n\necho \"Setting up the systemd service\"\nsystemctl --user daemon-reload\nsystemctl --user start xr-driver\n\n# check if systemd startup was successful\nif ! systemctl --user is-active --quiet xr-driver; then\n  echo \"systemd startup failed\"\n  exit 1\nfi\n\n# set it to run on startup\nsystemctl --user enable xr-driver"
  },
  {
    "path": "bin/xr_driver_cli",
    "content": "#!/usr/bin/env bash\n\nif ! systemctl --user --quiet is-active xr-driver >/dev/null 2>&1; then\n    if [ -z \"$IGNORE_SYSTEMD_ERRORS\" ]; then\n        echo \"xr-driver service is not active. Start it with:\" >&2\n        echo \"  systemctl --user start xr-driver\" >&2\n        echo \"\"\n        echo \"If the issue persists, please create an issue on the wheaney/XRLinuxDriver repository.\"\n        echo \"\"\n        echo \"To ignore this error, rerun with IGNORE_SYSTEMD_ERRORS=1\"\n        exit 1\n    else\n        echo \"Warning: xr-driver service is not active, most actions will be ineffective until this is resolved. Continuing due to IGNORE_SYSTEMD_ERRORS...\" >&2\n    fi\nfi\n\nUSER=${SUDO_USER:-$USER}\nUSER_HOME=$(getent passwd $USER | cut -d: -f6)\nif [ -z \"$XDG_CONFIG_HOME\" ]; then\n  XDG_CONFIG_HOME=\"$USER_HOME/.config\"\nfi\nCONFIG_DIR=\"$XDG_CONFIG_HOME/xr_driver\"\nif [ ! -d \"$CONFIG_DIR\" ]; then\n  mkdir -p $CONFIG_DIR\nfi\nif [ -z \"$XDG_STATE_HOME\" ]; then\n  XDG_STATE_HOME=\"$USER_HOME/.local/state\"\nfi\nLOG_FILE=\"$XDG_STATE_HOME/xr_driver/driver.log\"\n\nensure_config_file() {\n    local file=\"$1\"\n    if [ ! -f \"$file\" ]; then\n        touch \"$file\"\n    fi\n}\n\nwrite_config_value() {\n    local file=\"$1\"\n    local key=\"$2\"\n    local value=\"$3\"\n    if grep -q \"^$key=\" \"$file\"; then\n        sed -i \"s/^$key=.*/$key=$value/\" \"$file\"\n    else\n        echo \"$key=$value\" >> \"$file\"\n    fi\n}\n\nread_config_value() {\n    local file=\"$1\"\n    local key=\"$2\"\n    local type=\"$3\"\n    local value\n    if [ \"$type\" == \"string\" ]; then\n        value=\"Not set\"\n    else\n        value=\"enabled\"\n    fi\n\n    while read -r line; do\n        if [[ $line == \"$key=\"* ]]; then\n            local raw_value=${line#*=}\n            if [ \"$type\" == \"string\" ]; then\n                value=$raw_value\n            else\n                if [ \"$raw_value\" == \"true\" ]; then\n                    value=\"disabled\"\n                fi\n            fi\n            break\n        fi\n    done < \"$file\"\n\n    echo \"$value\"\n}\n\nprocess_config() {\n    local file=\"$1\"\n    local key=\"$2\"\n    local value=\"$3\"\n    local type=\"$4\"\n    local key2=\"$5\"\n    local value2=\"$6\"\n    local token_action=\"$7\"\n    local token_arg=\"$8\"\n\n    ensure_config_file \"$file\"\n\n    if [[ -n $value ]]; then\n        write_config_value \"$file\" \"$key\" \"$value\"\n        if [[ -n $key2 ]]; then\n            write_config_value \"$file\" \"$key2\" \"$value2\"\n        fi\n        return 0\n    fi\n\n    local read_value\n    read_value=$(read_config_value \"$file\" \"$key\" \"$type\")\n\n    if [[ -n $token_action ]]; then\n        local hardware_id=\"$read_value\"\n        local url=\"https://eu.driver-backend.xronlinux.com/tokens/v1\"\n        local message=\"\"\n\n        if [[ \"$token_action\" == \"request\" || \"$token_action\" == \"verify\" ]] && ! command -v jq >/dev/null 2>&1; then\n            echo \"Error: jq utility not found. Install jq to use this feature.\" >&2\n            exit 1\n        fi\n\n        if [ \"$token_action\" == \"request\" ]; then\n            postbody=$(jq -n \\\n                                    --arg hardwareId \"$hardware_id\" \\\n                                    --arg email \"$token_arg\" \\\n                                    '{hardwareId: $hardwareId, email: $email}')\n            message=$(curl -s -X POST -H \"Content-Type: application/json\" -d \"$postbody\" \"$url\" | jq -r '.message')\n        elif [ \"$token_action\" == \"verify\" ]; then\n            postbody=$(jq -n \\\n                                    --arg hardwareId \"$hardware_id\" \\\n                                    --arg token \"$token_arg\" \\\n                                    '{hardwareId: $hardwareId, token: $token}')\n            message=$(curl -s -X PUT -H \"Content-Type: application/json\" -d \"$postbody\" \"$url\" | jq -r '.message')\n        elif [ \"$token_action\" == \"refresh\" ]; then\n            echo \"refresh_device_license=true\" > /dev/shm/xr_driver_control\n            message=\"License refresh requested\"\n        elif [ \"$token_action\" == \"get\" ]; then\n            message=\"$hardware_id\"\n        fi\n\n        if [ -n \"$message\" ]; then\n            echo \"$message\"\n        fi\n    else\n        echo \"$read_value\"\n    fi\n}\n\nrequire_arg() {\n    local opt=\"$1\"\n    local arg=\"$2\"\n    if [ -z \"$arg\" ] || [ \"$arg\" == \"--\" ]; then\n        echo \"Error: $opt requires an argument.\" >&2\n        exit 1\n    fi\n}\n\nprint_usage() {\n    echo \"Usage: $0 [options]\nOptions:\n    -h, --help\n    -l, --view-log\n    -d, --disable\n    -e, --enable\n    -s, --status\n    -j, --use-joystick\n    -m, --use-mouse\n    --vr-lite-invert-x, --no-vr-lite-invert-x\n    --vr-lite-invert-y, --no-vr-lite-invert-y\n    --gamescope-reshade-wayland, --no-gamescope-reshade-wayland\n    -ms, --mouse-sensitivity [sensitivity_value]\n    --look-ahead-ms [milliseconds]\n    -dz, --deadzone-threshold-degrees [threshold_degrees]\n    --multi-tap, --no-multi-tap\n    -ds, --display-size [display_size]\n    -dd, --display-distance [display_distance]\n    -em, --external-mode\n    -de, --disable-external\n    -vd, --virtual-display\n    -bd, --breezy-desktop\n    --opentrack-app\n    -sv, --sideview\n    -svp, --sideview-position [top_left|top_right|bottom_left|bottom_right]\n    --smooth-follow, --no-smooth-follow\n    -sft, --smooth-follow-threshold [threshold_value]\n    --curved-display, --no-curved-display\n    --smooth-follow-track-roll, --no-smooth-follow-track-roll\n    --smooth-follow-track-pitch, --no-smooth-follow-track-pitch\n    --smooth-follow-track-yaw, --no-smooth-follow-track-yaw\n    -sbsms, --sbs-mode-stretched, --no-sbs-mode-stretched\n    -sbs3d, --sbs-content-3d, --no-sbs-content-3d\n    -nsh, --neck-saver-horizontal [multiplier]\n    -nsv, --neck-saver-vertical [multiplier]\n    --opentrack-app-ip [ip]\n    --opentrack-app-port [port]\n    --opentrack-listener, --no-opentrack-listener\n    --opentrack-listen-ip [ip]\n    --opentrack-listen-port [port]\n    --metrics, --no-metrics\n    --request-token [email]\n    --verify-token [token]\n    --refresh-license\n    --get-hardware-id\"\n}\n\nif [ $# -eq 0 ]; then\n    print_usage\n    exit 0\nfi\n\nif [ -n \"$1\" ]; then\n    if ! command -v getopt >/dev/null 2>&1; then\n        echo \"Error: getopt utility not found. Install getopt to use this CLI.\" >&2\n        exit 1\n    fi\n\n    normalized_args=()\n    for arg in \"$@\"; do\n        case \"$arg\" in\n            -ms) normalized_args+=(\"--mouse-sensitivity\") ;;\n            -dz) normalized_args+=(\"--deadzone-threshold-degrees\") ;;\n            -ds) normalized_args+=(\"--display-size\") ;;\n            -dd) normalized_args+=(\"--display-distance\") ;;\n            -em) normalized_args+=(\"--external-mode\") ;;\n            -de) normalized_args+=(\"--disable-external\") ;;\n            -vd) normalized_args+=(\"--virtual-display\") ;;\n            -bd) normalized_args+=(\"--breezy-desktop\") ;;\n            -sv) normalized_args+=(\"--sideview\") ;;\n            -svp) normalized_args+=(\"--sideview-position\") ;;\n            -sft) normalized_args+=(\"--smooth-follow-threshold\") ;;\n            -sbsms) normalized_args+=(\"--sbs-mode-stretched\") ;;\n            -sbs3d) normalized_args+=(\"--sbs-content-3d\") ;;\n            -nsh) normalized_args+=(\"--neck-saver-horizontal\") ;;\n            -nsv) normalized_args+=(\"--neck-saver-vertical\") ;;\n            *) normalized_args+=(\"$arg\") ;;\n        esac\n    done\n\n    PARSED=$(getopt -o hldesjm --long help,view-log,disable,enable,status,use-joystick,use-mouse,vr-lite-invert-x,no-vr-lite-invert-x,vr-lite-invert-y,no-vr-lite-invert-y,gamescope-reshade-wayland,no-gamescope-reshade-wayland,mouse-sensitivity:,look-ahead-ms:,deadzone-threshold-degrees:,debug:,display-size:,display-distance:,external-mode,disable-external,virtual-display,breezy-desktop,opentrack-app,sideview,sideview-position:,smooth-follow,no-smooth-follow,smooth-follow-threshold:,curved-display,no-curved-display,smooth-follow-track-roll,no-smooth-follow-track-roll,smooth-follow-track-pitch,no-smooth-follow-track-pitch,smooth-follow-track-yaw,no-smooth-follow-track-yaw,sbs-mode-stretched,no-sbs-mode-stretched,sbs-content-3d,no-sbs-content-3d,multi-tap,no-multi-tap,neck-saver-horizontal:,neck-saver-vertical:,opentrack-app-ip:,opentrack-app-port:,opentrack-listener,no-opentrack-listener,opentrack-listen-ip:,opentrack-listen-port:,metrics,no-metrics,request-token:,verify-token:,refresh-license,get-hardware-id -- \"${normalized_args[@]}\")\n    if [ $? -ne 0 ]; then\n        exit 1\n    fi\n\n    eval set -- \"$PARSED\"\n\n    default_config_file=\"$CONFIG_DIR/config.ini\"\n    state_config_file=\"/dev/shm/xr_driver_state\"\n\n    while true; do\n        case \"$1\" in\n            -h|--help)\n                print_usage\n                exit 0\n                ;;\n            -l|--view-log)\n                less +F \"$LOG_FILE\"\n                exit 0\n                ;;\n            -d|--disable)\n                process_config \"$default_config_file\" \"disabled\" \"true\"\n                shift\n                ;;\n            -e|--enable)\n                process_config \"$default_config_file\" \"disabled\" \"false\"\n                shift\n                ;;\n            -s|--status)\n                process_config \"$default_config_file\" \"disabled\" \"\" \"\"\n                shift\n                ;;\n            -j|--use-joystick)\n                process_config \"$default_config_file\" \"output_mode\" \"joystick\" \"string\" \"external_mode\" \"none\"\n                shift\n                ;;\n            -m|--use-mouse)\n                process_config \"$default_config_file\" \"output_mode\" \"mouse\" \"string\" \"external_mode\" \"none\"\n                shift\n                ;;\n            --vr-lite-invert-x)\n                process_config \"$default_config_file\" \"vr_lite_invert_x\" \"true\"\n                shift\n                ;;\n            --no-vr-lite-invert-x)\n                process_config \"$default_config_file\" \"vr_lite_invert_x\" \"false\"\n                shift\n                ;;\n            --vr-lite-invert-y)\n                process_config \"$default_config_file\" \"vr_lite_invert_y\" \"true\"\n                shift\n                ;;\n            --no-vr-lite-invert-y)\n                process_config \"$default_config_file\" \"vr_lite_invert_y\" \"false\"\n                shift\n                ;;\n            --gamescope-reshade-wayland)\n                process_config \"$default_config_file\" \"gamescope_reshade_wayland_disabled\" \"false\"\n                shift\n                ;;\n            --no-gamescope-reshade-wayland)\n                process_config \"$default_config_file\" \"gamescope_reshade_wayland_disabled\" \"true\"\n                shift\n                ;;\n            --mouse-sensitivity)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"mouse_sensitivity\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --look-ahead-ms)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"look_ahead\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --deadzone-threshold-degrees)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"dead_zone_threshold_deg\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --debug)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"debug\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --display-size)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"display_size\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --display-distance)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"display_distance\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --external-mode)\n                process_config \"$default_config_file\" \"external_mode\" \"\" \"string\"\n                shift\n                ;;\n            --disable-external)\n                process_config \"$default_config_file\" \"external_mode\" \"none\" \"string\"\n                shift\n                ;;\n            --virtual-display)\n                process_config \"$default_config_file\" \"output_mode\" \"external_only\" \"string\" \"external_mode\" \"virtual_display\"\n                shift\n                ;;\n            --breezy-desktop)\n                process_config \"$default_config_file\" \"output_mode\" \"external_only\" \"string\" \"external_mode\" \"breezy_desktop\"\n                shift\n                ;;\n            --opentrack-app)\n                process_config \"$default_config_file\" \"output_mode\" \"external_only\" \"string\" \"external_mode\" \"opentrack\"\n                shift\n                ;;\n            --sideview)\n                process_config \"$default_config_file\" \"output_mode\" \"external_only\" \"string\" \"external_mode\" \"sideview\"\n                shift\n                ;;\n            --sideview-position)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"sideview_position\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --smooth-follow)\n                process_config \"$default_config_file\" \"sideview_smooth_follow_enabled\" \"true\"\n                shift\n                ;;\n            --no-smooth-follow)\n                process_config \"$default_config_file\" \"sideview_smooth_follow_enabled\" \"false\"\n                shift\n                ;;\n            --smooth-follow-threshold)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"sideview_follow_threshold\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --curved-display)\n                process_config \"$default_config_file\" \"curved_display\" \"true\"\n                shift\n                ;;\n            --no-curved-display)\n                process_config \"$default_config_file\" \"curved_display\" \"false\"\n                shift\n                ;;\n            --smooth-follow-track-roll)\n                process_config \"$default_config_file\" \"smooth_follow_track_roll\" \"true\"\n                shift\n                ;;\n            --no-smooth-follow-track-roll)\n                process_config \"$default_config_file\" \"smooth_follow_track_roll\" \"false\"\n                shift\n                ;;\n            --smooth-follow-track-pitch)\n                process_config \"$default_config_file\" \"smooth_follow_track_pitch\" \"true\"\n                shift\n                ;;\n            --no-smooth-follow-track-pitch)\n                process_config \"$default_config_file\" \"smooth_follow_track_pitch\" \"false\"\n                shift\n                ;;\n            --smooth-follow-track-yaw)\n                process_config \"$default_config_file\" \"smooth_follow_track_yaw\" \"true\"\n                shift\n                ;;\n            --no-smooth-follow-track-yaw)\n                process_config \"$default_config_file\" \"smooth_follow_track_yaw\" \"false\"\n                shift\n                ;;\n            --sbs-mode-stretched)\n                process_config \"$default_config_file\" \"sbs_mode_stretched\" \"true\" \"string\"\n                shift\n                ;;\n            --no-sbs-mode-stretched)\n                process_config \"$default_config_file\" \"sbs_mode_stretched\" \"false\" \"string\"\n                shift\n                ;;\n            --sbs-content-3d)\n                process_config \"$default_config_file\" \"sbs_content\" \"true\" \"string\"\n                shift\n                ;;\n            --no-sbs-content-3d)\n                process_config \"$default_config_file\" \"sbs_content\" \"false\" \"string\"\n                shift\n                ;;\n            --neck-saver-horizontal)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"neck_saver_horizontal_multiplier\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --neck-saver-vertical)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"neck_saver_vertical_multiplier\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --opentrack-app-ip)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"opentrack_app_ip\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --opentrack-app-port)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"opentrack_app_port\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --opentrack-listener)\n                process_config \"$default_config_file\" \"opentrack_listener_enabled\" \"true\"\n                shift\n                ;;\n            --no-opentrack-listener)\n                process_config \"$default_config_file\" \"opentrack_listener_enabled\" \"false\"\n                shift\n                ;;\n            --opentrack-listen-ip)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"opentrack_listen_ip\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --opentrack-listen-port)\n                require_arg \"$1\" \"$2\"\n                process_config \"$default_config_file\" \"opentrack_listen_port\" \"$2\" \"string\"\n                shift 2\n                ;;\n            --multi-tap)\n                process_config \"$default_config_file\" \"multi_tap_enabled\" \"true\"\n                shift\n                ;;\n            --no-multi-tap)\n                process_config \"$default_config_file\" \"multi_tap_enabled\" \"false\"\n                shift\n                ;;\n            --metrics)\n                process_config \"$default_config_file\" \"metrics_disabled\" \"false\"\n                shift\n                ;;\n            --no-metrics)\n                process_config \"$default_config_file\" \"metrics_disabled\" \"true\"\n                shift\n                ;;\n            --request-token)\n                require_arg \"$1\" \"$2\"\n                process_config \"$state_config_file\" \"hardware_id\" \"\" \"string\" \"\" \"\" \"request\" \"$2\"\n                shift 2\n                ;;\n            --verify-token)\n                require_arg \"$1\" \"$2\"\n                process_config \"$state_config_file\" \"hardware_id\" \"\" \"string\" \"\" \"\" \"verify\" \"$2\"\n                shift 2\n                ;;\n            --refresh-license)\n                process_config \"$state_config_file\" \"hardware_id\" \"\" \"string\" \"\" \"\" \"refresh\"\n                shift\n                ;;\n            --get-hardware-id)\n                process_config \"$state_config_file\" \"hardware_id\" \"\" \"string\" \"\" \"\" \"get\"\n                shift\n                ;;\n            --)\n                shift\n                break\n                ;;\n            *)\n                break\n                ;;\n        esac\n    done\nfi\n"
  },
  {
    "path": "bin/xr_driver_logs",
    "content": "#!/usr/bin/env bash\n\n# exit when any command fails\nset -e\n\nif [ \"$(id -u)\" == \"0\" ]; then\n   echo \"This script must not be run as root\" 1>&2\n   exit 1\nfi\n\nXDG_STATE_HOME=\"${XDG_STATE_HOME:-$HOME/.local/state}\"\n\n# Determine the directory containing this script as invoked.\n# This makes the script packaging-friendly (e.g. distro/AUR installs), since\n# companion scripts are expected to be installed alongside it.\nscript_ref=\"$0\"\nif [[ \"$script_ref\" != */* ]]; then\n  script_ref=\"$(command -v -- \"$script_ref\" 2>/dev/null || echo \"$script_ref\")\"\nfi\nscript_dir=\"$(cd -P -- \"$(dirname -- \"$script_ref\")\" && pwd -P)\"\n\n# Create a temp directory to gather logs\ntmp_dir=$(mktemp -d -t xr-driver-logs-XXXXXXXXXX)\necho \"Gathering logs into temp directory: ${tmp_dir}\"\n\nmkdir -p \"$tmp_dir/xr_driver_logs\"\n\n# Copy XR driver log\nif [ -f \"$XDG_STATE_HOME/xr_driver/driver.log\" ]; then\n  cp \"$XDG_STATE_HOME/xr_driver/driver.log\" \"$tmp_dir/xr_driver_logs/driver.log\"\nelse\n  echo \"Warning: XR driver log not found at $XDG_STATE_HOME/xr_driver/driver.log\"\nfi\n\n# Copy XR driver config\nif [ -f \"$HOME/.config/xr_driver/config.ini\" ]; then\n  cp \"$HOME/.config/xr_driver/config.ini\" \"$tmp_dir/xr_driver_logs/config.ini\"\nelse\n  echo \"Warning: XR driver config not found at $HOME/.config/xr_driver/config.ini\"\nfi\n\ncopy_breezy_logs() {\n  if [ ! -d \"$script_dir\" ]; then\n    return 0\n  fi\n\n  local breezy_scripts\n  breezy_scripts=$(find \"$script_dir\" -maxdepth 1 -type f -name 'breezy_*_logs' -perm -u+x -print 2>/dev/null || true)\n  if [ -z \"$breezy_scripts\" ]; then\n    return 0\n  fi\n\n  while IFS= read -r script_path; do\n    [ -z \"$script_path\" ] && continue\n\n    local script_name\n    script_name=$(basename \"$script_path\")\n    echo \"Running $script_name to collect Breezy logs\"\n\n    local run_dir\n    run_dir=$(mktemp -d -p \"$tmp_dir\" breezy-run-XXXXXXXXXX)\n\n    set +e\n    (cd \"$run_dir\" && \"$script_path\")\n    local rc=$?\n    set -e\n\n    if [ \"$rc\" -ne 0 ]; then\n      echo \"Warning: $script_name exited with code $rc\"\n      rm -rf \"$run_dir\"\n      continue\n    fi\n\n    local archive\n    archive=$(find \"$run_dir\" -maxdepth 1 -type f -name '*.tar.gz' -printf '%T@ %p\\n' 2>/dev/null | sort -nr | head -n 1 | cut -d' ' -f2-)\n    if [ -z \"$archive\" ]; then\n      echo \"Warning: $script_name did not produce a .tar.gz archive\"\n      rm -rf \"$run_dir\"\n      continue\n    fi\n\n    cp \"$archive\" \"$tmp_dir/xr_driver_logs/\"\n    rm -rf \"$run_dir\"\n  done <<< \"$breezy_scripts\"\n}\n\ncopy_breezy_logs\n\n# Create archive\narchive_name=\"xr_driver_logs_$(date +%Y%m%d_%H%M%S).tar.gz\"\ntar -czf \"$archive_name\" -C \"$tmp_dir\" xr_driver_logs\necho \"Created log archive: $(pwd)/$archive_name\"\n\nrm -rf \"$tmp_dir\"\n"
  },
  {
    "path": "bin/xr_driver_ot_profile_setup",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\n\ndefault_ini=\"\"\n\n# Pick the newest ~/.config/opentrack-*/default.ini.\nshopt -s nullglob\ncandidates=(\"${HOME}/.config\"/opentrack-*/default.ini)\nshopt -u nullglob\nif [[ ${#candidates[@]} -gt 0 ]]; then\n    # Sort naturally (version-like) and take the last.\n  default_ini=\"$(printf '%s\\n' \"${candidates[@]}\" | sort -V | tail -n 1)\"\nfi\n\nif [[ -z \"$default_ini\" ]]; then\n    cat >&2 <<EOF\nerror: opentrack config not found\n\nLooked for:\n    ${HOME}/.config/opentrack-*/default.ini\n\nIf you haven't already, run opentrack once to generate the config, then re-run this script.\nIf issues persist, please open an Issue on this Github repository.\nEOF\n    exit 2\nfi\n\ncfg_dir=\"$(dirname \"$default_ini\")\"\ndst=\"${cfg_dir}/xr-driver.ini\"\n\ntmp=\"$(mktemp \"${cfg_dir}/.xr-driver.ini.tmp.XXXXXX\")\"\ncat >\"$tmp\" <<'EOF'\n[modules]\nfilter-dll=nm\nprotocol-dll=udp\ntracker-dll=neuralnet\n\n[opentrack-mappings]\nx-max-output-value=-100\nx-max-value=100\ny-max-output-value=-100\ny-max-value=100\nz-max-output-value=-100\nz-max-value=100\n\n[opentrack-ui]\npitch-invert-sign=true\nroll-invert-sign=true\nx-invert-sign=true\nx-source-index=0\ny-source-index=1\nyaw-invert-sign=true\nz-source-index=2\n\n[udp-proto]\nip1=127\nip2=0\nip3=0\nip4=1\nEOF\n\nchmod 0644 \"$tmp\" 2>/dev/null || true\nmv -f \"$tmp\" \"$dst\"\n\necho \"xr-driver profile created. Launch opentrack and choose \"xr-driver.ini\" from the Profile menu.\""
  },
  {
    "path": "bin/xr_driver_setup",
    "content": "#!/usr/bin/env bash\n\n# This setup script should do the minimum work required to download the release package, unzip it, and kick off the\n# setup script contained within.\n\n# exit when any command fails\nset -e\n\n# Make sure only root can run our script\nif [ \"$(id -u)\" != \"0\" ]; then\n   echo \"This script must be run as root\" 1>&2\n   exit 1\nfi\n\ncheck_command() {\n    if ! command -v \"$1\" &>/dev/null; then\n        echo \"Please install \\\"$1\\\" and make sure it's available in your \\$PATH, then rerun the setup.\"\n        exit 1\n    fi\n}\n\ncheck_command \"curl\"\n\nARCH=$(uname -m)\n\nstart_dir=$(pwd)\n\n# create temp directory\ntmp_dir=$(mktemp -d -t xr-driver-XXXXXXXXXX)\npushd $tmp_dir > /dev/null\necho \"Created temp directory: ${tmp_dir}\"\n\nbinary_download_url=\"https://github.com/wheaney/XRLinuxDriver/releases/latest/download/xrDriver-$ARCH.tar.gz\"\nlib_download_url=\"https://github.com/wheaney/XRLinuxDriver/releases/latest/download/xrDriver-libs-$ARCH.tar.gz\"\nif [ \"$1\" = \"-v\" ]\nthen\n  metrics_version=\"$2\"\n  local_dir_arg=\"$3\"\nelif [ \"$1\" = \"--tag\" ] && [ -n \"$2\" ]\nthen\n  binary_download_url=\"https://github.com/wheaney/XRLinuxDriver/releases/download/$2/xrDriver-$ARCH.tar.gz\"\n  lib_download_url=\"https://github.com/wheaney/XRLinuxDriver/releases/download/$2/xrDriver-libs-$ARCH.tar.gz\"\nelse\n  local_dir_arg=\"$1\"\nfi\n\n# Handle local directory if provided\nif [ -n \"$local_dir_arg\" ]\nthen\n  # Convert relative path to absolute path\n  if [[ \"$local_dir_arg\" = /* ]]; then\n    local_dir=\"$local_dir_arg\"\n  else\n    local_dir=$(realpath \"$start_dir/$local_dir_arg\")\n  fi\n  \n  # Check for driver archive in the local directory\n  binary_path_arg=\"$local_dir/xrDriver-$ARCH.tar.gz\"\n  if [ ! -f \"$binary_path_arg\" ]; then\n    echo \"Error: Driver archive not found at $binary_path_arg\"\n    exit 1\n  fi\n  \n  # Check for lib archive in the local directory\n  lib_path_arg=\"$local_dir/xrDriver-libs-$ARCH.tar.gz\"\n  if [ ! -f \"$lib_path_arg\" ]; then\n    echo \"Error: Lib archive not found at $lib_path_arg\"\n\n    YELLOW='\\e[1;33m'\n    RESET='\\e[0m'\n    echo -e \"\\n${YELLOW}IMPORTANT${RESET}: Be sure you're using the latest version of the setup script\\n\"\n    exit 1\n  fi\nfi\n\nif [ -z \"$binary_path_arg\" ]\nthen\n  # download and unzip the latest driver\n  binary_path_arg=\"xrDriver-$ARCH.tar.gz\"\n  echo \"Downloading to: ${tmp_dir}/$binary_path_arg\"\n\n  curl -L \"$binary_download_url\" > \"$binary_path_arg\"\nelse\n  cp $binary_path_arg $tmp_dir\nfi\n\necho \"Extracting to: ${tmp_dir}/xr_driver\"\ntar -xf $(basename $binary_path_arg)\n\n# Handle lib archive\nif [ -z \"$lib_path_arg\" ]\nthen\n  # download and unzip the latest lib archive\n  lib_path_arg=\"xrDriver-libs-$ARCH.tar.gz\"\n  echo \"Downloading to: ${tmp_dir}/$lib_path_arg\"\n\n  curl -L \"$lib_download_url\" > \"$lib_path_arg\"\nelse\n  cp $lib_path_arg $tmp_dir\nfi\n\necho \"Extracting lib to: ${tmp_dir}/xr_driver/lib\"\ntar -xf $(basename $lib_path_arg)\n# Move lib files to xr_driver/lib subdirectory\nmkdir -p xr_driver/lib\nmv xr_driver_lib/* xr_driver/lib/\nrmdir xr_driver_lib\n\npushd xr_driver > /dev/null\n\n# run the setup script that comes with this release, pass in the metrics version\n./setup $metrics_version\n\necho \"Deleting temp directory: ${tmp_dir}\"\nrm -rf $tmp_dir\ncd \"$(dirs -l -0)\" && dirs -c\n"
  },
  {
    "path": "bin/xr_driver_uninstall",
    "content": "#!/usr/bin/env bash\n\nfor_install=0\nif [[ -n \"$1\" ]] && [[ \"$1\" == \"--for-install\" ]]; then\n    for_install=1\nfi\n\n# we don't want the uninstall script to be able to cause a failure if being triggered by the setup script\n[ \"$for_install\" -eq 0 ] && set -e\n\n# Get the directory of the current script\nscript_dir=$(dirname \"$0\")\n\nUSER=${SUDO_USER:-$USER}\nUSER_HOME=$(getent passwd $USER | cut -d: -f6)\n\nif [ -z \"$XDG_DATA_HOME\" ]; then\n  XDG_DATA_HOME=\"$USER_HOME/.local/share\"\nfi\nSYSTEMD_DATA_DIR=\"$XDG_DATA_HOME/systemd\"\nSYSTEMD_USER_DIR=\"$SYSTEMD_DATA_DIR/user\"\nDATA_DIR=\"$XDG_DATA_HOME/xr_driver\"\n\nif [ -z \"$XDG_CONFIG_HOME\" ]; then\n  XDG_CONFIG_HOME=\"$USER_HOME/.config\"\nfi\n\nCONFIG_DIR=\"$XDG_CONFIG_HOME/xr_driver\"\n\nif [ -z \"$XDG_BIN_HOME\" ]; then\n  XDG_BIN_HOME=\"$USER_HOME/.local/bin\"\nfi\nOLD_BIN_DIR=\"$USER_HOME/bin\"\nBIN_DIR=\"$XDG_BIN_HOME\"\n\nif [ -z \"$XDG_STATE_HOME\" ]; then\n  XDG_STATE_HOME=\"$USER_HOME/.local/state\"\nfi\nSTATE_DIR=\"$XDG_STATE_HOME/xr_driver\"\n\n[ \"$for_install\" -eq 0 ] && echo \"Removing the systemd service\"\n# if this is root\nif [ \"$(id -u)\" == \"0\" ]; then\n  export XDG_RUNTIME_DIR=/run/user/$(id -u $USER)\n  if su -l -c \"XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR systemctl --user is-active --quiet xr-driver\" $USER; then\n      su -l -c \"XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR systemctl --user stop xr-driver\" $USER\n  fi\nelse\n  if systemctl --user is-active --quiet xr-driver; then\n      systemctl --user stop xr-driver\n  fi\nfi\n\n[ \"$for_install\" -eq 0 ] && echo \"Removing the systemd service from ${SYSTEMD_USER_DIR}\"\nrm -f $SYSTEMD_USER_DIR/xr-driver.service\n\nUDEV_RULES_DIR=\"/usr/lib/udev/rules.d\"\nALT_UDEV_RULES_DIR=\"/etc/udev/rules.d\"\n\n[ \"$for_install\" -eq 0 ] && echo \"Removing the udev rules from ${UDEV_RULES_DIR} or ${ALT_UDEV_RULES_DIR}\"\nsudo rm $UDEV_RULES_DIR/70-*-xr.rules > /dev/null 2>&1 || true\nsudo rm $ALT_UDEV_RULES_DIR/70-*-xr.rules > /dev/null 2>&1 || true\n\nif [ \"$for_install\" -eq 0 ]; then\n    echo \"Removing installed files from $STATE_DIR, $CONFIG_DIR, $DATA_DIR, and $BIN_DIR\"\n\n    UA_EVENT_NAME=\"uninstall\"\n    UA_CLIENT_ID=\"ARLinuxDriver\"\n    #INJECT_UA_CALL\n\n    rm -rf $STATE_DIR\n    rm -rf $CONFIG_DIR\nfi\nrm -rf $DATA_DIR\nrm -f $BIN_DIR/xrDriver\nrm -f $BIN_DIR/xr_driver_cli\nrm -f $BIN_DIR/xr_driver_verify\nrm -f $BIN_DIR/xr_driver_logs\n\nrm -f /tmp/shader_runtime_*\nrm -f /dev/shm/xr_*\nrm -f /dev/shm/breezy_desktop_imu\n\n# this script is self-deleting, leave this as the last command\n# remove the one we're not using first\nif [ \"$script_dir\" = \"$OLD_BIN_DIR\" ]; then\n    rm -f \"$BIN_DIR/xr_driver_uninstall\"\n    rm -f \"$OLD_BIN_DIR/xreal_driver_uninstall\"\nelse\n    rm -f \"$OLD_BIN_DIR/xreal_driver_uninstall\"\n    rm -f \"$BIN_DIR/xr_driver_uninstall\"\nfi"
  },
  {
    "path": "bin/xr_driver_verify",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nUSER=${SUDO_USER:-$USER}\nUSER_HOME=$(getent passwd $USER | cut -d: -f6)\n\nif [ -z \"$XDG_DATA_HOME\" ]; then\n  XDG_DATA_HOME=\"$USER_HOME/.local/share\"\nfi\nDATA_DIR=\"$XDG_DATA_HOME/xr_driver\"\nif [ ! -e \"$DATA_DIR/manifest\" ]; then\n  echo \"Verification failed\" >&2\n  exit 1\nfi\n\n# Get the directory of the current script\nscript_dir=$(dirname \"$0\")\n\n# create a string to string mapping, file name to expected file location\ndeclare -A file_paths\nfile_paths=(\n  [\"xrDriver\"]=\"{bin_dir}/xrDriver\"\n  [\"xr_driver_cli\"]=\"{bin_dir}/xr_driver_cli\"\n  [\"xr_driver_uninstall\"]=\"{bin_dir}/xr_driver_uninstall\"\n  [\"xr_driver_logs\"]=\"{bin_dir}/xr_driver_logs\"\n)\n\n# verify the file hashes in ./manifest\nwhile IFS= read -r line\ndo\n  # split the line into hash and filename\n  manifest_hash=$(echo $line | awk '{print $1}')\n  file=$(echo $line | awk '{print $2}')\n\n  actual_file_path=${file_paths[$file]}\n\n  # compute the SHA256 hash of the actual file\n  actual_hash=$(sha256sum $actual_file_path | awk '{print $1}')\n\n  # compare the hashes\n  if ! [ \"$manifest_hash\" = \"$actual_hash\" ]; then\n    echo \"Verification failed\" >&2\n    exit 1\n  fi\ndone < \"$DATA_DIR/manifest\"\n\necho \"Verification succeeded\""
  },
  {
    "path": "docker-build/Dockerfile",
    "content": "# To run the build from the package root:\n#    docker buildx build --platform linux/amd64,linux/arm64 -f ./docker-build/Dockerfile -t \"xr-driver\" .\n#    docker run --rm -t -v ./:/source -v --platform linux/amd64 \"xr-driver:amd64\"\n#    docker run --rm -t -v ./:/source -v --platform linux/arm64 \"xr-driver:arm64\"\n\nFROM --platform=$TARGETPLATFORM debian:stable-20250428-slim\n\nARG TARGETPLATFORM\nRUN echo \"Target platform: $TARGETPLATFORM\"\n\nRUN apt-get update && apt-get install -y \\\n    build-essential \\\n    cmake \\\n    pkg-config \\\n    libudev-dev \\\n    libusb-1.0-0-dev \\\n    libcurl4-openssl-dev \\\n    libevdev-dev \\\n    libssl-dev \\\n    libjson-c-dev \\\n    python3 \\\n    python3-yaml \\\n    libwayland-dev \\\n    cargo \\\n    rustc \\\n    git \\\n && rm -rf /var/lib/apt/lists/*\n\nWORKDIR /source\n\nCMD bin/package"
  },
  {
    "path": "docker-build/Dockerfile.aarch64",
    "content": "# To run the build from the package root:\n#    docker buildx build --platform linux/amd64,linux/arm64 -f ./docker-build/Dockerfile -t \"xr-driver\" .\n#    docker run --rm -t -v ./:/source -v --platform linux/amd64 \"xr-driver:amd64\"\n#    docker run --rm -t -v ./:/source -v --platform linux/arm64 \"xr-driver:arm64\"\n\n# Support Raspberry Pi OS Bookworm (64-bit) and later\nFROM --platform=$TARGETPLATFORM debian:bookworm-slim\n\nARG TARGETPLATFORM\nRUN echo \"Target platform: $TARGETPLATFORM\"\n\nARG RUST_TOOLCHAIN=stable\nENV DEBIAN_FRONTEND=noninteractive\n\nRUN apt-get update && apt-get install -y \\\n    build-essential \\\n    cmake \\\n    pkg-config \\\n    libudev-dev \\\n    libusb-1.0-0-dev \\\n    libcurl4-openssl-dev \\\n    libevdev-dev \\\n    libssl-dev \\\n    libjson-c-dev \\\n    python3 \\\n    python3-yaml \\\n    libwayland-dev \\\n    ca-certificates \\\n    curl \\\n    xz-utils \\\n    git \\\n && rm -rf /var/lib/apt/lists/*\n\nENV RUSTUP_HOME=/usr/local/rustup \\\n    CARGO_HOME=/usr/local/cargo \\\n    PATH=/usr/local/cargo/bin:$PATH\n\nRUN set -eux; \\\n    curl -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain \"${RUST_TOOLCHAIN}\"; \\\n    rustc --version; \\\n    cargo --version\n\nWORKDIR /source\n\nCMD bin/package"
  },
  {
    "path": "docker-build/init.sh",
    "content": "#!/bin/bash\n\n# might be needed on a fresh docker setup:\n#   install qemu and qemu-user-static packages\n#   sudo docker context rm default\n\ndocker run --privileged --rm tonistiigi/binfmt --install all\nsudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes\n\nif [[ \"$1\" == \"--init\" || ! $(docker buildx inspect xrdriverbuilder &>/dev/null; echo $?) -eq 0 ]]; then\n    # start fresh\n    echo \"Creating new docker builder instance\"\n    docker buildx rm xrdriverbuilder 2>/dev/null || true\n    docker buildx create --use --name xrdriverbuilder --driver docker-container --driver-opt image=moby/buildkit:latest\nelse\n    echo \"Using existing docker builder instance\"\n    docker buildx use xrdriverbuilder\nfi\n\necho \"Building docker image\"\ndocker buildx build --platform linux/amd64 -f ./docker-build/Dockerfile -t \"xr-driver:amd64\" --load .\ndocker buildx build --platform linux/arm64 -f ./docker-build/Dockerfile.aarch64 -t \"xr-driver:arm64\" --load ."
  },
  {
    "path": "docker-build/run-build.sh",
    "content": "#!/bin/bash\n\nset -e\n\nUSER=${SUDO_USER:-$USER}\nGROUP=$(id -gn $USER)\n\n# Run containers for each architecture\nif [[ \"$1\" == \"x86_64\" || -z \"$1\" ]]; then\n    sudo rm -rf build/\n    docker run --rm -t -v ./:/source --platform linux/amd64 -e STEAMOS -e UA_API_SECRET -e UA_API_SECRET_INTENTIONALLY_EMPTY \"xr-driver:amd64\"\n    sudo chown -R $USER:$GROUP out/\nfi\n\nif [[ \"$1\" == \"aarch64\" || -z \"$1\"  ]]; then\n    sudo rm -rf build/\n    docker run --rm -t -v ./:/source --platform linux/arm64 -e UA_API_SECRET -e UA_API_SECRET_INTENTIONALLY_EMPTY \"xr-driver:arm64\"\n    sudo chown -R $USER:$GROUP out/\nfi\n\n# build directory structure is all owned by root because of docker, delete it all now\nsudo rm -rf build/"
  },
  {
    "path": "docker-build/run-fpm.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nfunction libs_to_fpm_args {\n    local lib_dir=$1\n    local fpm_args=\"\"\n    for lib in $(ls $lib_dir); do\n        fpm_args=\"$fpm_args lib/$lib=/usr/lib/$lib\"\n    done\n    echo $fpm_args\n}\n\nfunction udev_files_to_fpm_args {\n    local udev_dir=$1\n    local fpm_args=\"\"\n    for udev_file in $(ls $udev_dir); do\n        fpm_args=\"$fpm_args udev/$udev_file=/usr/lib/udev/rules.d/$udev_file\"\n    done\n    echo $fpm_args\n}\n\n# parse the version from the CMakeLists.txt file\nversion=$(grep -oP 'project\\(xrDriver VERSION \\K[0-9]+\\.[0-9]+\\.[0-9]+' CMakeLists.txt)\n\n# Run containers for each architecture\nif [[ \"$1\" == \"x86_64\" || -z \"$1\" ]]; then\n    sudo rm -rf build/\n    docker run --rm -t -v ./:/source --platform linux/amd64 -e UA_API_SECRET -e UA_API_SECRET_INTENTIONALLY_EMPTY \"xr-driver:amd64\" ./fpm/build\n\n    lib_args=$(libs_to_fpm_args \"build/xr_driver/lib\")\n    udev_args=$(udev_files_to_fpm_args \"build/xr_driver/udev\")\n    fpm --architecture x86_64 --version $version \\\n        -t deb \\\n        --no-auto-depends \\\n        --depends libssl3 \\\n        --depends libevdev2 \\\n        --depends libusb-1.0-0 \\\n        --depends libjson-c5 \\\n        --depends libcurl4 \\\n        --depends libwayland-client0 \\\n        --depends libsystemd0 \\\n        $lib_args $udev_args\n\n    # this fails without my fix in https://github.com/jordansissel/fpm/pull/2082\n    fpm --architecture x86_64 --version $version \\\n        -t rpm \\\n        --no-auto-depends \\\n        --depends openssl-libs \\\n        --depends libevdev \\\n        --depends libusbx \\\n        --depends json-c \\\n        --depends libcurl \\\n        --depends libwayland-client \\\n        --depends systemd-libs \\\n        $lib_args $udev_args\nfi\n\nif [[ \"$1\" == \"aarch64\" || -z \"$1\"  ]]; then\n    sudo rm -rf build/\n    docker run --rm -t -v ./:/source --platform linux/arm64 -e UA_API_SECRET -e UA_API_SECRET_INTENTIONALLY_EMPTY \"xr-driver:arm64\" ./fpm/build\n\n    lib_args=$(libs_to_fpm_args \"build/xr_driver/lib\")\n    udev_args=$(udev_files_to_fpm_args \"build/xr_driver/udev\")\n    fpm --architecture aarch64 --version $version \\\n        -t deb \\\n        --no-auto-depends \\\n        --depends libssl3 \\\n        --depends libevdev2 \\\n        --depends libusb-1.0-0 \\\n        --depends libjson-c5 \\\n        --depends libcurl4 \\\n        --depends libwayland-client0 \\\n        --depends libsystemd0 \\\n        $lib_args $udev_args\n\n    # this fails without my fix in https://github.com/jordansissel/fpm/pull/2082\n    fpm --architecture aarch64 --version $version \\\n        -t rpm \\\n        --no-auto-depends \\\n        --depends openssl-libs \\\n        --depends libevdev \\\n        --depends libusbx \\\n        --depends json-c \\\n        --depends libcurl \\\n        --depends libwayland-client \\\n        --depends systemd-libs \\\n        $lib_args $udev_args\nfi\n\nmv xr-driver*.deb out/\nmv xr-driver*.rpm out/\n\n# build directory structure is all owned by root because of docker, delete it all now\nsudo rm -rf build/"
  },
  {
    "path": "docs/6dof-from-3dof-opentrack-neuralnet.md",
    "content": "# Getting 6DoF from 3DoF glasses (OpenTrack + NeuralNet)\n\nThis guide describes how to get **6DoF positional tracking** from any supported **3DoF glasses** by combining:\n\n- **XR Linux Driver** (for the glasses’ 3DoF IMU + runtime)\n- **OpenTrack** (for filtering/mapping and UDP output)\n- **NeuralNet Tracker** (OpenTrack input, for camera-based position tracking)\n\nThe high-level idea:\n\n1. Have XR Linux Driver consume a pose orientation from a set of 3DoF glasses acting as a \"primary\" device.\n2. Use a webcam + NeuralNet in OpenTrack to estimate a 6DoF pose, including **position** (XYZ).\n3. Have XR Linux Driver’s **OpenTrack listener** ingest that pose as a synthetic \"supplemental\" device.\n4. Merge the glasses' 3DoF orientation + OpenTrack's 6DoF position for use with Breezy Desktop, XR Gaming, or other external applications.\n\n## Prereqs\n\n- A working XR Linux Driver install (if you're installed Breezy Desktop or XR Gaming, you already have this)\n- A webcam (for NeuralNet position tracking)\n\n## Install OpenTrack (+ NeuralNet input)\n\n### Use the experimental AppImage\n\nI have an experimental AppImage CI build that may prevent the need for a more complicated installation on your system. \n\n1. Visit [the latest wheaney/opentrack-appimage-ci Release](https://github.com/wheaney/opentrack-appimage-ci/releases/latest) and download the ONNX-GPU build.\n2. If you've ever launched another version of OpenTrack on this machine before, you may want to delete (backup first, if you want) the config files found with `find ~/.config/opentrack-*`.\n3. If you plan on kicking it off from the command line (better to see log output, if debugging), first set the execute flag on the file: `chmod +x ~/Downloads/OpenTrack-*.AppImage`\n4. Run it.\n5. If it doesn't work (or the `Start` button causes an error later on in the instructions), you might want to try the ONNX-CPU build. Otherwise, you'll need to try to install via your package manager.\n\n### Setup via package manager\n\nOpenTrack won't typically come with NeuralNet out of the box. You'll need to make sure the appropriate `onnxruntime` is installed. Look up the necessary OpenTrack and ONNX runtime package names for your package manager and install them. For ONNX you may be able to choose between CPU and GPU variants; it's up to you which to choose but CPU is the easiest choice and it won't typically be very demanding from a resource perspective.\n\n#### Arch Linux installation example\n\n```bash\nsudo pacman -S onnxruntime\nyay -S opentrack\n```\n\n## Apply the recommended OpenTrack profile (one-liner)\n\nThis script configures an OpenTrack profile tuned for the XR Linux Driver listener. Before running this script, you will need to launch OpenTrack at least once to create the default profile.\n\n```bash\ncurl -fsSL https://github.com/wheaney/XRLinuxDriver/releases/latest/download/xr_driver_ot_profile_setup | bash\n```\n\nNote: piping a remote script to `bash` trades convenience for auditability. If you prefer to review it first, download it and inspect before running.\n\n## Enable the XR Linux Driver OpenTrack listener\n\nEnable the listener (input):\n\n```bash\nxr_driver_cli --opentrack-listener\n```\n\nIf you changed the OpenTrack UDP output port, update the listener to match:\n\n```bash\nxr_driver_cli --opentrack-listen-port 4242\n```\n\n## Run it\n\n1. Plug in your glasses first (confirm normal **3DoF** tracking is working).\n2. Launch OpenTrack and select the Profile named \"xr-driver.ini\". Hit the settings icon next to the NeuralNet input and make sure the appropriate camera is selected, set the `Diagonal FOV` and `Resolution` values to match your camera.\n3. Click **Start** in OpenTrack.\n4. Launch Breezy Desktop and enable the effect. You should now be able to lean in to see a closer view of your screens.\n\n**Note** - This will also be available in a future update of XR Gaming, if you've set up your deck with a webcam or you're sending the UDP data over the network.\n\n## Troubleshooting\n\n- View XR Linux Driver logs:\n\n  ```bash\n  xr_driver_cli --view-log\n  ```\n\n- Confirm the listener is bound:\n\n  ```bash\n  ss -u -lpn | grep 4242\n  ```\n\n- If OpenTrack is running but the listener never “connects”, double-check:\n  - OpenTrack output is **UDP over network**\n  - remote IP/port match the listener’s bind port\n  - you didn’t accidentally enable XR Linux Driver’s OpenTrack **app/output** mode at the same time (see the feedback-loop guard notes in the listener page)\n"
  },
  {
    "path": "docs/development.md",
    "content": "# Development (Docker Buildx)\n\nThis repo includes a Docker-based build pipeline that produces release artifacts for multiple architectures using Docker **Buildx**.\n\nThe main scripts are:\n\n- `docker-build/init.sh`: sets up a Buildx builder and builds the per-arch build images\n- `docker-build/run-build.sh`: runs the build inside those images and writes artifacts to `out/`\n- *Needs work* `docker-build/run-fpm.sh`: runs the build and produces `.deb` / `.rpm` packages (written to `out/`)\n\n## Requirements\n\n- Docker\n- Docker Buildx (`docker buildx version` should work)\n\nFor cross-arch builds (e.g. building `linux/arm64` on an x86_64 machine), you also need binfmt/qemu emulation enabled. The init script will attempt to install this via privileged containers.\n\n## 1) Initialize Buildx + build the build images\n\nRun from the repo root:\n\n```bash\n./docker-build/init.sh --init\n```\n\nThis will:\n\n- install binfmt/qemu handlers (for cross-arch builds)\n- create or recreate a Buildx builder named `xrdriverbuilder`\n- build and `--load` two images locally:\n\t- `xr-driver:amd64`\n\t- `xr-driver:arm64`\n\nIf you already have the builder and just want to reuse it, you can run:\n\n```bash\n./docker-build/init.sh\n```\n\n## 2) Build artifacts (tarball output)\n\nAfter the images exist, run:\n\n```bash\n./docker-build/run-build.sh\n```\n\nTo build only one architecture:\n\n```bash\n./docker-build/run-build.sh x86_64\n./docker-build/run-build.sh aarch64\n```\n\nBuild outputs are written under `out/`.\n\nNotes:\n\n- The build runs in containers, so intermediate files under `build/` may be owned by root; the script cleans `build/` afterwards.\n- The build passes through `UA_API_SECRET` (and `UA_API_SECRET_INTENTIONALLY_EMPTY`) as environment variables when running containers.\n\n## 3) Build distro packages (.deb / .rpm)\n\nIf you want Debian/RPM packages, run:\n\n```bash\n./docker-build/run-fpm.sh\n```\n\nOr per-arch:\n\n```bash\n./docker-build/run-fpm.sh x86_64\n./docker-build/run-fpm.sh aarch64\n```\n\nThe resulting packages are moved to `out/`.\n\n## Troubleshooting\n\n- If `linux/arm64` builds fail on x86_64, rerun init:\n\n\t```bash\n\t./docker-build/init.sh --init\n\t```\n\n- Confirm Buildx sees the builder:\n\n\t```bash\n\tdocker buildx ls\n\tdocker buildx inspect xrdriverbuilder\n\t```\n"
  },
  {
    "path": "docs/index.md",
    "content": "# XR Linux Driver Docs\n\nThis site documents selected XR Linux Driver features and integrations.\n\n## OpenTrack integrations\n\nThere are two separate OpenTrack-related components:\n\n- **OpenTrack app (output/source):** the driver **sends** pose data over UDP to an OpenTrack instance.\n- **OpenTrack listener (input):** the driver **receives** pose data over UDP (in the OpenTrack payload format) and exposes it as a synthetic IMU device.\n\n### Quick links\n\n- [Mouse / joystick modes](mouse-and-joystick-modes.md)\n- [OpenTrack app (output/source)](opentrack-app.md)\n- [OpenTrack listener (input)](opentrack-listener.md)\n- [6DoF with any supported 3DoF glasses + a webcam (OpenTrack + NeuralNet)](6dof-from-3dof-opentrack-neuralnet.md)\n- [Development](development.md)\n\n## Where settings live\n\nMost configuration is written by `xr_driver_cli` into:\n\n- `$XDG_CONFIG_HOME/xr_driver/config.ini` (usually `~/.config/xr_driver/config.ini`)\n\nLogs are written to:\n\n- `$XDG_STATE_HOME/xr_driver/driver.log` (usually `~/.local/state/xr_driver/driver.log`)\n\nTip: `xr_driver_cli --view-log` tails the log in `less`.\n"
  },
  {
    "path": "docs/mouse-and-joystick-modes.md",
    "content": "# Mouse / joystick modes\n\nXR Linux Driver turns head movement into input that games and apps can use.\n\nMost commonly that’s **mouse movement**, but you can also switch to a **virtual joystick** mode.\n\n## Mouse mode (default)\n\nSince device movements are converted to mouse movements, they should be recognized by any PC game that supports keyboard/mouse input. This will work most naturally for games where mouse movements is used to control \"look\"/camera movements. For point-and-click style games, you may want to disable the driver so your glasses act as just a simple display.\n\nTo adjust sensitivity, use the Decky UI on Steam Deck, or:\n\n```bash\nxr_driver_cli --mouse-sensitivity 20\n```\n\nIf you're using keyboard and mouse to control your games, then the mouse movements from this driver will simply add to your own mouse movements and they should work naturally together.\n\nIf you're using a game controller, Valve pushes pretty heavily for PC games support mouse input *in addition to* controller input, so you should find that most modern games will just work with this driver straight out of the box.\n\n## Controller mappings (Steam)\n\n1. Open your game's controller configuration in Steam\n2. Open the Layouts view\n3. Choose a keyboard/mouse template (e.g. \"Keyboard (WASD) and Mouse\"). Be sure to edit the configuration and set \"Gyro Behavior\" to \"As Mouse\" for any games where you want to use gyro.\n\n## Controller mappings (non-Steam)\n\nYou'll probably want to use a utility that does what Steam's controller layouts are doing behind the scenes: mapping controller buttons, joystick, and gyro inputs to keyboard/mouse inputs. One popular tool is [JoyShockMapper](https://github.com/Electronicks/JoyShockMapper).\n\n## Joystick mode\n\nIf mouse input just won't work for a specific game, you can enable joystick mode using the Decky UI on Steam Deck, or:\n\n```bash\nxr_driver_cli --use-joystick\n```\n\nRevert back to mouse mode with:\n\n```bash\nxr_driver_cli --use-mouse\n```\n\nJoystick mode creates a virtual gamepad whose right joystick is driven by movements from the glasses.\n\nNotes:\n\n- Joystick movement is capped (you can only move a joystick so far).\n- This creates a *second* controller on your PC.\n- If the game interprets another controller as a second player, its movements won't get combined with your real controller's movements.\n"
  },
  {
    "path": "docs/opentrack-app.md",
    "content": "# OpenTrack app (output/source)\n\nThe **OpenTrack app** integration makes the driver send pose data over UDP in an OpenTrack-compatible payload format.\n\nThis is useful when you want to consume the driver’s tracking in other applications via OpenTrack’s ecosystem (mappings, output protocols, etc.).\n\n## Enable it (via `xr_driver_cli`)\n\nEnable the OpenTrack external mode (this sets `output_mode=external_only` and `external_mode=opentrack`):\n\n```bash\nxr_driver_cli --opentrack-app\n```\n\nConfigure the UDP target (where OpenTrack is listening):\n\n```bash\nxr_driver_cli --opentrack-app-ip 127.0.0.1\nxr_driver_cli --opentrack-app-port 4242\n\n## OpenTrack side setup\n\nOn the OpenTrack machine:\n\n1. Configure OpenTrack to **receive** UDP pose data (exact UI wording varies by OpenTrack version).\n2. Set the listening **port** to match `--opentrack-app-port` (default: `4242`).\n3. If OpenTrack is on a different machine, make sure firewalls allow inbound UDP on that port.\n\n## Data format and notes\n\nThe driver sends a UDP packet containing:\n\n- 6 × `double`: `(x, y, z, yaw, pitch, roll)`\n- 1 × `uint32`: frame number\n\nAngles are in **degrees**.\n\nThe implementation converts the driver’s coordinate system into what OpenTrack expects (see the implementation in the OpenTrack source plugin).\n\n## Troubleshooting\n\n- Confirm the driver is running: `systemctl --user status xr-driver`\n- Check logs: `xr_driver_cli --view-log`\n- Verify packets are being sent (localhost example):\n\n  ```bash\n  sudo tcpdump -n -i lo udp port 4242\n  ```\n\n- If nothing arrives in OpenTrack, verify:\n  - the IP/port in `xr_driver_cli --opentrack-app-ip/--opentrack-app-port`\n  - OpenTrack is actually listening on that port\n  - you’re not trying to “receive from yourself” through the listener at the same time (see the listener page for the feedback-loop guard)\n"
  },
  {
    "path": "docs/opentrack-listener.md",
    "content": "# OpenTrack listener (input)\n\nThe **OpenTrack listener** integration makes the driver listen for OpenTrack UDP packets and expose them as a **synthetic IMU device** or as a **supplemental device** if a primary IMU device is already connected (see [6DoF from 3DoF](6dof-from-3dof-opentrack-neuralnet.md)).\n\nThis is primarily useful for:\n\n- Feeding externally-tracked pose data into the XR Linux Driver for use with Breezy Desktop or XR Gaming\n- Testing/debugging pose ingestion without relying on a physical glasses IMU\n\n## Enable it (via `xr_driver_cli`)\n\nTurn the listener on:\n\n```bash\nxr_driver_cli --opentrack-listener\n```\n\nBind address / port:\n\n```bash\n# Listen on all interfaces (default is typically 0.0.0.0)\nxr_driver_cli --opentrack-listen-ip 0.0.0.0\n\n# Default port used by the OpenTrack integrations\nxr_driver_cli --opentrack-listen-port 4242\n```\n\nDisable it:\n\n```bash\nxr_driver_cli --no-opentrack-listener\n```\n\n### What do these flags change?\n\n`xr_driver_cli` writes these keys into `~/.config/xr_driver/config.ini`:\n\n- `opentrack_listener_enabled=true|false`\n- `opentrack_listen_ip=...`\n- `opentrack_listen_port=...`\n\n## OpenTrack side setup\n\nOn the machine that will **send** tracking:\n\n1. Configure OpenTrack to **output** pose data via UDP.\n2. Set the destination IP to the machine running XR Linux Driver.\n3. Set the destination port to match `--opentrack-listen-port` (default: `4242`).\n\nIf you are sending from another host, ensure UDP traffic on that port is allowed.\n\n## Payload expectations\n\nThe listener expects packets containing at least:\n\n- 6 × `double`: `(x, y, z, yaw, pitch, roll)`\n\nIt will ignore packets smaller than that. (If your sender includes a trailing frame number, that’s fine — it will be ignored.)\n\nAngles are treated as **degrees**.\n\n## Feedback-loop guard (important)\n\nThe driver also has an OpenTrack **app/output** mode that can send UDP packets.\n\nTo prevent an accidental “send → receive → send …” feedback loop when both features are enabled on the same machine, the listener will **discard all packets** when:\n\n- the listener is enabled, **and**\n- OpenTrack app/output mode is enabled (`external_mode` includes `opentrack`), **and**\n- `opentrack_app_ip` is set to a localhost/unspecified address (e.g. `127.0.0.1`, `localhost`, `0.0.0.0`, `::1`, `::`), **and**\n- `opentrack_app_port` matches `opentrack_listen_port` (both default to `4242`).\n\nIf you want to use the listener, typically you should:\n\n- disable OpenTrack app/output mode: `xr_driver_cli --disable-external`\n\n…or run the sender on a different machine.\n\n## Troubleshooting\n\n- Check logs: `xr_driver_cli --view-log`\n- Confirm the socket is bound (example):\n\n  ```bash\n  ss -u -lpn | grep 4242\n  ```\n\n- If it binds but never connects, confirm OpenTrack is actually sending UDP packets to the correct IP/port.\n"
  },
  {
    "path": "docs/requirements.txt",
    "content": "mkdocs>=1.6.0\nmkdocs-material>=9.5.0\npymdown-extensions>=10.8\n"
  },
  {
    "path": "fpm/build",
    "content": "#!/usr/bin/env bash\n\n# exit when any command fails\nset -e\n\nUSER=${SUDO_USER:-$USER}\nGROUP=$(id -gn $USER)\n\nsource bin/inject_ua\n\nif [ -z \"$UA_API_SECRET\" ] && [ -z \"$UA_API_SECRET_INTENTIONALLY_EMPTY\" ]; then\n  echo \"UA_API_SECRET isn't set. If this is intentional, set UA_API_SECRET_INTENTIONALLY_EMPTY to a non-empty value.\"\n  exit 1\nfi\n\nARCH=$(uname -m)\necho \"Building for $ARCH\"\n\n# build the driver\nBUILD_PATH=build\nif [ ! -d \"$BUILD_PATH\" ]; then\n  mkdir $BUILD_PATH\nfi\n\npushd $BUILD_PATH\ncmake ..\nmake\n\n# create package\nPACKAGE_DIR=xr_driver\nPACKAGE_BIN_DIR=$PACKAGE_DIR/bin\nmkdir -p $PACKAGE_BIN_DIR\n\n# copy bin files\nmv xrDriver $PACKAGE_BIN_DIR\ncp ../bin/xr_driver_cli $PACKAGE_BIN_DIR\n\n# copy the systemd files needed to run our service\ncp -r ../systemd $PACKAGE_DIR\nsed -i -e '/ExecStart/c\\ExecStart=xrDriver' \\\n    -e '/WantedBy/c\\WantedBy=default.target' \\\n    -e '/Environment/d' \\\n    $PACKAGE_DIR/systemd/xr-driver.service\ncp -r ../udev $PACKAGE_DIR\n\n# copy the shared library files\nif [ ! -d \"$PACKAGE_DIR/lib\" ]; then\n  mkdir $PACKAGE_DIR/lib\nfi\ncp ../lib/$ARCH/*.so $PACKAGE_DIR/lib || true\n\npopd\n\nexit 0"
  },
  {
    "path": "fpm/postinstall",
    "content": "#!/usr/bin/env bash\n\nif ! lsmod | grep -q uinput; then\n    echo \"Setting up uinput kernel module\"\n    modprobe uinput\nfi\n\nif [ -x \"$(command -v udevadm)\" ]; then\n    udevadm control --reload-rules\n    udevadm trigger\nfi\n\n# Try multiple methods to detect the real user\nSUDO_USER=\"${SUDO_USER:-}\"\nDBUS_USER=\"${DBUS_SESSION_BUS_ADDRESS%%,*}\"\nDBUS_USER=\"${DBUS_USER#unix:user=}\"\nX11_USER=$(who | grep -F '(:0)' | head -n1 | cut -d' ' -f1)\n\n# Try each method in order of preference\nREAL_USER=\"${SUDO_USER:-${X11_USER:-$DBUS_USER}}\"\n\nif [ -n \"$REAL_USER\" ] && [ -x \"$(command -v systemctl)\" ]; then\n    REAL_UID=$(id -u \"$REAL_USER\")\n    XDG_RUNTIME_DIR=\"/run/user/$REAL_UID\"\n    echo \"Setting up the systemd service for $REAL_USER ($XDG_RUNTIME_DIR)\"\n    OUTPUT=$(su -l --shell /bin/sh -c \"export XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR; systemctl --user daemon-reload && systemctl --user start xr-driver\" \"$REAL_USER\" 2>&1)\n    EXIT_CODE=$?\n    if [ $EXIT_CODE -ne 0 ]; then\n        echo \"Command failed with exit code $EXIT_CODE. Output was:\"\n        echo \"$OUTPUT\"\n        exit $EXIT_CODE\n    fi\nelse\n    echo \"Unable to detect user, skipping systemd service restart\"\n    echo \"Debug info: SUDO_USER=$SUDO_USER, X11_USER=$X11_USER, DBUS_USER=$DBUS_USER\"\nfi\n\nexit 0"
  },
  {
    "path": "fpm/postupgrade",
    "content": "#!/usr/bin/env bash\n\nif [ -x \"$(command -v udevadm)\" ]; then\n    udevadm control --reload-rules\n    udevadm trigger\nfi\n\n# Try multiple methods to detect the real user\nSUDO_USER=\"${SUDO_USER:-}\"\nDBUS_USER=\"${DBUS_SESSION_BUS_ADDRESS%%,*}\"\nDBUS_USER=\"${DBUS_USER#unix:user=}\"\nX11_USER=$(who | grep -F '(:0)' | head -n1 | cut -d' ' -f1)\n\n# Try each method in order of preference\nREAL_USER=\"${SUDO_USER:-${X11_USER:-$DBUS_USER}}\"\n\nif [ -n \"$REAL_USER\" ] && [ -x \"$(command -v systemctl)\" ]; then\n    REAL_UID=$(id -u \"$REAL_USER\")\n    XDG_RUNTIME_DIR=\"/run/user/$REAL_UID\"\n    echo \"Setting up the systemd service for $REAL_USER ($XDG_RUNTIME_DIR)\"\n    OUTPUT=$(su -l --shell /bin/sh -c \"export XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR; systemctl --user daemon-reload && systemctl --user restart xr-driver\" \"$REAL_USER\" 2>&1)\n    EXIT_CODE=$?\n    if [ $EXIT_CODE -ne 0 ]; then\n        echo \"Command failed with exit code $EXIT_CODE. Output was:\"\n        echo \"$OUTPUT\"\n        exit $EXIT_CODE\n    fi\nelse\n    echo \"Unable to detect user, skipping systemd service restart\"\nfi\n\nexit 0"
  },
  {
    "path": "fpm/preinstall",
    "content": "#!/usr/bin/env bash\n\n# Try multiple methods to detect the real user\nSUDO_USER=\"${SUDO_USER:-}\"\nDBUS_USER=\"${DBUS_SESSION_BUS_ADDRESS%%,*}\"\nDBUS_USER=\"${DBUS_USER#unix:user=}\"\nX11_USER=$(who | grep -F '(:0)' | head -n1 | cut -d' ' -f1)\n\n# Try each method in order of preference\nREAL_USER=\"${SUDO_USER:-${X11_USER:-$DBUS_USER}}\"\n\nif [ -n \"$REAL_USER\" ]; then\n    REAL_UID=$(id -u \"$REAL_USER\")\n    USER_HOME=$(getent passwd $REAL_USER | cut -d: -f6)\n\n    if [ -f \"$USER_HOME/.local/bin/breezy_gnome_uninstall\" ]; then\n        echo \"Uninstalling old Breezy GNOME setup\"\n        $USER_HOME/.local/bin/breezy_gnome_uninstall\n    fi\n    \n    if [ -f \"$USER_HOME/.local/bin/breezy_vulkan_uninstall\" ]; then\n        echo \"Uninstalling old Breezy Vulkan setup\"\n        $USER_HOME/.local/bin/breezy_vulkan_uninstall\n    fi\n    \n    if [ -f \"$USER_HOME/.local/bin/xr_driver_uninstall\" ]; then\n        echo \"Uninstalling old XR Driver setup\"\n        $USER_HOME/.local/bin/xr_driver_uninstall\n    fi\nelse\n    echo \"Unable to detect user, skipping xr_driver_uninstall check\"\n    echo \"Debug info: SUDO_USER=$SUDO_USER, X11_USER=$X11_USER, DBUS_USER=$DBUS_USER\"\nfi\n\nexit 0"
  },
  {
    "path": "fpm/preuninstall",
    "content": "#!/usr/bin/env bash\n\n# Try multiple methods to detect the real user\nSUDO_USER=\"${SUDO_USER:-}\"\nDBUS_USER=\"${DBUS_SESSION_BUS_ADDRESS%%,*}\"\nDBUS_USER=\"${DBUS_USER#unix:user=}\"\nX11_USER=$(who | grep -F '(:0)' | head -n1 | cut -d' ' -f1)\n\n# Try each method in order of preference\nREAL_USER=\"${SUDO_USER:-${X11_USER:-$DBUS_USER}}\"\n\nif [ -n \"$REAL_USER\" ] && [ -x \"$(command -v systemctl)\" ]; then\n    REAL_UID=$(id -u \"$REAL_USER\")\n    XDG_RUNTIME_DIR=\"/run/user/$REAL_UID\"\n    echo \"Stopping the systemd service for $REAL_USER ($XDG_RUNTIME_DIR)\"\n    OUTPUT=$(su -l --shell /bin/sh -c \"export XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR; systemctl --user stop xr-driver && systemctl --user disable xr-driver\" \"$REAL_USER\" 2>&1)\n    EXIT_CODE=$?\n    if [ $EXIT_CODE -ne 0 ]; then\n        echo \"Command failed with exit code $EXIT_CODE. Output was:\"\n        echo \"$OUTPUT\"\n        exit $EXIT_CODE\n    fi\nelse\n    echo \"Unable to detect user, skipping systemd service restart\"\nfi\n\nrm -f /tmp/shader_runtime_*\nrm -f /dev/shm/xr_*\nrm -f /dev/shm/breezy_desktop_imu\n\nexit 0"
  },
  {
    "path": "include/buffer.h",
    "content": "#pragma once\n\n#include <imu.h>\n#include <stdbool.h>\n\n#define GYRO_BUFFERS_COUNT 5 // quat values: x, y, z, w, timestamp\n\nstruct buffer_t {\n    int size;\n    float* values;\n    int index;\n    int count;\n};\n\ntypedef struct buffer_t buffer_type;\n\nstruct imu_buffer_t {\n    buffer_type **stage_1;\n    buffer_type **stage_2;\n};\n\ntypedef struct imu_buffer_t imu_buffer_type;\n\nstruct imu_buffer_response_t {\n    bool ready;\n    float *data;\n};\n\ntypedef struct imu_buffer_response_t imu_buffer_response_type;\n\nbuffer_type *create_buffer(int size);\nvoid free_buffer(buffer_type *buffer);\n\nbool is_full(buffer_type *buffer);\n\n// push a new value, pop the oldest value and return it\nfloat push(buffer_type *buffer, float next_value);\n\nimu_buffer_type *create_imu_buffer(int buffer_size);\nvoid free_imu_buffer(imu_buffer_type *gyro_buffer);\nint imu_buffer_size(imu_buffer_type *gyro_buffer);\n\nimu_buffer_response_type *push_to_imu_buffer(imu_buffer_type *gyro_buffer, imu_quat_type quat, float timestamp_ms);"
  },
  {
    "path": "include/config.h",
    "content": "#pragma once\n\n#include <stdbool.h>\n#include <stdio.h>\n\nstruct driver_config_t {\n    bool disabled;\n    bool mouse_mode;\n    bool joystick_mode;\n    bool external_mode;\n    bool use_roll_axis;\n    bool vr_lite_invert_x;\n    bool vr_lite_invert_y;\n    int mouse_sensitivity;\n    char *output_mode;\n    bool multi_tap_enabled;\n    bool metrics_disabled;\n    float dead_zone_threshold_deg;\n\n    bool debug_threads;\n    bool debug_joystick;\n    bool debug_multi_tap;\n    bool debug_ipc;\n    bool debug_license;\n    bool debug_device;\n    bool debug_connections;\n};\n\ntypedef struct driver_config_t driver_config_type;\n\nextern const char *joystick_output_mode;\nextern const char *mouse_output_mode;\nextern const char *external_only_output_mode;\n\ndriver_config_type *default_config();\nvoid update_config(driver_config_type *config, driver_config_type *new_config);\ndriver_config_type* parse_config_file(FILE *fp);\n\nvoid boolean_config(char* key, char *value, bool *config_value);\nvoid float_config(char* key, char *value, float *config_value);\nvoid int_config(char* key, char *value, int *config_value);\nvoid string_config(char* key, char *value, char **config_value);"
  },
  {
    "path": "include/connection_pool.h",
    "content": "#pragma once\n\n#include \"devices.h\"\n#include \"imu.h\"\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdint.h>\n\ntypedef struct connection_t {\n    const device_driver_type* driver;\n    device_properties_type* device; // owned by pool\n    bool supplemental;\n    bool active;\n    pthread_t thread;\n    bool thread_running;\n} connection_t;\n\nstruct connection_pool_t {\n    pthread_mutex_t mutex;\n    connection_t** list;\n    int count;\n    int capacity;\n    int primary_index;      // index in list or -1\n    int supplemental_index; // index in list or -1\n};\n\n// Connection pool type that manages multiple device connections.\ntypedef struct connection_pool_t connection_pool_type;\n\n// Create/destroy a connection pool instance\ntypedef void (*pose_handler_t)(imu_pose_type pose);\ntypedef bool (*reference_pose_getter_t)(imu_pose_type* out_pose, bool* pose_updated);\nvoid connection_pool_init(pose_handler_t pose_handler_callback, reference_pose_getter_t reference_pose_getter);\n\n// Append a new connection (driver + device). The pool retains the driver pointer and\n// takes ownership of the device pointer. It will decide whether to make it the primary\n// (non-supplemental) or use it as a supplemental connection.\nvoid connection_pool_handle_device_added(const device_driver_type* driver, device_properties_type* device);\n\n// Delegate helpers the main driver uses (these generally forward to the primary connection)\nbool connection_pool_is_connected();\nbool connection_pool_device_is_sbs_mode();\nbool connection_pool_device_set_sbs_mode(bool enabled);\nvoid connection_pool_disconnect_all(bool soft);\n\n// Start blocking on active connections (primary and at most one supplemental). This function\n// will create per-connection threads and return when the primary connection stops blocking\n// (e.g., due to disconnect).\nvoid connection_pool_block_on_active();\n\n// Attempt to connect active connections (primary and, if present, supplemental). Returns true\n// if the primary connection connected successfully (supplemental is best-effort).\nbool connection_pool_connect_active();\n\n// Get the current primary device properties (borrowed; do not free). Returns NULL if none.\ndevice_properties_type* connection_pool_primary_device();\ndevice_properties_type* connection_pool_supplemental_device();\n\n// Get the primary driver pointer (borrowed; do not free). Returns NULL if none.\nconst device_driver_type* connection_pool_primary_driver();\n\n// Remove a connection by its unique source id. If the removed connection is currently\n// primary or supplemental, the pool will re-evaluate selection. If a thread is running for the\n// removed connection, it will be disconnected; cleanup occurs when the thread exits.\nvoid connection_pool_handle_device_removed(const char* driver_id);\n\nconnection_t* connection_pool_find_hid_connection(uint16_t id_vendor, int16_t id_product);\nconnection_t* connection_pool_find_driver_connection(const char* driver_id);\n\nvoid connection_pool_ingest_pose(const char* driver_id, imu_pose_type pose);\n\n// Returns true if the given driver id is currently the primary connection\nbool connection_pool_is_primary_driver_id(const char* driver_id);"
  },
  {
    "path": "include/curl.h",
    "content": "#pragma once\n\nvoid curl_init();\n\nvoid curl_cleanup();\n"
  },
  {
    "path": "include/devices/rayneo.h",
    "content": "#pragma once\n\nextern const device_properties_type rayneo_properties;\nextern const device_driver_type rayneo_driver;"
  },
  {
    "path": "include/devices/rokid.h",
    "content": "#pragma once\n\nextern const device_properties_type rokid_properties;\nextern const device_driver_type rokid_driver;"
  },
  {
    "path": "include/devices/viture.h",
    "content": "#pragma once\n\n#include <stdbool.h>\n#include <stdint.h>\n\n#include \"devices.h\"\n#include \"imu.h\"\n\nextern const device_properties_type viture_one_properties;\nextern const device_driver_type viture_driver;"
  },
  {
    "path": "include/devices/xreal.h",
    "content": "#pragma once\n\nextern const device_properties_type xreal_air_properties;\nextern const device_driver_type xreal_driver;"
  },
  {
    "path": "include/devices.h",
    "content": "#pragma once\n\n\n#include <stdbool.h>\n#include <stdint.h>\n\nenum calibration_setup_t {\n    CALIBRATION_SETUP_AUTOMATIC,\n    CALIBRATION_SETUP_INTERACTIVE\n};\ntypedef enum calibration_setup_t calibration_setup_type;\n\n// Standard display resolutions\n#define RESOLUTION_1080P_W 1920\n#define RESOLUTION_1080P_H 1080\n#define RESOLUTION_1200P_W 1920\n#define RESOLUTION_1200P_H 1200\n\n// distance from the pivot point (neck) to the lenses, in cm, typically ~5 inches\n#define LENS_TO_PIVOT_CM (5.0f * 2.54f)\n\nstruct device_properties_t {\n    char* brand;\n    char* model;\n\n    // USB information\n    int hid_vendor_id;\n    int hid_product_id;\n    uint8_t usb_bus;\n    uint8_t usb_address;\n\n    calibration_setup_type calibration_setup;\n\n    // resolution width and height\n    int resolution_w;\n    int resolution_h;\n\n    // FOV for diagonal, in degrees\n    float fov;\n\n    // ratio representing (from the center of the axes of rotation): lens distance / perceived display distance\n    float lens_distance_ratio;\n\n    int calibration_wait_s;\n\n    int imu_cycles_per_s;\n\n    // how many events to buffer for velocity smoothing\n    int imu_buffer_size;\n\n    // look-ahead = look_ahead_ftm * frametime + look_ahead_constant\n    // where frametime is the duration of a frame e.g. 33ms for 30Hz framerate\n    float look_ahead_constant;\n    float look_ahead_frametime_multiplier;\n\n    // if top and bottom rows of the display require different look-ahead\n    float look_ahead_scanline_adjust;\n\n    // maximum look-ahead for best experience, the shader may also provide an upper bound\n    float look_ahead_ms_cap;\n\n    bool sbs_mode_supported;\n    bool firmware_update_recommended;\n\n    // Tracking capabilities exposed by this device\n    bool provides_orientation; // 3DoF available\n    bool provides_position;    // 6DoF available\n    \n    // Whether this device may be used as a supplemental device alongside a primary one.\n    // When true, the driver may be run in a supplemental mode and will not be registered\n    // as the primary runtime device in the global context.\n    bool can_be_supplemental;\n};\n\ntypedef struct device_properties_t device_properties_type;\n\n// if this driver supports the device, return the device properties, otherwise NULL\ntypedef device_properties_type* (*supported_device_func)(uint16_t id_vendor, uint16_t id_product, uint8_t usb_bus, uint8_t usb_address);\n\n// open device connection, expected to perform cleanup on failure\ntypedef bool (*device_connect_func)();\n\n// hold open the connection while the device is present and disconnect_func has not been called\ntypedef void (*block_on_device_func)();\n\n// return true if device is in SBS mode\ntypedef bool (*device_is_sbs_mode_func)();\n\n// set SBS mode on device, return true on success\ntypedef bool (*device_set_sbs_mode_func)(bool enabled);\n\n// whether the driver is currently holding open a connection to the device\ntypedef bool (*is_connected_func)();\n\n// tells the driver to release its connection to the device, `soft` describes whether this is a \n// software-only disconnect, true means the device is still physically connected\ntypedef void (*disconnect_func)(bool soft);\n\nstruct device_driver_t {\n    char* id;\n    supported_device_func supported_device_func;\n    device_connect_func device_connect_func;\n    block_on_device_func block_on_device_func;\n    device_is_sbs_mode_func device_is_sbs_mode_func;\n    device_set_sbs_mode_func device_set_sbs_mode_func;\n    is_connected_func is_connected_func;\n    disconnect_func disconnect_func;\n};\n\ntypedef struct device_driver_t device_driver_type;\n\nstruct connected_device_t {\n    const device_driver_type* driver;\n    device_properties_type* device;\n};\n\ntypedef struct connected_device_t connected_device_type;\n\nbool device_equal(device_properties_type* device, device_properties_type* device2);\n\nvoid handle_device_connection_changed(bool is_added, connected_device_type* device);\n\nvoid init_devices();\n\nvoid deinit_devices();\n\nconnected_device_type* find_connected_device();\n\nvoid handle_device_connection_events();"
  },
  {
    "path": "include/driver.h",
    "content": "#pragma once\n\n#include \"devices.h\"\n#include \"imu.h\"\n\n#include <stdbool.h>\n#include <stdint.h>\n\n\nbool driver_reference_pose(imu_pose_type* out_pose, bool* pose_updated);\nvoid driver_handle_pose(imu_pose_type pose);\nbool driver_disabled();"
  },
  {
    "path": "include/epoch.h",
    "content": "#pragma once\n\n#include <stdint.h>\n\nuint64_t get_epoch_time_ms();"
  },
  {
    "path": "include/features/breezy_desktop.h",
    "content": "#include <stdbool.h>\n\nextern const char* productivity_basic_feature_name;\nextern const char* productivity_pro_feature_name;\n\nbool is_productivity_basic_granted();\nbool is_productivity_pro_granted();\nbool is_productivity_granted();\nvoid reset_productivity_features();"
  },
  {
    "path": "include/features/sbs.h",
    "content": "#include <stdbool.h>\n\nextern const char* sbs_feature_name;\n\nbool is_sbs_granted();\nvoid reset_sbs_features();"
  },
  {
    "path": "include/features/smooth_follow.h",
    "content": "#include <stdbool.h>\n\nextern const char* smooth_follow_feature_name;\n\nbool is_smooth_follow_granted();\nvoid reset_smooth_follow_features();"
  },
  {
    "path": "include/files.h",
    "content": "#pragma once\n\n#include <stdio.h>\n#include <stdbool.h>\n#include <sys/stat.h>\n\nextern const char* XDG_STATE_ENV_VAR;\nextern const char* XDG_RUNTIME_ENV_VAR;\nextern const char* XDG_CONFIG_ENV_VAR;\nextern const char* XDG_DATA_ENV_VAR;\nextern const char* XDG_STATE_FALLBACK_DIR;\nextern const char* XDG_CONFIG_FALLBACK_DIR;\nextern const char* XDG_RUNTIME_FALLBACK_DIR;\nextern const char* XDG_DATA_FALLBACK_DIR;\n\nchar* get_xdg_file_path_for_app(const char *app_name, const char *filename, const char *xdg_env_var, const char *xdg_fallback_dir);\n\nchar* get_state_file_path(const char *filename);\n\nchar* get_runtime_file_path(const char *filename);\n\nchar* get_config_file_path(const char *filename);\n\nFILE* get_or_create_file(const char *full_path, mode_t directory_mode, const char *file_mode, bool *file_created);\n\nFILE* get_or_create_state_file(const char *filename, const char *mode, char **full_path, bool *created);\n\nFILE* get_or_create_runtime_file(const char *filename, const char *mode, char **full_path, bool *created);\n\nFILE* get_or_create_config_file(const char *filename, const char *mode, char **full_path, bool *created);\n\n"
  },
  {
    "path": "include/imu.h",
    "content": "#pragma once\n\n#include <stdbool.h>\n#include <stdint.h>\n\nstruct imu_euler_t {\n\tfloat roll;\n\tfloat pitch;\n\tfloat yaw;\n};\n\nstruct imu_quat_t {\n\tfloat x;\n\tfloat y;\n\tfloat z;\n\tfloat w;\n};\n\nstruct imu_vec3_t {\n\tfloat x;\n\tfloat y;\n\tfloat z;\n};\n\nstruct imu_pose_t {\n\tstruct imu_quat_t orientation;\n\tstruct imu_vec3_t position;\n\tstruct imu_euler_t euler;\n\tbool has_orientation;\n\tbool has_position;\n\tuint32_t timestamp_ms;\n};\n\nextern const float pose_orientation_reset_data[16];\nextern const float pose_position_reset_data[3];\n\ntypedef struct imu_euler_t imu_euler_type;\ntypedef struct imu_quat_t imu_quat_type;\ntypedef struct imu_vec3_t imu_vec3_type;\ntypedef struct imu_pose_t imu_pose_type;\n\nfloat degree_to_radian(float deg);\nfloat radian_to_degree(float rad);\nimu_quat_type normalize_quaternion(imu_quat_type q);\nimu_quat_type conjugate(imu_quat_type q);\nimu_quat_type multiply_quaternions(imu_quat_type q1, imu_quat_type q2);\nimu_quat_type euler_to_quaternion_xyz(imu_euler_type euler);\nimu_quat_type euler_to_quaternion_zyx(imu_euler_type euler);\nimu_quat_type euler_to_quaternion_zxy(imu_euler_type euler);\nimu_euler_type quaternion_to_euler_xyz(imu_quat_type q);\nimu_euler_type quaternion_to_euler_zyx(imu_quat_type q);\nimu_euler_type quaternion_to_euler_zxy(imu_quat_type q);\nimu_quat_type device_pitch_adjustment(float adjustment_degrees);\nimu_vec3_type vector_rotate(imu_vec3_type v, imu_quat_type q);\nbool quat_equal(imu_quat_type q1, imu_quat_type q2);\n\nstatic inline void imu_pose_sync_euler_from_orientation(imu_pose_type *p) {\n\tif (!p) return;\n\tif (p->has_orientation) {\n\t\tp->euler = quaternion_to_euler_zyx(p->orientation);\n\t}\n}\nstatic inline void imu_pose_sync_orientation_from_euler(imu_pose_type *p) {\n\tif (!p) return;\n\tif (p->has_orientation) {\n\t\tp->orientation = euler_to_quaternion_zyx(p->euler);\n\t}\n}\n\nfloat quat_small_angle_rad(imu_quat_type q1, imu_quat_type q2);"
  },
  {
    "path": "include/ipc.h",
    "content": "#pragma once\n\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdio.h>\n\n// TODO - this is specific to the sombrero integration, either provide no default or move to a plug-in system where\n//        the plug-in library would be expected to provide this default, if this functionality is used\nextern const char *sombrero_ipc_file_prefix;\n\nextern const char *display_res_ipc_name;\nextern const char *disabled_ipc_name;\nextern const char *date_ipc_name;\nextern const char *pose_orientation_ipc_name;\nextern const char *pose_orientation_mutex_ipc_name;\nextern const char *pose_position_data_ipc_name;\n\n// deprecated - can be removed once this version is widely distributed\nextern const char *display_fov_ipc_name;\nextern const char *lens_distance_ratio_ipc_name;\n\nstruct ipc_values_t {\n    float *display_res;\n    bool *disabled;\n    float *date;\n    float *pose_orientation;\n    float *pose_position;\n    pthread_mutex_t *pose_orientation_mutex;\n\n    float *display_fov;\n    float *lens_distance_ratio;\n};\n\ntypedef struct ipc_values_t ipc_values_type;\n\nbool setup_ipc_values(ipc_values_type *ipc_values, bool debug);\n\nvoid setup_ipc_value(const char *name, void **shmemValue, size_t size, bool debug);\n\nvoid cleanup_ipc(char* file_prefix, bool debug);"
  },
  {
    "path": "include/logging.h",
    "content": "#pragma once\n\nvoid log_init();\nvoid log_message(const char* format, ...);\nvoid log_error(const char* format, ...);\nvoid log_debug(const char* format, ...);"
  },
  {
    "path": "include/memory.h",
    "content": "#pragma once\n\n#include <stdlib.h>\n\n#define free_and_clear(ptr) do { \\\n\tif (ptr != NULL && *ptr != NULL) { \\\n\t\tfree(*ptr); \\\n\t\t*ptr = NULL; \\\n\t} \\\n} while(0)\n\n// Free an array of strings\nstatic inline void free_string_array(char** array, int count) {\n    if (!array) return;\n    for (int i = 0; i < count; i++) {\n        free(array[i]);\n    }\n    free(array);\n}"
  },
  {
    "path": "include/multitap.h",
    "content": "#pragma once\n\n#include \"imu.h\"\n\n#include <stdbool.h>\n#include <stdint.h>\n\nvoid init_multi_tap(int init_imu_cycles_per_s);\n\nint detect_multi_tap(imu_euler_type velocities, uint32_t timestamp, bool debug);"
  },
  {
    "path": "include/outputs.h",
    "content": "#pragma once\n\n#include \"imu.h\"\n#include \"ipc.h\"\n\n#include <stdbool.h>\n#include <stdint.h>\n\n#define MS_PER_SEC 1000\n#define IMU_CHECKPOINT_MS MS_PER_SEC / 4\n\nvoid init_outputs();\n\nvoid deinit_outputs();\n\nvoid reinit_outputs();\n\n// return the rate-of-change of the euler value against the previous euler value, in degrees/sec\nimu_euler_type get_euler_velocities(imu_euler_type* previous, imu_euler_type current, int imu_cycles_per_sec);\n\nvoid handle_imu_update(imu_pose_type pose, imu_euler_type velocities, bool imu_calibrated, ipc_values_type *ipc_values);\nvoid reset_pose_data(ipc_values_type *ipc_values);\n\nbool wait_for_imu_start();\nbool is_imu_alive();"
  },
  {
    "path": "include/plugins/breezy_desktop.h",
    "content": "#pragma once\n\n#include \"plugins.h\"\n\nstruct breezy_desktop_config_t {\n    bool enabled;\n    float look_ahead_override;\n    float display_distance;\n    float display_size;\n    bool sbs_content;\n    bool sbs_mode_stretched;\n};\ntypedef struct breezy_desktop_config_t breezy_desktop_config;\n\nextern const plugin_type breezy_desktop_plugin;"
  },
  {
    "path": "include/plugins/custom_banner.h",
    "content": "#pragma once\n\n#include \"plugins.h\"\n\nstruct custom_banner_ipc_values_t {\n    bool *enabled;\n};\ntypedef struct custom_banner_ipc_values_t custom_banner_ipc_values_type;\n\nextern custom_banner_ipc_values_type *custom_banner_ipc_values;\nextern const plugin_type custom_banner_plugin;"
  },
  {
    "path": "include/plugins/device_license.h",
    "content": "#pragma once\n\n#include \"plugins.h\"\n\nextern const plugin_type device_license_plugin;"
  },
  {
    "path": "include/plugins/gamescope_reshade_wayland.h",
    "content": "#pragma once\n\n#include \"plugins.h\"\n\n#include <stdbool.h>\n#include <stddef.h>\n\nstruct gamescope_reshade_wayland_config_t {\n    bool disabled;\n};\ntypedef struct gamescope_reshade_wayland_config_t gamescope_reshade_wayland_config;\n\ntypedef void (*gamescope_reshade_effect_ready_callback)();\n\nbool is_gamescope_reshade_ipc_connected();\n\nvoid set_gamescope_reshade_effect_uniform_variable(const char *variable_name, const void *data, int entries, size_t size, bool flush);\n\n// will skip if there's already a lock on the wayland client, for values that are set repeatedly, like IMU data\nvoid set_skippable_gamescope_reshade_effect_uniform_variable(const char *variable_name, const void *data, int entries, size_t size, bool flush);\n\nextern const plugin_type gamescope_reshade_wayland_plugin;"
  },
  {
    "path": "include/plugins/metrics.h",
    "content": "#pragma once\n\n#include \"plugins.h\"\n\nextern const plugin_type metrics_plugin;"
  },
  {
    "path": "include/plugins/neck_saver.h",
    "content": "#pragma once\n#include \"plugins.h\"\n\ntypedef struct neck_saver_config_t {\n    float horizontal_multiplier; // applied to yaw (rotation about up axis)\n    float vertical_multiplier;   // applied to pitch (rotation about east/west axis)\n} neck_saver_config_type;\n\nextern const plugin_type neck_saver_plugin;\n"
  },
  {
    "path": "include/plugins/opentrack_listener.h",
    "content": "#pragma once\n\n#include <stdbool.h>\n#include \"plugins.h\"\n\nstruct opentrack_listener_config_t {\n\tbool enabled;\n\tchar *ip;\n\tint port;\n};\ntypedef struct opentrack_listener_config_t opentrack_listener_config;\n\nextern const plugin_type opentrack_listener_plugin;\n"
  },
  {
    "path": "include/plugins/opentrack_source.h",
    "content": "#pragma once\n\n#include <stdbool.h>\n#include \"plugins.h\"\n\nstruct opentrack_source_config_t {\n    bool enabled;\n    char *ip;\n    int port;\n};\ntypedef struct opentrack_source_config_t opentrack_source_config;\n\nextern const plugin_type opentrack_source_plugin;\n"
  },
  {
    "path": "include/plugins/sideview.h",
    "content": "#pragma once\n\n#include \"plugins.h\"\n\n#define SIDEVIEW_POSITION_COUNT 5\nextern const char *sideview_position_names[SIDEVIEW_POSITION_COUNT];\n\nstruct sideview_ipc_values_t {\n    bool *enabled;\n    float *position;\n};\ntypedef struct sideview_ipc_values_t sideview_ipc_values_type;\n\nstruct sideview_config_t {\n    bool enabled;\n    int position;\n    bool smooth_follow_enabled;\n};\ntypedef struct sideview_config_t sideview_config;\n\nextern const plugin_type sideview_plugin;"
  },
  {
    "path": "include/plugins/smooth_follow.h",
    "content": "#pragma once\n\n#include \"plugins.h\"\n\n#include <stdint.h>\n\nstruct smooth_follow_ipc_values_t {\n    bool *enabled;\n};\ntypedef struct smooth_follow_ipc_values_t smooth_follow_ipc_values_type;\n\nstruct smooth_follow_config_t {\n    bool virtual_display_enabled;\n    bool virtual_display_follow_enabled;\n    bool sideview_enabled;\n    bool sideview_follow_enabled;\n    float sideview_follow_threshold;\n    bool breezy_desktop_enabled;\n    float display_distance;\n    float display_size;\n\n    bool track_roll;\n    bool track_pitch; // vertical\n    bool track_yaw; // horizontal\n};\ntypedef struct smooth_follow_config_t smooth_follow_config;\n\nstruct smooth_follow_params_t {\n    // The distance threshold at which a time-delayed trigger will begin counting down\n    float lower_angle_threshold;\n    uint32_t delay_ms;\n\n    // The distance threshold at which movement is immediately triggered\n    float upper_angle_threshold;\n\n    // The angle to slerp to once a threshold is triggered\n    float return_to_angle;\n\n    // value is compounding, so 1.0 - pow(1.0 - interpolation_ratio_ms, 1000) is the effective ratio for a full second,\n    // closer to 1.0 means faster acceleration towards the current position\n    float interpolation_ratio_ms;\n};\ntypedef struct smooth_follow_params_t smooth_follow_params;\n\nextern const plugin_type smooth_follow_plugin;"
  },
  {
    "path": "include/plugins/virtual_display.h",
    "content": "#pragma once\n\n#include \"plugins.h\"\n\nextern const char *virtual_display_look_ahead_cfg_ipc_name;\nextern const char *virtual_display_display_size_ipc_name;\nextern const char *virtual_display_display_north_offset_ipc_name;\nextern const char *virtual_display_sbs_enabled_ipc_name;\nextern const char *virtual_display_sbs_content_ipc_name;\nextern const char *virtual_display_sbs_mode_stretched_ipc_name;\nextern const char *virtual_display_curved_display_ipc_name;\nextern const char *virtual_display_half_fov_z_rads_ipc_name;\nextern const char *virtual_display_half_fov_y_rads_ipc_name;\nextern const char *virtual_display_fov_half_widths_ipc_name;\nextern const char *virtual_display_fov_widths_ipc_name;\nextern const char *virtual_display_texcoord_x_limits_ipc_name;\nextern const char *virtual_display_texcoord_x_limits_r_ipc_name;\nextern const char *virtual_display_lens_vector_ipc_name;\nextern const char *virtual_display_lens_vector_r_ipc_name;\n\nstruct virtual_display_ipc_values_t {\n    bool *enabled;\n    bool *show_banner;\n    float *look_ahead_cfg;\n    float *display_size;\n    float *display_north_offset;\n    bool *sbs_enabled;\n    bool *sbs_content;\n    bool *sbs_mode_stretched;\n    bool *curved_display;\n    float *half_fov_z_rads;\n    float *half_fov_y_rads;\n    float *fov_half_widths;\n    float *fov_widths;\n    float *texcoord_x_limits;\n    float *texcoord_x_limits_r;\n    float *lens_vector;\n    float *lens_vector_r;\n};\ntypedef struct virtual_display_ipc_values_t virtual_display_ipc_values_type;\n\nstruct virtual_display_config_t {\n    bool enabled;\n    float look_ahead_override;\n    float display_size;\n    float display_distance;\n    bool sbs_content;\n    bool sbs_mode_stretched;\n    bool follow_mode_enabled;\n    bool passthrough_smooth_follow_enabled;\n    bool curved_display;\n};\ntypedef struct virtual_display_config_t virtual_display_config;\n\nextern const plugin_type virtual_display_plugin;"
  },
  {
    "path": "include/plugins.h",
    "content": "#pragma once\n\n#include \"imu.h\"\n#include \"ipc.h\"\n\n#include <stdbool.h>\n#include <stdint.h>\n\n// config and control flag parsing/handling functions\ntypedef void* (*default_config_func)();\ntypedef void (*handle_config_line_func)(void* config, char* key, char* value);\ntypedef void (*handle_control_flag_line_func)(char* key, char* value);\ntypedef void (*set_config_func)(void* config);\n\n// hook functions\ntypedef void (*start_func)();\n\ntypedef bool (*setup_ipc_func)();\ntypedef void (*handle_ipc_change_func)();\ntypedef bool (*modify_reference_pose_func)(imu_pose_type pose, imu_pose_type* ref_pose);\ntypedef void (*handle_reference_pose_updated_func)(imu_pose_type old_reference_pose, imu_pose_type new_reference_pose);\ntypedef void (*modify_pose_func)(imu_pose_type* pose);\ntypedef void (*handle_pose_data_func)(imu_pose_type pose, imu_euler_type velocities, bool imu_calibrated, ipc_values_type *ipc_values);\ntypedef void (*reset_pose_data_func)();\ntypedef void (*handle_state_func)();\ntypedef void (*handle_device_connect_func)();\ntypedef void (*handle_device_disconnect_func)();\n\nstruct plugin_t {\n    char* id;\n\n    start_func start;\n\n    default_config_func default_config;\n    handle_config_line_func handle_config_line;\n    handle_control_flag_line_func handle_control_flag_line;\n    set_config_func set_config;\n\n    setup_ipc_func setup_ipc;\n    handle_ipc_change_func handle_ipc_change;\n    modify_reference_pose_func modify_reference_pose;\n    handle_reference_pose_updated_func handle_reference_pose_updated;\n    modify_pose_func modify_pose;\n    handle_pose_data_func handle_pose_data;\n    reset_pose_data_func reset_pose_data;\n    handle_state_func handle_state;\n    handle_device_connect_func handle_device_connect;\n    handle_device_disconnect_func handle_device_disconnect;\n\n    // TODO handle feature access change\n};\ntypedef struct plugin_t plugin_type;\n\nextern const plugin_type plugins;"
  },
  {
    "path": "include/runtime_context.h",
    "content": "#pragma once\n\n#include \"config.h\"\n#include \"connection_pool.h\"\n#include \"devices.h\"\n#include \"state.h\"\n\nstruct runtime_context_t {\n    // user-controlled, read-only driver configurations (plugin configs not present), persistent\n    driver_config_type *config;\n\n    // properties of the currently connected device, modified only by the device driver module\n    device_properties_type *device;\n\n    // live view of the state of the driver, reflects real-world state, not intentions\n    driver_state_type *state;\n\n    connection_pool_type *conn_pool;\n};\n\ntypedef struct runtime_context_t runtime_context;\n\n// Global runtime context instance.\n// This is intentionally exposed so the most frequently-called accessors below can be\n// `static inline` and compile down to a single load/store even without LTO.\nextern runtime_context g_runtime_context;\n\nstatic inline void set_state(driver_state_type *state) {\n    g_runtime_context.state = state;\n}\n\nstatic inline driver_state_type* state(void) {\n    return g_runtime_context.state;\n}\n\nstatic inline void set_config(driver_config_type *config) {\n    g_runtime_context.config = config;\n}\n\nstatic inline driver_config_type* config(void) {\n    return g_runtime_context.config;\n}\n\nstatic inline void set_connection_pool(connection_pool_type *pool) {\n    g_runtime_context.conn_pool = pool;\n}\n\nstatic inline connection_pool_type* connection_pool(void) {\n    return g_runtime_context.conn_pool;\n}\n\n// device is so heavily used across threads that it becomes difficult to find a good time to free() it,\n// so the below functions keep a reference count and free it when the count reaches 0\n//\n// if a device is already set, this will queue it and set it after the current device is released.\n// once set, it's considered checked out by the setting thread and the reference count is initialized at 1\nvoid set_device_and_checkout(device_properties_type *device);\n\n// returns the current device properties and increments the reference count\ndevice_properties_type* device_checkout();\n\n// decrements the reference count for the current device properties, releasing the device if the count reaches 0\nvoid device_checkin(device_properties_type* device);\n\nbool device_present();\n\ntypedef void (*on_device_change_callback)();\n\nvoid set_on_device_change_callback(on_device_change_callback callback);"
  },
  {
    "path": "include/sdks/rayneo.h",
    "content": "#ifndef XR_MINI_SDK_H\n#define XR_MINI_SDK_H\n\n#include \"base/FXRError.h\"\n#include \"base/FXRMacro.h\"\n#include \"device/usb/XRDeviceState.h\"\n\nvoid RegisterIMUEventCallback(IMUEventCallback callback);\n\nvoid UnregisterIMUEventCallback(IMUEventCallback callback);\n\nvoid RegisterStateEventCallback(StateEventCallback callback);\n\nvoid UnregisterStateEventCallback(StateEventCallback callback);\n\nint EstablishUsbConnection(int32_t vid, int32_t pid);\n\nint ResetUsbConnection();\n\nvoid NotifyDeviceConnected();\n\nvoid NotifyDeviceDisconnected();\n\nvoid StartXR();\n\nvoid StopXR();\n\nvoid SwitchTo2D();\n\nvoid SwitchTo3D();\n\nvoid OpenIMU();\n\nvoid CloseIMU();\n\nvoid Recenter();\n\nvoid GetHeadTrackerPose(float rotation[4], float position[3], uint64_t* timeNsInDevice);\n\nuint64_t ConvertHostTime2DeviceTime(uint64_t timeNsInHost);\n\nvoid GetDeviceType(char* device);\n\nvoid AcquireDeviceInfo();\n\nint8_t GetSideBySideStatus();\n#endif"
  },
  {
    "path": "include/sdks/rokid.h",
    "content": "//\n// Created by 曾滔 on 6/8/21.\n//\n\n#ifndef _GLASS_SDK_H_\n#define _GLASS_SDK_H_\n\n#define GLASS_SDK_NATIVE_VERSION \"2.1.9\"\n#define ROKID_GLASS_VID (1234)\n\n/*\n * Sensor Event Type.\n */\nenum EVENT_TYPE{\n    ACC_EVENT = 0x1<<0,\n    GYRO_EVENT =  0x1<<1,\n    FUSION_EVENT= 0x1<<2,\n    KEY_EVENT= 0x1<<3,\n    P_SENSOR_EVENT= 0x1<<4,\n    TOUCH_EVENT = 0x1<<5,\n    ROTATION_EVENT=0x1<<6,\n    GAME_ROTATION_EVENT=0x1<<7,\n    L_SENSOR_EVENT = 0x1<<8,\n    MAGNET_EVENT = 0x1<<9,\n    VSYNC_EVENT = 0x1<<10,\n    RAW_EVENT=0x1<<31,\n};\n\n/*\n * Represent a vector in 3D space.\n */\ntypedef struct Axes{\n    double x;\n    double y;\n    double z;\n}_Axes;\n\n/*\n * Sensor Data Type.\n */\ntypedef struct SensorData {\n    uint64_t system_timestamp; // timestamp in nanoseconds when it's received (phone clock)\n    uint64_t sensor_timestamp_ns; // sensor timestamp in nanoseconds (glass clock)\n    uint32_t sequence; // reserved\n    struct Axes data; // sensor data\n}_SensorData;\n\n/*\n * Represent fusion data, including accelerometer, gyroscope, and magnetometer data.\n * deprecated\n */\ntypedef struct FusionData{\n    uint64_t system_timestamp;\n    uint64_t sensor_timestamp_ns;\n    uint32_t sequence;\n    struct Axes acc;\n    struct Axes gyro;\n    struct Axes magnet;\n}_FusionData;\n\n/*\n * Represent rotation vector and game rotation vector\n */\ntypedef struct RotationData{\n    uint64_t system_timestamp; // timestamp in nanoseconds when it's received (phone clock)\n    uint64_t sensor_timestamp_ns; // sensor timestamp in nanoseconds (glass clock)\n    uint32_t sequence; // reserved\n    float Q[4]; // sensor data in quaternion\n    int status; // reserved\n}_RotationData;\n\n/*\n * Represent key data\n * deprecated\n */\ntypedef struct KeyData{\n    int keyCode;\n    bool status;\n}_KeyData;\n\n/*\n * Represent event data\n * deprecated\n */\ntypedef struct EventData{\n    uint32_t type;\n    union{\n        struct SensorData acc; // Accelerometer data\n        struct SensorData gyro; // Gyroscope data\n        struct SensorData magnet; // Magnetometer data\n        struct FusionData imu; // FusionData, reserved\n        struct RotationData rotation; // Rotation data\n        uint64_t vsync_timestamp_ns; // VSync timestamp in nanoseconds\n        int KeyData; // Key data, reserved\n        bool pSensor; // Proximity sensor data, reserved\n        uint8_t raw_data[64]; // Raw data in 64 bytes\n    };\n}_EventData;\n\n\n/* Get usb context\n * Call after GlassEventInit or GlassControlInit\n *\n * \\returns libusb_context*\n */\nvoid* _Z21GlassSDKGetUsbContextv();\n\n/* Init glass event and create instance\n *\n * \\returns glass event instance\n */\nvoid* _Z14GlassEventInitv(void);\n\n/*\n * Open glass event instance with fd\n *\n * \\param handle a glass event instance\n * \\param fd the new file descriptor\n * \\returns true on success, false on failure\n */\nbool  _Z14GlassEventOpenPvi(void* handle, int fd);\n\n/*\n * Open glass event instance with vid and pid\n *\n * \\param handle a glass event instance\n * \\param vid usb vendor id\n * \\param pid usb product id\n * \\returns true on success, false on failure\n */\nbool  _Z14GlassEventOpenPvii(void* handle, int vid, int pid);\n\n/*\n * Close glass event instance\n *\n * \\param handle a glass event instance\n * \\returns true on success, false on failure\n */\nbool  _Z15GlassEventClosePv(void* handle);\n\n/*\n * Release glass event instance\n *\n * \\param handle a glass event instance\n * \\returns true on success, false on failure\n */\nbool  _Z17GlassEventReleasePv(void* handle);\n\n/*event queue interface*/\n/*\n * Register sensor event with required type\n *\n * \\param handle a glass event instance\n * \\param EVENT_TYPE the sensor event type\n * \\returns a registered event\n */\nvoid *GlassRegisterEvent(void* handle, enum EVENT_TYPE type);\n/*\n * Register sensor event with required type and size\n *\n * \\param handle a glass event instance\n * \\param type the sensor event type\n * \\param size the event number\n * \\returns a registered event\n */\nvoid *_Z26GlassRegisterEventWithSizePv10EVENT_TYPEi(void* handle, enum EVENT_TYPE type, int size);\n\n/*\n * UnRegister sensor event\n *\n * \\param handle a glass event instance\n * \\param type the sensor event type\n * \\returns true on success, false on failure\n */\nbool _Z20GlassUnRegisterEventPvS_(void* handle, void* eventHandle);\n\n/*\n * Get sensor event\n *\n * \\param handle a glass event instance\n * \\param eventHandle the sensor event handle\n * \\param data the event data\n * \\param timeout operation timed out\n * \\returns true on success, false on failure\n */\nbool  _Z14GlassWaitEventPvS_P9EventDatai(void* handle, void* eventHandle, struct EventData* data, int timeout);\n\n/*\n * Get sensor event\n *\n * \\param handle a glass event instance\n * \\param eventHandle the sensor event handle\n * \\param data the event data\n * \\param timeout operation timed out\n * \\returns 0  get event success\n *          1  timeout\n *          -1 GlassEvent closed\n *          -2 invalid param or GlassEventRelease\n */\nint   _Z14GlassWaitEventPvS_P9EventDatai2(void* handle, void* ehandle, struct EventData* data, int timeout);\n\n/*\n * enable or close fusion event\n *\n * \\param handle a glass event instance\n * \\param enable whether enable the fusion event or not\n */\nvoid  _Z14AddFusionEventPvi(void* handle, int enable);\n\n\n/* Init glass control and create instance\n *\n * \\returns glass control instance\n */\nvoid* _Z16GlassControlInitv   (void);\n\n/*\n * Open glass control instance with fd\n *\n * \\param handle a glass control instance\n * \\param fd the new file descriptor\n * \\returns true on success, false on failure\n */\nbool  _Z16GlassControlOpenPvi   (void* handle, int fd);\n\n/*\n * Open glass control instance with fd\n *\n * \\param handle a glass control instance\n * \\param vid usb vendor id\n * \\param pid usb product id\n * \\returns true on success, false on failure\n */\nbool  _Z16GlassControlOpenPvii   (void* handle, int vid, int pid);\n\n/*\n * Close glass control instance\n *\n * \\param handle a glass control instance\n * \\returns true on success, false on failure\n */\nbool  _Z17GlassControlClosePv  (void* handle);\n\n/*\n * Release glass control instance\n *\n * \\param handle a glass control instance\n * \\returns true on success, false on failure\n */\nbool  _Z19GlassControlReleasePv(void* handle);\n\n/*\n * Glass control interface\n */\n\n/*\n * Set glass display mode\n *\n * \\param handle a glass control instance\n * \\param mode\n *          0   2D_3840*1080_60Hz\n *          1   3D_3840*1080_60Hz\n *          2   SBS //deprecated in some devices\n *          3   deprecated\n *          4   3D_3840*1200_90Hz\n *          5   3D_3840*1200_60Hz\n * \\returns true on success, false on failure\n */\nbool _Z19GlassSetDisplayModePvi(void*handle, int mode);\n\n/*\n * Set glass volume\n *\n * \\param handle a glass control instance\n * \\param volume range from 0 to 100\n * \\returns true on success, false on failure\n */\nbool  SetVolume          (void*handle, int level);\n\n/*\n * Set glass brightness\n *\n * \\param handle a glass control instance\n * \\param channel always 0\n * \\param level range from 0 to 100\n * \\returns true on success, false on failure\n */\nbool  SetBrightness      (void*handle, int channel, int level);\n\n/*\n * Get glass vsync status\n *\n * \\param handle a glass control instance\n * \\returns\n *      true    glass display is on\n *      false   glass display is off\n */\nbool  GetVsyncStatus     (void*handle);\n\n/*\n * Sync glass timestamp in us (glass clock) with target device(phone clock)\n * deprecated\n *\n * \\param handle a glass control instance\n * \\returns true on success, false on failure\n */\nbool  GlassSyncTimeStamp (void*handle);\n\n/*\n * Get glass brightness\n *\n * \\param handle a glass control instance\n * \\param channel always 0\n * \\returns brightness, see \\ref SetBrightness\n */\nint   GetBrightness      (void*handle, int channel);\n\n/*\n * Get glass volume\n *\n * \\param handle a glass control instance\n * \\returns volume, see \\ref SetVolume\n */\nint   GetVolume          (void*handle);\n\n/*\n * Get glass display mode\n *\n * \\param handle a glass control instance\n * \\returns display mode, see \\ref GetDisplayMode\n */\nint   _Z14GetDisplayModePv     (void*handle);\n\n/*\n * Get glass serial number\n *\n * \\param handle a glass control instance\n * \\returns serial number in char*\n */\nchar*  GetSerialNumber   (void*handle);\n\n/*\n * Get glass seed\n *\n * \\param handle a glass control instance\n * \\returns seed in char*\n */\nchar*  GetSeed           (void*handle);\n\n/*\n * Get glass firmware version\n *\n * \\param handle a glass control instance\n * \\returns firmware version in char*\n */\nchar*  GetFirmwareVersion(void*handle);\n\n/*\n * Get glass hardware version\n *\n * \\param handle a glass control instance\n * \\returns hardware version in char*\n */\nchar*  GetHardwareVersion(void*handle);\n\n/*\n * Get glass product name\n *\n * \\param handle a glass control instance\n * \\returns product name in char*\n */\nchar*  _Z14GetProductNamePv(void* handle);\n\n/*\n * Get glass product id\n *\n * \\param handle a glass control instance\n * \\returns product id in char*\n */\nint GetProductId(void* handle);\n\n/*\n * Get glass vendor id\n *\n * \\param handle a glass control instance\n * \\returns vendor id in char*\n */\nint GetVendorId(void* handle);\n\n/*\n * Get timestamp in nano to sync glass time & phone time\n *\n * for example:\n *      long long delta_t_glass_to_phone = sysTimestamp - hmdTimestamp;\n *      long long timestamp = curTimestamp + detla_t_glass_to_phone;\n *\n * curTimestamp means actual timestamp in nano (imu or camera on phone clock)\n * timestamp means calculated timestamp in nano, reflect glass clock sensor data to phone clock\n *\n * \\param handle a glass control instance\n * \\param hmdTimestamp [out] glass timestamp in nano\n * \\param sysTimestamp [out] phone timestamp in nano\n * \\returns true on success, false on failure\n */\nint GlassGetTimeNano(void *handle, long long *hmdTimestamp, long long *sysTimestamp);\n\n\n// redefine the mangled function names here so we can use the API as intended\ntypedef bool (*GlassControlCloseFunc)(void* handle);\ntypedef bool (*GlassControlReleaseFunc)(void* handle);\ntypedef void* (*GlassControlInitFunc)(void);\ntypedef bool (*GlassControlOpenFunc)(void* handle, int vid, int pid);\ntypedef bool (*GlassSetDisplayModeFunc)(void* handle, int mode);\ntypedef void* (*GlassEventInitFunc)(void);\ntypedef void* (*GlassRegisterEventWithSizeFunc)(void* handle, enum EVENT_TYPE type, int size);\ntypedef bool (*GlassUnRegisterEventFunc)(void* handle, void* eventHandle);\ntypedef bool (*GlassWaitEventFunc)(void* handle, void* eventHandle, struct EventData* data, int timeout);\ntypedef void* (*GlassSDKGetUsbContextFunc)(void);\ntypedef void (*GlassAddFusionEventFunc)(void* handle, int enable);\ntypedef bool (*GlassEventOpenFunc)(void* handle, int vid, int pid);\ntypedef bool (*GlassEventCloseFunc)(void* handle);\ntypedef int (*GetDisplayModeFunc)(void* handle);\ntypedef char* (*GetProductNameFunc)(void* handle);\n\nextern GlassControlCloseFunc GlassControlClose;\nextern GlassControlReleaseFunc GlassControlRelease;\nextern GlassControlInitFunc GlassControlInit;\nextern GlassControlOpenFunc GlassControlOpen;\nextern GlassSetDisplayModeFunc GlassSetDisplayMode;\nextern GlassEventInitFunc GlassEventInit;\nextern GlassRegisterEventWithSizeFunc GlassRegisterEventWithSize;\nextern GlassUnRegisterEventFunc GlassUnRegisterEvent;\nextern GlassWaitEventFunc GlassWaitEvent;\nextern GlassSDKGetUsbContextFunc GlassSDKGetUsbContext;\nextern GlassAddFusionEventFunc GlassAddFusionEvent;\nextern GlassEventOpenFunc GlassEventOpen;\nextern GlassEventCloseFunc GlassEventClose;\nextern GetDisplayModeFunc GetDisplayMode;\nextern GetProductNameFunc GetProductName;\n\n// retrieved using readelf (e.g. `readelf -W -s lib/x86_64/libGlassSDK.so  | grep GlassControlClose`)\n#define GlassControlClose ((GlassControlCloseFunc)_Z17GlassControlClosePv)\n#define GlassControlRelease ((GlassControlReleaseFunc)_Z19GlassControlReleasePv)\n#define GlassControlInit ((GlassControlInitFunc)_Z16GlassControlInitv)\n#define GlassControlOpen ((GlassControlOpenFunc)_Z16GlassControlOpenPvii)\n#define GlassSetDisplayMode ((GlassSetDisplayModeFunc)_Z19GlassSetDisplayModePvi)\n#define GlassEventInit ((GlassEventInitFunc)_Z14GlassEventInitv)\n#define GlassRegisterEventWithSize ((GlassRegisterEventWithSizeFunc)_Z26GlassRegisterEventWithSizePv10EVENT_TYPEi)\n#define GlassUnRegisterEvent ((GlassUnRegisterEventFunc)_Z20GlassUnRegisterEventPvS_)\n#define GlassWaitEvent ((GlassWaitEventFunc)_Z14GlassWaitEventPvS_P9EventDatai)\n#define GlassSDKGetUsbContext ((GlassSDKGetUsbContextFunc)_Z21GlassSDKGetUsbContextv)\n#define GlassAddFusionEvent ((GlassAddFusionEventFunc)_Z14AddFusionEventPvi)\n#define GlassEventOpen ((GlassEventOpenFunc)_Z14GlassEventOpenPvii)\n#define GlassEventClose ((GlassEventCloseFunc)_Z15GlassEventClosePv)\n#define GetDisplayMode ((GetDisplayModeFunc)_Z14GetDisplayModePv)\n#define GetProductName ((GetProductNameFunc)_Z14GetProductNamePv)\n\n#endif //_GLASS_SDK_H_"
  },
  {
    "path": "include/sdks/viture_device.h",
    "content": "/**\n * @file\n * @brief Non-carina device API and callback types.\n * @copyright 2025 VITURE Inc. All rights reserved.\n *\n * These callbacks are only applicable when the provider was created\n * for `XR_DEVICE_TYPE_VITURE_GEN1` or `XR_DEVICE_TYPE_VITURE_GEN2`.\n */\n\n#ifndef VITURE_DEVICE_H\n#define VITURE_DEVICE_H\n\n#include \"viture_glasses_provider.h\"\n\n/**\n * @brief Callback function type for imu raw data.\n *\n * @param data      Pointer to raw data buffer (device-defined layout).\n * @param timestamp Timestamp in device timebase for IMU sample.\n * @param vsync     VSync timestamp associated with the sample.\n *\n * Should be set before calling open_imu with Imu::Mode::MODE_RAW\n * Data format:\n * 1. Viture One / Pro / Lite: [gyroscope_raw_x, gyroscope_raw_y, gyroscope_raw_z,\n *                              accelerometer_raw_x, accelerometer_raw_y, accelerometer_raw_z,\n *                              0, 0, 0,\n *                              temperature]\n * 2. Viture Luma / Luma Pro / Beast:  [gyroscope_raw_x, gyroscope_raw_y, gyroscope_raw_z,\n *                                      accelerometer_raw_x, accelerometer_raw_y, accelerometer_raw_z,\n *                                      magnetometer_raw_x, magnetometer_raw_y, magnetometer_raw_z,\n *                                      temperature]\n */\ntypedef void (*VitureImuRawCallback)(float* data, uint64_t timestamp, uint64_t vsync);\n\n/**\n * @brief Callback function type for imu pose data.\n *\n * @param data      Pointer to pose data buffer\n * @param timestamp Timestamp in device timebase for IMU sample.\n *\n * Should be set before calling open_imu with Imu::Mode::MODE_POSE\n * Data format: [roll, pitch, yaw, quaternion_0, quaternion_1, quaternion_2, quaternion_3]\n */\ntypedef void (*VitureImuPoseCallback)(float* data, uint64_t timestamp);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @brief Register imu raw data callback.\n *\n * This function associates a user-provided callback with the device\n * identified by `handle`. The callback will be invoked from the internal\n * imu read thread when imu raw data is available.\n *\n * @param handle           Handle to the `XRDeviceProvider` instance.\n * @param imu_raw_callback Callback function pointer.\n * @return 0 on success, -1 on failure.\n */\nVITURE_API int register_raw_callback(XRDeviceProviderHandle handle, VitureImuRawCallback imu_raw_callback);\n\n/**\n * @brief Register a combined IMU + VSync callback for a Viture device.\n *\n * This function associates a user-provided callback with the device\n * identified by `handle`. The callback will be invoked from the internal\n * imu read thread when imu pose data is available.\n *\n * @param handle            Handle to the `XRDeviceProvider` instance.\n * @param imu_pose_callback Callback function pointer.\n * @return 0 on success, -1 on failure.\n */\nVITURE_API int register_pose_callback(XRDeviceProviderHandle handle, VitureImuPoseCallback imu_pose_callback);\n\n/**\n * @brief Open imu (no effect for carina device)\n * @param handle Handle to the XRDeviceProvider instance\n * @param imu_mode viture::protocol::imu::Mode\n * @param imu_report_frequency viture::protocol::imu::Frequency\n * @return 0: Success, -1: Param error, -2: USB execution error\n * @return -3: Device type not supported, -4: Other error\n */\nVITURE_API int open_imu(XRDeviceProviderHandle handle, uint8_t imu_mode, uint8_t imu_report_frequency);\n\n/**\n * @brief Close IMU (no effect for Carina device)\n * @param handle Handle to the XRDeviceProvider instance\n * @param imu_mode viture::protocol::imu::Mode\n * @return 0: Success, -1: Param error, -2: USB execution error\n * @return -3: Device type not supported, -4: Other error\n */\nVITURE_API int close_imu(XRDeviceProviderHandle handle, uint8_t imu_mode);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // VITURE_DEVICE_H\n"
  },
  {
    "path": "include/sdks/viture_device_carina.h",
    "content": "/**\n * @file\n * @brief Carina-specific device API and callback types.\n * @copyright 2025 VITURE Inc. All rights reserved.\n *\n * The Carina device (Viture Luma Ultra) provides higher-level callbacks for\n * pose, IMU, VSync and camera frames. These callbacks are only applicable\n * when the provider was created for `XR_DEVICE_TYPE_VITURE_CARINA`.\n */\n\n#ifndef VITURE_DEVICE_CARINA_H\n#define VITURE_DEVICE_CARINA_H\n\n#include \"viture_glasses_provider.h\"\n\n/**\n * @brief Callback invoked when a new pose sample is available.\n *\n * @param pose      Array of 7 floats: position (x,y,z) and quaternion (w,x,y,z).\n * @param timestamp Monotonic timestamp in seconds.\n */\ntypedef void (*XRPoseCallback)(float* pose, double timestamp);\n\n/**\n * @brief VSync notification callback.\n *\n * @param timestamp Monotonic timestamp in seconds when VSync occurred.\n */\ntypedef void (*XRVSyncCallback)(double timestamp);\n\n/**\n * @brief IMU data callback for Carina device.\n *\n * @param imu       Pointer to IMU buffer (device-defined layout).\n * @param timestamp Timestamp in seconds for the IMU sample.\n */\ntypedef void (*XRImuCallback)(float* imu, double timestamp);\n\n/**\n * @brief Camera frame callback for stereo frames.\n *\n * @param image_left0   Pointer to left image buffer (frame 0).\n * @param image_right0  Pointer to right image buffer (frame 0).\n * @param image_left1   Pointer to left image buffer (frame 1).\n * @param image_right1  Pointer to right image buffer (frame 1).\n * @param timestamp     Frame timestamp.\n * @param width         Frame width in pixels.\n * @param height        Frame height in pixels.\n */\ntypedef void (*XRCameraCallback)(char* image_left0,\n                                 char* image_right0,\n                                 char* image_left1,\n                                 char* image_right1,\n                                 double timestamp,\n                                 int width,\n                                 int height);\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @brief Register callbacks for a Carina device instance.\n *\n * Callbacks registered here are ignored for devices that are not\n * `XR_DEVICE_TYPE_VITURE_CARINA`.\n *\n * @param handle         Opaque device provider handle.\n * @param pose_callback  Callback for pose samples.\n * @param vsync_callback Callback for VSync events.\n * @param imu_callback   Callback for IMU samples.\n * @param camera_callback Callback for stereo camera frames.\n * @return 0 on success, -1 on failure.\n */\nVITURE_API int register_callbacks_carina(XRDeviceProviderHandle handle,\n                                         XRPoseCallback pose_callback,\n                                         XRVSyncCallback vsync_callback,\n                                         XRImuCallback imu_callback,\n                                         XRCameraCallback camera_callback);\n\n/**\n * @brief Reset position\n * @param handle Handle to the XRDeviceProvider instance\n * @return 0 on success, -1 on failure\n */\nVITURE_API int reset_pose_carina(XRDeviceProviderHandle handle);\n\n/**\n * @brief Get IMU pose data with prediction time (Twb matrix in OpenGL coordinate system: x -> right, y -> up, z -> backward)\n * @param handle Handle to the XRDeviceProvider instance\n * @param pose Array to store pose data (7 floats for position and quaternion)\n * @param predict_time Prediction time in nanoseconds, 0 for current pose data\n * @return 0 on success, -1 on failure\n */\nVITURE_API int get_gl_pose_carina(XRDeviceProviderHandle handle, float* pose, double predict_time);\n\n/**\n * Toggle glasses status report\n * @param handle Handle to the XRDeviceProvider instance\n * @param toggle Enable / disable\n * @return 0 on success\n */\nVITURE_API int toggle_status_report_carina(XRDeviceProviderHandle handle, bool toggle);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // VITURE_DEVICE_CARINA_H\n"
  },
  {
    "path": "include/sdks/viture_glasses_constants.h",
    "content": "#ifndef VITURE_GLASSES_CONSTANTS_H\n#define VITURE_GLASSES_CONSTANTS_H\n\n#include <cstdint>\n\nnamespace viture {\nnamespace product {\nnamespace VendorId {\nconstexpr std::uint16_t VITURE = 0x35CA;\n} // namespace VendorId\n} // namespace product\n} // namespace viture\n\n#endif // VITURE_GLASSES_CONSTANTS_H\n"
  },
  {
    "path": "include/sdks/viture_glasses_provider.h",
    "content": "/**\n * @file\n * @brief Public C API for Viture Glasses device providers.\n * @copyright 2025 VITURE Inc. All rights reserved.\n *\n * This header defines the public C API used to create, control and query\n * XR device provider instances. It provides lifecycle functions, command\n * submission entry points, and callback registration for external clients.\n */\n\n#ifndef VITURE_GLASSES_PROVIDER_H\n#define VITURE_GLASSES_PROVIDER_H\n\n#include \"viture_macros.h\"\n\n/**\n * @brief Handle type for XRDeviceProvider instances. This is an opaque pointer\n * returned by `xr_device_provider_create` and consumed by other API calls.\n */\ntypedef void* XRDeviceProviderHandle;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @brief Callback for reporting glass state changes (brightness, volume, display mode, etc.)\n *\n * See `viture::protocol::Callback::ID` for detailed id and values\n *\n * @param glass_state_id  Identifier for the state being reported.\n * @param glass_value     Integer value associated with the state.\n */\ntypedef void (*GlassStateCallback)(int glass_state_id, int glass_value);\n\n/**\n * @brief Device types supported by the SDK.\n *\n * Use these values to determine device-specific behavior after creating an\n * `XRDeviceProvider` instance, e.g. registering callbacks.\n */\ntypedef enum {\n    XR_DEVICE_TYPE_VITURE_GEN1 = 0,\n    XR_DEVICE_TYPE_VITURE_GEN2 = 1,\n    XR_DEVICE_TYPE_VITURE_CARINA = 2\n} XRDeviceType;\n\n#ifdef __ANDROID__\n/**\n * @brief Android variant: Create an XRDeviceProvider instance\n *\n * Due to Android restrictions, detailed usb information is needed for creation\n *\n * @param product_id Product ID of the opened usb device\n * @param file_descriptor File descriptor of the opened usb device\n * @param bus_num Bus number for viture carina device\n * @param dev_addr Device address for viture carina device\n * @return Handle to the created instance, or NULL on failure\n */\nVITURE_API XRDeviceProviderHandle xr_device_provider_create(int product_id,\n                                                            int file_descriptor,\n                                                            int bus_num,\n                                                            int dev_addr);\n#else\n/**\n * @brief Non-Android variant: Create an XRDeviceProvider instance\n *\n * The non-Android signature accepts only `product_id`\n *\n * @param product_id Product ID of the opened usb device\n * @return Handle to the created instance, or NULL on failure\n */\nVITURE_API XRDeviceProviderHandle xr_device_provider_create(int product_id);\n#endif\n\n/**\n * @brief Initialize the XRDeviceProvider\n * @param handle Handle to the XRDeviceProvider instance\n * @param custom_config Optional custom configuration string (can be NULL)\n * @return 0: Success, -1: Param error, -2: Other error\n */\nVITURE_API int xr_device_provider_initialize(XRDeviceProviderHandle handle, const char* custom_config);\n\n/**\n * @brief Start the XRDeviceProvider\n * @param handle Handle to the XRDeviceProvider instance\n * @return 0: Success, -1: Param error, -2: Other error\n */\nVITURE_API int xr_device_provider_start(XRDeviceProviderHandle handle);\n\n/**\n * @brief Stop the XRDeviceProvider\n * @param handle Handle to the XRDeviceProvider instance\n * @return 0: Success, -1: Param error, -2: Other error\n */\nVITURE_API int xr_device_provider_stop(XRDeviceProviderHandle handle);\n\n/**\n * @brief Shutdown the XRDeviceProvider\n * @param handle Handle to the XRDeviceProvider instance\n * @return 0: Success, -1: Param error, -2: Other error\n */\nVITURE_API int xr_device_provider_shutdown(XRDeviceProviderHandle handle);\n\n/**\n * @brief Destroy the XRDeviceProvider instance\n * @param handle Handle to the XRDeviceProvider instance\n */\nVITURE_API void xr_device_provider_destroy(XRDeviceProviderHandle handle);\n\n/**\n * @brief Register glass state callback\n * @param handle Handle to the XRDeviceProvider instance\n * @param callback Called when glass state changes\n * @return 0: Success, -1: Param error, -2: USB not available, -3: Other error\n */\nVITURE_API int xr_device_provider_register_state_callback(XRDeviceProviderHandle handle, GlassStateCallback callback);\n\n/**\n * @brief Execute a USB control command synchronously\n * @param handle Handle to the XRDeviceProvider instance\n * @param msgId Message ID for the command\n * @param data Command data to send\n * @param length Length of the command data\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: Other error\n */\nVITURE_API int xr_device_provider_execute_usb_command(XRDeviceProviderHandle handle,\n                                                      int msgId,\n                                                      const char* data,\n                                                      int length);\n\n/**\n * @brief Execute a USB control command synchronously and return response data\n * @param handle Handle to the XRDeviceProvider instance\n * @param msgId Message ID for the command\n * @param data Command data to send\n * @param length Length of the command data\n * @param response_data Buffer to store response data\n * @param response_length Pointer to store the length of response data\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: Result cast success but execution is not success\n * @return -5: Result not casteded and execution is not success, -6: Other error\n */\nVITURE_API int xr_device_provider_execute_usb_command_with_response(\n    XRDeviceProviderHandle handle, int msgId, const char* data, int length, char* response_data, int* response_length);\n\n/**\n * @brief Get electrochomic film mode synchronously\n * @param handle Handle to the XRDeviceProvider instance\n * @param voltage Pointer to store voltage data.\n *                Gen1 devices: 0.0F / 1.0F;\n *                Gen2 devices: 0F / 0.125F ... / 0.875F / 1.0F.\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: Other error\n */\nVITURE_API int xr_device_provider_get_film_mode(XRDeviceProviderHandle handle, float* voltage);\n\n/**\n * @brief Set electrochomic film mode synchronously\n * @param handle Handle to the XRDeviceProvider instance\n * @param voltage Voltage parameter (0.0 - 1.0). Interpretation differs by\n *                generation: on Gen1 a non-zero value enables the film;\n *                Gen2 uses ranges to map to discrete levels.\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: Other error\n */\nVITURE_API int xr_device_provider_set_film_mode(XRDeviceProviderHandle handle, float voltage);\n\n/**\n * @brief Get screen duty cycle\n * @param handle Handle to the XRDeviceProvider instance\n * @return Duty cycle value, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: No valid data, -5: Other error\n */\nVITURE_API int xr_device_provider_get_duty_cycle(XRDeviceProviderHandle handle);\n\n/**\n * @brief Set screen duty cycle\n * @param handle Handle to the XRDeviceProvider instance\n * @param duty_cycle Duty cycle value (0-100)\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: Duty cycle value incorrect, -5: Other error\n */\nVITURE_API int xr_device_provider_set_duty_cycle(XRDeviceProviderHandle handle, int duty_cycle);\n\n/**\n * @brief Get display mode\n * @param handle Handle to the XRDeviceProvider instance\n * @return Display mode value (see viture::protocol::DisplayMode), -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: No valid data, -5: Other error\n */\nVITURE_API int xr_device_provider_get_display_mode(XRDeviceProviderHandle handle);\n\n/**\n * @brief Set display mode synchronously\n * @param handle Handle to the XRDeviceProvider instance\n * @param display_mode Display mode value (see viture::protocol::DisplayMode)\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: Display mode value incorrect, -4: USB execution error\n * @return -5: Other error\n */\nVITURE_API int xr_device_provider_set_display_mode(XRDeviceProviderHandle handle, int display_mode);\n\n/**\n * @brief Get display mode and native dof type (only for devices with native 3DOF, e.g. Viture Beast)\n * @param handle Handle to the XRDeviceProvider instance\n * @param display_mode Pointer to store display mode data\n * @param dof_type Pointer to store dof data\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: Interface not support for device, -4: USB execution error\n * @return -5: No valid data, -6: Other error\n */\nVITURE_API int xr_device_provider_get_display_mode_and_native_dof(XRDeviceProviderHandle handle,\n                                                                  int* display_mode,\n                                                                  int* dof_type);\n\n/**\n * @brief Set display mode and dof type (only for devices with native 3DOF, e.g. Viture Beast)\n * @param handle Handle to the XRDeviceProvider instance\n * @param display_mode Display mode value\n * @param dof_type Dof value\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: Interface not support for device, -4: Display mode value incorrect\n * @return -5: USB execution error, -6: Other error\n */\nVITURE_API int xr_device_provider_set_display_mode_and_native_dof(XRDeviceProviderHandle handle,\n                                                                  int display_mode,\n                                                                  int dof_type);\n\n/**\n * @brief Get display distance (only for Viture Beast)\n * @param handle Handle to the XRDeviceProvider instance\n * @param distance Pointer to store display distance data\n * @return [1, 10]: Success, -1: Param error, -2: USB not available\n * @return -3: Interface not support for device, -4: USB execution error\n * @return -5: No valid data, -6: Other error\n */\nVITURE_API int xr_device_provider_get_display_distance(XRDeviceProviderHandle handle);\n\n/**\n * @brief Set display distance (only for Viture Beast)\n * @param handle Handle to the XRDeviceProvider instance\n * @param distance Range [1, 10]\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: Interface not support for device, -4: Display mode value incorrect\n * @return -5: USB execution error, -6: Other error\n */\nVITURE_API int xr_device_provider_set_display_distance(XRDeviceProviderHandle handle, int distance);\n\n/**\n * @brief Get display mode and native dof type (only for devices with native 3DOF, e.g. Viture Beast)\n * @param handle Handle to the XRDeviceProvider instance\n * @return [0, 4]: Success (viture::protocol::DisplaySize), -1: Param error, -2: USB not available\n * @return -3: Interface not support for device, -4: USB execution error\n * @return -5: No valid data, -6: Other error\n */\nVITURE_API int xr_device_provider_get_display_size(XRDeviceProviderHandle handle);\n\n/**\n * @brief Set display size (only for Viture Beast)\n * @param handle Handle to the XRDeviceProvider instance\n * @param size See viture::protocol::DisplaySize\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: Interface not support for device, -4: Display mode value incorrect\n * @return -5: USB execution error, -6: Other error\n */\nVITURE_API int xr_device_provider_set_display_size(XRDeviceProviderHandle handle, int size);\n\n/**\n * @brief Recenter display (only for devices with native 3DOF, e.g. Viture Beast)\n * @param handle Handle to the XRDeviceProvider instance\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: Interface not support for device, -4: USB execution error\n * @return -5: Other error\n */\nVITURE_API int xr_device_provider_native_dof_recenter(XRDeviceProviderHandle handle);\n\n/**\n * @brief Switch between 2D (1920 x 1080 @ 60Hz) / 3D (3840 x 1080 @ 60Hz)\n *\n * If higher resolution or refresh rate is needed, use xr_device_provider_set_display_mode\n * Note that when already at the same display mode and refresh rate, the return\n * is 0 and nothing will happen\n *\n * @param handle Handle to the XRDeviceProvider instance\n * @param is_3d true: switch to 3D, false: switch to 2D\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: Display mode value incorrect, -4: USB execution error\n * @return -5: Other error\n */\nVITURE_API int xr_device_provider_switch_dimension(XRDeviceProviderHandle handle, bool is_3d);\n\n/**\n * @brief Get screen brightness level\n * @param handle Handle to the XRDeviceProvider instance\n * @return Brightness level, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: Response length incorrect\n * @return -5: Response cast error, -6: Other error\n */\nVITURE_API int xr_device_provider_get_brightness_level(XRDeviceProviderHandle handle);\n\n/**\n * @brief Set screen brightness level\n * @param handle Handle to the XRDeviceProvider instance\n * @param level Brightness level to set\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: Other error\n */\nVITURE_API int xr_device_provider_set_brightness_level(XRDeviceProviderHandle handle, int level);\n\n/**\n * @brief Get speaker volume level\n * @param handle Handle to the XRDeviceProvider instance\n * @return Volume level, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: Other error\n */\nVITURE_API int xr_device_provider_get_volume_level(XRDeviceProviderHandle handle);\n\n/**\n * @brief Set speaker volume level\n * @param handle Handle to the XRDeviceProvider instance\n * @param level Volume level to set\n * @return 0: Success, -1: Param error, -2: USB not available\n * @return -3: USB execution error, -4: Response length incorrect,\n * @return -5: Response cast error, -6: Other error\n */\nVITURE_API int xr_device_provider_set_volume_level(XRDeviceProviderHandle handle, int level);\n\n/**\n * @brief Get the device type\n * @param handle Handle to the XRDeviceProvider instance\n * @return XRDeviceType enum value, or -1 on failure\n */\nVITURE_API int xr_device_provider_get_device_type(XRDeviceProviderHandle handle);\n\n/**\n * @brief Get glasses firmware version\n * @param handle Handle to the XRDeviceProvider instance\n * @param response Store response\n * @param length Store response length\n * @return 0: Success, -1: Parameter error, -2: USB protocol not available\n * @return -3: USB response error, -4: No valid data, -5: Exception happened\n */\nVITURE_API int xr_device_provider_get_glasses_version(XRDeviceProviderHandle handle, char* response, int* length);\n\n/**\n * Check if product id is valid\n * @param product_id Product id to check\n * @return Product id is valid or not\n */\nVITURE_API bool xr_device_provider_is_product_id_valid(int product_id);\n\n/**\n * Get glasses market name\n * @param product_id Viture product id\n * @param response_data Buffer to store market name\n * @param response_length Pointer to store the length of market name\n */\nVITURE_API int xr_device_provider_get_market_name(int product_id, char* market_name, int* length);\n\n/**\n * Set log level\n * @param level 0: No log, 1: Error, 2: Info, 3: Debug\n */\nVITURE_API void xr_device_provider_set_log_level(int level);\n\n/**\n * Get log level\n * @return 0: No log, 1: Error, 2: Info, 3: Debug\n */\nVITURE_API int xr_device_provider_get_log_level();\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // VITURE_GLASSES_PROVIDER_H\n"
  },
  {
    "path": "include/sdks/viture_macros.h",
    "content": "/*\n * Copyright (C) 2025 VITURE Inc. All rights reserved.\n */\n\n#pragma once\n\n// Unified platform-specific export macro\n// Always exports (dllexport), never imports (no dllimport)\n#if defined(_WIN32) || defined(__CYGWIN__)\n#  define VITURE_API __declspec(dllexport)\n#else\n#  if defined(__GNUC__) || defined(__clang__)\n#    define VITURE_API __attribute__((visibility(\"default\")))\n#  else\n#    define VITURE_API\n#  endif\n#endif\n"
  },
  {
    "path": "include/sdks/viture_protocol.h",
    "content": "/**\n * @file\n * @brief Protocol constants and identifiers used by the Viture USB protocol.\n * @copyright 2025 VITURE Inc. All rights reserved.\n *\n * This header exposes constants for display modes, DOF settings, IMU modes\n * and callback identifiers. These constants are intended for use by\n * application code and protocol builders/parsers.\n */\n\n#ifndef VITURE_PROTOCOL_H\n#define VITURE_PROTOCOL_H\n\n#include <cstdint>\n\nnamespace viture::protocol {\n    /**\n     * @brief Product market names\n     */\n    namespace MarketName {\n        constexpr const char* ONE = \"One\";\n        constexpr const char* PRO = \"Pro\";\n        constexpr const char* LITE = \"Lite\";\n        constexpr const char* LUMA = \"Luma\";\n        constexpr const char* LUMA_PRO = \"Luma Pro\";\n        constexpr const char* LUMA_ULTRA = \"Luma Ultra\";\n        constexpr const char* LUMA_CYBER = \"Luma Cyber\";\n        constexpr const char* BEAST = \"Beast\";\n    } // namespace MarketName\n    /**\n     * @brief Result codes used by various protocol helpers and APIs.\n     */\n    namespace Result {\n        constexpr int SUCCESS = 0; /**< Success code */\n        constexpr int FAILURE = 1; /**< Failure code */\n    }; // namespace Result\n\n    namespace DisplaySize {\n        constexpr uint8_t SMALL = 0x00;\n        constexpr uint8_t MEDIUM = 0x01;\n        constexpr uint8_t LARGE = 0x02;\n        constexpr uint8_t EXTRA = 0x03;\n        constexpr uint8_t ULTRA = 0x04;\n    } // namespace DisplaySize\n\n    /**\n     * @brief Display mode identifiers for switching device display output\n     * and refresh-rate configurations.\n     */\n    namespace DisplayMode {\n        constexpr uint8_t MODE_1920_1080_60HZ = 0x31; /**< 1920x1080 @ 60Hz */\n        constexpr uint8_t MODE_3840_1080_60HZ = 0x32; /**< 3840x1080 @ 60Hz */\n        constexpr uint8_t MODE_1920_1080_90HZ = 0x33; /**< 1920x1080 @ 90Hz */\n        constexpr uint8_t MODE_1920_1080_120HZ = 0x34; /**< 1920x1080 @ 120Hz */\n        constexpr uint8_t MODE_3840_1080_90HZ = 0x35; /**< 3840x1080 @ 90Hz */\n        constexpr uint8_t MODE_1920_1080_60HZ_120HZ =\n            0x36; /**< 1920x1080, input is 60Hz, output is 120Hz (frame interpolation) */\n        constexpr uint8_t MODE_1920_1200_60HZ = 0x41; /**< 1920x1200 @ 60Hz */\n        constexpr uint8_t MODE_3840_1200_60HZ = 0x42; /**< 3840x1200 @ 60Hz */\n        constexpr uint8_t MODE_1920_1200_90HZ = 0x43; /**< 1920x1200 @ 90Hz */\n        constexpr uint8_t MODE_1920_1200_120HZ = 0x44; /**< 1920x1200 @ 120Hz */\n        constexpr uint8_t MODE_3840_1200_90HZ = 0x45; /**< 3840x1200 @ 90Hz */\n        constexpr uint8_t MODE_1920_1200_60HZ_120HZ =\n            0x46; /**< 1920x1280, input is 60Hz, output is 120Hz (frame interpolation) */\n\n        /**\n         * Added for Beast\n         */\n        constexpr uint8_t MODE_ULTRAWIDE_60HZ_120HZ =\n            0x51; /**< Ultrawide mode, input is 60Hz, output is 120Hz (frame interpolation) */\n        constexpr uint8_t MODE_SIDEMODE_60HZ = 0x61; /**< Side-by-side mode @ 60Hz */\n    } // namespace DisplayMode\n\n    /**\n     * @brief Native device DOF modes (used for devices that support native 3DOF, e.g. Viture Beast).\n     */\n    namespace NativeDOF {\n        constexpr uint8_t DOF_0 = 0x00; /**< No native DOF */\n        constexpr uint8_t DOF_3 = 0x01; /**< Native 3DOF */\n        constexpr uint8_t DOF_SMOOTH_FOLLOW = 0x02; /**< Smooth follow mode */\n    } // namespace NativeDOF\n\n    /**\n     * @brief Duty cycle presets used by the display controller.\n     */\n    namespace DutyCycle {\n        constexpr uint8_t H = 98; /**< High duty cycle */\n        constexpr uint8_t M = 42; /**< Medium duty cycle */\n        constexpr uint8_t L = 30; /**< Low duty cycle */\n    } // namespace DutyCycle\n\n    /**\n     * @brief IMU configuration options.\n     */\n    namespace Imu {\n        namespace Mode {\n            constexpr uint8_t MODE_RAW = 0; /**< Report IMU raw data */\n            constexpr uint8_t MODE_POSE = 1; /**< Report IMU pose data */\n        } // namespace Mode\n\n        namespace Frequency {\n            constexpr uint8_t LOW = 0; /**< 60Hz */\n            constexpr uint8_t MEDIUM_LOW = 1; /**< 90Hz */\n            constexpr uint8_t MEDIUM = 2; /**< 120Hz */\n            constexpr uint8_t MEDIUM_HIGH = 3; /**< 240Hz */\n            constexpr uint8_t HIGH = 4; /**< 500Hz */\n        } // namespace Frequency\n    } // namespace Imu\n\n    /**\n     * @brief Callback identifiers used when reporting glass state changes.\n     */\n    namespace Callback {\n        namespace ID {\n            /**\n             * @brief Brightness change\n             *\n             * | Device Model            | Value Range |\n             * |-------------------------|-------------|\n             * | Viture One & Viture Pro | [0, 6]      |\n             * | Viture Luma Series      | [0, 8]      |\n             * | Viture Beast            | [0, 8]      |\n             */\n            constexpr uint8_t BRIGHTNESS = 0;\n            /**\n             * @brief Volume change\n             *\n             * | Device Model       | Value Range |\n             * |--------------------|-------------|\n             * | Viture One         | [0, 7]      |\n             * | Viture Pro         | [0, 8]      |\n             * | Viture Luma Series | [0, 8]      |\n             * | Viture Beast       | [0, 15]     |\n             */\n            constexpr uint8_t VOLUME = 1;\n            /**\n             * @brief Volume change\n             *\n             * See `DisplayMode` for possible values.\n             */\n            constexpr uint8_t DISPLAY_MODE = 2;\n            /**\n             * @brief Electronchromic film status change\n             *\n             * | Device Model            | Value Range |\n             * |-------------------------|-------------|\n             * | Viture One & Viture Pro | [0, 1]      |\n             * | Viture Luma Series      | [0, 1]      |\n             * | Viture Beast            | [0, 8]      |\n             */\n            constexpr uint8_t ELECTROCHROMIC_FILM = 3;\n            /**\n             * @brief Native dof type change\n             *\n             * See `NativeDOF` for possible values.\n             */\n            constexpr uint8_t NATIVE_DOF = 4;\n        } // namespace ID\n    } // namespace Callback\n} // namespace viture::protocol\n\n#endif // VITURE_PROTOCOL_H\n"
  },
  {
    "path": "include/sdks/viture_version.h",
    "content": "/*\n * Copyright (C) 2025 VITURE Inc. All rights reserved.\n */\n\n#pragma once\n\n#include \"viture_macros.h\"\n\n// Version defined as macros so they can be used in preprocessor checks\n#define VITURE_VERSION_MAJOR 2\n#define VITURE_VERSION_MINOR 0\n#define VITURE_VERSION_PATCH 0\n\n// Helper macros to stringify numeric macros after expansion.\n#define VITURE_STRINGIFY_IMPL(x) #x\n#define VITURE_STRINGIFY(x) VITURE_STRINGIFY_IMPL(x)\n\n// Compose the version string from the three numeric macros.\n#define VITURE_VERSION_STRING              \\\n    VITURE_STRINGIFY(VITURE_VERSION_MAJOR) \\\n    \".\" VITURE_STRINGIFY(VITURE_VERSION_MINOR) \".\" VITURE_STRINGIFY(VITURE_VERSION_PATCH)\n\n// C-style accessor exported with C linkage. Returns a pointer to a\n// null-terminated static string owned by the library; callers must not free it.\nextern \"C\" VITURE_API const char* GetVersionString();\n\nnamespace viture::version {\n    // Expose version pieces as compile-time constants\n    constexpr int kMajor = VITURE_VERSION_MAJOR;\n    constexpr int kMinor = VITURE_VERSION_MINOR;\n    constexpr int kPatch = VITURE_VERSION_PATCH;\n} // namespace viture::version\n"
  },
  {
    "path": "include/state.h",
    "content": "#pragma once\n\n#include \"devices.h\" // for calibration_setup_type\n#include \"imu.h\" // for imu_quat_type\n\n#include <inttypes.h>\n#include <stdbool.h>\n#include <stdio.h>\n\nenum calibration_state_t {\n    NOT_CALIBRATED,\n    CALIBRATED,\n    CALIBRATING,\n    WAITING_ON_USER\n};\ntypedef enum calibration_state_t calibration_state_type;\n\nstruct driver_state_t {\n    uint32_t heartbeat;\n    char* connected_device_brand;\n    char* connected_device_model;\n    float connected_device_full_distance_cm;\n    float connected_device_full_size_cm;\n    bool connected_device_pose_has_position;\n    calibration_setup_type calibration_setup;\n    calibration_state_type calibration_state;\n    bool sbs_mode_supported;\n    bool sbs_mode_enabled;\n    bool breezy_desktop_smooth_follow_enabled;\n    float breezy_desktop_follow_threshold;\n    float *smooth_follow_origin;\n    bool smooth_follow_origin_ready;\n    float breezy_desktop_display_distance;\n    bool firmware_update_recommended;\n    bool is_gamescope_reshade_ipc_connected;\n\n    int granted_features_count;\n    char** granted_features;\n\n    int license_features_count;\n    char** license_features;\n\n    char* device_license;\n};\ntypedef struct driver_state_t driver_state_type;\n\nenum sbs_control_t {\n    SBS_CONTROL_UNSET,\n    SBS_CONTROL_ENABLE,\n    SBS_CONTROL_DISABLE\n};\ntypedef enum sbs_control_t sbs_control_type;\nstruct control_flags_t {\n    bool recenter_screen;\n    bool recalibrate;\n    bool force_quit;\n    sbs_control_type sbs_mode;\n    char* request_features;\n};\ntypedef struct control_flags_t control_flags_type;\n\nextern const char* state_files_directory;\nextern const char* state_filename;\nextern const char* control_flags_filename;\n\nFILE* get_driver_state_file(const char *filename, char *mode, char **full_path);\nvoid write_state(driver_state_type *state);\nvoid read_control_flags(FILE *fp, control_flags_type *flags);\nvoid update_state_from_device(driver_state_type *state, device_properties_type *primary_device, device_properties_type *supplemental_device, device_driver_type *device_driver);"
  },
  {
    "path": "include/strings.h",
    "content": "#pragma once\n\n#include <stdlib.h>\n#include <stdbool.h>\n\nbool equal(const char *a, const char *b);\n\nbool in_array(const char *str, const char **array, int size);\n\nbool list_string_contains(const char* str, const char* list_string);\n\nconst char* concat(const char* path, const char* extension);\n\n// Parse comma-separated string into array of strings\n// Returns number of strings parsed, or 0 on error\n// Caller must free the returned array and its elements\nint parse_comma_separated_string(const char* str, char*** result);\n\n// Deep copy an array of strings\n// Returns NULL on error or if input is NULL/empty\n// Caller must free the returned array and its elements\nchar** deep_copy_string_array(char** array, int count);\n\n// Comparison function intended for qsort\nint compare_strings(const void* a, const void* b);"
  },
  {
    "path": "include/system.h",
    "content": "#pragma once\n\nchar *get_hardware_id();"
  },
  {
    "path": "include/version.h.in",
    "content": "#define PROJECT_VERSION \"@PROJECT_VERSION@\""
  },
  {
    "path": "include/wl_client/gamescope_reshade.h",
    "content": "/* Generated by wayland-scanner 1.23.0 */\n\n#ifndef GAMESCOPE_RESHADE_CLIENT_PROTOCOL_H\n#define GAMESCOPE_RESHADE_CLIENT_PROTOCOL_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"wayland-client.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @page page_gamescope_reshade The gamescope_reshade protocol\n * gamescope-specific reshade integration\n *\n * @section page_desc_gamescope_reshade Description\n *\n * This protocol allows applications to load and interact with a reshade FX shader in gamescope.\n *\n * @section page_ifaces_gamescope_reshade Interfaces\n * - @subpage page_iface_gamescope_reshade - \n * @section page_copyright_gamescope_reshade Copyright\n * <pre>\n *\n * Copyright © 2024 Wayne Heaney\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n * </pre>\n */\nstruct gamescope_reshade;\n\n#ifndef GAMESCOPE_RESHADE_INTERFACE\n#define GAMESCOPE_RESHADE_INTERFACE\n/**\n * @page page_iface_gamescope_reshade gamescope_reshade\n * @section page_iface_gamescope_reshade_api API\n * See @ref iface_gamescope_reshade.\n */\n/**\n * @defgroup iface_gamescope_reshade The gamescope_reshade interface\n */\nextern const struct wl_interface gamescope_reshade_interface;\n#endif\n\n/**\n * @ingroup iface_gamescope_reshade\n * @struct gamescope_reshade_listener\n */\nstruct gamescope_reshade_listener {\n\t/**\n\t * alerts when the requested effect is ready\n\t *\n\t * This event alerts the client when an effect has been enabled.\n\t * @param effect_path Path to the FX file\n\t */\n\tvoid (*effect_ready)(void *data,\n\t\t\t     struct gamescope_reshade *gamescope_reshade,\n\t\t\t     const char *effect_path);\n};\n\n/**\n * @ingroup iface_gamescope_reshade\n */\nstatic inline int\ngamescope_reshade_add_listener(struct gamescope_reshade *gamescope_reshade,\n\t\t\t       const struct gamescope_reshade_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) gamescope_reshade,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define GAMESCOPE_RESHADE_DESTROY 0\n#define GAMESCOPE_RESHADE_SET_EFFECT 1\n#define GAMESCOPE_RESHADE_ENABLE_EFFECT 2\n#define GAMESCOPE_RESHADE_SET_UNIFORM_VARIABLE 3\n#define GAMESCOPE_RESHADE_DISABLE_EFFECT 4\n\n/**\n * @ingroup iface_gamescope_reshade\n */\n#define GAMESCOPE_RESHADE_EFFECT_READY_SINCE_VERSION 1\n\n/**\n * @ingroup iface_gamescope_reshade\n */\n#define GAMESCOPE_RESHADE_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_gamescope_reshade\n */\n#define GAMESCOPE_RESHADE_SET_EFFECT_SINCE_VERSION 1\n/**\n * @ingroup iface_gamescope_reshade\n */\n#define GAMESCOPE_RESHADE_ENABLE_EFFECT_SINCE_VERSION 1\n/**\n * @ingroup iface_gamescope_reshade\n */\n#define GAMESCOPE_RESHADE_SET_UNIFORM_VARIABLE_SINCE_VERSION 1\n/**\n * @ingroup iface_gamescope_reshade\n */\n#define GAMESCOPE_RESHADE_DISABLE_EFFECT_SINCE_VERSION 1\n\n/** @ingroup iface_gamescope_reshade */\nstatic inline void\ngamescope_reshade_set_user_data(struct gamescope_reshade *gamescope_reshade, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) gamescope_reshade, user_data);\n}\n\n/** @ingroup iface_gamescope_reshade */\nstatic inline void *\ngamescope_reshade_get_user_data(struct gamescope_reshade *gamescope_reshade)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) gamescope_reshade);\n}\n\nstatic inline uint32_t\ngamescope_reshade_get_version(struct gamescope_reshade *gamescope_reshade)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) gamescope_reshade);\n}\n\n/**\n * @ingroup iface_gamescope_reshade\n */\nstatic inline void\ngamescope_reshade_destroy(struct gamescope_reshade *gamescope_reshade)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) gamescope_reshade,\n\t\t\t GAMESCOPE_RESHADE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) gamescope_reshade), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_gamescope_reshade\n *\n * The effect will be disabled to allow an opportunity to set uniform variables before enabling it.\n */\nstatic inline void\ngamescope_reshade_set_effect(struct gamescope_reshade *gamescope_reshade, const char *path)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) gamescope_reshade,\n\t\t\t GAMESCOPE_RESHADE_SET_EFFECT, NULL, wl_proxy_get_version((struct wl_proxy *) gamescope_reshade), 0, path);\n}\n\n/**\n * @ingroup iface_gamescope_reshade\n *\n * Enables the effect that was previously loaded by set_effect.\n */\nstatic inline void\ngamescope_reshade_enable_effect(struct gamescope_reshade *gamescope_reshade)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) gamescope_reshade,\n\t\t\t GAMESCOPE_RESHADE_ENABLE_EFFECT, NULL, wl_proxy_get_version((struct wl_proxy *) gamescope_reshade), 0);\n}\n\n/**\n * @ingroup iface_gamescope_reshade\n *\n * Set the value of a uniform variable. Can be called before or after enabling the effect.\n */\nstatic inline void\ngamescope_reshade_set_uniform_variable(struct gamescope_reshade *gamescope_reshade, const char *key, struct wl_array *value)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) gamescope_reshade,\n\t\t\t GAMESCOPE_RESHADE_SET_UNIFORM_VARIABLE, NULL, wl_proxy_get_version((struct wl_proxy *) gamescope_reshade), 0, key, value);\n}\n\n/**\n * @ingroup iface_gamescope_reshade\n *\n * Disables the effect that was previously enabled by enable_effect.\n */\nstatic inline void\ngamescope_reshade_disable_effect(struct gamescope_reshade *gamescope_reshade)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) gamescope_reshade,\n\t\t\t GAMESCOPE_RESHADE_DISABLE_EFFECT, NULL, wl_proxy_get_version((struct wl_proxy *) gamescope_reshade), 0);\n}\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "license_public_key.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuJuIZFWthQEOn4KbYYs70aMk9sna\nQT+7sDCZEEjpVyRPZQHP3zkY55jwNCzyCzZpdTDf3PHYHACvx3PT9wttUQ==\n-----END PUBLIC KEY-----"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: XR Linux Driver\nsite_description: Documentation for the XR Linux Driver project\nrepo_url: https://github.com/wheaney/XRLinuxDriver\nrepo_name: wheaney/XRLinuxDriver\n\ndocs_dir: docs\n\ntheme:\n  name: material\n  features:\n    - navigation.instant\n    - navigation.tracking\n    - navigation.tabs\n    - navigation.top\n    - content.code.copy\n\nplugins:\n  - search\n\nmarkdown_extensions:\n  - admonition\n  - toc:\n      permalink: true\n  - tables\n  - pymdownx.highlight\n  - pymdownx.superfences\n\nnav:\n  - Home: index.md\n  - Usage:\n    - Mouse / joystick modes: mouse-and-joystick-modes.md\n  - OpenTrack:\n      - Listener (Input): opentrack-listener.md\n      - App (Output): opentrack-app.md\n      - 6DoF from 3DoF glasses + a webcam: 6dof-from-3dof-opentrack-neuralnet.md\n  - Development: development.md\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/base/FXRDebug.h",
    "content": "#ifndef FFALCONXR_DEBUG_H\n#define FFALCONXR_DEBUG_H\n\n#ifndef LOG_TAG\n#define LOG_TAG \"RayNeoXR\"\n#endif\n\n#ifdef ANDROID\n\n#include <android/log.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef NDEBUG\n#define FXR_LOG(LEVEL, format, ...)                                                                                    \\\n    ((void) __android_log_print(ANDROID_LOG_##LEVEL, LOG_TAG, \"[%s:%d] \" format, __FILE__, __LINE__, ##__VA_ARGS__))\n#else\n#define FXR_LOG(LEVEL, format, ...) ((void) __android_log_print(ANDROID_LOG_##LEVEL, LOG_TAG, format, ##__VA_ARGS__))\n\n#ifndef LOGD\n#define LOGD(format, ...)\n#endif\n#endif\n\n#define FXR_LOG_FATAL(condition, format, ...) ((void) __android_log_assert(condition, LOG_TAG, format, ##__VA_ARGS__))\n#define FXR_CHECK(condition, format, ...)                                                                              \\\n    (__predict_false(condition)) ? FXR_LOG_FATAL(condition, format, ##__VA_ARGS__) : ((void)0))\n\n\n#ifndef LOGD\n#define LOGD(format, ...) FXR_LOG(DEBUG, format, ##__VA_ARGS__)\n#endif\n#ifndef LOGI\n#define LOGI(format, ...) FXR_LOG(INFO, format, ##__VA_ARGS__)\n#endif\n#ifndef LOGW\n#define LOGW(format, ...) FXR_LOG(WARN, format, ##__VA_ARGS__)\n#endif\n#ifndef LOGE\n#define LOGE(format, ...) FXR_LOG(ERROR, format, ##__VA_ARGS__)\n#endif\n#ifndef LOG_FATAL\n#define LOG_FATAL(format, ...) FXR_LOG_FATAL(NULL, format, ##__VA_ARGS__)\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#else\n#include \"stdio.h\"\n\n#define FXR_LOG(LEVEL, format, ...) printf(\"[%s]\" format \"\\r\\n\", LEVEL, ##__VA_ARGS__)\n#ifndef LOGD\n#define LOGD(format, ...) FXR_LOG(\"DEBUG\", format, ##__VA_ARGS__)\n#endif\n#ifndef LOGI\n#define LOGI(format, ...) FXR_LOG(\"INFO\", format, ##__VA_ARGS__)\n#endif\n#ifndef LOGW\n#define LOGW(format, ...) FXR_LOG(\"WARN\", format, ##__VA_ARGS__)\n#endif\n#ifndef LOGE\n#define LOGE(format, ...) FXR_LOG(\"ERROR\", format, ##__VA_ARGS__)\n#endif\n\n#endif // ANDROID\n\n#include <stdint.h>\n\nextern const char* GetEventStateName(int32_t state);\nextern int32_t GetFFalconErrorCode(int32_t libusbErrCode);\n\n#endif //FFALCONXR_DEBUG_H\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/base/FXRError.h",
    "content": "#ifndef FFALCONXR_ERROR_H\n#define FFALCONXR_ERROR_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <errno.h>\n#include <stdint.h>\n\ntypedef enum {\n    OK = 0,\n\n    UNKNOWN_ERROR = INT32_MIN,\n\n    FAILED = -EPERM,\n    NO_MEMORY = -ENOMEM,\n    UNSUPPORTED = -ENOSYS,\n    INVALID_ARGS = -EINVAL,\n    NOT_FOUND = -ENOENT,\n    NO_DEVICE = -ENODEV,\n    ALREADY_EXISTS = -EEXIST,\n    DEAD_PIPE = -EPIPE,\n    DATA_OVERFLOW = -EOVERFLOW,\n    NO_DATA = -ENODATA,\n    TRY_AGAIN = -EAGAIN,\n    TIMED_OUT = -ETIMEDOUT,\n    BAD_MSG = -EBADMSG,\n    BAD_FD = -EBADFD,\n} FXRResult;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif //FFALCONXR_ERROR_H\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/base/FXRMacro.h",
    "content": "#ifndef FFALCONXR_MACR_H\n#define FFALCONXR_MACR_H\n\n#include \"base/FXRError.h\"\n#include <stddef.h>\n#include <stdint.h>\n#ifdef ANDROID\n#include <android/hardware_buffer.h>\n#endif\n\ntypedef void (*IMUEventCallback)(const float acc[3], const float gyro[3], const float mag[3], uint64_t timeInNs);\ntypedef void (*VsyncEventCallback)();\ntypedef void (*StateEventCallback)(uint32_t state, uint64_t timestamp, size_t length, const void* data);\ntypedef void* (*SensorFusionFactory)();\ntypedef void (*XRConfigBroadcastCallback)();\ntypedef FXRResult (*XRConfigExternalReader)(const char* item, void*);\n#ifdef  ANDROID\ntypedef void (*FrameEventCallback)(AHardwareBuffer* buffer, int64_t timestamp, int64_t exposureTime);\n#else\ntypedef void (*FrameEventCallback)(void* buffer, int64_t timestamp, int64_t exposureTime);\n#endif\ntypedef void (*FrameDataCallback)(uint8_t* data, uint32_t w, uint32_t h, int64_t timestamp, int64_t exposureTime);\n\n#define XR_CHARACTER_ARRAYS_MAX_LEN (256)\n#define XR_PLANE_ARRAY_DEFAULT_SIZE (15)\n\n#if defined(__CYGWIN32__)\n#define RAYNEO_API_CALL __stdcall\n#define RAYNEO_API_EXPORT __declspec(dllexport)\n#define RAYNEO_API_PTR RAYNEO_API_CALL\n#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(WINAPI_FAMILY)\n#define RAYNEO_API_CALL __stdcall\n#define RAYNEO_API_EXPORT __declspec(dllexport)\n#define RAYNEO_API_PTR RAYNEO_API_CALL\n#elif defined(__MACH__) || defined(__ANDROID__) || defined(__linux__) || defined(LUMIN)\n#define RAYNEO_API_CALL\n#define RAYNEO_API_EXPORT __attribute__((visibility(\"default\")))\n#define RAYNEO_API_PTR\n#else\n#define RAYNEO_API_CALL\n#define RAYNEO_API_EXPORT\n#define RAYNEO_API_PTR\n#endif\n\n#define AUTO_GENERATED\n\n#endif //FFALCONXR_MACR_H\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/base/FXRType.h",
    "content": "#ifndef FFALCONXR_TYPE_H\n#define FFALCONXR_TYPE_H\n\n\n#include \"base/FXRMacro.h\"\n#include <limits.h>\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\ntypedef struct FXRRuntimeVersion {\n    char commitTime[XR_CHARACTER_ARRAYS_MAX_LEN];   //build time\n    char branch[XR_CHARACTER_ARRAYS_MAX_LEN]; //code branch\n    char version[XR_CHARACTER_ARRAYS_MAX_LEN];\n    char buildTime[XR_CHARACTER_ARRAYS_MAX_LEN];\n} FXRRuntimeVersion;\n\nenum FXRRuntimeStateType { kDevice = 0, kImu = 1 };\n\n\ntypedef enum FXRDeviceType {\n    kProductUnknown = 0x00,\n    kProductNextViewPro = 0x20,   //一代眼镜nextviewpro\n    kProductAries = 0x21,         //二代眼镜白羊\n    kProductAries1p5Seeya = 0x22, //白羊1.5 Seeya屏\n    kProductAries1p5Sony = 0x23,  //白羊1.5 Sony屏\n    kProductAries1p8 = 0x24,      //白羊1.8\n    kProductTaurus = 0x30,        //金牛\n\n\n    kProductMercury = 0x1000, //水星\n} FXRDeviceType;\n\ntypedef enum FXREye {\n    kEyeLeft = 0,\n    kEyeRight,\n    kNumEyes,\n    kEyeMono = kEyeLeft,\n    kEyeMultiview = kEyeLeft,\n} FXREye;\n\ntypedef enum {\n    PLANE_HORIZONTAL_UP,   /*like ceiling */\n    PLANE_HORIZONTAL_DOWN, /*like floor or table*/\n    PLANE_VERTICAL,        /*like wall*/\n    PLANE_NON\n} XRPlaneProperty;\n\nenum FXRDistortionParamIndex {\n    K1 = 0,\n    K2 = 1,\n    K3 = 2,\n    P1 = 3,\n    P2 = 4\n};\n\ntypedef struct {\n    bool deviceConnected;\n    bool imuEnabled;\n} XRRuntimeStateInfo;\n\ntypedef struct {\n    uint64_t timestamp;\n    float rotation[4]; //x,y,z,w\n    float position[3];\n} XRPoseInfo;\n\ntypedef struct XRINFO4PREDICTPOSE {\n    float latestGyro[3];\n    uint64_t latestSensorTimeStamp; //in nanoseconds\n    XRPoseInfo latestPose;\n} XRInfo4PredictPose;\n\ntypedef struct XRALGOSTATE {\n    #ifdef __cplusplus\n    XRALGOSTATE() {\n        ffvinsStatus = -1;\n        predictInfo = {.latestSensorTimeStamp = INT_MAX};\n    }\n    #endif\n    int32_t ffvinsStatus;\n    XRInfo4PredictPose predictInfo; //for pose prediction\n} XRAlgoState;\n\ntypedef struct {\n    struct {\n        float x, y, z, w;\n    } rotation;\n    struct {\n        float x, y, z;\n    } position;\n} HeadPose;\n\ntypedef struct {\n    HeadPose pose;                  //!< Head pose\n    int32_t poseStatus;             //!< Bit field (sxrTrackingMode) indicating pose status\n    uint64_t poseTimeStampNs;       //!< Time stamp in which the head pose was generated (nanoseconds)\n    uint64_t poseFetchTimeNs;       //!< Time stamp when this pose was retrieved\n    uint64_t expectedDisplayTimeNs; //!< Expected time when this pose should be on screen (nanoseconds)\n} HeadPoseState;\n\ntypedef struct {\n    XRPoseInfo pose;\n    float azimuth;\n    float mag_field_strength;\n    int mag_sensor_accuracy;\n} XRNineAxisPoseInfo;\n\ntypedef struct {\n    XRPlaneProperty property;\n    XRPoseInfo pose;\n    struct {\n        float x, z;\n    } local_range;\n    float local_polygon[100];\n    int32_t local_polygon_size;\n} XRPlaneInfo;\n\ntypedef struct {\n    XRPlaneInfo data[XR_PLANE_ARRAY_DEFAULT_SIZE];\n    int32_t size;\n} XRPlaneArray;\n\n#ifdef __cplusplus\n}\n#endif\n#endif //FFALCONXR_TYPE_H\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/device/XRDevice.h",
    "content": "#pragma once\n\n#include <functional>\n#include <memory>\n#include <vector>\n\n#include \"xr/XRMacro.h\"\n#include \"base/FXRType.h\"\n\nnamespace ffalcon {\n\nstruct XRDeviceStateCallback {\n    virtual void OnConnected(int64_t id) = 0;\n    virtual void OnDisconnect(int64_t id) = 0;\n};\n\nclass XRDeviceBase {\n    PREVENT_COPY_AND_ASSIGN(XRDeviceBase);\n\nprotected:\n    using Callback = XRDeviceStateCallback;\n\npublic:\n    XRDeviceBase() = default;\n\n    void SetId(int64_t id) { mId = id; }\n    [[nodiscard]] inline int64_t Id() const { return mId; }\n    [[nodiscard]] inline bool IsConnected() const { return mIsConnected; }\n    void SetStateCallback(Callback* callback) { mCallback = callback; }\n\n    virtual uint64_t Capabilities() { return 0; }\n    virtual void Connect() = 0;\n    virtual void Disconnect() = 0;\n    virtual void Open() {}\n    virtual void Close() {}\n\nprotected:\n    int64_t mId = -1;\n    Callback* mCallback = nullptr;\n    bool mIsConnected = false;\n};\n\nclass XRDeviceComponent : public XRDeviceBase {\npublic:\n    void SetParent(XRDeviceBase* parent) { mParent = parent; }\n    [[nodiscard]] XRDeviceBase* GetParent() const { return mParent; }\n\n    void Connect() override {}\n    void Disconnect() override {}\n    void Open() override { XRDeviceBase::Open(); }\n    void Close() override { XRDeviceBase::Close(); }\n\nprotected:\n    XRDeviceBase* mParent = nullptr;\n};\n\nclass XRDeviceEntity : public XRDeviceBase, public XRDeviceStateCallback {\npublic:\n    uint64_t Capabilities() override {\n        uint64_t cap = 0;\n        for (auto& c: mComponents) {\n            cap |= c->Capabilities();\n        }\n        return cap;\n    }\n\nprotected:\n    std::vector<std::shared_ptr<XRDeviceComponent>> mComponents;\n};\n\nclass DevCapImu {\npublic:\n    using ImuEventCallback =\n            std::function<int64_t(std::array<float, 3>& acc, std::array<float, 4>& gyro, std::array<float, 3>& mag)>;\n\n    void SetImuEventCallback(ImuEventCallback&& callback) { mImuEventCallback = callback; }\n\nprotected:\n    ImuEventCallback mImuEventCallback;\n};\n\nclass DevCapCamera {\npublic:\n    using PreviewFrameCallback = std::function<void(uint64_t timestamp, void* image)>;\n    using SnapshotCallback = std::function<void(int64_t timestamp, void* image)>;\n    const static uint64_t kCapMask = kCamera;\n\n    void SetPreviewFrameCallback(PreviewFrameCallback&& callback) { mPreviewFrameCallback = callback; }\n    void SetSnapshotCallback(SnapshotCallback&& callback) { mSnapshotCallback = callback; }\n    [[nodiscard]] inline float FocalLength() const { return mFocalLengthMM; }\n    [[nodiscard]] inline bool FacingFront() const { return mFacingFront; }\n\n    virtual void StartPreview(int32_t width, int32_t height, int32_t frameRate) = 0;\n    virtual void StopPreview() = 0;\n    virtual void TakePhoto(int32_t width, int32_t height) = 0;\n\nprotected:\n    PreviewFrameCallback mPreviewFrameCallback;\n    SnapshotCallback mSnapshotCallback;\n\n    float mFocalLengthMM = 0;\n    bool mFacingFront = false;\n};\n\nclass DevCapDisplay {\npublic:\n    using VsyncEventCallback = std::function<void(int64_t vsyncTimestampUs)>;\n\n    [[nodiscard]] inline uint32_t GetDisplayWidth() const { return mDisplayWidth; }\n    [[nodiscard]] inline uint32_t GetDisplayHeight() const { return mDisplayHeight; }\n\n    void SetVsyncEventCallback(VsyncEventCallback&& callback) { mVsyncEventCallback = callback; }\n    virtual int32_t GetRefreshRate() = 0;\n    virtual int64_t GetLatestVsync() = 0;\n\nprotected:\n    uint32_t mDisplayWidth = 0;\n    uint32_t mDisplayHeight = 0;\n\n    VsyncEventCallback mVsyncEventCallback;\n};\n\ntemplate<class... Caps>\nclass Component : public Caps..., public XRDeviceComponent {};\n\n} // namespace ffalcon"
  },
  {
    "path": "modules/rayneoSDKHeaders/device/usb/XRDeviceState.h",
    "content": "#pragma once\n\n#include \"base/FXRType.h\"\n\n#define FXR_HID_SEND_MAGIC 0x66\n#define FXR_HID_ACK_MAGIC 0x99\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nenum FXRColorAdjustOp {\n    opWhiteBalanceWx = 0x01,\n    opWhiteBalanceWy = 0x02,\n    opColorGainR = 0x03,\n    opColorGainG = 0x04,\n    opColorGainB = 0x05,\n    opColorEnhancementR = 0x06,\n    opColorEnhancementG = 0x07,\n    opColorEnhancementB = 0x08,\n    opContrast = 0x09,\n    opColorTemperature = 0x0A,\n    opHue = 0x0B,\n    opLoad = 0xF0,\n    opReset = 0xFE,\n    opSave = 0xFF,\n};\n\n\n//kCmd* 为双向命令\n//kAck* 为单向命令, 眼镜端->设备端\nenum FXRUsbCommand {\n    kCmdDeviceInfo = 0,\n    kCmdImuOn = 1,\n    kCmdImuOff = 2,\n    kCmdSensorGyroCorrection = 3,\n    kCmdDisplay3dMode = 6,\n    kCmdDisplay2dMode = 7,\n    kCmdPanelPresetSet = 9,\n    kCmdSetPanelRotation = 0xA,\n    kCmdPanelLumaSave = 0xD,\n    kCmdPanelPowerOn = 0xE,\n    kCmdPanelPowerOff = 0xF,\n    kCmdPanelPowerSwitch = 0x10,\n    kCmdPanelSwap = 0x12,\n    kCmdAccelerateRate = 0x19,\n    kCmdGyroRate = 0x1A,\n    kCmdMagnetRate = 0x1B,\n    kCmdParamReset = 0x1D,\n    kCmdParamSave = 0x1F,\n    kCmdPanelSet60fps = 0x20,\n    kCmdPanelSet120fps = 0x21,\n    kAckWheelKeyDoublePressed = 0x22,\n    kCmdPanelGetFov = 0x23,\n    KCmdAudioEnablePersistence = 0x25, //静音模式, 仅白羊1.0支持\n    kCmdSideBySideChange = 0x30,\n    kCmdTraceReport = 0x33, //设备ID\n    kCmdAudioEnable = 0x34,\n    kCmdPsensorEnable = 0x38,\n    kCmdImuCalibration = 0x3C,\n    kCmdGetGyroBias = 0x3E,\n    kCmdSetGyroBias = 0x3F,\n    kAckGlassesSleepNotify = 0x41,\n    kAckGlassesWakeupNotify = 0x42,\n    kCmdAudioMode = 0x49,\n    kCmdVolumeSet = 0x50,\n    kCmdVolumeUp = 0x51,\n    kCmdVolumeDown = 0x52,\n    kAckWheelKeyPressed = 0x54,\n    kCmdLuminanceUp = 0x55,\n    kCmdLuminanceDown = 0x56,\n    kAckWheelKeyLongPressed = 0x57,\n    kCmdWheelKeySideBySideDisable = 0x58,\n    kAckImuData = 0x65,\n    kCmdReboot2Bootloader = 0x66,\n    kCmdCaluLum = 0x67,\n    kCmdGetLT7211Version = 0x6A,\n    kCmdPanelColorAdjust = 0x73,\n    kAckCommand = 0xC8,\n    kAckUsbCommandLog = 0xC9,\n    kAckTraceReport = 0xCA,\n    kCmdUsbCommandPARGESDump = 0xCB,\n    kCmdTimeSynchronize = 0xE1, //设备间时钟同步\n};\n\n\ntypedef struct {\n    float tsb[3][3];\n    float ta[3];\n    float tg[3];\n} XRImuCalibrateInfo;\n\n\n/**\n * 新增成员请在结构体底部增加来确保向前兼容！！！\n * 并且修改ipc/XRRuntimeStateDesc.hpp涉及的定义！！！\n */\ntypedef struct {\n    int32_t year;\n    int32_t month;\n    int32_t day;\n} TIME;\n\ntypedef struct {\n    float horizontalLeft;\n    float horizontalRight;\n    float verticalUp;\n    float verticalDown;\n} FOV;\n\ntypedef struct {\n    uint8_t whiteBalanceWx;\n    uint8_t whiteBalanceWy;\n    uint8_t colorGainR;\n    uint8_t colorGainG;\n    uint8_t colorGainB;\n    uint8_t colorEnhancementR;\n    uint8_t colorEnhancementG;\n    uint8_t colorEnhancementB;\n    uint8_t contrast;\n    uint8_t colorTemperature;\n    uint8_t hue;\n} XRPanelColorParms;\n\ntypedef union {\n    XRPanelColorParms params;\n    uint8_t data[12];\n} PANELPARAMS;\n\ntypedef struct {\n    char manufacturer[32];\n    char hostManufacturer[32]; //Server所运行的设备manufacturer\n    char glassesId[64];        //device id, SN码\n\n    int32_t firmwareVersion;\n    TIME time;\n\n    bool wakeUp;   //true: wakeup, false: sleep\n    bool dpStatus; //dp信号\n    bool sideBySide;\n    bool whisper;\n    bool psensorState;\n    bool psensorValid; //接近传感器使能状态, 0使能, 眼镜会自动休眠. 1关闭,眼镜always wakeup\n    bool lsensorValid;\n    bool gsensorValid;\n    bool msensorValid;\n    bool muteMode; //静音模式, 仅白羊1.0支持\n    FOV fov;       //FOV, 数值采用角度制\n\n    uint8_t volume; //current, [0, 12]\n    uint8_t maxVolume;\n    uint8_t luminance;    //current luminance level, [0, maxLuminance]\n    uint8_t maxLuminance; //max luminance level\n    uint8_t frameRate;    //fps\n\n    PANELPARAMS panelParams; //屏幕参数\n    bool supportPanelColorAdjust;\n\n} XRDeviceState, XRDeviceInfo;\n\n#ifdef __cplusplus\n}\n#endif"
  },
  {
    "path": "modules/rayneoSDKHeaders/device/usb/XRPacket.h",
    "content": "#ifndef FFALCONXR_PACKET_H\n#define FFALCONXR_PACKET_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <inttypes.h>\n\ntypedef struct {\n    uint8_t magic;\n    uint8_t type;\n    uint8_t value;\n    uint8_t data[52];\n    uint8_t reserved[9];\n} XrHidCommand;\n\ntypedef struct {\n    uint8_t magic;\n    uint8_t type;\n    uint16_t length;\n} XrHidMsgHeader;\n\ntypedef struct {\n    float acc[3];\n    float gyro[3];\n    float temperature;\n    float magnet[2];\n    uint32_t tick;\n    float psensor;\n    float lsensor;\n    float magnet_2;     //magnet第三个字节\n} XrHidSensorData;\n\ntypedef struct {\n    XrHidMsgHeader head;\n    XrHidSensorData sensor;\n    union {\n        struct {\n            uint32_t count;\n            uint8_t reserved[2];\n            uint8_t checksum;\n            uint8_t flag;\n        } normal;\n        struct {\n            uint32_t left;\n            uint32_t right;\n        } vsync;\n    } end;\n} XrHidSensorEvent;\n\ntypedef struct {\n    XrHidMsgHeader head;\n    uint32_t tick;\n    uint8_t value;\n    uint8_t cpuid[12]; //unique ID of MCU Device\n    uint8_t board_id;  //0x21 aries; //0x22 aries1p5_v1; //0x23 aries1p5 v2s\n    uint8_t sensor_on;\n    uint8_t support_fov; //1 for support, others for not support\n    uint8_t date[12];    //example: “May 05 2020”\n    uint16_t year;\n    uint8_t month;\n    uint8_t day;\n    uint8_t glasses_fps; //120=120fps, others=60fps\n    uint8_t luminance;\n    uint8_t volume;       // 0 ~ 12，0最小，12最大\n    uint8_t side_by_side; //1: sidebyside; 0: mirror\n    uint8_t psesnor_enable;\n    uint8_t audio_mode; //0 for normal mode; 1 for quiet mode\n    uint8_t dp_status;  //0 for dp not ready; 1 for dp ready\n    uint8_t status3;\n    uint8_t psensor_valid;\n    uint8_t lsensor_valid;\n    uint8_t gyro_valid;\n    uint8_t magnet_valid;\n    float reserve1; //smart PA left\n    float reserve2; //smart PA right\n    uint8_t max_luminance;\n    uint8_t max_volume;\n    uint8_t support_panel_color_adjust;\n    uint8_t flag;\n} XrHidDeviceInfo;\n\ntypedef struct {\n    XrHidMsgHeader head;\n    uint32_t tick;\n    uint8_t value;\n    uint8_t data[52];\n    uint8_t reserved;\n    uint8_t checksum;\n    uint8_t flag;\n} XrHidResponse;\n\ntypedef struct {\n    XrHidMsgHeader head;\n    uint32_t tick; //此次消息由设备发往host时的时间戳\n    uint8_t value;\n    uint8_t index; //时间同步response会连续发送10条\n    uint8_t reserve[2];\n    uint32_t receiveTick; //收到时间同步请求时的时间戳\n    uint8_t reserve2[48];\n} XrHidTimeSyncResponse;\n\ntypedef struct {\n    uint32_t event;\n    uint32_t length;\n    uint64_t timestamp;\n    uint8_t data[0];\n} XrStateEvent;\n\ntypedef struct {\n    uint64_t host_time; //host time\n    /**\n     * 分体式 & 使用USB协议的设备, Vsync信号随IMU数据一起捎带给出\n     * 设计上携带了上一次Vsync的时间戳以及对应的SensorTime\n     * 由这两个数据估计得到下一次vsync\n     */\n    uint64_t last_vsync;  //sensor time\n    uint64_t sensor_time; //sensor time\n} XrVsyncEvent;\n\ntypedef union {\n    uint8_t data[64];\n    XrHidResponse response;\n    XrHidSensorEvent sensor_data;\n    XrHidDeviceInfo device_info;\n    XrStateEvent state_event;\n    XrVsyncEvent vsync_event;\n} XrDataPacket;\nstatic_assert(sizeof(XrDataPacket) == 64, \"XrDataPacket size must be 64\");\n\ntypedef struct {\n    XrHidMsgHeader head;\n    uint32_t tick;\n    uint8_t type;\n    uint8_t left_low;\n    uint8_t left_high;\n    uint8_t right_low;\n    uint8_t right_high;\n    uint8_t up_low;\n    uint8_t up_high;\n    uint8_t down_low;\n    uint8_t down_high;\n} XrHidDeviceFov;\n\ntypedef struct {\n    uint8_t index;\n    int64_t timestamp;\n    int64_t exposure_time;\n} XrFrameEvent;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif //FFALCONXR_PACKET_H\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/interface/FXRApi.h",
    "content": "#ifndef FFALCONXR_API_H\n#define FFALCONXR_API_H\n\n#include \"base/FXRMacro.h\"\n#include \"base/FXRType.h\"\n#include \"device/usb/XRDeviceState.h\"\n#include \"ipc/FXRProtocol.h\"\n\n\nextern \"C\" {\n\n\n/**\n * 初始化\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL InitInstance();\n\n/**\n * IMU传感器的数据回调\n * @param acc       加速度计数据\n * @param gyro      陀螺仪数据\n * @param mag       磁力计数据\n * @param timeInNs  采集数据时间\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL RegisterIMUEventCallback(IMUEventCallback callback);\nRAYNEO_API_EXPORT void RAYNEO_API_CALL UnregisterIMUEventCallback(IMUEventCallback callback);\n\n/**\n * Vsync事件回调\n * @param leftEyeInMs   左眼屏幕的Vsync时间\n * @param rightEyeInMs  右眼屏幕的Vsync时间\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL RegisterVsyncEventCallback(VsyncEventCallback callback);\nRAYNEO_API_EXPORT void RAYNEO_API_CALL UnregisterVsyncEventCallback(VsyncEventCallback callback);\n\n/**\n * 运行状态事件回调\n * @param state 状态编码\n * @param data  状态信息\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL RegisterStateEventCallback(StateEventCallback callback);\nRAYNEO_API_EXPORT void RAYNEO_API_CALL UnregisterStateEventCallback(StateEventCallback callback);\n\n/**\n * 相机帧参数回调 (需先调用AcquireHardwareBuffer)\n * @param buffer       图像缓冲区\n * @param timestamp    时间戳\n * @param exposureTime 曝光时间\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL RegisterFrameEventCallback(FrameEventCallback callback);\nRAYNEO_API_EXPORT void RAYNEO_API_CALL UnregisterFrameEventCallback(FrameEventCallback callback);\n\n/**\n * 相机帧数据回调\n * @param data         图像原始数据\n * @param w            宽\n * @param h            高\n * @param timestamp    时间戳\n * @param exposureTime 曝光时间\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL RegisterFrameDataCallback(FrameDataCallback callback);\nRAYNEO_API_EXPORT void RAYNEO_API_CALL UnregisterFrameDataCallback(FrameDataCallback callback);\n\n/**\n * 启动XR模式，进入Runtime的生命周期\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL StartXR();\n\n/**\n * 停止XR模式，退出Runtime的生命周期\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL StopXR();\n\n/**\n * 切换到2D镜像模式\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL SwitchTo2D();\n\n/**\n * 切换到3D的双目模式\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL SwitchTo3D();\n\n/**\n * 开启眼镜上报IMU数据\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL OpenIMU();\n\n/**\n * 关闭眼镜上报IMU数据\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL CloseIMU();\n\n/**\n * 设置声音模式\n * @param mode 0 for 普通模式, 1 for 轻语模式\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL SetAudioMode(uint8_t mode);\n\n/**\n * 设置音量\n * @param val volume index (0~12)\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL SetAudioVolume(uint8_t val);\n\n/**\n * Disable hardware SBS switch\n * @param seconds 时长\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL DisableWheelKeySideBySide(uint8_t seconds);\n\n/**\n * 保存设置\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL SaveSettings();\n\n/**\n * 请求设备信息\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL AcquireDeviceInfo();\n\n/**\n * 读取设备信息\n * @return 设备信息\n */\nRAYNEO_API_EXPORT XRDeviceInfo RAYNEO_API_CALL FetchDeviceInfo();\n\n/**\n * Panel Display on\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL PanelPowerOn();\n\n/**\n * Panel Display off\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL PanelPowerOff();\n\n/**\n * Swap Two Panels Display Content\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL PanelPowerSwap();\n\n/**\n * set panel preset luminance\n * @param val\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL PanelLunaSet(uint8_t val);\n\n/**\n * save luminance value to ROM\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL PanelLunaSave();\n\n/**\n * set frame rate of device\n * only support 120fps and 60fps\n * @param val 120 means 120fps, other value means 60fps\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL PanelFrameRateSet(uint8_t val);\n\n/**\n * Reset all saved parameters\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL ResetSettings();\n\n/**\n * Change SIDE_BY_SIDE on/off\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL SwitchSideBySide();\n\n/**\n * 音频使能\n * @param channel  0 for left, 1 for right\n * @param state  0 for disable, 1 for enable\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL EnableAudio(uint8_t channel, uint8_t state);\n\n/**\n * P-Sensor detect enable/disable\n * @param state  0 for enable P-Sensor, 1 for Always wakeup\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL EnablePSensorDetect(uint8_t state);\n\n/**\n * Reboot the device to boot loader\n * @param seconds\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL RebootAndBootloader();\n\n/**\n * set mute mode, 仅白羊1.0支持\n * @param mute\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL EnableAudioPersistence(uint8_t mute);\n\n/**\n * 屏幕颜色参数设置\n * @param op 具体操作\n * @param value 值\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL PanelColorParamsAdjust(uint8_t op, uint8_t value);\n\n//--------------------- Tracking -----------------------------\n\n/**\n * Get/Predict pose of device\n * @param offsetInNs 0 means current pose, other means predict\n * @param rotation Quart(x, y, z, w)\n * @param position Vector3(x, y, z)\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL GetHeadTrackerPose(uint64_t offsetInNs, float* rotation, float* position);\n\n/**\n * Get the current pose of mobile device\n * @param rotation Quart(x, y, z, w)\n * @param position Vector3(x, y, z)\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL GetMobileTrackerPose(float* rotation, float* position);\n\n/**\n * Get current status of algo\n * @return status\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL GetHeadTrackerStatus();\n\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL GetNineAxisOrientation(float* orientation);\n\nRAYNEO_API_EXPORT float RAYNEO_API_CALL GetNineAxisAzimuth();\n\nRAYNEO_API_EXPORT float RAYNEO_API_CALL GetMagnetometerFieldStrength();\n\nRAYNEO_API_EXPORT int RAYNEO_API_CALL GetMagnetometerSensorAccuracy();\n\n/**\n * Recenter the internal head tracker pose\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL RecenterHeadTracker();\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL EnableSlamHeadTracker();\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL DisableSlamHeadTracker();\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL EnablePlaneDetection();\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL DisablePlaneDetection();\n\n/**\n * Get Plane Info\n * @param XRPlaneArray\n * @return\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL GetPlaneInfo(XRPlaneArray* planeInfo);\n\n// TODO:后续需要传入参数配置Camera输出流\nRAYNEO_API_EXPORT void RAYNEO_API_CALL OpenCamera();\n\n// 临时接口, 指定最大画幅比16:9分辨率打开相机\nRAYNEO_API_EXPORT void RAYNEO_API_CALL OpenMaxResCamera();\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL CloseCamera();\n\n/**\n * Acquire hardware buffers\n *\n * @param buffers           is a pointer to an array of AHardwareBuffer* used to store the acquired\n *                          hardware buffers. , but can be NULL if capacityInput is 0.\n * @param capacityInput     is the capacity of the buffers array, or 0 to indicate a request to\n *                          retrieve the required capacity.\n * @param countOutput       pointer to the count of buffers written, or a pointer to the required\n *                          capacity in the case that capacityInput is 0.\n * @return Error code or success flag.\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL AcquireHardwareBuffer(AHardwareBuffer** buffers, uint8_t capacityInput, uint8_t* countOutput);\n\n/**\n * Get the latest AHardwareBuffer\n *\n * @param buffer         the latest AHardwareBuffer\n * @param timestamp      the timestamp of the latest frame\n * @param exposureTime   the exposure time of the latest frame\n * @return Error code or success flag.\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL GetLatestBuffer(AHardwareBuffer** buffer, int64_t* timestamp, int64_t* exposureTime);\n\n/**\n * Get the latest frame\n *\n * @param data           the latest frame data\n * @param width          the width of the latest frame\n * @param height         the height of the latest frame\n * @param timestamp      the timestamp of the latest frame\n * @param exposureTime   the exposure time of the latest frame\n * @return Error code or success flag.\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL\nGetLatestFrame(uint8_t** data, uint32_t* width, uint32_t* height, int64_t* timestamp, int64_t* exposureTime);\n\n/**\n * Send command to runtime\n * @param unit runtime unit\n * @param command command detail\n * @param param\n * @param len\n * @return\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL SendCommand(FXRControlUnit unit,\n                                                      FXRControlCommand command,\n                                                      void* param = nullptr,\n                                                      uint32_t len = 0);\n\n/**\n * set property\n * @param item\n * @param value\n * @param len\n * @return\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL SetProp(const char* item, void* value, const int32_t len);\n\n/**\n * get set property\n * @param item\n * @param value\n * @param len\n * @return\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL GetProp(const char* item, void* value, int32_t& len);\n\n\n//--------------------- Query -----------------------------\n\n/**\n * Query the specific type's code of Runtime state\n */\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL QueryRuntimeState(FXRRuntimeStateType type);\n\n\n//--------------------- Configuration ----------------------\n/**\n * read configuration from external\n * @param reader callback\n */\nRAYNEO_API_EXPORT void RAYNEO_API_CALL RegisterXRConfigurationExternalReader(XRConfigExternalReader reader);\n}\n\n\n#endif //FFALCONXR_API_H\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/interface/FXRClient.h",
    "content": "#ifndef FFALCONXR_CLIENT_H\n#define FFALCONXR_CLIENT_H\n\n#include \"interface/FXRApi.h\"\n#include <android/native_window.h>\n\nextern \"C\" {\n\n\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL EstablishServiceConnection(int32_t fd);\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL ReleaseServiceConnection();\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL NativeVsync(int64_t frameTimeNanos, float displayRefreshRateHz);\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL LoadConfigFromMemory(const uint8_t* buf, const uint32_t len);\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL SetSurface(ANativeWindow* window, int32_t width, int32_t height);\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL SetWindowFocus(bool hasFocus);\n}\n\n\n#endif //FFALCONXR_CLIENT_H\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/interface/FXRServer.h",
    "content": "#ifndef FFALCONXR_SERVER_H\n#define FFALCONXR_SERVER_H\n\n#include \"interface/FXRApi.h\"\n\n\nextern \"C\" {\n\n\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL EstablishUsbConnection(int32_t fileDescriptor);\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL ReleaseUsbConnection();\n\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL AcceptConnection(int32_t fd);\n\nRAYNEO_API_EXPORT int32_t RAYNEO_API_CALL LoadConfigFromStorage(const char* path);\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL SetSensorFusionFactory(SensorFusionFactory factory);\n\nRAYNEO_API_EXPORT void RAYNEO_API_CALL RegisterConfigChangesNotifier(XRConfigBroadcastCallback notifier);\n}\n\n#endif //FFALCONXR_SERVER_H\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/ipc/FXRProtocol.h",
    "content": "#ifndef FFALCONXR_IPC_PROTOCOL_H\n#define FFALCONXR_IPC_PROTOCOL_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nenum FXRStateEvent {\n    kStateUnknown = 0,\n    kStateDeviceConnected,\n    kStateDeviceDisconnected,\n    kStateImuOn,\n    kStateImuOff,\n    kStateVolumeChanged,\n    kStateWheelKeyPressed,\n    kStateWheelKeyLongPressed,\n    kStateWheelKeyDoublePressed,\n    kStateDeviceInterrupt,\n    kStateDevicePlugged,\n    kStateDeviceUnPlugged,\n    kStatePanelLunaChanged,\n    kStateAudioModeChanged,\n    kStateGlassSleep,\n    kStateGlassWakeup,\n\n\n    //response\n    kStateDeviceInfoResponseArrived = 0x4000,\n\n\n    //Mag Calibration\n    kStateMagNeedCalibrate = 0x6000,\n    kStateMagDoingCalibrate = 0x6001,\n    kStateMagCalibrateSuccess = 0x6002,\n    kStateMagCalibrateFailed = 0x6003,\n\n    //time sync\n    kStateSynchronizeTime = 0x8001,\n};\n\n//注意与FxrApi.java中的定义保持一致\nenum CallbackType {\n    IMUEvent = 0,\n    StateEvent = 1,\n    VsyncEvent = 2,\n    FrameEvent = 3,\n};\n\nenum FXRControlUnit {\n    kUnitUnknown,\n    kUnitHeadTracker,\n    kUnitConfiguration,\n};\n\nenum FXRControlCommand {\n    kCtlCmdUnknown,\n    kCtlCmdStartMagCalibration,\n    kCtlCmdStopMagCalibration,\n    kCtlCmdResetRenderParameters,\n    kCtlCmdUseATW,\n    kCtlCmdUseSinglePass,\n};\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif //FFALCONXR_IPC_PROTOCOL_H\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/openxr/openxr.h",
    "content": "#ifndef OPENXR_H_\n#define OPENXR_H_ 1\n\n/*\n** Copyright 2017-2023 The Khronos Group Inc.\n**\n** SPDX-License-Identifier: Apache-2.0 OR MIT\n*/\n\n/*\n** This header is generated from the Khronos OpenXR XML API Registry.\n**\n*/\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n#define XR_VERSION_1_0 1\n#include \"openxr_platform_defines.h\"\n#define XR_MAKE_VERSION(major, minor, patch) \\\n    ((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL))\n\n// OpenXR current version number.\n#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 28)\n\n#define XR_VERSION_MAJOR(version) (uint16_t)(((uint64_t)(version) >> 48)& 0xffffULL)\n#define XR_VERSION_MINOR(version) (uint16_t)(((uint64_t)(version) >> 32) & 0xffffULL)\n#define XR_VERSION_PATCH(version) (uint32_t)((uint64_t)(version) & 0xffffffffULL)\n\n#define XR_MIN_COMPOSITION_LAYERS_SUPPORTED 16\n\n\n#if !defined(XR_NULL_HANDLE)\n#if (XR_PTR_SIZE == 8) && XR_CPP_NULLPTR_SUPPORTED\n#define XR_NULL_HANDLE nullptr\n#else\n#define XR_NULL_HANDLE 0\n#endif\n#endif\n\n\n#define XR_NULL_SYSTEM_ID 0\n\n\n#define XR_NULL_PATH 0\n\n\n#define XR_SUCCEEDED(result) ((result) >= 0)\n\n\n#define XR_FAILED(result) ((result) < 0)\n\n\n#define XR_UNQUALIFIED_SUCCESS(result) ((result) == 0)\n\n\n#define XR_NO_DURATION 0\n\n\n#define XR_INFINITE_DURATION 0x7fffffffffffffffLL\n\n\n#define XR_MIN_HAPTIC_DURATION -1\n\n\n#define XR_FREQUENCY_UNSPECIFIED 0\n\n\n#define XR_MAX_EVENT_DATA_SIZE sizeof(XrEventDataBuffer)\n\n\n#define XR_EXTENSION_ENUM_BASE 1000000000\n\n\n#define XR_EXTENSION_ENUM_STRIDE 1000\n\n\n#if !defined(XR_MAY_ALIAS)\n#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4))\n#define XR_MAY_ALIAS __attribute__((__may_alias__))\n#else\n#define XR_MAY_ALIAS\n#endif\n#endif\n\n\n#if !defined(XR_DEFINE_HANDLE)\n#if (XR_PTR_SIZE == 8)\n#define XR_DEFINE_HANDLE(object) typedef struct object##_T* object;\n#else\n#define XR_DEFINE_HANDLE(object) typedef uint64_t object;\n#endif\n#endif\n\n\n#if !defined(XR_DEFINE_ATOM)\n#define XR_DEFINE_ATOM(object) typedef uint64_t object;\n#endif\n\n\ntypedef uint64_t XrVersion;\ntypedef uint64_t XrFlags64;\nXR_DEFINE_ATOM(XrSystemId)\ntypedef uint32_t XrBool32;\nXR_DEFINE_ATOM(XrPath)\ntypedef int64_t XrTime;\ntypedef int64_t XrDuration;\nXR_DEFINE_HANDLE(XrInstance)\nXR_DEFINE_HANDLE(XrSession)\nXR_DEFINE_HANDLE(XrSpace)\nXR_DEFINE_HANDLE(XrAction)\nXR_DEFINE_HANDLE(XrSwapchain)\nXR_DEFINE_HANDLE(XrActionSet)\n#define XR_TRUE                           1\n#define XR_FALSE                          0\n#define XR_MAX_EXTENSION_NAME_SIZE        128\n#define XR_MAX_API_LAYER_NAME_SIZE        256\n#define XR_MAX_API_LAYER_DESCRIPTION_SIZE 256\n#define XR_MAX_SYSTEM_NAME_SIZE           256\n#define XR_MAX_APPLICATION_NAME_SIZE      128\n#define XR_MAX_ENGINE_NAME_SIZE           128\n#define XR_MAX_RUNTIME_NAME_SIZE          128\n#define XR_MAX_PATH_LENGTH                256\n#define XR_MAX_STRUCTURE_NAME_SIZE        64\n#define XR_MAX_RESULT_STRING_SIZE         64\n#define XR_MAX_ACTION_SET_NAME_SIZE       64\n#define XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE 128\n#define XR_MAX_ACTION_NAME_SIZE           64\n#define XR_MAX_LOCALIZED_ACTION_NAME_SIZE 128\n\ntypedef enum XrResult {\n    XR_SUCCESS = 0,\n    XR_TIMEOUT_EXPIRED = 1,\n    XR_SESSION_LOSS_PENDING = 3,\n    XR_EVENT_UNAVAILABLE = 4,\n    XR_SPACE_BOUNDS_UNAVAILABLE = 7,\n    XR_SESSION_NOT_FOCUSED = 8,\n    XR_FRAME_DISCARDED = 9,\n    XR_ERROR_VALIDATION_FAILURE = -1,\n    XR_ERROR_RUNTIME_FAILURE = -2,\n    XR_ERROR_OUT_OF_MEMORY = -3,\n    XR_ERROR_API_VERSION_UNSUPPORTED = -4,\n    XR_ERROR_INITIALIZATION_FAILED = -6,\n    XR_ERROR_FUNCTION_UNSUPPORTED = -7,\n    XR_ERROR_FEATURE_UNSUPPORTED = -8,\n    XR_ERROR_EXTENSION_NOT_PRESENT = -9,\n    XR_ERROR_LIMIT_REACHED = -10,\n    XR_ERROR_SIZE_INSUFFICIENT = -11,\n    XR_ERROR_HANDLE_INVALID = -12,\n    XR_ERROR_INSTANCE_LOST = -13,\n    XR_ERROR_SESSION_RUNNING = -14,\n    XR_ERROR_SESSION_NOT_RUNNING = -16,\n    XR_ERROR_SESSION_LOST = -17,\n    XR_ERROR_SYSTEM_INVALID = -18,\n    XR_ERROR_PATH_INVALID = -19,\n    XR_ERROR_PATH_COUNT_EXCEEDED = -20,\n    XR_ERROR_PATH_FORMAT_INVALID = -21,\n    XR_ERROR_PATH_UNSUPPORTED = -22,\n    XR_ERROR_LAYER_INVALID = -23,\n    XR_ERROR_LAYER_LIMIT_EXCEEDED = -24,\n    XR_ERROR_SWAPCHAIN_RECT_INVALID = -25,\n    XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED = -26,\n    XR_ERROR_ACTION_TYPE_MISMATCH = -27,\n    XR_ERROR_SESSION_NOT_READY = -28,\n    XR_ERROR_SESSION_NOT_STOPPING = -29,\n    XR_ERROR_TIME_INVALID = -30,\n    XR_ERROR_REFERENCE_SPACE_UNSUPPORTED = -31,\n    XR_ERROR_FILE_ACCESS_ERROR = -32,\n    XR_ERROR_FILE_CONTENTS_INVALID = -33,\n    XR_ERROR_FORM_FACTOR_UNSUPPORTED = -34,\n    XR_ERROR_FORM_FACTOR_UNAVAILABLE = -35,\n    XR_ERROR_API_LAYER_NOT_PRESENT = -36,\n    XR_ERROR_CALL_ORDER_INVALID = -37,\n    XR_ERROR_GRAPHICS_DEVICE_INVALID = -38,\n    XR_ERROR_POSE_INVALID = -39,\n    XR_ERROR_INDEX_OUT_OF_RANGE = -40,\n    XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED = -41,\n    XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED = -42,\n    XR_ERROR_NAME_DUPLICATED = -44,\n    XR_ERROR_NAME_INVALID = -45,\n    XR_ERROR_ACTIONSET_NOT_ATTACHED = -46,\n    XR_ERROR_ACTIONSETS_ALREADY_ATTACHED = -47,\n    XR_ERROR_LOCALIZED_NAME_DUPLICATED = -48,\n    XR_ERROR_LOCALIZED_NAME_INVALID = -49,\n    XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING = -50,\n    XR_ERROR_RUNTIME_UNAVAILABLE = -51,\n    XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR = -1000003000,\n    XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR = -1000003001,\n    XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT = -1000039001,\n    XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT = -1000053000,\n    XR_ERROR_CONTROLLER_MODEL_KEY_INVALID_MSFT = -1000055000,\n    XR_ERROR_REPROJECTION_MODE_UNSUPPORTED_MSFT = -1000066000,\n    XR_ERROR_COMPUTE_NEW_SCENE_NOT_COMPLETED_MSFT = -1000097000,\n    XR_ERROR_SCENE_COMPONENT_ID_INVALID_MSFT = -1000097001,\n    XR_ERROR_SCENE_COMPONENT_TYPE_MISMATCH_MSFT = -1000097002,\n    XR_ERROR_SCENE_MESH_BUFFER_ID_INVALID_MSFT = -1000097003,\n    XR_ERROR_SCENE_COMPUTE_FEATURE_INCOMPATIBLE_MSFT = -1000097004,\n    XR_ERROR_SCENE_COMPUTE_CONSISTENCY_MISMATCH_MSFT = -1000097005,\n    XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB = -1000101000,\n    XR_ERROR_COLOR_SPACE_UNSUPPORTED_FB = -1000108000,\n    XR_ERROR_SPACE_COMPONENT_NOT_SUPPORTED_FB = -1000113000,\n    XR_ERROR_SPACE_COMPONENT_NOT_ENABLED_FB = -1000113001,\n    XR_ERROR_SPACE_COMPONENT_STATUS_PENDING_FB = -1000113002,\n    XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB = -1000113003,\n    XR_ERROR_UNEXPECTED_STATE_PASSTHROUGH_FB = -1000118000,\n    XR_ERROR_FEATURE_ALREADY_CREATED_PASSTHROUGH_FB = -1000118001,\n    XR_ERROR_FEATURE_REQUIRED_PASSTHROUGH_FB = -1000118002,\n    XR_ERROR_NOT_PERMITTED_PASSTHROUGH_FB = -1000118003,\n    XR_ERROR_INSUFFICIENT_RESOURCES_PASSTHROUGH_FB = -1000118004,\n    XR_ERROR_UNKNOWN_PASSTHROUGH_FB = -1000118050,\n    XR_ERROR_RENDER_MODEL_KEY_INVALID_FB = -1000119000,\n    XR_RENDER_MODEL_UNAVAILABLE_FB = 1000119020,\n    XR_ERROR_MARKER_NOT_TRACKED_VARJO = -1000124000,\n    XR_ERROR_MARKER_ID_INVALID_VARJO = -1000124001,\n    XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT = -1000142001,\n    XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT = -1000142002,\n    XR_ERROR_SPACE_MAPPING_INSUFFICIENT_FB = -1000169000,\n    XR_ERROR_SPACE_LOCALIZATION_FAILED_FB = -1000169001,\n    XR_ERROR_SPACE_NETWORK_TIMEOUT_FB = -1000169002,\n    XR_ERROR_SPACE_NETWORK_REQUEST_FAILED_FB = -1000169003,\n    XR_ERROR_SPACE_CLOUD_STORAGE_DISABLED_FB = -1000169004,\n    XR_ERROR_PASSTHROUGH_COLOR_LUT_BUFFER_SIZE_MISMATCH_META = -1000266000,\n    XR_ERROR_HINT_ALREADY_SET_QCOM = -1000306000,\n    XR_ERROR_SPACE_NOT_LOCATABLE_EXT = -1000429000,\n    XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT = -1000429001,\n    XR_RESULT_MAX_ENUM = 0x7FFFFFFF\n} XrResult;\n\ntypedef enum XrStructureType {\n    XR_TYPE_UNKNOWN = 0,\n    XR_TYPE_API_LAYER_PROPERTIES = 1,\n    XR_TYPE_EXTENSION_PROPERTIES = 2,\n    XR_TYPE_INSTANCE_CREATE_INFO = 3,\n    XR_TYPE_SYSTEM_GET_INFO = 4,\n    XR_TYPE_SYSTEM_PROPERTIES = 5,\n    XR_TYPE_VIEW_LOCATE_INFO = 6,\n    XR_TYPE_VIEW = 7,\n    XR_TYPE_SESSION_CREATE_INFO = 8,\n    XR_TYPE_SWAPCHAIN_CREATE_INFO = 9,\n    XR_TYPE_SESSION_BEGIN_INFO = 10,\n    XR_TYPE_VIEW_STATE = 11,\n    XR_TYPE_FRAME_END_INFO = 12,\n    XR_TYPE_HAPTIC_VIBRATION = 13,\n    XR_TYPE_EVENT_DATA_BUFFER = 16,\n    XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING = 17,\n    XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED = 18,\n    XR_TYPE_ACTION_STATE_BOOLEAN = 23,\n    XR_TYPE_ACTION_STATE_FLOAT = 24,\n    XR_TYPE_ACTION_STATE_VECTOR2F = 25,\n    XR_TYPE_ACTION_STATE_POSE = 27,\n    XR_TYPE_ACTION_SET_CREATE_INFO = 28,\n    XR_TYPE_ACTION_CREATE_INFO = 29,\n    XR_TYPE_INSTANCE_PROPERTIES = 32,\n    XR_TYPE_FRAME_WAIT_INFO = 33,\n    XR_TYPE_COMPOSITION_LAYER_PROJECTION = 35,\n    XR_TYPE_COMPOSITION_LAYER_QUAD = 36,\n    XR_TYPE_REFERENCE_SPACE_CREATE_INFO = 37,\n    XR_TYPE_ACTION_SPACE_CREATE_INFO = 38,\n    XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING = 40,\n    XR_TYPE_VIEW_CONFIGURATION_VIEW = 41,\n    XR_TYPE_SPACE_LOCATION = 42,\n    XR_TYPE_SPACE_VELOCITY = 43,\n    XR_TYPE_FRAME_STATE = 44,\n    XR_TYPE_VIEW_CONFIGURATION_PROPERTIES = 45,\n    XR_TYPE_FRAME_BEGIN_INFO = 46,\n    XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW = 48,\n    XR_TYPE_EVENT_DATA_EVENTS_LOST = 49,\n    XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING = 51,\n    XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED = 52,\n    XR_TYPE_INTERACTION_PROFILE_STATE = 53,\n    XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO = 55,\n    XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO = 56,\n    XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO = 57,\n    XR_TYPE_ACTION_STATE_GET_INFO = 58,\n    XR_TYPE_HAPTIC_ACTION_INFO = 59,\n    XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO = 60,\n    XR_TYPE_ACTIONS_SYNC_INFO = 61,\n    XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO = 62,\n    XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO = 63,\n    XR_TYPE_COMPOSITION_LAYER_CUBE_KHR = 1000006000,\n    XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR = 1000008000,\n    XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR = 1000010000,\n    XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR = 1000014000,\n    XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT = 1000015000,\n    XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR = 1000017000,\n    XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR = 1000018000,\n    XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000019000,\n    XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000019001,\n    XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000019002,\n    XR_TYPE_DEBUG_UTILS_LABEL_EXT = 1000019003,\n    XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR = 1000023000,\n    XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR = 1000023001,\n    XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR = 1000023002,\n    XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR = 1000023003,\n    XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR = 1000023004,\n    XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR = 1000023005,\n    XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR = 1000024001,\n    XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR = 1000024002,\n    XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR = 1000024003,\n    XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR = 1000025000,\n    XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR = 1000025001,\n    XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR = 1000025002,\n    XR_TYPE_GRAPHICS_BINDING_D3D11_KHR = 1000027000,\n    XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR = 1000027001,\n    XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR = 1000027002,\n    XR_TYPE_GRAPHICS_BINDING_D3D12_KHR = 1000028000,\n    XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR = 1000028001,\n    XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR = 1000028002,\n    XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT = 1000030000,\n    XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT = 1000030001,\n    XR_TYPE_VISIBILITY_MASK_KHR = 1000031000,\n    XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR = 1000031001,\n    XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX = 1000033000,\n    XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX = 1000033003,\n    XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR = 1000034000,\n    XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT = 1000039000,\n    XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT = 1000039001,\n    XR_TYPE_COMPOSITION_LAYER_IMAGE_LAYOUT_FB = 1000040000,\n    XR_TYPE_COMPOSITION_LAYER_ALPHA_BLEND_FB = 1000041001,\n    XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT = 1000046000,\n    XR_TYPE_GRAPHICS_BINDING_EGL_MNDX = 1000048004,\n    XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT = 1000049000,\n    XR_TYPE_SPATIAL_GRAPH_STATIC_NODE_BINDING_CREATE_INFO_MSFT = 1000049001,\n    XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_GET_INFO_MSFT = 1000049002,\n    XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_MSFT = 1000049003,\n    XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT = 1000051000,\n    XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT = 1000051001,\n    XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT = 1000051002,\n    XR_TYPE_HAND_JOINT_LOCATIONS_EXT = 1000051003,\n    XR_TYPE_HAND_JOINT_VELOCITIES_EXT = 1000051004,\n    XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT = 1000052000,\n    XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT = 1000052001,\n    XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT = 1000052002,\n    XR_TYPE_HAND_MESH_MSFT = 1000052003,\n    XR_TYPE_HAND_POSE_TYPE_INFO_MSFT = 1000052004,\n    XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT = 1000053000,\n    XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT = 1000053001,\n    XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT = 1000053002,\n    XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT = 1000053003,\n    XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT = 1000053004,\n    XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT = 1000053005,\n    XR_TYPE_CONTROLLER_MODEL_KEY_STATE_MSFT = 1000055000,\n    XR_TYPE_CONTROLLER_MODEL_NODE_PROPERTIES_MSFT = 1000055001,\n    XR_TYPE_CONTROLLER_MODEL_PROPERTIES_MSFT = 1000055002,\n    XR_TYPE_CONTROLLER_MODEL_NODE_STATE_MSFT = 1000055003,\n    XR_TYPE_CONTROLLER_MODEL_STATE_MSFT = 1000055004,\n    XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC = 1000059000,\n    XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT = 1000063000,\n    XR_TYPE_COMPOSITION_LAYER_REPROJECTION_INFO_MSFT = 1000066000,\n    XR_TYPE_COMPOSITION_LAYER_REPROJECTION_PLANE_OVERRIDE_MSFT = 1000066001,\n    XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB = 1000070000,\n    XR_TYPE_COMPOSITION_LAYER_SECURE_CONTENT_FB = 1000072000,\n    XR_TYPE_BODY_TRACKER_CREATE_INFO_FB = 1000076001,\n    XR_TYPE_BODY_JOINTS_LOCATE_INFO_FB = 1000076002,\n    XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_FB = 1000076004,\n    XR_TYPE_BODY_JOINT_LOCATIONS_FB = 1000076005,\n    XR_TYPE_BODY_SKELETON_FB = 1000076006,\n    XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT = 1000078000,\n    XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE = 1000079000,\n    XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT = 1000080000,\n    XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR = 1000089000,\n    XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR = 1000090000,\n    XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR = 1000090001,\n    XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR = 1000090003,\n    XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR = 1000091000,\n    XR_TYPE_SCENE_OBSERVER_CREATE_INFO_MSFT = 1000097000,\n    XR_TYPE_SCENE_CREATE_INFO_MSFT = 1000097001,\n    XR_TYPE_NEW_SCENE_COMPUTE_INFO_MSFT = 1000097002,\n    XR_TYPE_VISUAL_MESH_COMPUTE_LOD_INFO_MSFT = 1000097003,\n    XR_TYPE_SCENE_COMPONENTS_MSFT = 1000097004,\n    XR_TYPE_SCENE_COMPONENTS_GET_INFO_MSFT = 1000097005,\n    XR_TYPE_SCENE_COMPONENT_LOCATIONS_MSFT = 1000097006,\n    XR_TYPE_SCENE_COMPONENTS_LOCATE_INFO_MSFT = 1000097007,\n    XR_TYPE_SCENE_OBJECTS_MSFT = 1000097008,\n    XR_TYPE_SCENE_COMPONENT_PARENT_FILTER_INFO_MSFT = 1000097009,\n    XR_TYPE_SCENE_OBJECT_TYPES_FILTER_INFO_MSFT = 1000097010,\n    XR_TYPE_SCENE_PLANES_MSFT = 1000097011,\n    XR_TYPE_SCENE_PLANE_ALIGNMENT_FILTER_INFO_MSFT = 1000097012,\n    XR_TYPE_SCENE_MESHES_MSFT = 1000097013,\n    XR_TYPE_SCENE_MESH_BUFFERS_GET_INFO_MSFT = 1000097014,\n    XR_TYPE_SCENE_MESH_BUFFERS_MSFT = 1000097015,\n    XR_TYPE_SCENE_MESH_VERTEX_BUFFER_MSFT = 1000097016,\n    XR_TYPE_SCENE_MESH_INDICES_UINT32_MSFT = 1000097017,\n    XR_TYPE_SCENE_MESH_INDICES_UINT16_MSFT = 1000097018,\n    XR_TYPE_SERIALIZED_SCENE_FRAGMENT_DATA_GET_INFO_MSFT = 1000098000,\n    XR_TYPE_SCENE_DESERIALIZE_INFO_MSFT = 1000098001,\n    XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB = 1000101000,\n    XR_TYPE_VIVE_TRACKER_PATHS_HTCX = 1000103000,\n    XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX = 1000103001,\n    XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC = 1000104000,\n    XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC = 1000104001,\n    XR_TYPE_FACIAL_EXPRESSIONS_HTC = 1000104002,\n    XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB = 1000108000,\n    XR_TYPE_HAND_TRACKING_MESH_FB = 1000110001,\n    XR_TYPE_HAND_TRACKING_SCALE_FB = 1000110003,\n    XR_TYPE_HAND_TRACKING_AIM_STATE_FB = 1000111001,\n    XR_TYPE_HAND_TRACKING_CAPSULES_STATE_FB = 1000112000,\n    XR_TYPE_SYSTEM_SPATIAL_ENTITY_PROPERTIES_FB = 1000113004,\n    XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_FB = 1000113003,\n    XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB = 1000113007,\n    XR_TYPE_SPACE_COMPONENT_STATUS_FB = 1000113001,\n    XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB = 1000113005,\n    XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB = 1000113006,\n    XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB = 1000114000,\n    XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB = 1000114001,\n    XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB = 1000114002,\n    XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB = 1000115000,\n    XR_TYPE_KEYBOARD_SPACE_CREATE_INFO_FB = 1000116009,\n    XR_TYPE_KEYBOARD_TRACKING_QUERY_FB = 1000116004,\n    XR_TYPE_SYSTEM_KEYBOARD_TRACKING_PROPERTIES_FB = 1000116002,\n    XR_TYPE_TRIANGLE_MESH_CREATE_INFO_FB = 1000117001,\n    XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB = 1000118000,\n    XR_TYPE_PASSTHROUGH_CREATE_INFO_FB = 1000118001,\n    XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB = 1000118002,\n    XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB = 1000118003,\n    XR_TYPE_GEOMETRY_INSTANCE_CREATE_INFO_FB = 1000118004,\n    XR_TYPE_GEOMETRY_INSTANCE_TRANSFORM_FB = 1000118005,\n    XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB = 1000118006,\n    XR_TYPE_PASSTHROUGH_STYLE_FB = 1000118020,\n    XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB = 1000118021,\n    XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB = 1000118022,\n    XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB = 1000118023,\n    XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB = 1000118030,\n    XR_TYPE_RENDER_MODEL_PATH_INFO_FB = 1000119000,\n    XR_TYPE_RENDER_MODEL_PROPERTIES_FB = 1000119001,\n    XR_TYPE_RENDER_MODEL_BUFFER_FB = 1000119002,\n    XR_TYPE_RENDER_MODEL_LOAD_INFO_FB = 1000119003,\n    XR_TYPE_SYSTEM_RENDER_MODEL_PROPERTIES_FB = 1000119004,\n    XR_TYPE_RENDER_MODEL_CAPABILITIES_REQUEST_FB = 1000119005,\n    XR_TYPE_BINDING_MODIFICATIONS_KHR = 1000120000,\n    XR_TYPE_VIEW_LOCATE_FOVEATED_RENDERING_VARJO = 1000121000,\n    XR_TYPE_FOVEATED_VIEW_CONFIGURATION_VIEW_VARJO = 1000121001,\n    XR_TYPE_SYSTEM_FOVEATED_RENDERING_PROPERTIES_VARJO = 1000121002,\n    XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_VARJO = 1000122000,\n    XR_TYPE_SYSTEM_MARKER_TRACKING_PROPERTIES_VARJO = 1000124000,\n    XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO = 1000124001,\n    XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO = 1000124002,\n    XR_TYPE_FRAME_END_INFO_ML = 1000135000,\n    XR_TYPE_GLOBAL_DIMMER_FRAME_END_INFO_ML = 1000136000,\n    XR_TYPE_COORDINATE_SPACE_CREATE_INFO_ML = 1000137000,\n    XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT = 1000142000,\n    XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT = 1000142001,\n    XR_TYPE_SPACE_QUERY_INFO_FB = 1000156001,\n    XR_TYPE_SPACE_QUERY_RESULTS_FB = 1000156002,\n    XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB = 1000156003,\n    XR_TYPE_SPACE_UUID_FILTER_INFO_FB = 1000156054,\n    XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB = 1000156052,\n    XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB = 1000156103,\n    XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB = 1000156104,\n    XR_TYPE_SPACE_SAVE_INFO_FB = 1000158000,\n    XR_TYPE_SPACE_ERASE_INFO_FB = 1000158001,\n    XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB = 1000158106,\n    XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB = 1000158107,\n    XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB = 1000160000,\n    XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB = 1000161000,\n    XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB = 1000162000,\n    XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB = 1000163000,\n    XR_TYPE_SPACE_SHARE_INFO_FB = 1000169001,\n    XR_TYPE_EVENT_DATA_SPACE_SHARE_COMPLETE_FB = 1000169002,\n    XR_TYPE_COMPOSITION_LAYER_SPACE_WARP_INFO_FB = 1000171000,\n    XR_TYPE_SYSTEM_SPACE_WARP_PROPERTIES_FB = 1000171001,\n    XR_TYPE_HAPTIC_AMPLITUDE_ENVELOPE_VIBRATION_FB = 1000173001,\n    XR_TYPE_SEMANTIC_LABELS_FB = 1000175000,\n    XR_TYPE_ROOM_LAYOUT_FB = 1000175001,\n    XR_TYPE_BOUNDARY_2D_FB = 1000175002,\n    XR_TYPE_SEMANTIC_LABELS_SUPPORT_INFO_FB = 1000175010,\n    XR_TYPE_DIGITAL_LENS_CONTROL_ALMALENCE = 1000196000,\n    XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB = 1000198001,\n    XR_TYPE_SCENE_CAPTURE_REQUEST_INFO_FB = 1000198050,\n    XR_TYPE_SPACE_CONTAINER_FB = 1000199000,\n    XR_TYPE_FOVEATION_EYE_TRACKED_PROFILE_CREATE_INFO_META = 1000200000,\n    XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META = 1000200001,\n    XR_TYPE_SYSTEM_FOVEATION_EYE_TRACKED_PROPERTIES_META = 1000200002,\n    XR_TYPE_SYSTEM_FACE_TRACKING_PROPERTIES_FB = 1000201004,\n    XR_TYPE_FACE_TRACKER_CREATE_INFO_FB = 1000201005,\n    XR_TYPE_FACE_EXPRESSION_INFO_FB = 1000201002,\n    XR_TYPE_FACE_EXPRESSION_WEIGHTS_FB = 1000201006,\n    XR_TYPE_EYE_TRACKER_CREATE_INFO_FB = 1000202001,\n    XR_TYPE_EYE_GAZES_INFO_FB = 1000202002,\n    XR_TYPE_EYE_GAZES_FB = 1000202003,\n    XR_TYPE_SYSTEM_EYE_TRACKING_PROPERTIES_FB = 1000202004,\n    XR_TYPE_PASSTHROUGH_KEYBOARD_HANDS_INTENSITY_FB = 1000203002,\n    XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB = 1000204000,\n    XR_TYPE_HAPTIC_PCM_VIBRATION_FB = 1000209001,\n    XR_TYPE_DEVICE_PCM_SAMPLE_RATE_STATE_FB = 1000209002,\n    XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_FB = 1000212000,\n    XR_TYPE_LOCAL_DIMMING_FRAME_END_INFO_META = 1000216000,\n    XR_TYPE_SYSTEM_VIRTUAL_KEYBOARD_PROPERTIES_META = 1000219001,\n    XR_TYPE_VIRTUAL_KEYBOARD_CREATE_INFO_META = 1000219002,\n    XR_TYPE_VIRTUAL_KEYBOARD_SPACE_CREATE_INFO_META = 1000219003,\n    XR_TYPE_VIRTUAL_KEYBOARD_LOCATION_INFO_META = 1000219004,\n    XR_TYPE_VIRTUAL_KEYBOARD_MODEL_VISIBILITY_SET_INFO_META = 1000219005,\n    XR_TYPE_VIRTUAL_KEYBOARD_ANIMATION_STATE_META = 1000219006,\n    XR_TYPE_VIRTUAL_KEYBOARD_MODEL_ANIMATION_STATES_META = 1000219007,\n    XR_TYPE_VIRTUAL_KEYBOARD_TEXTURE_DATA_META = 1000219009,\n    XR_TYPE_VIRTUAL_KEYBOARD_INPUT_INFO_META = 1000219010,\n    XR_TYPE_VIRTUAL_KEYBOARD_TEXT_CONTEXT_CHANGE_INFO_META = 1000219011,\n    XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_COMMIT_TEXT_META = 1000219014,\n    XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_BACKSPACE_META = 1000219015,\n    XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_ENTER_META = 1000219016,\n    XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_SHOWN_META = 1000219017,\n    XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_HIDDEN_META = 1000219018,\n    XR_TYPE_EXTERNAL_CAMERA_OCULUS = 1000226000,\n    XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META = 1000227000,\n    XR_TYPE_PERFORMANCE_METRICS_STATE_META = 1000232001,\n    XR_TYPE_PERFORMANCE_METRICS_COUNTER_META = 1000232002,\n    XR_TYPE_SPACE_LIST_SAVE_INFO_FB = 1000238000,\n    XR_TYPE_EVENT_DATA_SPACE_LIST_SAVE_COMPLETE_FB = 1000238001,\n    XR_TYPE_SPACE_USER_CREATE_INFO_FB = 1000241001,\n    XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META = 1000245000,\n    XR_TYPE_SYSTEM_PASSTHROUGH_COLOR_LUT_PROPERTIES_META = 1000266000,\n    XR_TYPE_PASSTHROUGH_COLOR_LUT_CREATE_INFO_META = 1000266001,\n    XR_TYPE_PASSTHROUGH_COLOR_LUT_UPDATE_INFO_META = 1000266002,\n    XR_TYPE_PASSTHROUGH_COLOR_MAP_LUT_META = 1000266100,\n    XR_TYPE_PASSTHROUGH_COLOR_MAP_INTERPOLATED_LUT_META = 1000266101,\n    XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC = 1000317001,\n    XR_TYPE_PASSTHROUGH_COLOR_HTC = 1000317002,\n    XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC = 1000317003,\n    XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC = 1000317004,\n    XR_TYPE_FOVEATION_APPLY_INFO_HTC = 1000318000,\n    XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC = 1000318001,\n    XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC = 1000318002,\n    XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT = 1000373000,\n    XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX = 1000375000,\n    XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX = 1000375001,\n    XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT = 1000428000,\n    XR_TYPE_HAND_TRACKING_DATA_SOURCE_STATE_EXT = 1000428001,\n    XR_TYPE_PLANE_DETECTOR_CREATE_INFO_EXT = 1000429001,\n    XR_TYPE_PLANE_DETECTOR_BEGIN_INFO_EXT = 1000429002,\n    XR_TYPE_PLANE_DETECTOR_GET_INFO_EXT = 1000429003,\n    XR_TYPE_PLANE_DETECTOR_LOCATIONS_EXT = 1000429004,\n    XR_TYPE_PLANE_DETECTOR_LOCATION_EXT = 1000429005,\n    XR_TYPE_PLANE_DETECTOR_POLYGON_BUFFER_EXT = 1000429006,\n    XR_TYPE_SYSTEM_PLANE_DETECTION_PROPERTIES_EXT = 1000429007,\n    XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR = XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR,\n    XR_TYPE_SWAPCHAIN_IMAGE_VULKAN2_KHR = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR,\n    XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR,\n    XR_TYPE_DEVICE_PCM_SAMPLE_RATE_GET_INFO_FB = XR_TYPE_DEVICE_PCM_SAMPLE_RATE_STATE_FB,\n    XR_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF\n} XrStructureType;\n\ntypedef enum XrFormFactor {\n    XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY = 1,\n    XR_FORM_FACTOR_HANDHELD_DISPLAY = 2,\n    XR_FORM_FACTOR_MAX_ENUM = 0x7FFFFFFF\n} XrFormFactor;\n\ntypedef enum XrViewConfigurationType {\n    XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO = 1,\n    XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO = 2,\n    XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO = 1000037000,\n    XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT = 1000054000,\n    XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM = 0x7FFFFFFF\n} XrViewConfigurationType;\n\ntypedef enum XrEnvironmentBlendMode {\n    XR_ENVIRONMENT_BLEND_MODE_OPAQUE = 1,\n    XR_ENVIRONMENT_BLEND_MODE_ADDITIVE = 2,\n    XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND = 3,\n    XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM = 0x7FFFFFFF\n} XrEnvironmentBlendMode;\n\ntypedef enum XrReferenceSpaceType {\n    XR_REFERENCE_SPACE_TYPE_VIEW = 1,\n    XR_REFERENCE_SPACE_TYPE_LOCAL = 2,\n    XR_REFERENCE_SPACE_TYPE_STAGE = 3,\n    XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT = 1000038000,\n    XR_REFERENCE_SPACE_TYPE_COMBINED_EYE_VARJO = 1000121000,\n    XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT = 1000426000,\n    XR_REFERENCE_SPACE_TYPE_MAX_ENUM = 0x7FFFFFFF\n} XrReferenceSpaceType;\n\ntypedef enum XrActionType {\n    XR_ACTION_TYPE_BOOLEAN_INPUT = 1,\n    XR_ACTION_TYPE_FLOAT_INPUT = 2,\n    XR_ACTION_TYPE_VECTOR2F_INPUT = 3,\n    XR_ACTION_TYPE_POSE_INPUT = 4,\n    XR_ACTION_TYPE_VIBRATION_OUTPUT = 100,\n    XR_ACTION_TYPE_MAX_ENUM = 0x7FFFFFFF\n} XrActionType;\n\ntypedef enum XrEyeVisibility {\n    XR_EYE_VISIBILITY_BOTH = 0,\n    XR_EYE_VISIBILITY_LEFT = 1,\n    XR_EYE_VISIBILITY_RIGHT = 2,\n    XR_EYE_VISIBILITY_MAX_ENUM = 0x7FFFFFFF\n} XrEyeVisibility;\n\ntypedef enum XrSessionState {\n    XR_SESSION_STATE_UNKNOWN = 0,\n    XR_SESSION_STATE_IDLE = 1,\n    XR_SESSION_STATE_READY = 2,\n    XR_SESSION_STATE_SYNCHRONIZED = 3,\n    XR_SESSION_STATE_VISIBLE = 4,\n    XR_SESSION_STATE_FOCUSED = 5,\n    XR_SESSION_STATE_STOPPING = 6,\n    XR_SESSION_STATE_LOSS_PENDING = 7,\n    XR_SESSION_STATE_EXITING = 8,\n    XR_SESSION_STATE_MAX_ENUM = 0x7FFFFFFF\n} XrSessionState;\n\ntypedef enum XrObjectType {\n    XR_OBJECT_TYPE_UNKNOWN = 0,\n    XR_OBJECT_TYPE_INSTANCE = 1,\n    XR_OBJECT_TYPE_SESSION = 2,\n    XR_OBJECT_TYPE_SWAPCHAIN = 3,\n    XR_OBJECT_TYPE_SPACE = 4,\n    XR_OBJECT_TYPE_ACTION_SET = 5,\n    XR_OBJECT_TYPE_ACTION = 6,\n    XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000019000,\n    XR_OBJECT_TYPE_SPATIAL_ANCHOR_MSFT = 1000039000,\n    XR_OBJECT_TYPE_SPATIAL_GRAPH_NODE_BINDING_MSFT = 1000049000,\n    XR_OBJECT_TYPE_HAND_TRACKER_EXT = 1000051000,\n    XR_OBJECT_TYPE_BODY_TRACKER_FB = 1000076000,\n    XR_OBJECT_TYPE_SCENE_OBSERVER_MSFT = 1000097000,\n    XR_OBJECT_TYPE_SCENE_MSFT = 1000097001,\n    XR_OBJECT_TYPE_FACIAL_TRACKER_HTC = 1000104000,\n    XR_OBJECT_TYPE_FOVEATION_PROFILE_FB = 1000114000,\n    XR_OBJECT_TYPE_TRIANGLE_MESH_FB = 1000117000,\n    XR_OBJECT_TYPE_PASSTHROUGH_FB = 1000118000,\n    XR_OBJECT_TYPE_PASSTHROUGH_LAYER_FB = 1000118002,\n    XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB = 1000118004,\n    XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT = 1000142000,\n    XR_OBJECT_TYPE_FACE_TRACKER_FB = 1000201000,\n    XR_OBJECT_TYPE_EYE_TRACKER_FB = 1000202000,\n    XR_OBJECT_TYPE_VIRTUAL_KEYBOARD_META = 1000219000,\n    XR_OBJECT_TYPE_SPACE_USER_FB = 1000241000,\n    XR_OBJECT_TYPE_PASSTHROUGH_COLOR_LUT_META = 1000266000,\n    XR_OBJECT_TYPE_PASSTHROUGH_HTC = 1000317000,\n    XR_OBJECT_TYPE_PLANE_DETECTOR_EXT = 1000429000,\n    XR_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF\n} XrObjectType;\ntypedef XrFlags64 XrInstanceCreateFlags;\n\n// Flag bits for XrInstanceCreateFlags\n\ntypedef XrFlags64 XrSessionCreateFlags;\n\n// Flag bits for XrSessionCreateFlags\n\ntypedef XrFlags64 XrSpaceVelocityFlags;\n\n// Flag bits for XrSpaceVelocityFlags\nstatic const XrSpaceVelocityFlags XR_SPACE_VELOCITY_LINEAR_VALID_BIT = 0x00000001;\nstatic const XrSpaceVelocityFlags XR_SPACE_VELOCITY_ANGULAR_VALID_BIT = 0x00000002;\n\ntypedef XrFlags64 XrSpaceLocationFlags;\n\n// Flag bits for XrSpaceLocationFlags\nstatic const XrSpaceLocationFlags XR_SPACE_LOCATION_ORIENTATION_VALID_BIT = 0x00000001;\nstatic const XrSpaceLocationFlags XR_SPACE_LOCATION_POSITION_VALID_BIT = 0x00000002;\nstatic const XrSpaceLocationFlags XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT = 0x00000004;\nstatic const XrSpaceLocationFlags XR_SPACE_LOCATION_POSITION_TRACKED_BIT = 0x00000008;\n\ntypedef XrFlags64 XrSwapchainCreateFlags;\n\n// Flag bits for XrSwapchainCreateFlags\nstatic const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT = 0x00000001;\nstatic const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT = 0x00000002;\n\ntypedef XrFlags64 XrSwapchainUsageFlags;\n\n// Flag bits for XrSwapchainUsageFlags\nstatic const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT = 0x00000001;\nstatic const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000002;\nstatic const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT = 0x00000004;\nstatic const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT = 0x00000008;\nstatic const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT = 0x00000010;\nstatic const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_SAMPLED_BIT = 0x00000020;\nstatic const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT = 0x00000040;\nstatic const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND = 0x00000080;\nstatic const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_KHR = 0x00000080;  // alias of XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND\n\ntypedef XrFlags64 XrCompositionLayerFlags;\n\n// Flag bits for XrCompositionLayerFlags\nstatic const XrCompositionLayerFlags XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT = 0x00000001;\nstatic const XrCompositionLayerFlags XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT = 0x00000002;\nstatic const XrCompositionLayerFlags XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT = 0x00000004;\n\ntypedef XrFlags64 XrViewStateFlags;\n\n// Flag bits for XrViewStateFlags\nstatic const XrViewStateFlags XR_VIEW_STATE_ORIENTATION_VALID_BIT = 0x00000001;\nstatic const XrViewStateFlags XR_VIEW_STATE_POSITION_VALID_BIT = 0x00000002;\nstatic const XrViewStateFlags XR_VIEW_STATE_ORIENTATION_TRACKED_BIT = 0x00000004;\nstatic const XrViewStateFlags XR_VIEW_STATE_POSITION_TRACKED_BIT = 0x00000008;\n\ntypedef XrFlags64 XrInputSourceLocalizedNameFlags;\n\n// Flag bits for XrInputSourceLocalizedNameFlags\nstatic const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT = 0x00000001;\nstatic const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT = 0x00000002;\nstatic const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT = 0x00000004;\n\ntypedef void (XRAPI_PTR *PFN_xrVoidFunction)(void);\ntypedef struct XrApiLayerProperties {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    char layerName[XR_MAX_API_LAYER_NAME_SIZE];\n    XrVersion specVersion;\n    uint32_t layerVersion;\n    char description[XR_MAX_API_LAYER_DESCRIPTION_SIZE];\n} XrApiLayerProperties;\n\ntypedef struct XrExtensionProperties {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    char extensionName[XR_MAX_EXTENSION_NAME_SIZE];\n    uint32_t extensionVersion;\n} XrExtensionProperties;\n\ntypedef struct XrApplicationInfo {\n    char applicationName[XR_MAX_APPLICATION_NAME_SIZE];\n    uint32_t applicationVersion;\n    char engineName[XR_MAX_ENGINE_NAME_SIZE];\n    uint32_t engineVersion;\n    XrVersion apiVersion;\n} XrApplicationInfo;\n\ntypedef struct XrInstanceCreateInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrInstanceCreateFlags createFlags;\n    XrApplicationInfo applicationInfo;\n    uint32_t enabledApiLayerCount;\n    const char *const *enabledApiLayerNames;\n    uint32_t enabledExtensionCount;\n    const char *const *enabledExtensionNames;\n} XrInstanceCreateInfo;\n\ntypedef struct XrInstanceProperties {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrVersion runtimeVersion;\n    char runtimeName[XR_MAX_RUNTIME_NAME_SIZE];\n} XrInstanceProperties;\n\ntypedef struct XrEventDataBuffer {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint8_t varying[4000];\n} XrEventDataBuffer;\n\ntypedef struct XrSystemGetInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrFormFactor formFactor;\n} XrSystemGetInfo;\n\ntypedef struct XrSystemGraphicsProperties {\n    uint32_t maxSwapchainImageHeight;\n    uint32_t maxSwapchainImageWidth;\n    uint32_t maxLayerCount;\n} XrSystemGraphicsProperties;\n\ntypedef struct XrSystemTrackingProperties {\n    XrBool32 orientationTracking;\n    XrBool32 positionTracking;\n} XrSystemTrackingProperties;\n\ntypedef struct XrSystemProperties {\n    XrStructureType type;\n    void *XR_MAY_ALIAS            next;\n    XrSystemId systemId;\n    uint32_t vendorId;\n    char systemName[XR_MAX_SYSTEM_NAME_SIZE];\n    XrSystemGraphicsProperties graphicsProperties;\n    XrSystemTrackingProperties trackingProperties;\n} XrSystemProperties;\n\ntypedef struct XrSessionCreateInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSessionCreateFlags createFlags;\n    XrSystemId systemId;\n} XrSessionCreateInfo;\n\ntypedef struct XrVector3f {\n    float x;\n    float y;\n    float z;\n} XrVector3f;\n\n// XrSpaceVelocity extends XrSpaceLocation\ntypedef struct XrSpaceVelocity {\n    XrStructureType type;\n    void *XR_MAY_ALIAS      next;\n    XrSpaceVelocityFlags velocityFlags;\n    XrVector3f linearVelocity;\n    XrVector3f angularVelocity;\n} XrSpaceVelocity;\n\ntypedef struct XrQuaternionf {\n    float x;\n    float y;\n    float z;\n    float w;\n} XrQuaternionf;\n\ntypedef struct XrPosef {\n    XrQuaternionf orientation;\n    XrVector3f position;\n} XrPosef;\n\ntypedef struct XrReferenceSpaceCreateInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrReferenceSpaceType referenceSpaceType;\n    XrPosef poseInReferenceSpace;\n} XrReferenceSpaceCreateInfo;\n\ntypedef struct XrExtent2Df {\n    float width;\n    float height;\n} XrExtent2Df;\n\ntypedef struct XrActionSpaceCreateInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAction action;\n    XrPath subactionPath;\n    XrPosef poseInActionSpace;\n} XrActionSpaceCreateInfo;\n\ntypedef struct XrSpaceLocation {\n    XrStructureType type;\n    void *XR_MAY_ALIAS      next;\n    XrSpaceLocationFlags locationFlags;\n    XrPosef pose;\n} XrSpaceLocation;\n\ntypedef struct XrViewConfigurationProperties {\n    XrStructureType type;\n    void *XR_MAY_ALIAS         next;\n    XrViewConfigurationType viewConfigurationType;\n    XrBool32 fovMutable;\n} XrViewConfigurationProperties;\n\ntypedef struct XrViewConfigurationView {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t recommendedImageRectWidth;\n    uint32_t maxImageRectWidth;\n    uint32_t recommendedImageRectHeight;\n    uint32_t maxImageRectHeight;\n    uint32_t recommendedSwapchainSampleCount;\n    uint32_t maxSwapchainSampleCount;\n} XrViewConfigurationView;\n\ntypedef struct XrSwapchainCreateInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSwapchainCreateFlags createFlags;\n    XrSwapchainUsageFlags usageFlags;\n    int64_t format;\n    uint32_t sampleCount;\n    uint32_t width;\n    uint32_t height;\n    uint32_t faceCount;\n    uint32_t arraySize;\n    uint32_t mipCount;\n} XrSwapchainCreateInfo;\n\ntypedef struct XR_MAY_ALIAS XrSwapchainImageBaseHeader {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n} XrSwapchainImageBaseHeader;\n\ntypedef struct XrSwapchainImageAcquireInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrSwapchainImageAcquireInfo;\n\ntypedef struct XrSwapchainImageWaitInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrDuration timeout;\n} XrSwapchainImageWaitInfo;\n\ntypedef struct XrSwapchainImageReleaseInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrSwapchainImageReleaseInfo;\n\ntypedef struct XrSessionBeginInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrViewConfigurationType primaryViewConfigurationType;\n} XrSessionBeginInfo;\n\ntypedef struct XrFrameWaitInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrFrameWaitInfo;\n\ntypedef struct XrFrameState {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrTime predictedDisplayTime;\n    XrDuration predictedDisplayPeriod;\n    XrBool32 shouldRender;\n} XrFrameState;\n\ntypedef struct XrFrameBeginInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrFrameBeginInfo;\n\ntypedef struct XR_MAY_ALIAS XrCompositionLayerBaseHeader {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrCompositionLayerFlags layerFlags;\n    XrSpace space;\n} XrCompositionLayerBaseHeader;\n\ntypedef struct XrFrameEndInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                      next;\n    XrTime displayTime;\n    XrEnvironmentBlendMode environmentBlendMode;\n    uint32_t layerCount;\n    const XrCompositionLayerBaseHeader *const *layers;\n} XrFrameEndInfo;\n\ntypedef struct XrViewLocateInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrViewConfigurationType viewConfigurationType;\n    XrTime displayTime;\n    XrSpace space;\n} XrViewLocateInfo;\n\ntypedef struct XrViewState {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrViewStateFlags viewStateFlags;\n} XrViewState;\n\ntypedef struct XrFovf {\n    float angleLeft;\n    float angleRight;\n    float angleUp;\n    float angleDown;\n} XrFovf;\n\ntypedef struct XrView {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrPosef pose;\n    XrFovf fov;\n} XrView;\n\ntypedef struct XrActionSetCreateInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    char actionSetName[XR_MAX_ACTION_SET_NAME_SIZE];\n    char localizedActionSetName[XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE];\n    uint32_t priority;\n} XrActionSetCreateInfo;\n\ntypedef struct XrActionCreateInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    char actionName[XR_MAX_ACTION_NAME_SIZE];\n    XrActionType actionType;\n    uint32_t countSubactionPaths;\n    const XrPath *subactionPaths;\n    char localizedActionName[XR_MAX_LOCALIZED_ACTION_NAME_SIZE];\n} XrActionCreateInfo;\n\ntypedef struct XrActionSuggestedBinding {\n    XrAction action;\n    XrPath binding;\n} XrActionSuggestedBinding;\n\ntypedef struct XrInteractionProfileSuggestedBinding {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS           next;\n    XrPath interactionProfile;\n    uint32_t countSuggestedBindings;\n    const XrActionSuggestedBinding *suggestedBindings;\n} XrInteractionProfileSuggestedBinding;\n\ntypedef struct XrSessionActionSetsAttachInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t countActionSets;\n    const XrActionSet *actionSets;\n} XrSessionActionSetsAttachInfo;\n\ntypedef struct XrInteractionProfileState {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrPath interactionProfile;\n} XrInteractionProfileState;\n\ntypedef struct XrActionStateGetInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAction action;\n    XrPath subactionPath;\n} XrActionStateGetInfo;\n\ntypedef struct XrActionStateBoolean {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 currentState;\n    XrBool32 changedSinceLastSync;\n    XrTime lastChangeTime;\n    XrBool32 isActive;\n} XrActionStateBoolean;\n\ntypedef struct XrActionStateFloat {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    float currentState;\n    XrBool32 changedSinceLastSync;\n    XrTime lastChangeTime;\n    XrBool32 isActive;\n} XrActionStateFloat;\n\ntypedef struct XrVector2f {\n    float x;\n    float y;\n} XrVector2f;\n\ntypedef struct XrActionStateVector2f {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrVector2f currentState;\n    XrBool32 changedSinceLastSync;\n    XrTime lastChangeTime;\n    XrBool32 isActive;\n} XrActionStateVector2f;\n\ntypedef struct XrActionStatePose {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 isActive;\n} XrActionStatePose;\n\ntypedef struct XrActiveActionSet {\n    XrActionSet actionSet;\n    XrPath subactionPath;\n} XrActiveActionSet;\n\ntypedef struct XrActionsSyncInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t countActiveActionSets;\n    const XrActiveActionSet *activeActionSets;\n} XrActionsSyncInfo;\n\ntypedef struct XrBoundSourcesForActionEnumerateInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAction action;\n} XrBoundSourcesForActionEnumerateInfo;\n\ntypedef struct XrInputSourceLocalizedNameGetInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS           next;\n    XrPath sourcePath;\n    XrInputSourceLocalizedNameFlags whichComponents;\n} XrInputSourceLocalizedNameGetInfo;\n\ntypedef struct XrHapticActionInfo {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAction action;\n    XrPath subactionPath;\n} XrHapticActionInfo;\n\ntypedef struct XR_MAY_ALIAS XrHapticBaseHeader {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrHapticBaseHeader;\n\ntypedef struct XR_MAY_ALIAS XrBaseInStructure {\n    XrStructureType type;\n    const struct XrBaseInStructure *next;\n} XrBaseInStructure;\n\ntypedef struct XR_MAY_ALIAS XrBaseOutStructure {\n    XrStructureType type;\n    struct XrBaseOutStructure *next;\n} XrBaseOutStructure;\n\ntypedef struct XrOffset2Di {\n    int32_t x;\n    int32_t y;\n} XrOffset2Di;\n\ntypedef struct XrExtent2Di {\n    int32_t width;\n    int32_t height;\n} XrExtent2Di;\n\ntypedef struct XrRect2Di {\n    XrOffset2Di offset;\n    XrExtent2Di extent;\n} XrRect2Di;\n\ntypedef struct XrSwapchainSubImage {\n    XrSwapchain swapchain;\n    XrRect2Di imageRect;\n    uint32_t imageArrayIndex;\n} XrSwapchainSubImage;\n\ntypedef struct XrCompositionLayerProjectionView {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrPosef pose;\n    XrFovf fov;\n    XrSwapchainSubImage subImage;\n} XrCompositionLayerProjectionView;\n\ntypedef struct XrCompositionLayerProjection {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                   next;\n    XrCompositionLayerFlags layerFlags;\n    XrSpace space;\n    uint32_t viewCount;\n    const XrCompositionLayerProjectionView *views;\n} XrCompositionLayerProjection;\n\ntypedef struct XrCompositionLayerQuad {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrCompositionLayerFlags layerFlags;\n    XrSpace space;\n    XrEyeVisibility eyeVisibility;\n    XrSwapchainSubImage subImage;\n    XrPosef pose;\n    XrExtent2Df size;\n} XrCompositionLayerQuad;\n\ntypedef struct XR_MAY_ALIAS XrEventDataBaseHeader {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrEventDataBaseHeader;\n\ntypedef struct XrEventDataEventsLost {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t lostEventCount;\n} XrEventDataEventsLost;\n\ntypedef struct XrEventDataInstanceLossPending {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrTime lossTime;\n} XrEventDataInstanceLossPending;\n\ntypedef struct XrEventDataSessionStateChanged {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSession session;\n    XrSessionState state;\n    XrTime time;\n} XrEventDataSessionStateChanged;\n\ntypedef struct XrEventDataReferenceSpaceChangePending {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSession session;\n    XrReferenceSpaceType referenceSpaceType;\n    XrTime changeTime;\n    XrBool32 poseValid;\n    XrPosef poseInPreviousSpace;\n} XrEventDataReferenceSpaceChangePending;\n\ntypedef struct XrEventDataInteractionProfileChanged {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSession session;\n} XrEventDataInteractionProfileChanged;\n\ntypedef struct XrHapticVibration {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrDuration duration;\n    float frequency;\n    float amplitude;\n} XrHapticVibration;\n\ntypedef struct XrOffset2Df {\n    float x;\n    float y;\n} XrOffset2Df;\n\ntypedef struct XrRect2Df {\n    XrOffset2Df offset;\n    XrExtent2Df extent;\n} XrRect2Df;\n\ntypedef struct XrVector4f {\n    float x;\n    float y;\n    float z;\n    float w;\n} XrVector4f;\n\ntypedef struct XrColor4f {\n    float r;\n    float g;\n    float b;\n    float a;\n} XrColor4f;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProcAddr)(XrInstance instance, const char *name,\n                                                        PFN_xrVoidFunction *function);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateApiLayerProperties)(uint32_t propertyCapacityInput,\n                                                                uint32_t *propertyCountOutput,\n                                                                XrApiLayerProperties *properties);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateInstanceExtensionProperties)(const char *layerName,\n                                                                         uint32_t propertyCapacityInput,\n                                                                         uint32_t *propertyCountOutput,\n                                                                         XrExtensionProperties *properties);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateInstance)(const XrInstanceCreateInfo *createInfo,\n                                                   XrInstance *instance);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyInstance)(XrInstance instance);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProperties)(XrInstance instance,\n                                                          XrInstanceProperties *instanceProperties);\ntypedef XrResult (XRAPI_PTR *PFN_xrPollEvent)(XrInstance instance, XrEventDataBuffer *eventData);\ntypedef XrResult (XRAPI_PTR *PFN_xrResultToString)(XrInstance instance, XrResult value,\n                                                   char buffer[XR_MAX_RESULT_STRING_SIZE]);\ntypedef XrResult (XRAPI_PTR *PFN_xrStructureTypeToString)(XrInstance instance,\n                                                          XrStructureType value,\n                                                          char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSystem)(XrInstance instance, const XrSystemGetInfo *getInfo,\n                                              XrSystemId *systemId);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSystemProperties)(XrInstance instance, XrSystemId systemId,\n                                                        XrSystemProperties *properties);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateEnvironmentBlendModes)(XrInstance instance,\n                                                                   XrSystemId systemId,\n                                                                   XrViewConfigurationType viewConfigurationType,\n                                                                   uint32_t environmentBlendModeCapacityInput,\n                                                                   uint32_t *environmentBlendModeCountOutput,\n                                                                   XrEnvironmentBlendMode *environmentBlendModes);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSession)(XrInstance instance,\n                                                  const XrSessionCreateInfo *createInfo,\n                                                  XrSession *session);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroySession)(XrSession session);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateReferenceSpaces)(XrSession session,\n                                                             uint32_t spaceCapacityInput,\n                                                             uint32_t *spaceCountOutput,\n                                                             XrReferenceSpaceType *spaces);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateReferenceSpace)(XrSession session,\n                                                         const XrReferenceSpaceCreateInfo *createInfo,\n                                                         XrSpace *space);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetReferenceSpaceBoundsRect)(XrSession session,\n                                                                XrReferenceSpaceType referenceSpaceType,\n                                                                XrExtent2Df *bounds);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateActionSpace)(XrSession session,\n                                                      const XrActionSpaceCreateInfo *createInfo,\n                                                      XrSpace *space);\ntypedef XrResult (XRAPI_PTR *PFN_xrLocateSpace)(XrSpace space, XrSpace baseSpace, XrTime time,\n                                                XrSpaceLocation *location);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroySpace)(XrSpace space);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurations)(XrInstance instance,\n                                                                XrSystemId systemId,\n                                                                uint32_t viewConfigurationTypeCapacityInput,\n                                                                uint32_t *viewConfigurationTypeCountOutput,\n                                                                XrViewConfigurationType *viewConfigurationTypes);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetViewConfigurationProperties)(XrInstance instance,\n                                                                   XrSystemId systemId,\n                                                                   XrViewConfigurationType viewConfigurationType,\n                                                                   XrViewConfigurationProperties *configurationProperties);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurationViews)(XrInstance instance,\n                                                                    XrSystemId systemId,\n                                                                    XrViewConfigurationType viewConfigurationType,\n                                                                    uint32_t viewCapacityInput,\n                                                                    uint32_t *viewCountOutput,\n                                                                    XrViewConfigurationView *views);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainFormats)(XrSession session,\n                                                              uint32_t formatCapacityInput,\n                                                              uint32_t *formatCountOutput,\n                                                              int64_t *formats);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchain)(XrSession session,\n                                                    const XrSwapchainCreateInfo *createInfo,\n                                                    XrSwapchain *swapchain);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroySwapchain)(XrSwapchain swapchain);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainImages)(XrSwapchain swapchain,\n                                                             uint32_t imageCapacityInput,\n                                                             uint32_t *imageCountOutput,\n                                                             XrSwapchainImageBaseHeader *images);\ntypedef XrResult (XRAPI_PTR *PFN_xrAcquireSwapchainImage)(XrSwapchain swapchain,\n                                                          const XrSwapchainImageAcquireInfo *acquireInfo,\n                                                          uint32_t *index);\ntypedef XrResult (XRAPI_PTR *PFN_xrWaitSwapchainImage)(XrSwapchain swapchain,\n                                                       const XrSwapchainImageWaitInfo *waitInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrReleaseSwapchainImage)(XrSwapchain swapchain,\n                                                          const XrSwapchainImageReleaseInfo *releaseInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrBeginSession)(XrSession session,\n                                                 const XrSessionBeginInfo *beginInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrEndSession)(XrSession session);\ntypedef XrResult (XRAPI_PTR *PFN_xrRequestExitSession)(XrSession session);\ntypedef XrResult (XRAPI_PTR *PFN_xrWaitFrame)(XrSession session,\n                                              const XrFrameWaitInfo *frameWaitInfo,\n                                              XrFrameState *frameState);\ntypedef XrResult (XRAPI_PTR *PFN_xrBeginFrame)(XrSession session,\n                                               const XrFrameBeginInfo *frameBeginInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrEndFrame)(XrSession session, const XrFrameEndInfo *frameEndInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrLocateViews)(XrSession session,\n                                                const XrViewLocateInfo *viewLocateInfo,\n                                                XrViewState *viewState, uint32_t viewCapacityInput,\n                                                uint32_t *viewCountOutput, XrView *views);\ntypedef XrResult (XRAPI_PTR *PFN_xrStringToPath)(XrInstance instance, const char *pathString,\n                                                 XrPath *path);\ntypedef XrResult (XRAPI_PTR *PFN_xrPathToString)(XrInstance instance, XrPath path,\n                                                 uint32_t bufferCapacityInput,\n                                                 uint32_t *bufferCountOutput, char *buffer);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateActionSet)(XrInstance instance,\n                                                    const XrActionSetCreateInfo *createInfo,\n                                                    XrActionSet *actionSet);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyActionSet)(XrActionSet actionSet);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateAction)(XrActionSet actionSet,\n                                                 const XrActionCreateInfo *createInfo,\n                                                 XrAction *action);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyAction)(XrAction action);\ntypedef XrResult (XRAPI_PTR *PFN_xrSuggestInteractionProfileBindings)(XrInstance instance,\n                                                                      const XrInteractionProfileSuggestedBinding *suggestedBindings);\ntypedef XrResult (XRAPI_PTR *PFN_xrAttachSessionActionSets)(XrSession session,\n                                                            const XrSessionActionSetsAttachInfo *attachInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetCurrentInteractionProfile)(XrSession session,\n                                                                 XrPath topLevelUserPath,\n                                                                 XrInteractionProfileState *interactionProfile);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetActionStateBoolean)(XrSession session,\n                                                          const XrActionStateGetInfo *getInfo,\n                                                          XrActionStateBoolean *state);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetActionStateFloat)(XrSession session,\n                                                        const XrActionStateGetInfo *getInfo,\n                                                        XrActionStateFloat *state);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetActionStateVector2f)(XrSession session,\n                                                           const XrActionStateGetInfo *getInfo,\n                                                           XrActionStateVector2f *state);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetActionStatePose)(XrSession session,\n                                                       const XrActionStateGetInfo *getInfo,\n                                                       XrActionStatePose *state);\ntypedef XrResult (XRAPI_PTR *PFN_xrSyncActions)(XrSession session,\n                                                const XrActionsSyncInfo *syncInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateBoundSourcesForAction)(XrSession session,\n                                                                   const XrBoundSourcesForActionEnumerateInfo *enumerateInfo,\n                                                                   uint32_t sourceCapacityInput,\n                                                                   uint32_t *sourceCountOutput,\n                                                                   XrPath *sources);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetInputSourceLocalizedName)(XrSession session,\n                                                                const XrInputSourceLocalizedNameGetInfo *getInfo,\n                                                                uint32_t bufferCapacityInput,\n                                                                uint32_t *bufferCountOutput,\n                                                                char *buffer);\ntypedef XrResult (XRAPI_PTR *PFN_xrApplyHapticFeedback)(XrSession session,\n                                                        const XrHapticActionInfo *hapticActionInfo,\n                                                        const XrHapticBaseHeader *hapticFeedback);\ntypedef XrResult (XRAPI_PTR *PFN_xrStopHapticFeedback)(XrSession session,\n                                                       const XrHapticActionInfo *hapticActionInfo);\n\n#ifndef XR_NO_PROTOTYPES\nXRAPI_ATTR __attribute__((unused)) XrResult XRAPI_CALL xrGetInstanceProcAddr(\n        XrInstance instance,\n        const char *name,\n        PFN_xrVoidFunction *function);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(\n        uint32_t propertyCapacityInput,\n        uint32_t *propertyCountOutput,\n        XrApiLayerProperties *properties);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(\n        const char *layerName,\n        uint32_t propertyCapacityInput,\n        uint32_t *propertyCountOutput,\n        XrExtensionProperties *properties);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(\n        const XrInstanceCreateInfo *createInfo,\n        XrInstance *instance);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(\n        XrInstance instance);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(\n        XrInstance instance,\n        XrInstanceProperties *instanceProperties);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(\n        XrInstance instance,\n        XrEventDataBuffer *eventData);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrResultToString(\n        XrInstance instance,\n        XrResult value,\n        char buffer[XR_MAX_RESULT_STRING_SIZE]);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(\n        XrInstance instance,\n        XrStructureType value,\n        char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(\n        XrInstance instance,\n        const XrSystemGetInfo *getInfo,\n        XrSystemId *systemId);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(\n        XrInstance instance,\n        XrSystemId systemId,\n        XrSystemProperties *properties);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(\n        XrInstance instance,\n        XrSystemId systemId,\n        XrViewConfigurationType viewConfigurationType,\n        uint32_t environmentBlendModeCapacityInput,\n        uint32_t *environmentBlendModeCountOutput,\n        XrEnvironmentBlendMode *environmentBlendModes);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(\n        XrInstance instance,\n        const XrSessionCreateInfo *createInfo,\n        XrSession *session);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroySession(\n        XrSession session);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReferenceSpaces(\n        XrSession session,\n        uint32_t spaceCapacityInput,\n        uint32_t *spaceCountOutput,\n        XrReferenceSpaceType *spaces);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateReferenceSpace(\n        XrSession session,\n        const XrReferenceSpaceCreateInfo *createInfo,\n        XrSpace *space);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(\n        XrSession session,\n        XrReferenceSpaceType referenceSpaceType,\n        XrExtent2Df *bounds);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSpace(\n        XrSession session,\n        const XrActionSpaceCreateInfo *createInfo,\n        XrSpace *space);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrLocateSpace(\n        XrSpace space,\n        XrSpace baseSpace,\n        XrTime time,\n        XrSpaceLocation *location);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroySpace(\n        XrSpace space);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(\n        XrInstance instance,\n        XrSystemId systemId,\n        uint32_t viewConfigurationTypeCapacityInput,\n        uint32_t *viewConfigurationTypeCountOutput,\n        XrViewConfigurationType *viewConfigurationTypes);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(\n        XrInstance instance,\n        XrSystemId systemId,\n        XrViewConfigurationType viewConfigurationType,\n        XrViewConfigurationProperties *configurationProperties);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(\n        XrInstance instance,\n        XrSystemId systemId,\n        XrViewConfigurationType viewConfigurationType,\n        uint32_t viewCapacityInput,\n        uint32_t *viewCountOutput,\n        XrViewConfigurationView *views);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainFormats(\n        XrSession session,\n        uint32_t formatCapacityInput,\n        uint32_t *formatCountOutput,\n        int64_t *formats);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchain(\n        XrSession session,\n        const XrSwapchainCreateInfo *createInfo,\n        XrSwapchain *swapchain);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroySwapchain(\n        XrSwapchain swapchain);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainImages(\n        XrSwapchain swapchain,\n        uint32_t imageCapacityInput,\n        uint32_t *imageCountOutput,\n        XrSwapchainImageBaseHeader *images);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrAcquireSwapchainImage(\n        XrSwapchain swapchain,\n        const XrSwapchainImageAcquireInfo *acquireInfo,\n        uint32_t *index);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrWaitSwapchainImage(\n        XrSwapchain swapchain,\n        const XrSwapchainImageWaitInfo *waitInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrReleaseSwapchainImage(\n        XrSwapchain swapchain,\n        const XrSwapchainImageReleaseInfo *releaseInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrBeginSession(\n        XrSession session,\n        const XrSessionBeginInfo *beginInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEndSession(\n        XrSession session);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrRequestExitSession(\n        XrSession session);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrWaitFrame(\n        XrSession session,\n        const XrFrameWaitInfo *frameWaitInfo,\n        XrFrameState *frameState);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrBeginFrame(\n        XrSession session,\n        const XrFrameBeginInfo *frameBeginInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEndFrame(\n        XrSession session,\n        const XrFrameEndInfo *frameEndInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrLocateViews(\n        XrSession session,\n        const XrViewLocateInfo *viewLocateInfo,\n        XrViewState *viewState,\n        uint32_t viewCapacityInput,\n        uint32_t *viewCountOutput,\n        XrView *views);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(\n        XrInstance instance,\n        const char *pathString,\n        XrPath *path);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrPathToString(\n        XrInstance instance,\n        XrPath path,\n        uint32_t bufferCapacityInput,\n        uint32_t *bufferCountOutput,\n        char *buffer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(\n        XrInstance instance,\n        const XrActionSetCreateInfo *createInfo,\n        XrActionSet *actionSet);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyActionSet(\n        XrActionSet actionSet);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateAction(\n        XrActionSet actionSet,\n        const XrActionCreateInfo *createInfo,\n        XrAction *action);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyAction(\n        XrAction action);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(\n        XrInstance instance,\n        const XrInteractionProfileSuggestedBinding *suggestedBindings);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrAttachSessionActionSets(\n        XrSession session,\n        const XrSessionActionSetsAttachInfo *attachInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetCurrentInteractionProfile(\n        XrSession session,\n        XrPath topLevelUserPath,\n        XrInteractionProfileState *interactionProfile);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateBoolean(\n        XrSession session,\n        const XrActionStateGetInfo *getInfo,\n        XrActionStateBoolean *state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateFloat(\n        XrSession session,\n        const XrActionStateGetInfo *getInfo,\n        XrActionStateFloat *state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateVector2f(\n        XrSession session,\n        const XrActionStateGetInfo *getInfo,\n        XrActionStateVector2f *state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetActionStatePose(\n        XrSession session,\n        const XrActionStateGetInfo *getInfo,\n        XrActionStatePose *state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSyncActions(\n        XrSession session,\n        const XrActionsSyncInfo *syncInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(\n        XrSession session,\n        const XrBoundSourcesForActionEnumerateInfo *enumerateInfo,\n        uint32_t sourceCapacityInput,\n        uint32_t *sourceCountOutput,\n        XrPath *sources);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetInputSourceLocalizedName(\n        XrSession session,\n        const XrInputSourceLocalizedNameGetInfo *getInfo,\n        uint32_t bufferCapacityInput,\n        uint32_t *bufferCountOutput,\n        char *buffer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrApplyHapticFeedback(\n        XrSession session,\n        const XrHapticActionInfo *hapticActionInfo,\n        const XrHapticBaseHeader *hapticFeedback);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback(\n        XrSession session,\n        const XrHapticActionInfo *hapticActionInfo);\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_KHR_composition_layer_cube 1\n#define XR_KHR_composition_layer_cube_SPEC_VERSION 8\n#define XR_KHR_COMPOSITION_LAYER_CUBE_EXTENSION_NAME \"XR_KHR_composition_layer_cube\"\ntypedef struct XrCompositionLayerCubeKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrCompositionLayerFlags layerFlags;\n    XrSpace space;\n    XrEyeVisibility eyeVisibility;\n    XrSwapchain swapchain;\n    uint32_t imageArrayIndex;\n    XrQuaternionf orientation;\n} XrCompositionLayerCubeKHR;\n\n\n#define XR_KHR_composition_layer_depth 1\n#define XR_KHR_composition_layer_depth_SPEC_VERSION 6\n#define XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME \"XR_KHR_composition_layer_depth\"\n// XrCompositionLayerDepthInfoKHR extends XrCompositionLayerProjectionView\ntypedef struct XrCompositionLayerDepthInfoKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSwapchainSubImage subImage;\n    float minDepth;\n    float maxDepth;\n    float nearZ;\n    float farZ;\n} XrCompositionLayerDepthInfoKHR;\n\n\n#define XR_KHR_composition_layer_cylinder 1\n#define XR_KHR_composition_layer_cylinder_SPEC_VERSION 4\n#define XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME \"XR_KHR_composition_layer_cylinder\"\ntypedef struct XrCompositionLayerCylinderKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrCompositionLayerFlags layerFlags;\n    XrSpace space;\n    XrEyeVisibility eyeVisibility;\n    XrSwapchainSubImage subImage;\n    XrPosef pose;\n    float radius;\n    float centralAngle;\n    float aspectRatio;\n} XrCompositionLayerCylinderKHR;\n\n\n#define XR_KHR_composition_layer_equirect 1\n#define XR_KHR_composition_layer_equirect_SPEC_VERSION 3\n#define XR_KHR_COMPOSITION_LAYER_EQUIRECT_EXTENSION_NAME \"XR_KHR_composition_layer_equirect\"\ntypedef struct XrCompositionLayerEquirectKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrCompositionLayerFlags layerFlags;\n    XrSpace space;\n    XrEyeVisibility eyeVisibility;\n    XrSwapchainSubImage subImage;\n    XrPosef pose;\n    float radius;\n    XrVector2f scale;\n    XrVector2f bias;\n} XrCompositionLayerEquirectKHR;\n\n\n#define XR_KHR_visibility_mask 1\n#define XR_KHR_visibility_mask_SPEC_VERSION 2\n#define XR_KHR_VISIBILITY_MASK_EXTENSION_NAME \"XR_KHR_visibility_mask\"\n\ntypedef enum XrVisibilityMaskTypeKHR {\n    XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR = 1,\n    XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR = 2,\n    XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR = 3,\n    XR_VISIBILITY_MASK_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF\n} XrVisibilityMaskTypeKHR;\ntypedef struct XrVisibilityMaskKHR {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t vertexCapacityInput;\n    uint32_t vertexCountOutput;\n    XrVector2f *vertices;\n    uint32_t indexCapacityInput;\n    uint32_t indexCountOutput;\n    uint32_t *indices;\n} XrVisibilityMaskKHR;\n\ntypedef struct XrEventDataVisibilityMaskChangedKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSession session;\n    XrViewConfigurationType viewConfigurationType;\n    uint32_t viewIndex;\n} XrEventDataVisibilityMaskChangedKHR;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVisibilityMaskKHR)(XrSession session,\n                                                         XrViewConfigurationType viewConfigurationType,\n                                                         uint32_t viewIndex,\n                                                         XrVisibilityMaskTypeKHR visibilityMaskType,\n                                                         XrVisibilityMaskKHR *visibilityMask);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrGetVisibilityMaskKHR(\n    XrSession                                   session,\n    XrViewConfigurationType                     viewConfigurationType,\n    uint32_t                                    viewIndex,\n    XrVisibilityMaskTypeKHR                     visibilityMaskType,\n    XrVisibilityMaskKHR*                        visibilityMask);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_KHR_composition_layer_color_scale_bias 1\n#define XR_KHR_composition_layer_color_scale_bias_SPEC_VERSION 5\n#define XR_KHR_COMPOSITION_LAYER_COLOR_SCALE_BIAS_EXTENSION_NAME \"XR_KHR_composition_layer_color_scale_bias\"\n// XrCompositionLayerColorScaleBiasKHR extends XrCompositionLayerBaseHeader\ntypedef struct XrCompositionLayerColorScaleBiasKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrColor4f colorScale;\n    XrColor4f colorBias;\n} XrCompositionLayerColorScaleBiasKHR;\n\n\n#define XR_KHR_loader_init 1\n#define XR_KHR_loader_init_SPEC_VERSION   1\n#define XR_KHR_LOADER_INIT_EXTENSION_NAME \"XR_KHR_loader_init\"\ntypedef struct XR_MAY_ALIAS XrLoaderInitInfoBaseHeaderKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrLoaderInitInfoBaseHeaderKHR;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrInitializeLoaderKHR)(\n        const XrLoaderInitInfoBaseHeaderKHR *loaderInitInfo);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrInitializeLoaderKHR(\n    const XrLoaderInitInfoBaseHeaderKHR*        loaderInitInfo);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_KHR_composition_layer_equirect2 1\n#define XR_KHR_composition_layer_equirect2_SPEC_VERSION 1\n#define XR_KHR_COMPOSITION_LAYER_EQUIRECT2_EXTENSION_NAME \"XR_KHR_composition_layer_equirect2\"\ntypedef struct XrCompositionLayerEquirect2KHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrCompositionLayerFlags layerFlags;\n    XrSpace space;\n    XrEyeVisibility eyeVisibility;\n    XrSwapchainSubImage subImage;\n    XrPosef pose;\n    float radius;\n    float centralHorizontalAngle;\n    float upperVerticalAngle;\n    float lowerVerticalAngle;\n} XrCompositionLayerEquirect2KHR;\n\n\n#define XR_KHR_binding_modification 1\n#define XR_KHR_binding_modification_SPEC_VERSION 1\n#define XR_KHR_BINDING_MODIFICATION_EXTENSION_NAME \"XR_KHR_binding_modification\"\ntypedef struct XR_MAY_ALIAS XrBindingModificationBaseHeaderKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrBindingModificationBaseHeaderKHR;\n\n// XrBindingModificationsKHR extends XrInteractionProfileSuggestedBinding\ntypedef struct XrBindingModificationsKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                            next;\n    uint32_t bindingModificationCount;\n    const XrBindingModificationBaseHeaderKHR *const *bindingModifications;\n} XrBindingModificationsKHR;\n\n\n#define XR_KHR_swapchain_usage_input_attachment_bit 1\n#define XR_KHR_swapchain_usage_input_attachment_bit_SPEC_VERSION 3\n#define XR_KHR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_EXTENSION_NAME \"XR_KHR_swapchain_usage_input_attachment_bit\"\n\n\n#define XR_EXT_performance_settings 1\n#define XR_EXT_performance_settings_SPEC_VERSION 4\n#define XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME \"XR_EXT_performance_settings\"\n\ntypedef enum XrPerfSettingsDomainEXT {\n    XR_PERF_SETTINGS_DOMAIN_CPU_EXT = 1,\n    XR_PERF_SETTINGS_DOMAIN_GPU_EXT = 2,\n    XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrPerfSettingsDomainEXT;\n\ntypedef enum XrPerfSettingsSubDomainEXT {\n    XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT = 1,\n    XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT = 2,\n    XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT = 3,\n    XR_PERF_SETTINGS_SUB_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrPerfSettingsSubDomainEXT;\n\ntypedef enum XrPerfSettingsLevelEXT {\n    XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT = 0,\n    XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT = 25,\n    XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT = 50,\n    XR_PERF_SETTINGS_LEVEL_BOOST_EXT = 75,\n    XR_PERF_SETTINGS_LEVEL_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrPerfSettingsLevelEXT;\n\ntypedef enum XrPerfSettingsNotificationLevelEXT {\n    XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT = 0,\n    XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT = 25,\n    XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT = 75,\n    XR_PERF_SETTINGS_NOTIFICATION_LEVEL_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrPerfSettingsNotificationLevelEXT;\ntypedef struct XrEventDataPerfSettingsEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS              next;\n    XrPerfSettingsDomainEXT domain;\n    XrPerfSettingsSubDomainEXT subDomain;\n    XrPerfSettingsNotificationLevelEXT fromLevel;\n    XrPerfSettingsNotificationLevelEXT toLevel;\n} XrEventDataPerfSettingsEXT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrPerfSettingsSetPerformanceLevelEXT)(XrSession session,\n                                                                       XrPerfSettingsDomainEXT domain,\n                                                                       XrPerfSettingsLevelEXT level);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrPerfSettingsSetPerformanceLevelEXT(\n    XrSession                                   session,\n    XrPerfSettingsDomainEXT                     domain,\n    XrPerfSettingsLevelEXT                      level);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_EXT_thermal_query 1\n#define XR_EXT_thermal_query_SPEC_VERSION 2\n#define XR_EXT_THERMAL_QUERY_EXTENSION_NAME \"XR_EXT_thermal_query\"\ntypedef XrResult (XRAPI_PTR *PFN_xrThermalGetTemperatureTrendEXT)(XrSession session,\n                                                                  XrPerfSettingsDomainEXT domain,\n                                                                  XrPerfSettingsNotificationLevelEXT *notificationLevel,\n                                                                  float *tempHeadroom,\n                                                                  float *tempSlope);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrThermalGetTemperatureTrendEXT(\n    XrSession                                   session,\n    XrPerfSettingsDomainEXT                     domain,\n    XrPerfSettingsNotificationLevelEXT*         notificationLevel,\n    float*                                      tempHeadroom,\n    float*                                      tempSlope);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_EXT_debug_utils 1\nXR_DEFINE_HANDLE(XrDebugUtilsMessengerEXT)\n#define XR_EXT_debug_utils_SPEC_VERSION   4\n#define XR_EXT_DEBUG_UTILS_EXTENSION_NAME \"XR_EXT_debug_utils\"\ntypedef XrFlags64 XrDebugUtilsMessageSeverityFlagsEXT;\n\n// Flag bits for XrDebugUtilsMessageSeverityFlagsEXT\nstatic const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001;\nstatic const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010;\nstatic const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100;\nstatic const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000;\n\ntypedef XrFlags64 XrDebugUtilsMessageTypeFlagsEXT;\n\n// Flag bits for XrDebugUtilsMessageTypeFlagsEXT\nstatic const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001;\nstatic const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002;\nstatic const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004;\nstatic const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT = 0x00000008;\n\ntypedef struct XrDebugUtilsObjectNameInfoEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrObjectType objectType;\n    uint64_t objectHandle;\n    const char *objectName;\n} XrDebugUtilsObjectNameInfoEXT;\n\ntypedef struct XrDebugUtilsLabelEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    const char *labelName;\n} XrDebugUtilsLabelEXT;\n\ntypedef struct XrDebugUtilsMessengerCallbackDataEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS          next;\n    const char *messageId;\n    const char *functionName;\n    const char *message;\n    uint32_t objectCount;\n    XrDebugUtilsObjectNameInfoEXT *objects;\n    uint32_t sessionLabelCount;\n    XrDebugUtilsLabelEXT *sessionLabels;\n} XrDebugUtilsMessengerCallbackDataEXT;\n\ntypedef XrBool32 (XRAPI_PTR *PFN_xrDebugUtilsMessengerCallbackEXT)(\n        XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,\n        XrDebugUtilsMessageTypeFlagsEXT messageTypes,\n        const XrDebugUtilsMessengerCallbackDataEXT *callbackData,\n        void *userData);\n\n\n// XrDebugUtilsMessengerCreateInfoEXT extends XrInstanceCreateInfo\ntypedef struct XrDebugUtilsMessengerCreateInfoEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                next;\n    XrDebugUtilsMessageSeverityFlagsEXT messageSeverities;\n    XrDebugUtilsMessageTypeFlagsEXT messageTypes;\n    PFN_xrDebugUtilsMessengerCallbackEXT userCallback;\n    void *XR_MAY_ALIAS                      userData;\n} XrDebugUtilsMessengerCreateInfoEXT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrSetDebugUtilsObjectNameEXT)(XrInstance instance,\n                                                               const XrDebugUtilsObjectNameInfoEXT *nameInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateDebugUtilsMessengerEXT)(XrInstance instance,\n                                                                 const XrDebugUtilsMessengerCreateInfoEXT *createInfo,\n                                                                 XrDebugUtilsMessengerEXT *messenger);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyDebugUtilsMessengerEXT)(\n        XrDebugUtilsMessengerEXT messenger);\ntypedef XrResult                                    (XRAPI_PTR *PFN_xrSubmitDebugUtilsMessageEXT)(\n        XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,\n        XrDebugUtilsMessageTypeFlagsEXT messageTypes,\n        const XrDebugUtilsMessengerCallbackDataEXT *callbackData);\ntypedef XrResult (XRAPI_PTR *PFN_xrSessionBeginDebugUtilsLabelRegionEXT)(XrSession session,\n                                                                         const XrDebugUtilsLabelEXT *labelInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrSessionEndDebugUtilsLabelRegionEXT)(XrSession session);\ntypedef XrResult (XRAPI_PTR *PFN_xrSessionInsertDebugUtilsLabelEXT)(XrSession session,\n                                                                    const XrDebugUtilsLabelEXT *labelInfo);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrSetDebugUtilsObjectNameEXT(\n    XrInstance                                  instance,\n    const XrDebugUtilsObjectNameInfoEXT*        nameInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateDebugUtilsMessengerEXT(\n    XrInstance                                  instance,\n    const XrDebugUtilsMessengerCreateInfoEXT*   createInfo,\n    XrDebugUtilsMessengerEXT*                   messenger);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyDebugUtilsMessengerEXT(\n    XrDebugUtilsMessengerEXT                    messenger);\n\nXRAPI_ATTR XrResult                                    XRAPI_CALL xrSubmitDebugUtilsMessageEXT(\n    XrInstance                                  instance,\n    XrDebugUtilsMessageSeverityFlagsEXT         messageSeverity,\n    XrDebugUtilsMessageTypeFlagsEXT             messageTypes,\n    const XrDebugUtilsMessengerCallbackDataEXT* callbackData);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSessionBeginDebugUtilsLabelRegionEXT(\n    XrSession                                   session,\n    const XrDebugUtilsLabelEXT*                 labelInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSessionEndDebugUtilsLabelRegionEXT(\n    XrSession                                   session);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSessionInsertDebugUtilsLabelEXT(\n    XrSession                                   session,\n    const XrDebugUtilsLabelEXT*                 labelInfo);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_EXT_eye_gaze_interaction 1\n#define XR_EXT_eye_gaze_interaction_SPEC_VERSION 2\n#define XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME \"XR_EXT_eye_gaze_interaction\"\n// XrSystemEyeGazeInteractionPropertiesEXT extends XrSystemProperties\ntypedef struct XrSystemEyeGazeInteractionPropertiesEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsEyeGazeInteraction;\n} XrSystemEyeGazeInteractionPropertiesEXT;\n\n// XrEyeGazeSampleTimeEXT extends XrSpaceLocation\ntypedef struct XrEyeGazeSampleTimeEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrTime time;\n} XrEyeGazeSampleTimeEXT;\n\n\n#define XR_EXTX_overlay 1\n#define XR_EXTX_overlay_SPEC_VERSION      5\n#define XR_EXTX_OVERLAY_EXTENSION_NAME    \"XR_EXTX_overlay\"\ntypedef XrFlags64 XrOverlaySessionCreateFlagsEXTX;\n\n// Flag bits for XrOverlaySessionCreateFlagsEXTX\n\ntypedef XrFlags64 XrOverlayMainSessionFlagsEXTX;\n\n// Flag bits for XrOverlayMainSessionFlagsEXTX\nstatic const XrOverlayMainSessionFlagsEXTX XR_OVERLAY_MAIN_SESSION_ENABLED_COMPOSITION_LAYER_INFO_DEPTH_BIT_EXTX = 0x00000001;\n\n// XrSessionCreateInfoOverlayEXTX extends XrSessionCreateInfo\ntypedef struct XrSessionCreateInfoOverlayEXTX {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS           next;\n    XrOverlaySessionCreateFlagsEXTX createFlags;\n    uint32_t sessionLayersPlacement;\n} XrSessionCreateInfoOverlayEXTX;\n\ntypedef struct XrEventDataMainSessionVisibilityChangedEXTX {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS         next;\n    XrBool32 visible;\n    XrOverlayMainSessionFlagsEXTX flags;\n} XrEventDataMainSessionVisibilityChangedEXTX;\n\n\n#define XR_VARJO_quad_views 1\n#define XR_VARJO_quad_views_SPEC_VERSION  1\n#define XR_VARJO_QUAD_VIEWS_EXTENSION_NAME \"XR_VARJO_quad_views\"\n\n\n#define XR_MSFT_unbounded_reference_space 1\n#define XR_MSFT_unbounded_reference_space_SPEC_VERSION 1\n#define XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME \"XR_MSFT_unbounded_reference_space\"\n\n\n#define XR_MSFT_spatial_anchor 1\nXR_DEFINE_HANDLE(XrSpatialAnchorMSFT)\n#define XR_MSFT_spatial_anchor_SPEC_VERSION 2\n#define XR_MSFT_SPATIAL_ANCHOR_EXTENSION_NAME \"XR_MSFT_spatial_anchor\"\ntypedef struct XrSpatialAnchorCreateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace space;\n    XrPosef pose;\n    XrTime time;\n} XrSpatialAnchorCreateInfoMSFT;\n\ntypedef struct XrSpatialAnchorSpaceCreateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpatialAnchorMSFT anchor;\n    XrPosef poseInAnchorSpace;\n} XrSpatialAnchorSpaceCreateInfoMSFT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorMSFT)(XrSession session,\n                                                            const XrSpatialAnchorCreateInfoMSFT *createInfo,\n                                                            XrSpatialAnchorMSFT *anchor);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorSpaceMSFT)(XrSession session,\n                                                                 const XrSpatialAnchorSpaceCreateInfoMSFT *createInfo,\n                                                                 XrSpace *space);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialAnchorMSFT)(XrSpatialAnchorMSFT anchor);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorMSFT(\n    XrSession                                   session,\n    const XrSpatialAnchorCreateInfoMSFT*        createInfo,\n    XrSpatialAnchorMSFT*                        anchor);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorSpaceMSFT(\n    XrSession                                   session,\n    const XrSpatialAnchorSpaceCreateInfoMSFT*   createInfo,\n    XrSpace*                                    space);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroySpatialAnchorMSFT(\n    XrSpatialAnchorMSFT                         anchor);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_composition_layer_image_layout 1\n#define XR_FB_composition_layer_image_layout_SPEC_VERSION 1\n#define XR_FB_COMPOSITION_LAYER_IMAGE_LAYOUT_EXTENSION_NAME \"XR_FB_composition_layer_image_layout\"\ntypedef XrFlags64 XrCompositionLayerImageLayoutFlagsFB;\n\n// Flag bits for XrCompositionLayerImageLayoutFlagsFB\nstatic const XrCompositionLayerImageLayoutFlagsFB XR_COMPOSITION_LAYER_IMAGE_LAYOUT_VERTICAL_FLIP_BIT_FB = 0x00000001;\n\n// XrCompositionLayerImageLayoutFB extends XrCompositionLayerBaseHeader\ntypedef struct XrCompositionLayerImageLayoutFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                      next;\n    XrCompositionLayerImageLayoutFlagsFB flags;\n} XrCompositionLayerImageLayoutFB;\n\n\n#define XR_FB_composition_layer_alpha_blend 1\n#define XR_FB_composition_layer_alpha_blend_SPEC_VERSION 2\n#define XR_FB_COMPOSITION_LAYER_ALPHA_BLEND_EXTENSION_NAME \"XR_FB_composition_layer_alpha_blend\"\n\ntypedef enum XrBlendFactorFB {\n    XR_BLEND_FACTOR_ZERO_FB = 0,\n    XR_BLEND_FACTOR_ONE_FB = 1,\n    XR_BLEND_FACTOR_SRC_ALPHA_FB = 2,\n    XR_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA_FB = 3,\n    XR_BLEND_FACTOR_DST_ALPHA_FB = 4,\n    XR_BLEND_FACTOR_ONE_MINUS_DST_ALPHA_FB = 5,\n    XR_BLEND_FACTOR_MAX_ENUM_FB = 0x7FFFFFFF\n} XrBlendFactorFB;\n// XrCompositionLayerAlphaBlendFB extends XrCompositionLayerBaseHeader\ntypedef struct XrCompositionLayerAlphaBlendFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBlendFactorFB srcFactorColor;\n    XrBlendFactorFB dstFactorColor;\n    XrBlendFactorFB srcFactorAlpha;\n    XrBlendFactorFB dstFactorAlpha;\n} XrCompositionLayerAlphaBlendFB;\n\n\n#define XR_MND_headless 1\n#define XR_MND_headless_SPEC_VERSION      2\n#define XR_MND_HEADLESS_EXTENSION_NAME    \"XR_MND_headless\"\n\n\n#define XR_OCULUS_android_session_state_enable 1\n#define XR_OCULUS_android_session_state_enable_SPEC_VERSION 1\n#define XR_OCULUS_ANDROID_SESSION_STATE_ENABLE_EXTENSION_NAME \"XR_OCULUS_android_session_state_enable\"\n\n\n#define XR_EXT_view_configuration_depth_range 1\n#define XR_EXT_view_configuration_depth_range_SPEC_VERSION 1\n#define XR_EXT_VIEW_CONFIGURATION_DEPTH_RANGE_EXTENSION_NAME \"XR_EXT_view_configuration_depth_range\"\n// XrViewConfigurationDepthRangeEXT extends XrViewConfigurationView\ntypedef struct XrViewConfigurationDepthRangeEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    float recommendedNearZ;\n    float minNearZ;\n    float recommendedFarZ;\n    float maxFarZ;\n} XrViewConfigurationDepthRangeEXT;\n\n\n#define XR_EXT_conformance_automation 1\n#define XR_EXT_conformance_automation_SPEC_VERSION 3\n#define XR_EXT_CONFORMANCE_AUTOMATION_EXTENSION_NAME \"XR_EXT_conformance_automation\"\ntypedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceActiveEXT)(XrSession session,\n                                                            XrPath interactionProfile,\n                                                            XrPath topLevelPath, XrBool32 isActive);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateBoolEXT)(XrSession session,\n                                                               XrPath topLevelPath,\n                                                               XrPath inputSourcePath,\n                                                               XrBool32 state);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateFloatEXT)(XrSession session,\n                                                                XrPath topLevelPath,\n                                                                XrPath inputSourcePath,\n                                                                float state);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateVector2fEXT)(XrSession session,\n                                                                   XrPath topLevelPath,\n                                                                   XrPath inputSourcePath,\n                                                                   XrVector2f state);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceLocationEXT)(XrSession session,\n                                                              XrPath topLevelPath,\n                                                              XrPath inputSourcePath, XrSpace space,\n                                                              XrPosef pose);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceActiveEXT(\n    XrSession                                   session,\n    XrPath                                      interactionProfile,\n    XrPath                                      topLevelPath,\n    XrBool32                                    isActive);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceStateBoolEXT(\n    XrSession                                   session,\n    XrPath                                      topLevelPath,\n    XrPath                                      inputSourcePath,\n    XrBool32                                    state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceStateFloatEXT(\n    XrSession                                   session,\n    XrPath                                      topLevelPath,\n    XrPath                                      inputSourcePath,\n    float                                       state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceStateVector2fEXT(\n    XrSession                                   session,\n    XrPath                                      topLevelPath,\n    XrPath                                      inputSourcePath,\n    XrVector2f                                  state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceLocationEXT(\n    XrSession                                   session,\n    XrPath                                      topLevelPath,\n    XrPath                                      inputSourcePath,\n    XrSpace                                     space,\n    XrPosef                                     pose);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_MSFT_spatial_graph_bridge 1\nXR_DEFINE_HANDLE(XrSpatialGraphNodeBindingMSFT)\n#define XR_MSFT_spatial_graph_bridge_SPEC_VERSION 2\n#define XR_MSFT_SPATIAL_GRAPH_BRIDGE_EXTENSION_NAME \"XR_MSFT_spatial_graph_bridge\"\n#define XR_GUID_SIZE_MSFT                 16\n\ntypedef enum XrSpatialGraphNodeTypeMSFT {\n    XR_SPATIAL_GRAPH_NODE_TYPE_STATIC_MSFT = 1,\n    XR_SPATIAL_GRAPH_NODE_TYPE_DYNAMIC_MSFT = 2,\n    XR_SPATIAL_GRAPH_NODE_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrSpatialGraphNodeTypeMSFT;\ntypedef struct XrSpatialGraphNodeSpaceCreateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS      next;\n    XrSpatialGraphNodeTypeMSFT nodeType;\n    uint8_t nodeId[XR_GUID_SIZE_MSFT];\n    XrPosef pose;\n} XrSpatialGraphNodeSpaceCreateInfoMSFT;\n\ntypedef struct XrSpatialGraphStaticNodeBindingCreateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace space;\n    XrPosef poseInSpace;\n    XrTime time;\n} XrSpatialGraphStaticNodeBindingCreateInfoMSFT;\n\ntypedef struct XrSpatialGraphNodeBindingPropertiesGetInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrSpatialGraphNodeBindingPropertiesGetInfoMSFT;\n\ntypedef struct XrSpatialGraphNodeBindingPropertiesMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint8_t nodeId[XR_GUID_SIZE_MSFT];\n    XrPosef poseInNodeSpace;\n} XrSpatialGraphNodeBindingPropertiesMSFT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialGraphNodeSpaceMSFT)(XrSession session,\n                                                                    const XrSpatialGraphNodeSpaceCreateInfoMSFT *createInfo,\n                                                                    XrSpace *space);\ntypedef XrResult (XRAPI_PTR *PFN_xrTryCreateSpatialGraphStaticNodeBindingMSFT)(XrSession session,\n                                                                               const XrSpatialGraphStaticNodeBindingCreateInfoMSFT *createInfo,\n                                                                               XrSpatialGraphNodeBindingMSFT *nodeBinding);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialGraphNodeBindingMSFT)(\n        XrSpatialGraphNodeBindingMSFT nodeBinding);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpatialGraphNodeBindingPropertiesMSFT)(\n        XrSpatialGraphNodeBindingMSFT nodeBinding,\n        const XrSpatialGraphNodeBindingPropertiesGetInfoMSFT *getInfo,\n        XrSpatialGraphNodeBindingPropertiesMSFT *properties);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialGraphNodeSpaceMSFT(\n    XrSession                                   session,\n    const XrSpatialGraphNodeSpaceCreateInfoMSFT* createInfo,\n    XrSpace*                                    space);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrTryCreateSpatialGraphStaticNodeBindingMSFT(\n    XrSession                                   session,\n    const XrSpatialGraphStaticNodeBindingCreateInfoMSFT* createInfo,\n    XrSpatialGraphNodeBindingMSFT*              nodeBinding);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroySpatialGraphNodeBindingMSFT(\n    XrSpatialGraphNodeBindingMSFT               nodeBinding);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSpatialGraphNodeBindingPropertiesMSFT(\n    XrSpatialGraphNodeBindingMSFT               nodeBinding,\n    const XrSpatialGraphNodeBindingPropertiesGetInfoMSFT* getInfo,\n    XrSpatialGraphNodeBindingPropertiesMSFT*    properties);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_MSFT_hand_interaction 1\n#define XR_MSFT_hand_interaction_SPEC_VERSION 1\n#define XR_MSFT_HAND_INTERACTION_EXTENSION_NAME \"XR_MSFT_hand_interaction\"\n\n\n#define XR_EXT_hand_tracking 1\n\n#define XR_HAND_JOINT_COUNT_EXT 26\n\nXR_DEFINE_HANDLE(XrHandTrackerEXT)\n#define XR_EXT_hand_tracking_SPEC_VERSION 4\n#define XR_EXT_HAND_TRACKING_EXTENSION_NAME \"XR_EXT_hand_tracking\"\n\ntypedef enum XrHandEXT {\n    XR_HAND_LEFT_EXT = 1,\n    XR_HAND_RIGHT_EXT = 2,\n    XR_HAND_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrHandEXT;\n\ntypedef enum XrHandJointEXT {\n    XR_HAND_JOINT_PALM_EXT = 0,\n    XR_HAND_JOINT_WRIST_EXT = 1,\n    XR_HAND_JOINT_THUMB_METACARPAL_EXT = 2,\n    XR_HAND_JOINT_THUMB_PROXIMAL_EXT = 3,\n    XR_HAND_JOINT_THUMB_DISTAL_EXT = 4,\n    XR_HAND_JOINT_THUMB_TIP_EXT = 5,\n    XR_HAND_JOINT_INDEX_METACARPAL_EXT = 6,\n    XR_HAND_JOINT_INDEX_PROXIMAL_EXT = 7,\n    XR_HAND_JOINT_INDEX_INTERMEDIATE_EXT = 8,\n    XR_HAND_JOINT_INDEX_DISTAL_EXT = 9,\n    XR_HAND_JOINT_INDEX_TIP_EXT = 10,\n    XR_HAND_JOINT_MIDDLE_METACARPAL_EXT = 11,\n    XR_HAND_JOINT_MIDDLE_PROXIMAL_EXT = 12,\n    XR_HAND_JOINT_MIDDLE_INTERMEDIATE_EXT = 13,\n    XR_HAND_JOINT_MIDDLE_DISTAL_EXT = 14,\n    XR_HAND_JOINT_MIDDLE_TIP_EXT = 15,\n    XR_HAND_JOINT_RING_METACARPAL_EXT = 16,\n    XR_HAND_JOINT_RING_PROXIMAL_EXT = 17,\n    XR_HAND_JOINT_RING_INTERMEDIATE_EXT = 18,\n    XR_HAND_JOINT_RING_DISTAL_EXT = 19,\n    XR_HAND_JOINT_RING_TIP_EXT = 20,\n    XR_HAND_JOINT_LITTLE_METACARPAL_EXT = 21,\n    XR_HAND_JOINT_LITTLE_PROXIMAL_EXT = 22,\n    XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT = 23,\n    XR_HAND_JOINT_LITTLE_DISTAL_EXT = 24,\n    XR_HAND_JOINT_LITTLE_TIP_EXT = 25,\n    XR_HAND_JOINT_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrHandJointEXT;\n\ntypedef enum XrHandJointSetEXT {\n    XR_HAND_JOINT_SET_DEFAULT_EXT = 0,\n    XR_HAND_JOINT_SET_HAND_WITH_FOREARM_ULTRALEAP = 1000149000,\n    XR_HAND_JOINT_SET_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrHandJointSetEXT;\n// XrSystemHandTrackingPropertiesEXT extends XrSystemProperties\ntypedef struct XrSystemHandTrackingPropertiesEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsHandTracking;\n} XrSystemHandTrackingPropertiesEXT;\n\ntypedef struct XrHandTrackerCreateInfoEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrHandEXT hand;\n    XrHandJointSetEXT handJointSet;\n} XrHandTrackerCreateInfoEXT;\n\ntypedef struct XrHandJointsLocateInfoEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace baseSpace;\n    XrTime time;\n} XrHandJointsLocateInfoEXT;\n\ntypedef struct XrHandJointLocationEXT {\n    XrSpaceLocationFlags locationFlags;\n    XrPosef pose;\n    float radius;\n} XrHandJointLocationEXT;\n\ntypedef struct XrHandJointVelocityEXT {\n    XrSpaceVelocityFlags velocityFlags;\n    XrVector3f linearVelocity;\n    XrVector3f angularVelocity;\n} XrHandJointVelocityEXT;\n\ntypedef struct XrHandJointLocationsEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS         next;\n    XrBool32 isActive;\n    uint32_t jointCount;\n    XrHandJointLocationEXT *jointLocations;\n} XrHandJointLocationsEXT;\n\n// XrHandJointVelocitiesEXT extends XrHandJointLocationsEXT\ntypedef struct XrHandJointVelocitiesEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS         next;\n    uint32_t jointCount;\n    XrHandJointVelocityEXT *jointVelocities;\n} XrHandJointVelocitiesEXT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateHandTrackerEXT)(XrSession session,\n                                                         const XrHandTrackerCreateInfoEXT *createInfo,\n                                                         XrHandTrackerEXT *handTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyHandTrackerEXT)(XrHandTrackerEXT handTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrLocateHandJointsEXT)(XrHandTrackerEXT handTracker,\n                                                        const XrHandJointsLocateInfoEXT *locateInfo,\n                                                        XrHandJointLocationsEXT *locations);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateHandTrackerEXT(\n    XrSession                                   session,\n    const XrHandTrackerCreateInfoEXT*           createInfo,\n    XrHandTrackerEXT*                           handTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyHandTrackerEXT(\n    XrHandTrackerEXT                            handTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrLocateHandJointsEXT(\n    XrHandTrackerEXT                            handTracker,\n    const XrHandJointsLocateInfoEXT*            locateInfo,\n    XrHandJointLocationsEXT*                    locations);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_MSFT_hand_tracking_mesh 1\n#define XR_MSFT_hand_tracking_mesh_SPEC_VERSION 4\n#define XR_MSFT_HAND_TRACKING_MESH_EXTENSION_NAME \"XR_MSFT_hand_tracking_mesh\"\n\ntypedef enum XrHandPoseTypeMSFT {\n    XR_HAND_POSE_TYPE_TRACKED_MSFT = 0,\n    XR_HAND_POSE_TYPE_REFERENCE_OPEN_PALM_MSFT = 1,\n    XR_HAND_POSE_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrHandPoseTypeMSFT;\n// XrSystemHandTrackingMeshPropertiesMSFT extends XrSystemProperties\ntypedef struct XrSystemHandTrackingMeshPropertiesMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsHandTrackingMesh;\n    uint32_t maxHandMeshIndexCount;\n    uint32_t maxHandMeshVertexCount;\n} XrSystemHandTrackingMeshPropertiesMSFT;\n\ntypedef struct XrHandMeshSpaceCreateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrHandPoseTypeMSFT handPoseType;\n    XrPosef poseInHandMeshSpace;\n} XrHandMeshSpaceCreateInfoMSFT;\n\ntypedef struct XrHandMeshUpdateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrTime time;\n    XrHandPoseTypeMSFT handPoseType;\n} XrHandMeshUpdateInfoMSFT;\n\ntypedef struct XrHandMeshIndexBufferMSFT {\n    uint32_t indexBufferKey;\n    uint32_t indexCapacityInput;\n    uint32_t indexCountOutput;\n    uint32_t *indices;\n} XrHandMeshIndexBufferMSFT;\n\ntypedef struct XrHandMeshVertexMSFT {\n    XrVector3f position;\n    XrVector3f normal;\n} XrHandMeshVertexMSFT;\n\ntypedef struct XrHandMeshVertexBufferMSFT {\n    XrTime vertexUpdateTime;\n    uint32_t vertexCapacityInput;\n    uint32_t vertexCountOutput;\n    XrHandMeshVertexMSFT *vertices;\n} XrHandMeshVertexBufferMSFT;\n\ntypedef struct XrHandMeshMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS            next;\n    XrBool32 isActive;\n    XrBool32 indexBufferChanged;\n    XrBool32 vertexBufferChanged;\n    XrHandMeshIndexBufferMSFT indexBuffer;\n    XrHandMeshVertexBufferMSFT vertexBuffer;\n} XrHandMeshMSFT;\n\n// XrHandPoseTypeInfoMSFT extends XrHandTrackerCreateInfoEXT\ntypedef struct XrHandPoseTypeInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrHandPoseTypeMSFT handPoseType;\n} XrHandPoseTypeInfoMSFT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateHandMeshSpaceMSFT)(XrHandTrackerEXT handTracker,\n                                                            const XrHandMeshSpaceCreateInfoMSFT *createInfo,\n                                                            XrSpace *space);\ntypedef XrResult (XRAPI_PTR *PFN_xrUpdateHandMeshMSFT)(XrHandTrackerEXT handTracker,\n                                                       const XrHandMeshUpdateInfoMSFT *updateInfo,\n                                                       XrHandMeshMSFT *handMesh);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateHandMeshSpaceMSFT(\n    XrHandTrackerEXT                            handTracker,\n    const XrHandMeshSpaceCreateInfoMSFT*        createInfo,\n    XrSpace*                                    space);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrUpdateHandMeshMSFT(\n    XrHandTrackerEXT                            handTracker,\n    const XrHandMeshUpdateInfoMSFT*             updateInfo,\n    XrHandMeshMSFT*                             handMesh);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_MSFT_secondary_view_configuration 1\n#define XR_MSFT_secondary_view_configuration_SPEC_VERSION 1\n#define XR_MSFT_SECONDARY_VIEW_CONFIGURATION_EXTENSION_NAME \"XR_MSFT_secondary_view_configuration\"\n// XrSecondaryViewConfigurationSessionBeginInfoMSFT extends XrSessionBeginInfo\ntypedef struct XrSecondaryViewConfigurationSessionBeginInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS          next;\n    uint32_t viewConfigurationCount;\n    const XrViewConfigurationType *enabledViewConfigurationTypes;\n} XrSecondaryViewConfigurationSessionBeginInfoMSFT;\n\ntypedef struct XrSecondaryViewConfigurationStateMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS         next;\n    XrViewConfigurationType viewConfigurationType;\n    XrBool32 active;\n} XrSecondaryViewConfigurationStateMSFT;\n\n// XrSecondaryViewConfigurationFrameStateMSFT extends XrFrameState\ntypedef struct XrSecondaryViewConfigurationFrameStateMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                        next;\n    uint32_t viewConfigurationCount;\n    XrSecondaryViewConfigurationStateMSFT *viewConfigurationStates;\n} XrSecondaryViewConfigurationFrameStateMSFT;\n\ntypedef struct XrSecondaryViewConfigurationLayerInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                      next;\n    XrViewConfigurationType viewConfigurationType;\n    XrEnvironmentBlendMode environmentBlendMode;\n    uint32_t layerCount;\n    const XrCompositionLayerBaseHeader *const *layers;\n} XrSecondaryViewConfigurationLayerInfoMSFT;\n\n// XrSecondaryViewConfigurationFrameEndInfoMSFT extends XrFrameEndInfo\ntypedef struct XrSecondaryViewConfigurationFrameEndInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                            next;\n    uint32_t viewConfigurationCount;\n    const XrSecondaryViewConfigurationLayerInfoMSFT *viewConfigurationLayersInfo;\n} XrSecondaryViewConfigurationFrameEndInfoMSFT;\n\n// XrSecondaryViewConfigurationSwapchainCreateInfoMSFT extends XrSwapchainCreateInfo\ntypedef struct XrSecondaryViewConfigurationSwapchainCreateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrViewConfigurationType viewConfigurationType;\n} XrSecondaryViewConfigurationSwapchainCreateInfoMSFT;\n\n\n#define XR_MSFT_first_person_observer 1\n#define XR_MSFT_first_person_observer_SPEC_VERSION 1\n#define XR_MSFT_FIRST_PERSON_OBSERVER_EXTENSION_NAME \"XR_MSFT_first_person_observer\"\n\n\n#define XR_MSFT_controller_model 1\n\n#define XR_NULL_CONTROLLER_MODEL_KEY_MSFT 0\n\nXR_DEFINE_ATOM(XrControllerModelKeyMSFT)\n#define XR_MSFT_controller_model_SPEC_VERSION 2\n#define XR_MSFT_CONTROLLER_MODEL_EXTENSION_NAME \"XR_MSFT_controller_model\"\n#define XR_MAX_CONTROLLER_MODEL_NODE_NAME_SIZE_MSFT 64\ntypedef struct XrControllerModelKeyStateMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS          next;\n    XrControllerModelKeyMSFT modelKey;\n} XrControllerModelKeyStateMSFT;\n\ntypedef struct XrControllerModelNodePropertiesMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    char parentNodeName[XR_MAX_CONTROLLER_MODEL_NODE_NAME_SIZE_MSFT];\n    char nodeName[XR_MAX_CONTROLLER_MODEL_NODE_NAME_SIZE_MSFT];\n} XrControllerModelNodePropertiesMSFT;\n\ntypedef struct XrControllerModelPropertiesMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                      next;\n    uint32_t nodeCapacityInput;\n    uint32_t nodeCountOutput;\n    XrControllerModelNodePropertiesMSFT *nodeProperties;\n} XrControllerModelPropertiesMSFT;\n\ntypedef struct XrControllerModelNodeStateMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrPosef nodePose;\n} XrControllerModelNodeStateMSFT;\n\ntypedef struct XrControllerModelStateMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                 next;\n    uint32_t nodeCapacityInput;\n    uint32_t nodeCountOutput;\n    XrControllerModelNodeStateMSFT *nodeStates;\n} XrControllerModelStateMSFT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetControllerModelKeyMSFT)(XrSession session,\n                                                              XrPath topLevelUserPath,\n                                                              XrControllerModelKeyStateMSFT *controllerModelKeyState);\ntypedef XrResult (XRAPI_PTR *PFN_xrLoadControllerModelMSFT)(XrSession session,\n                                                            XrControllerModelKeyMSFT modelKey,\n                                                            uint32_t bufferCapacityInput,\n                                                            uint32_t *bufferCountOutput,\n                                                            uint8_t *buffer);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetControllerModelPropertiesMSFT)(XrSession session,\n                                                                     XrControllerModelKeyMSFT modelKey,\n                                                                     XrControllerModelPropertiesMSFT *properties);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetControllerModelStateMSFT)(XrSession session,\n                                                                XrControllerModelKeyMSFT modelKey,\n                                                                XrControllerModelStateMSFT *state);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrGetControllerModelKeyMSFT(\n    XrSession                                   session,\n    XrPath                                      topLevelUserPath,\n    XrControllerModelKeyStateMSFT*              controllerModelKeyState);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrLoadControllerModelMSFT(\n    XrSession                                   session,\n    XrControllerModelKeyMSFT                    modelKey,\n    uint32_t                                    bufferCapacityInput,\n    uint32_t*                                   bufferCountOutput,\n    uint8_t*                                    buffer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetControllerModelPropertiesMSFT(\n    XrSession                                   session,\n    XrControllerModelKeyMSFT                    modelKey,\n    XrControllerModelPropertiesMSFT*            properties);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetControllerModelStateMSFT(\n    XrSession                                   session,\n    XrControllerModelKeyMSFT                    modelKey,\n    XrControllerModelStateMSFT*                 state);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_EXT_win32_appcontainer_compatible 1\n#define XR_EXT_win32_appcontainer_compatible_SPEC_VERSION 1\n#define XR_EXT_WIN32_APPCONTAINER_COMPATIBLE_EXTENSION_NAME \"XR_EXT_win32_appcontainer_compatible\"\n\n\n#define XR_EPIC_view_configuration_fov 1\n#define XR_EPIC_view_configuration_fov_SPEC_VERSION 2\n#define XR_EPIC_VIEW_CONFIGURATION_FOV_EXTENSION_NAME \"XR_EPIC_view_configuration_fov\"\n// XrViewConfigurationViewFovEPIC extends XrViewConfigurationView\ntypedef struct XrViewConfigurationViewFovEPIC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrFovf recommendedFov;\n    XrFovf maxMutableFov;\n} XrViewConfigurationViewFovEPIC;\n\n\n#define XR_MSFT_composition_layer_reprojection 1\n#define XR_MSFT_composition_layer_reprojection_SPEC_VERSION 1\n#define XR_MSFT_COMPOSITION_LAYER_REPROJECTION_EXTENSION_NAME \"XR_MSFT_composition_layer_reprojection\"\n\ntypedef enum XrReprojectionModeMSFT {\n    XR_REPROJECTION_MODE_DEPTH_MSFT = 1,\n    XR_REPROJECTION_MODE_PLANAR_FROM_DEPTH_MSFT = 2,\n    XR_REPROJECTION_MODE_PLANAR_MANUAL_MSFT = 3,\n    XR_REPROJECTION_MODE_ORIENTATION_ONLY_MSFT = 4,\n    XR_REPROJECTION_MODE_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrReprojectionModeMSFT;\n// XrCompositionLayerReprojectionInfoMSFT extends XrCompositionLayerProjection\ntypedef struct XrCompositionLayerReprojectionInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrReprojectionModeMSFT reprojectionMode;\n} XrCompositionLayerReprojectionInfoMSFT;\n\n// XrCompositionLayerReprojectionPlaneOverrideMSFT extends XrCompositionLayerProjection\ntypedef struct XrCompositionLayerReprojectionPlaneOverrideMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrVector3f position;\n    XrVector3f normal;\n    XrVector3f velocity;\n} XrCompositionLayerReprojectionPlaneOverrideMSFT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateReprojectionModesMSFT)(XrInstance instance,\n                                                                   XrSystemId systemId,\n                                                                   XrViewConfigurationType viewConfigurationType,\n                                                                   uint32_t modeCapacityInput,\n                                                                   uint32_t *modeCountOutput,\n                                                                   XrReprojectionModeMSFT *modes);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReprojectionModesMSFT(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    XrViewConfigurationType                     viewConfigurationType,\n    uint32_t                                    modeCapacityInput,\n    uint32_t*                                   modeCountOutput,\n    XrReprojectionModeMSFT*                     modes);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_HUAWEI_controller_interaction 1\n#define XR_HUAWEI_controller_interaction_SPEC_VERSION 1\n#define XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME \"XR_HUAWEI_controller_interaction\"\n\n\n#define XR_FB_swapchain_update_state 1\n#define XR_FB_swapchain_update_state_SPEC_VERSION 3\n#define XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME \"XR_FB_swapchain_update_state\"\ntypedef struct XR_MAY_ALIAS XrSwapchainStateBaseHeaderFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n} XrSwapchainStateBaseHeaderFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrUpdateSwapchainFB)(XrSwapchain swapchain,\n                                                      const XrSwapchainStateBaseHeaderFB *state);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSwapchainStateFB)(XrSwapchain swapchain,\n                                                        XrSwapchainStateBaseHeaderFB *state);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrUpdateSwapchainFB(\n    XrSwapchain                                 swapchain,\n    const XrSwapchainStateBaseHeaderFB*         state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSwapchainStateFB(\n    XrSwapchain                                 swapchain,\n    XrSwapchainStateBaseHeaderFB*               state);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_composition_layer_secure_content 1\n#define XR_FB_composition_layer_secure_content_SPEC_VERSION 1\n#define XR_FB_COMPOSITION_LAYER_SECURE_CONTENT_EXTENSION_NAME \"XR_FB_composition_layer_secure_content\"\ntypedef XrFlags64 XrCompositionLayerSecureContentFlagsFB;\n\n// Flag bits for XrCompositionLayerSecureContentFlagsFB\nstatic const XrCompositionLayerSecureContentFlagsFB XR_COMPOSITION_LAYER_SECURE_CONTENT_EXCLUDE_LAYER_BIT_FB = 0x00000001;\nstatic const XrCompositionLayerSecureContentFlagsFB XR_COMPOSITION_LAYER_SECURE_CONTENT_REPLACE_LAYER_BIT_FB = 0x00000002;\n\n// XrCompositionLayerSecureContentFB extends XrCompositionLayerBaseHeader\ntypedef struct XrCompositionLayerSecureContentFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                  next;\n    XrCompositionLayerSecureContentFlagsFB flags;\n} XrCompositionLayerSecureContentFB;\n\n\n#define XR_FB_body_tracking 1\nXR_DEFINE_HANDLE(XrBodyTrackerFB)\n#define XR_FB_body_tracking_SPEC_VERSION  1\n#define XR_FB_BODY_TRACKING_EXTENSION_NAME \"XR_FB_body_tracking\"\n\ntypedef enum XrBodyJointFB {\n    XR_BODY_JOINT_ROOT_FB = 0,\n    XR_BODY_JOINT_HIPS_FB = 1,\n    XR_BODY_JOINT_SPINE_LOWER_FB = 2,\n    XR_BODY_JOINT_SPINE_MIDDLE_FB = 3,\n    XR_BODY_JOINT_SPINE_UPPER_FB = 4,\n    XR_BODY_JOINT_CHEST_FB = 5,\n    XR_BODY_JOINT_NECK_FB = 6,\n    XR_BODY_JOINT_HEAD_FB = 7,\n    XR_BODY_JOINT_LEFT_SHOULDER_FB = 8,\n    XR_BODY_JOINT_LEFT_SCAPULA_FB = 9,\n    XR_BODY_JOINT_LEFT_ARM_UPPER_FB = 10,\n    XR_BODY_JOINT_LEFT_ARM_LOWER_FB = 11,\n    XR_BODY_JOINT_LEFT_HAND_WRIST_TWIST_FB = 12,\n    XR_BODY_JOINT_RIGHT_SHOULDER_FB = 13,\n    XR_BODY_JOINT_RIGHT_SCAPULA_FB = 14,\n    XR_BODY_JOINT_RIGHT_ARM_UPPER_FB = 15,\n    XR_BODY_JOINT_RIGHT_ARM_LOWER_FB = 16,\n    XR_BODY_JOINT_RIGHT_HAND_WRIST_TWIST_FB = 17,\n    XR_BODY_JOINT_LEFT_HAND_PALM_FB = 18,\n    XR_BODY_JOINT_LEFT_HAND_WRIST_FB = 19,\n    XR_BODY_JOINT_LEFT_HAND_THUMB_METACARPAL_FB = 20,\n    XR_BODY_JOINT_LEFT_HAND_THUMB_PROXIMAL_FB = 21,\n    XR_BODY_JOINT_LEFT_HAND_THUMB_DISTAL_FB = 22,\n    XR_BODY_JOINT_LEFT_HAND_THUMB_TIP_FB = 23,\n    XR_BODY_JOINT_LEFT_HAND_INDEX_METACARPAL_FB = 24,\n    XR_BODY_JOINT_LEFT_HAND_INDEX_PROXIMAL_FB = 25,\n    XR_BODY_JOINT_LEFT_HAND_INDEX_INTERMEDIATE_FB = 26,\n    XR_BODY_JOINT_LEFT_HAND_INDEX_DISTAL_FB = 27,\n    XR_BODY_JOINT_LEFT_HAND_INDEX_TIP_FB = 28,\n    XR_BODY_JOINT_LEFT_HAND_MIDDLE_METACARPAL_FB = 29,\n    XR_BODY_JOINT_LEFT_HAND_MIDDLE_PROXIMAL_FB = 30,\n    XR_BODY_JOINT_LEFT_HAND_MIDDLE_INTERMEDIATE_FB = 31,\n    XR_BODY_JOINT_LEFT_HAND_MIDDLE_DISTAL_FB = 32,\n    XR_BODY_JOINT_LEFT_HAND_MIDDLE_TIP_FB = 33,\n    XR_BODY_JOINT_LEFT_HAND_RING_METACARPAL_FB = 34,\n    XR_BODY_JOINT_LEFT_HAND_RING_PROXIMAL_FB = 35,\n    XR_BODY_JOINT_LEFT_HAND_RING_INTERMEDIATE_FB = 36,\n    XR_BODY_JOINT_LEFT_HAND_RING_DISTAL_FB = 37,\n    XR_BODY_JOINT_LEFT_HAND_RING_TIP_FB = 38,\n    XR_BODY_JOINT_LEFT_HAND_LITTLE_METACARPAL_FB = 39,\n    XR_BODY_JOINT_LEFT_HAND_LITTLE_PROXIMAL_FB = 40,\n    XR_BODY_JOINT_LEFT_HAND_LITTLE_INTERMEDIATE_FB = 41,\n    XR_BODY_JOINT_LEFT_HAND_LITTLE_DISTAL_FB = 42,\n    XR_BODY_JOINT_LEFT_HAND_LITTLE_TIP_FB = 43,\n    XR_BODY_JOINT_RIGHT_HAND_PALM_FB = 44,\n    XR_BODY_JOINT_RIGHT_HAND_WRIST_FB = 45,\n    XR_BODY_JOINT_RIGHT_HAND_THUMB_METACARPAL_FB = 46,\n    XR_BODY_JOINT_RIGHT_HAND_THUMB_PROXIMAL_FB = 47,\n    XR_BODY_JOINT_RIGHT_HAND_THUMB_DISTAL_FB = 48,\n    XR_BODY_JOINT_RIGHT_HAND_THUMB_TIP_FB = 49,\n    XR_BODY_JOINT_RIGHT_HAND_INDEX_METACARPAL_FB = 50,\n    XR_BODY_JOINT_RIGHT_HAND_INDEX_PROXIMAL_FB = 51,\n    XR_BODY_JOINT_RIGHT_HAND_INDEX_INTERMEDIATE_FB = 52,\n    XR_BODY_JOINT_RIGHT_HAND_INDEX_DISTAL_FB = 53,\n    XR_BODY_JOINT_RIGHT_HAND_INDEX_TIP_FB = 54,\n    XR_BODY_JOINT_RIGHT_HAND_MIDDLE_METACARPAL_FB = 55,\n    XR_BODY_JOINT_RIGHT_HAND_MIDDLE_PROXIMAL_FB = 56,\n    XR_BODY_JOINT_RIGHT_HAND_MIDDLE_INTERMEDIATE_FB = 57,\n    XR_BODY_JOINT_RIGHT_HAND_MIDDLE_DISTAL_FB = 58,\n    XR_BODY_JOINT_RIGHT_HAND_MIDDLE_TIP_FB = 59,\n    XR_BODY_JOINT_RIGHT_HAND_RING_METACARPAL_FB = 60,\n    XR_BODY_JOINT_RIGHT_HAND_RING_PROXIMAL_FB = 61,\n    XR_BODY_JOINT_RIGHT_HAND_RING_INTERMEDIATE_FB = 62,\n    XR_BODY_JOINT_RIGHT_HAND_RING_DISTAL_FB = 63,\n    XR_BODY_JOINT_RIGHT_HAND_RING_TIP_FB = 64,\n    XR_BODY_JOINT_RIGHT_HAND_LITTLE_METACARPAL_FB = 65,\n    XR_BODY_JOINT_RIGHT_HAND_LITTLE_PROXIMAL_FB = 66,\n    XR_BODY_JOINT_RIGHT_HAND_LITTLE_INTERMEDIATE_FB = 67,\n    XR_BODY_JOINT_RIGHT_HAND_LITTLE_DISTAL_FB = 68,\n    XR_BODY_JOINT_RIGHT_HAND_LITTLE_TIP_FB = 69,\n    XR_BODY_JOINT_COUNT_FB = 70,\n    XR_BODY_JOINT_NONE_FB = -1,\n    XR_BODY_JOINT_MAX_ENUM_FB = 0x7FFFFFFF\n} XrBodyJointFB;\n\ntypedef enum XrBodyJointSetFB {\n    XR_BODY_JOINT_SET_DEFAULT_FB = 0,\n    XR_BODY_JOINT_SET_MAX_ENUM_FB = 0x7FFFFFFF\n} XrBodyJointSetFB;\ntypedef struct XrBodyJointLocationFB {\n    XrSpaceLocationFlags locationFlags;\n    XrPosef pose;\n} XrBodyJointLocationFB;\n\n// XrSystemBodyTrackingPropertiesFB extends XrSystemProperties\ntypedef struct XrSystemBodyTrackingPropertiesFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsBodyTracking;\n} XrSystemBodyTrackingPropertiesFB;\n\ntypedef struct XrBodyTrackerCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrBodyJointSetFB bodyJointSet;\n} XrBodyTrackerCreateInfoFB;\n\ntypedef struct XrBodySkeletonJointFB {\n    int32_t joint;\n    int32_t parentJoint;\n    XrPosef pose;\n} XrBodySkeletonJointFB;\n\ntypedef struct XrBodySkeletonFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS        next;\n    uint32_t jointCount;\n    XrBodySkeletonJointFB *joints;\n} XrBodySkeletonFB;\n\ntypedef struct XrBodyJointsLocateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace baseSpace;\n    XrTime time;\n} XrBodyJointsLocateInfoFB;\n\ntypedef struct XrBodyJointLocationsFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS        next;\n    XrBool32 isActive;\n    float confidence;\n    uint32_t jointCount;\n    XrBodyJointLocationFB *jointLocations;\n    uint32_t skeletonChangedCount;\n    XrTime time;\n} XrBodyJointLocationsFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateBodyTrackerFB)(XrSession session,\n                                                        const XrBodyTrackerCreateInfoFB *createInfo,\n                                                        XrBodyTrackerFB *bodyTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyBodyTrackerFB)(XrBodyTrackerFB bodyTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrLocateBodyJointsFB)(XrBodyTrackerFB bodyTracker,\n                                                       const XrBodyJointsLocateInfoFB *locateInfo,\n                                                       XrBodyJointLocationsFB *locations);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetBodySkeletonFB)(XrBodyTrackerFB bodyTracker,\n                                                      XrBodySkeletonFB *skeleton);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateBodyTrackerFB(\n    XrSession                                   session,\n    const XrBodyTrackerCreateInfoFB*            createInfo,\n    XrBodyTrackerFB*                            bodyTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyBodyTrackerFB(\n    XrBodyTrackerFB                             bodyTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrLocateBodyJointsFB(\n    XrBodyTrackerFB                             bodyTracker,\n    const XrBodyJointsLocateInfoFB*             locateInfo,\n    XrBodyJointLocationsFB*                     locations);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetBodySkeletonFB(\n    XrBodyTrackerFB                             bodyTracker,\n    XrBodySkeletonFB*                           skeleton);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_EXT_dpad_binding 1\n#define XR_EXT_dpad_binding_SPEC_VERSION  1\n#define XR_EXT_DPAD_BINDING_EXTENSION_NAME \"XR_EXT_dpad_binding\"\ntypedef struct XrInteractionProfileDpadBindingEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS     next;\n    XrPath binding;\n    XrActionSet actionSet;\n    float forceThreshold;\n    float forceThresholdReleased;\n    float centerRegion;\n    float wedgeAngle;\n    XrBool32 isSticky;\n    const XrHapticBaseHeader *onHaptic;\n    const XrHapticBaseHeader *offHaptic;\n} XrInteractionProfileDpadBindingEXT;\n\n\n#define XR_VALVE_analog_threshold 1\n#define XR_VALVE_analog_threshold_SPEC_VERSION 2\n#define XR_VALVE_ANALOG_THRESHOLD_EXTENSION_NAME \"XR_VALVE_analog_threshold\"\ntypedef struct XrInteractionProfileAnalogThresholdVALVE {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS     next;\n    XrAction action;\n    XrPath binding;\n    float onThreshold;\n    float offThreshold;\n    const XrHapticBaseHeader *onHaptic;\n    const XrHapticBaseHeader *offHaptic;\n} XrInteractionProfileAnalogThresholdVALVE;\n\n\n#define XR_EXT_hand_joints_motion_range 1\n#define XR_EXT_hand_joints_motion_range_SPEC_VERSION 1\n#define XR_EXT_HAND_JOINTS_MOTION_RANGE_EXTENSION_NAME \"XR_EXT_hand_joints_motion_range\"\n\ntypedef enum XrHandJointsMotionRangeEXT {\n    XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT = 1,\n    XR_HAND_JOINTS_MOTION_RANGE_CONFORMING_TO_CONTROLLER_EXT = 2,\n    XR_HAND_JOINTS_MOTION_RANGE_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrHandJointsMotionRangeEXT;\n// XrHandJointsMotionRangeInfoEXT extends XrHandJointsLocateInfoEXT\ntypedef struct XrHandJointsMotionRangeInfoEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS      next;\n    XrHandJointsMotionRangeEXT handJointsMotionRange;\n} XrHandJointsMotionRangeInfoEXT;\n\n\n#define XR_EXT_samsung_odyssey_controller 1\n#define XR_EXT_samsung_odyssey_controller_SPEC_VERSION 1\n#define XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME \"XR_EXT_samsung_odyssey_controller\"\n\n\n#define XR_EXT_hp_mixed_reality_controller 1\n#define XR_EXT_hp_mixed_reality_controller_SPEC_VERSION 1\n#define XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME \"XR_EXT_hp_mixed_reality_controller\"\n\n\n#define XR_MND_swapchain_usage_input_attachment_bit 1\n#define XR_MND_swapchain_usage_input_attachment_bit_SPEC_VERSION 2\n#define XR_MND_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_EXTENSION_NAME \"XR_MND_swapchain_usage_input_attachment_bit\"\n\n\n#define XR_MSFT_scene_understanding 1\n\nXR_DEFINE_HANDLE(XrSceneObserverMSFT)\n\n\nXR_DEFINE_HANDLE(XrSceneMSFT)\n\n#define XR_MSFT_scene_understanding_SPEC_VERSION 2\n#define XR_MSFT_SCENE_UNDERSTANDING_EXTENSION_NAME \"XR_MSFT_scene_understanding\"\n\ntypedef enum XrSceneComputeFeatureMSFT {\n    XR_SCENE_COMPUTE_FEATURE_PLANE_MSFT = 1,\n    XR_SCENE_COMPUTE_FEATURE_PLANE_MESH_MSFT = 2,\n    XR_SCENE_COMPUTE_FEATURE_VISUAL_MESH_MSFT = 3,\n    XR_SCENE_COMPUTE_FEATURE_COLLIDER_MESH_MSFT = 4,\n    XR_SCENE_COMPUTE_FEATURE_SERIALIZE_SCENE_MSFT = 1000098000,\n    XR_SCENE_COMPUTE_FEATURE_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrSceneComputeFeatureMSFT;\n\ntypedef enum XrSceneComputeConsistencyMSFT {\n    XR_SCENE_COMPUTE_CONSISTENCY_SNAPSHOT_COMPLETE_MSFT = 1,\n    XR_SCENE_COMPUTE_CONSISTENCY_SNAPSHOT_INCOMPLETE_FAST_MSFT = 2,\n    XR_SCENE_COMPUTE_CONSISTENCY_OCCLUSION_OPTIMIZED_MSFT = 3,\n    XR_SCENE_COMPUTE_CONSISTENCY_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrSceneComputeConsistencyMSFT;\n\ntypedef enum XrMeshComputeLodMSFT {\n    XR_MESH_COMPUTE_LOD_COARSE_MSFT = 1,\n    XR_MESH_COMPUTE_LOD_MEDIUM_MSFT = 2,\n    XR_MESH_COMPUTE_LOD_FINE_MSFT = 3,\n    XR_MESH_COMPUTE_LOD_UNLIMITED_MSFT = 4,\n    XR_MESH_COMPUTE_LOD_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrMeshComputeLodMSFT;\n\ntypedef enum XrSceneComponentTypeMSFT {\n    XR_SCENE_COMPONENT_TYPE_INVALID_MSFT = -1,\n    XR_SCENE_COMPONENT_TYPE_OBJECT_MSFT = 1,\n    XR_SCENE_COMPONENT_TYPE_PLANE_MSFT = 2,\n    XR_SCENE_COMPONENT_TYPE_VISUAL_MESH_MSFT = 3,\n    XR_SCENE_COMPONENT_TYPE_COLLIDER_MESH_MSFT = 4,\n    XR_SCENE_COMPONENT_TYPE_SERIALIZED_SCENE_FRAGMENT_MSFT = 1000098000,\n    XR_SCENE_COMPONENT_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrSceneComponentTypeMSFT;\n\ntypedef enum XrSceneObjectTypeMSFT {\n    XR_SCENE_OBJECT_TYPE_UNCATEGORIZED_MSFT = -1,\n    XR_SCENE_OBJECT_TYPE_BACKGROUND_MSFT = 1,\n    XR_SCENE_OBJECT_TYPE_WALL_MSFT = 2,\n    XR_SCENE_OBJECT_TYPE_FLOOR_MSFT = 3,\n    XR_SCENE_OBJECT_TYPE_CEILING_MSFT = 4,\n    XR_SCENE_OBJECT_TYPE_PLATFORM_MSFT = 5,\n    XR_SCENE_OBJECT_TYPE_INFERRED_MSFT = 6,\n    XR_SCENE_OBJECT_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrSceneObjectTypeMSFT;\n\ntypedef enum XrScenePlaneAlignmentTypeMSFT {\n    XR_SCENE_PLANE_ALIGNMENT_TYPE_NON_ORTHOGONAL_MSFT = 0,\n    XR_SCENE_PLANE_ALIGNMENT_TYPE_HORIZONTAL_MSFT = 1,\n    XR_SCENE_PLANE_ALIGNMENT_TYPE_VERTICAL_MSFT = 2,\n    XR_SCENE_PLANE_ALIGNMENT_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrScenePlaneAlignmentTypeMSFT;\n\ntypedef enum XrSceneComputeStateMSFT {\n    XR_SCENE_COMPUTE_STATE_NONE_MSFT = 0,\n    XR_SCENE_COMPUTE_STATE_UPDATING_MSFT = 1,\n    XR_SCENE_COMPUTE_STATE_COMPLETED_MSFT = 2,\n    XR_SCENE_COMPUTE_STATE_COMPLETED_WITH_ERROR_MSFT = 3,\n    XR_SCENE_COMPUTE_STATE_MAX_ENUM_MSFT = 0x7FFFFFFF\n} XrSceneComputeStateMSFT;\ntypedef struct XrUuidMSFT {\n    uint8_t bytes[16];\n} XrUuidMSFT;\n\ntypedef struct XrSceneObserverCreateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrSceneObserverCreateInfoMSFT;\n\ntypedef struct XrSceneCreateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrSceneCreateInfoMSFT;\n\ntypedef struct XrSceneSphereBoundMSFT {\n    XrVector3f center;\n    float radius;\n} XrSceneSphereBoundMSFT;\n\ntypedef struct XrSceneOrientedBoxBoundMSFT {\n    XrPosef pose;\n    XrVector3f extents;\n} XrSceneOrientedBoxBoundMSFT;\n\ntypedef struct XrSceneFrustumBoundMSFT {\n    XrPosef pose;\n    XrFovf fov;\n    float farDistance;\n} XrSceneFrustumBoundMSFT;\n\ntypedef struct XrSceneBoundsMSFT {\n    XrSpace space;\n    XrTime time;\n    uint32_t sphereCount;\n    const XrSceneSphereBoundMSFT *spheres;\n    uint32_t boxCount;\n    const XrSceneOrientedBoxBoundMSFT *boxes;\n    uint32_t frustumCount;\n    const XrSceneFrustumBoundMSFT *frustums;\n} XrSceneBoundsMSFT;\n\ntypedef struct XrNewSceneComputeInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS            next;\n    uint32_t requestedFeatureCount;\n    const XrSceneComputeFeatureMSFT *requestedFeatures;\n    XrSceneComputeConsistencyMSFT consistency;\n    XrSceneBoundsMSFT bounds;\n} XrNewSceneComputeInfoMSFT;\n\n// XrVisualMeshComputeLodInfoMSFT extends XrNewSceneComputeInfoMSFT\ntypedef struct XrVisualMeshComputeLodInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrMeshComputeLodMSFT lod;\n} XrVisualMeshComputeLodInfoMSFT;\n\ntypedef struct XrSceneComponentMSFT {\n    XrSceneComponentTypeMSFT componentType;\n    XrUuidMSFT id;\n    XrUuidMSFT parentId;\n    XrTime updateTime;\n} XrSceneComponentMSFT;\n\ntypedef struct XrSceneComponentsMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS       next;\n    uint32_t componentCapacityInput;\n    uint32_t componentCountOutput;\n    XrSceneComponentMSFT *components;\n} XrSceneComponentsMSFT;\n\ntypedef struct XrSceneComponentsGetInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSceneComponentTypeMSFT componentType;\n} XrSceneComponentsGetInfoMSFT;\n\ntypedef struct XrSceneComponentLocationMSFT {\n    XrSpaceLocationFlags flags;\n    XrPosef pose;\n} XrSceneComponentLocationMSFT;\n\ntypedef struct XrSceneComponentLocationsMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS               next;\n    uint32_t locationCount;\n    XrSceneComponentLocationMSFT *locations;\n} XrSceneComponentLocationsMSFT;\n\ntypedef struct XrSceneComponentsLocateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace baseSpace;\n    XrTime time;\n    uint32_t componentIdCount;\n    const XrUuidMSFT *componentIds;\n} XrSceneComponentsLocateInfoMSFT;\n\ntypedef struct XrSceneObjectMSFT {\n    XrSceneObjectTypeMSFT objectType;\n} XrSceneObjectMSFT;\n\n// XrSceneObjectsMSFT extends XrSceneComponentsMSFT\ntypedef struct XrSceneObjectsMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t sceneObjectCount;\n    XrSceneObjectMSFT *sceneObjects;\n} XrSceneObjectsMSFT;\n\n// XrSceneComponentParentFilterInfoMSFT extends XrSceneComponentsGetInfoMSFT\ntypedef struct XrSceneComponentParentFilterInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrUuidMSFT parentId;\n} XrSceneComponentParentFilterInfoMSFT;\n\n// XrSceneObjectTypesFilterInfoMSFT extends XrSceneComponentsGetInfoMSFT\ntypedef struct XrSceneObjectTypesFilterInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS        next;\n    uint32_t objectTypeCount;\n    const XrSceneObjectTypeMSFT *objectTypes;\n} XrSceneObjectTypesFilterInfoMSFT;\n\ntypedef struct XrScenePlaneMSFT {\n    XrScenePlaneAlignmentTypeMSFT alignment;\n    XrExtent2Df size;\n    uint64_t meshBufferId;\n    XrBool32 supportsIndicesUint16;\n} XrScenePlaneMSFT;\n\n// XrScenePlanesMSFT extends XrSceneComponentsMSFT\ntypedef struct XrScenePlanesMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t scenePlaneCount;\n    XrScenePlaneMSFT *scenePlanes;\n} XrScenePlanesMSFT;\n\n// XrScenePlaneAlignmentFilterInfoMSFT extends XrSceneComponentsGetInfoMSFT\ntypedef struct XrScenePlaneAlignmentFilterInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                next;\n    uint32_t alignmentCount;\n    const XrScenePlaneAlignmentTypeMSFT *alignments;\n} XrScenePlaneAlignmentFilterInfoMSFT;\n\ntypedef struct XrSceneMeshMSFT {\n    uint64_t meshBufferId;\n    XrBool32 supportsIndicesUint16;\n} XrSceneMeshMSFT;\n\n// XrSceneMeshesMSFT extends XrSceneComponentsMSFT\ntypedef struct XrSceneMeshesMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t sceneMeshCount;\n    XrSceneMeshMSFT *sceneMeshes;\n} XrSceneMeshesMSFT;\n\ntypedef struct XrSceneMeshBuffersGetInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint64_t meshBufferId;\n} XrSceneMeshBuffersGetInfoMSFT;\n\ntypedef struct XrSceneMeshBuffersMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n} XrSceneMeshBuffersMSFT;\n\ntypedef struct XrSceneMeshVertexBufferMSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t vertexCapacityInput;\n    uint32_t vertexCountOutput;\n    XrVector3f *vertices;\n} XrSceneMeshVertexBufferMSFT;\n\ntypedef struct XrSceneMeshIndicesUint32MSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t indexCapacityInput;\n    uint32_t indexCountOutput;\n    uint32_t *indices;\n} XrSceneMeshIndicesUint32MSFT;\n\ntypedef struct XrSceneMeshIndicesUint16MSFT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t indexCapacityInput;\n    uint32_t indexCountOutput;\n    uint16_t *indices;\n} XrSceneMeshIndicesUint16MSFT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateSceneComputeFeaturesMSFT)(XrInstance instance,\n                                                                      XrSystemId systemId,\n                                                                      uint32_t featureCapacityInput,\n                                                                      uint32_t *featureCountOutput,\n                                                                      XrSceneComputeFeatureMSFT *features);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSceneObserverMSFT)(XrSession session,\n                                                            const XrSceneObserverCreateInfoMSFT *createInfo,\n                                                            XrSceneObserverMSFT *sceneObserver);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroySceneObserverMSFT)(XrSceneObserverMSFT sceneObserver);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSceneMSFT)(XrSceneObserverMSFT sceneObserver,\n                                                    const XrSceneCreateInfoMSFT *createInfo,\n                                                    XrSceneMSFT *scene);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroySceneMSFT)(XrSceneMSFT scene);\ntypedef XrResult (XRAPI_PTR *PFN_xrComputeNewSceneMSFT)(XrSceneObserverMSFT sceneObserver,\n                                                        const XrNewSceneComputeInfoMSFT *computeInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSceneComputeStateMSFT)(XrSceneObserverMSFT sceneObserver,\n                                                             XrSceneComputeStateMSFT *state);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSceneComponentsMSFT)(XrSceneMSFT scene,\n                                                           const XrSceneComponentsGetInfoMSFT *getInfo,\n                                                           XrSceneComponentsMSFT *components);\ntypedef XrResult (XRAPI_PTR *PFN_xrLocateSceneComponentsMSFT)(XrSceneMSFT scene,\n                                                              const XrSceneComponentsLocateInfoMSFT *locateInfo,\n                                                              XrSceneComponentLocationsMSFT *locations);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSceneMeshBuffersMSFT)(XrSceneMSFT scene,\n                                                            const XrSceneMeshBuffersGetInfoMSFT *getInfo,\n                                                            XrSceneMeshBuffersMSFT *buffers);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSceneComputeFeaturesMSFT(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    uint32_t                                    featureCapacityInput,\n    uint32_t*                                   featureCountOutput,\n    XrSceneComputeFeatureMSFT*                  features);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateSceneObserverMSFT(\n    XrSession                                   session,\n    const XrSceneObserverCreateInfoMSFT*        createInfo,\n    XrSceneObserverMSFT*                        sceneObserver);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroySceneObserverMSFT(\n    XrSceneObserverMSFT                         sceneObserver);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateSceneMSFT(\n    XrSceneObserverMSFT                         sceneObserver,\n    const XrSceneCreateInfoMSFT*                createInfo,\n    XrSceneMSFT*                                scene);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroySceneMSFT(\n    XrSceneMSFT                                 scene);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrComputeNewSceneMSFT(\n    XrSceneObserverMSFT                         sceneObserver,\n    const XrNewSceneComputeInfoMSFT*            computeInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSceneComputeStateMSFT(\n    XrSceneObserverMSFT                         sceneObserver,\n    XrSceneComputeStateMSFT*                    state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSceneComponentsMSFT(\n    XrSceneMSFT                                 scene,\n    const XrSceneComponentsGetInfoMSFT*         getInfo,\n    XrSceneComponentsMSFT*                      components);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrLocateSceneComponentsMSFT(\n    XrSceneMSFT                                 scene,\n    const XrSceneComponentsLocateInfoMSFT*      locateInfo,\n    XrSceneComponentLocationsMSFT*              locations);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSceneMeshBuffersMSFT(\n    XrSceneMSFT                                 scene,\n    const XrSceneMeshBuffersGetInfoMSFT*        getInfo,\n    XrSceneMeshBuffersMSFT*                     buffers);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_MSFT_scene_understanding_serialization 1\n#define XR_MSFT_scene_understanding_serialization_SPEC_VERSION 2\n#define XR_MSFT_SCENE_UNDERSTANDING_SERIALIZATION_EXTENSION_NAME \"XR_MSFT_scene_understanding_serialization\"\ntypedef struct XrSerializedSceneFragmentDataGetInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrUuidMSFT sceneFragmentId;\n} XrSerializedSceneFragmentDataGetInfoMSFT;\n\ntypedef struct XrDeserializeSceneFragmentMSFT {\n    uint32_t bufferSize;\n    const uint8_t *buffer;\n} XrDeserializeSceneFragmentMSFT;\n\ntypedef struct XrSceneDeserializeInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                 next;\n    uint32_t fragmentCount;\n    const XrDeserializeSceneFragmentMSFT *fragments;\n} XrSceneDeserializeInfoMSFT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrDeserializeSceneMSFT)(XrSceneObserverMSFT sceneObserver,\n                                                         const XrSceneDeserializeInfoMSFT *deserializeInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSerializedSceneFragmentDataMSFT)(XrSceneMSFT scene,\n                                                                       const XrSerializedSceneFragmentDataGetInfoMSFT *getInfo,\n                                                                       uint32_t countInput,\n                                                                       uint32_t *readOutput,\n                                                                       uint8_t *buffer);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrDeserializeSceneMSFT(\n    XrSceneObserverMSFT                         sceneObserver,\n    const XrSceneDeserializeInfoMSFT*           deserializeInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSerializedSceneFragmentDataMSFT(\n    XrSceneMSFT                                 scene,\n    const XrSerializedSceneFragmentDataGetInfoMSFT* getInfo,\n    uint32_t                                    countInput,\n    uint32_t*                                   readOutput,\n    uint8_t*                                    buffer);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_display_refresh_rate 1\n#define XR_FB_display_refresh_rate_SPEC_VERSION 1\n#define XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME \"XR_FB_display_refresh_rate\"\ntypedef struct XrEventDataDisplayRefreshRateChangedFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    float fromDisplayRefreshRate;\n    float toDisplayRefreshRate;\n} XrEventDataDisplayRefreshRateChangedFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateDisplayRefreshRatesFB)(XrSession session,\n                                                                   uint32_t displayRefreshRateCapacityInput,\n                                                                   uint32_t *displayRefreshRateCountOutput,\n                                                                   float *displayRefreshRates);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetDisplayRefreshRateFB)(XrSession session,\n                                                            float *displayRefreshRate);\ntypedef XrResult (XRAPI_PTR *PFN_xrRequestDisplayRefreshRateFB)(XrSession session,\n                                                                float displayRefreshRate);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateDisplayRefreshRatesFB(\n    XrSession                                   session,\n    uint32_t                                    displayRefreshRateCapacityInput,\n    uint32_t*                                   displayRefreshRateCountOutput,\n    float*                                      displayRefreshRates);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetDisplayRefreshRateFB(\n    XrSession                                   session,\n    float*                                      displayRefreshRate);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrRequestDisplayRefreshRateFB(\n    XrSession                                   session,\n    float                                       displayRefreshRate);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_HTC_vive_cosmos_controller_interaction 1\n#define XR_HTC_vive_cosmos_controller_interaction_SPEC_VERSION 1\n#define XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME \"XR_HTC_vive_cosmos_controller_interaction\"\n\n\n#define XR_HTCX_vive_tracker_interaction 1\n#define XR_HTCX_vive_tracker_interaction_SPEC_VERSION 2\n#define XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME \"XR_HTCX_vive_tracker_interaction\"\ntypedef struct XrViveTrackerPathsHTCX {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrPath persistentPath;\n    XrPath rolePath;\n} XrViveTrackerPathsHTCX;\n\ntypedef struct XrEventDataViveTrackerConnectedHTCX {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrViveTrackerPathsHTCX *paths;\n} XrEventDataViveTrackerConnectedHTCX;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateViveTrackerPathsHTCX)(XrInstance instance,\n                                                                  uint32_t pathCapacityInput,\n                                                                  uint32_t *pathCountOutput,\n                                                                  XrViveTrackerPathsHTCX *paths);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViveTrackerPathsHTCX(\n    XrInstance                                  instance,\n    uint32_t                                    pathCapacityInput,\n    uint32_t*                                   pathCountOutput,\n    XrViveTrackerPathsHTCX*                     paths);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_HTC_facial_tracking 1\n\n#define XR_FACIAL_EXPRESSION_EYE_COUNT_HTC 14\n\n\n#define XR_FACIAL_EXPRESSION_LIP_COUNT_HTC 37\n\nXR_DEFINE_HANDLE(XrFacialTrackerHTC)\n#define XR_HTC_facial_tracking_SPEC_VERSION 2\n#define XR_HTC_FACIAL_TRACKING_EXTENSION_NAME \"XR_HTC_facial_tracking\"\n\ntypedef enum XrEyeExpressionHTC {\n    XR_EYE_EXPRESSION_LEFT_BLINK_HTC = 0,\n    XR_EYE_EXPRESSION_LEFT_WIDE_HTC = 1,\n    XR_EYE_EXPRESSION_RIGHT_BLINK_HTC = 2,\n    XR_EYE_EXPRESSION_RIGHT_WIDE_HTC = 3,\n    XR_EYE_EXPRESSION_LEFT_SQUEEZE_HTC = 4,\n    XR_EYE_EXPRESSION_RIGHT_SQUEEZE_HTC = 5,\n    XR_EYE_EXPRESSION_LEFT_DOWN_HTC = 6,\n    XR_EYE_EXPRESSION_RIGHT_DOWN_HTC = 7,\n    XR_EYE_EXPRESSION_LEFT_OUT_HTC = 8,\n    XR_EYE_EXPRESSION_RIGHT_IN_HTC = 9,\n    XR_EYE_EXPRESSION_LEFT_IN_HTC = 10,\n    XR_EYE_EXPRESSION_RIGHT_OUT_HTC = 11,\n    XR_EYE_EXPRESSION_LEFT_UP_HTC = 12,\n    XR_EYE_EXPRESSION_RIGHT_UP_HTC = 13,\n    XR_EYE_EXPRESSION_MAX_ENUM_HTC = 0x7FFFFFFF\n} XrEyeExpressionHTC;\n\ntypedef enum XrLipExpressionHTC {\n    XR_LIP_EXPRESSION_JAW_RIGHT_HTC = 0,\n    XR_LIP_EXPRESSION_JAW_LEFT_HTC = 1,\n    XR_LIP_EXPRESSION_JAW_FORWARD_HTC = 2,\n    XR_LIP_EXPRESSION_JAW_OPEN_HTC = 3,\n    XR_LIP_EXPRESSION_MOUTH_APE_SHAPE_HTC = 4,\n    XR_LIP_EXPRESSION_MOUTH_UPPER_RIGHT_HTC = 5,\n    XR_LIP_EXPRESSION_MOUTH_UPPER_LEFT_HTC = 6,\n    XR_LIP_EXPRESSION_MOUTH_LOWER_RIGHT_HTC = 7,\n    XR_LIP_EXPRESSION_MOUTH_LOWER_LEFT_HTC = 8,\n    XR_LIP_EXPRESSION_MOUTH_UPPER_OVERTURN_HTC = 9,\n    XR_LIP_EXPRESSION_MOUTH_LOWER_OVERTURN_HTC = 10,\n    XR_LIP_EXPRESSION_MOUTH_POUT_HTC = 11,\n    XR_LIP_EXPRESSION_MOUTH_SMILE_RIGHT_HTC = 12,\n    XR_LIP_EXPRESSION_MOUTH_SMILE_LEFT_HTC = 13,\n    XR_LIP_EXPRESSION_MOUTH_SAD_RIGHT_HTC = 14,\n    XR_LIP_EXPRESSION_MOUTH_SAD_LEFT_HTC = 15,\n    XR_LIP_EXPRESSION_CHEEK_PUFF_RIGHT_HTC = 16,\n    XR_LIP_EXPRESSION_CHEEK_PUFF_LEFT_HTC = 17,\n    XR_LIP_EXPRESSION_CHEEK_SUCK_HTC = 18,\n    XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC = 19,\n    XR_LIP_EXPRESSION_MOUTH_UPPER_UPLEFT_HTC = 20,\n    XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNRIGHT_HTC = 21,\n    XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNLEFT_HTC = 22,\n    XR_LIP_EXPRESSION_MOUTH_UPPER_INSIDE_HTC = 23,\n    XR_LIP_EXPRESSION_MOUTH_LOWER_INSIDE_HTC = 24,\n    XR_LIP_EXPRESSION_MOUTH_LOWER_OVERLAY_HTC = 25,\n    XR_LIP_EXPRESSION_TONGUE_LONGSTEP1_HTC = 26,\n    XR_LIP_EXPRESSION_TONGUE_LEFT_HTC = 27,\n    XR_LIP_EXPRESSION_TONGUE_RIGHT_HTC = 28,\n    XR_LIP_EXPRESSION_TONGUE_UP_HTC = 29,\n    XR_LIP_EXPRESSION_TONGUE_DOWN_HTC = 30,\n    XR_LIP_EXPRESSION_TONGUE_ROLL_HTC = 31,\n    XR_LIP_EXPRESSION_TONGUE_LONGSTEP2_HTC = 32,\n    XR_LIP_EXPRESSION_TONGUE_UPRIGHT_MORPH_HTC = 33,\n    XR_LIP_EXPRESSION_TONGUE_UPLEFT_MORPH_HTC = 34,\n    XR_LIP_EXPRESSION_TONGUE_DOWNRIGHT_MORPH_HTC = 35,\n    XR_LIP_EXPRESSION_TONGUE_DOWNLEFT_MORPH_HTC = 36,\n    XR_LIP_EXPRESSION_MAX_ENUM_HTC = 0x7FFFFFFF\n} XrLipExpressionHTC;\n\ntypedef enum XrFacialTrackingTypeHTC {\n    XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC = 1,\n    XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC = 2,\n    XR_FACIAL_TRACKING_TYPE_MAX_ENUM_HTC = 0x7FFFFFFF\n} XrFacialTrackingTypeHTC;\n// XrSystemFacialTrackingPropertiesHTC extends XrSystemProperties\ntypedef struct XrSystemFacialTrackingPropertiesHTC {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportEyeFacialTracking;\n    XrBool32 supportLipFacialTracking;\n} XrSystemFacialTrackingPropertiesHTC;\n\ntypedef struct XrFacialExpressionsHTC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrBool32 isActive;\n    XrTime sampleTime;\n    uint32_t expressionCount;\n    float *expressionWeightings;\n} XrFacialExpressionsHTC;\n\ntypedef struct XrFacialTrackerCreateInfoHTC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrFacialTrackingTypeHTC facialTrackingType;\n} XrFacialTrackerCreateInfoHTC;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateFacialTrackerHTC)(XrSession session,\n                                                           const XrFacialTrackerCreateInfoHTC *createInfo,\n                                                           XrFacialTrackerHTC *facialTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyFacialTrackerHTC)(XrFacialTrackerHTC facialTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetFacialExpressionsHTC)(XrFacialTrackerHTC facialTracker,\n                                                            XrFacialExpressionsHTC *facialExpressions);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateFacialTrackerHTC(\n    XrSession                                   session,\n    const XrFacialTrackerCreateInfoHTC*         createInfo,\n    XrFacialTrackerHTC*                         facialTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyFacialTrackerHTC(\n    XrFacialTrackerHTC                          facialTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetFacialExpressionsHTC(\n    XrFacialTrackerHTC                          facialTracker,\n    XrFacialExpressionsHTC*                     facialExpressions);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_HTC_vive_focus3_controller_interaction 1\n#define XR_HTC_vive_focus3_controller_interaction_SPEC_VERSION 2\n#define XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME \"XR_HTC_vive_focus3_controller_interaction\"\n\n\n#define XR_HTC_hand_interaction 1\n#define XR_HTC_hand_interaction_SPEC_VERSION 1\n#define XR_HTC_HAND_INTERACTION_EXTENSION_NAME \"XR_HTC_hand_interaction\"\n\n\n#define XR_HTC_vive_wrist_tracker_interaction 1\n#define XR_HTC_vive_wrist_tracker_interaction_SPEC_VERSION 1\n#define XR_HTC_VIVE_WRIST_TRACKER_INTERACTION_EXTENSION_NAME \"XR_HTC_vive_wrist_tracker_interaction\"\n\n\n#define XR_FB_color_space 1\n#define XR_FB_color_space_SPEC_VERSION    3\n#define XR_FB_COLOR_SPACE_EXTENSION_NAME  \"XR_FB_color_space\"\n\ntypedef enum XrColorSpaceFB {\n    XR_COLOR_SPACE_UNMANAGED_FB = 0,\n    XR_COLOR_SPACE_REC2020_FB = 1,\n    XR_COLOR_SPACE_REC709_FB = 2,\n    XR_COLOR_SPACE_RIFT_CV1_FB = 3,\n    XR_COLOR_SPACE_RIFT_S_FB = 4,\n    XR_COLOR_SPACE_QUEST_FB = 5,\n    XR_COLOR_SPACE_P3_FB = 6,\n    XR_COLOR_SPACE_ADOBE_RGB_FB = 7,\n    XR_COLOR_SPACE_MAX_ENUM_FB = 0x7FFFFFFF\n} XrColorSpaceFB;\n// XrSystemColorSpacePropertiesFB extends XrSystemProperties\ntypedef struct XrSystemColorSpacePropertiesFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrColorSpaceFB colorSpace;\n} XrSystemColorSpacePropertiesFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateColorSpacesFB)(XrSession session,\n                                                           uint32_t colorSpaceCapacityInput,\n                                                           uint32_t *colorSpaceCountOutput,\n                                                           XrColorSpaceFB *colorSpaces);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetColorSpaceFB)(XrSession session,\n                                                    const XrColorSpaceFB colorspace);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateColorSpacesFB(\n    XrSession                                   session,\n    uint32_t                                    colorSpaceCapacityInput,\n    uint32_t*                                   colorSpaceCountOutput,\n    XrColorSpaceFB*                             colorSpaces);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetColorSpaceFB(\n    XrSession                                   session,\n    const XrColorSpaceFB                        colorspace);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_hand_tracking_mesh 1\n#define XR_FB_hand_tracking_mesh_SPEC_VERSION 3\n#define XR_FB_HAND_TRACKING_MESH_EXTENSION_NAME \"XR_FB_hand_tracking_mesh\"\ntypedef struct XrVector4sFB {\n    int16_t x;\n    int16_t y;\n    int16_t z;\n    int16_t w;\n} XrVector4sFB;\n\ntypedef struct XrHandTrackingMeshFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t jointCapacityInput;\n    uint32_t jointCountOutput;\n    XrPosef *jointBindPoses;\n    float *jointRadii;\n    XrHandJointEXT *jointParents;\n    uint32_t vertexCapacityInput;\n    uint32_t vertexCountOutput;\n    XrVector3f *vertexPositions;\n    XrVector3f *vertexNormals;\n    XrVector2f *vertexUVs;\n    XrVector4sFB *vertexBlendIndices;\n    XrVector4f *vertexBlendWeights;\n    uint32_t indexCapacityInput;\n    uint32_t indexCountOutput;\n    int16_t *indices;\n} XrHandTrackingMeshFB;\n\n// XrHandTrackingScaleFB extends XrHandJointLocationsEXT\ntypedef struct XrHandTrackingScaleFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    float sensorOutput;\n    float currentOutput;\n    XrBool32 overrideHandScale;\n    float overrideValueInput;\n} XrHandTrackingScaleFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetHandMeshFB)(XrHandTrackerEXT handTracker,\n                                                  XrHandTrackingMeshFB *mesh);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrGetHandMeshFB(\n    XrHandTrackerEXT                            handTracker,\n    XrHandTrackingMeshFB*                       mesh);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_hand_tracking_aim 1\n#define XR_FB_hand_tracking_aim_SPEC_VERSION 2\n#define XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME \"XR_FB_hand_tracking_aim\"\ntypedef XrFlags64 XrHandTrackingAimFlagsFB;\n\n// Flag bits for XrHandTrackingAimFlagsFB\nstatic const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_COMPUTED_BIT_FB = 0x00000001;\nstatic const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_VALID_BIT_FB = 0x00000002;\nstatic const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_INDEX_PINCHING_BIT_FB = 0x00000004;\nstatic const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_MIDDLE_PINCHING_BIT_FB = 0x00000008;\nstatic const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_RING_PINCHING_BIT_FB = 0x00000010;\nstatic const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_LITTLE_PINCHING_BIT_FB = 0x00000020;\nstatic const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_SYSTEM_GESTURE_BIT_FB = 0x00000040;\nstatic const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_DOMINANT_HAND_BIT_FB = 0x00000080;\nstatic const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_MENU_PRESSED_BIT_FB = 0x00000100;\n\n// XrHandTrackingAimStateFB extends XrHandJointLocationsEXT\ntypedef struct XrHandTrackingAimStateFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS          next;\n    XrHandTrackingAimFlagsFB status;\n    XrPosef aimPose;\n    float pinchStrengthIndex;\n    float pinchStrengthMiddle;\n    float pinchStrengthRing;\n    float pinchStrengthLittle;\n} XrHandTrackingAimStateFB;\n\n\n#define XR_FB_hand_tracking_capsules 1\n#define XR_HAND_TRACKING_CAPSULE_POINT_COUNT_FB 2\n#define XR_HAND_TRACKING_CAPSULE_COUNT_FB 19\n#define XR_FB_hand_tracking_capsules_SPEC_VERSION 3\n#define XR_FB_HAND_TRACKING_CAPSULES_EXTENSION_NAME \"XR_FB_hand_tracking_capsules\"\n#define XR_FB_HAND_TRACKING_CAPSULE_POINT_COUNT XR_HAND_TRACKING_CAPSULE_POINT_COUNT_FB\n#define XR_FB_HAND_TRACKING_CAPSULE_COUNT XR_HAND_TRACKING_CAPSULE_COUNT_FB\ntypedef struct XrHandCapsuleFB {\n    XrVector3f points[XR_HAND_TRACKING_CAPSULE_POINT_COUNT_FB];\n    float radius;\n    XrHandJointEXT joint;\n} XrHandCapsuleFB;\n\n// XrHandTrackingCapsulesStateFB extends XrHandJointLocationsEXT\ntypedef struct XrHandTrackingCapsulesStateFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrHandCapsuleFB capsules[XR_HAND_TRACKING_CAPSULE_COUNT_FB];\n} XrHandTrackingCapsulesStateFB;\n\n\n#define XR_FB_spatial_entity 1\nXR_DEFINE_ATOM(XrAsyncRequestIdFB)\n#define XR_UUID_SIZE_EXT                  16\n#define XR_FB_spatial_entity_SPEC_VERSION 2\n#define XR_FB_SPATIAL_ENTITY_EXTENSION_NAME \"XR_FB_spatial_entity\"\n\ntypedef enum XrSpaceComponentTypeFB {\n    XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB = 0,\n    XR_SPACE_COMPONENT_TYPE_STORABLE_FB = 1,\n    XR_SPACE_COMPONENT_TYPE_SHARABLE_FB = 2,\n    XR_SPACE_COMPONENT_TYPE_BOUNDED_2D_FB = 3,\n    XR_SPACE_COMPONENT_TYPE_BOUNDED_3D_FB = 4,\n    XR_SPACE_COMPONENT_TYPE_SEMANTIC_LABELS_FB = 5,\n    XR_SPACE_COMPONENT_TYPE_ROOM_LAYOUT_FB = 6,\n    XR_SPACE_COMPONENT_TYPE_SPACE_CONTAINER_FB = 7,\n    XR_SPACE_COMPONENT_TYPE_MAX_ENUM_FB = 0x7FFFFFFF\n} XrSpaceComponentTypeFB;\n// XrSystemSpatialEntityPropertiesFB extends XrSystemProperties\ntypedef struct XrSystemSpatialEntityPropertiesFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrBool32 supportsSpatialEntity;\n} XrSystemSpatialEntityPropertiesFB;\n\ntypedef struct XrSpatialAnchorCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace space;\n    XrPosef poseInSpace;\n    XrTime time;\n} XrSpatialAnchorCreateInfoFB;\n\ntypedef struct XrSpaceComponentStatusSetInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpaceComponentTypeFB componentType;\n    XrBool32 enabled;\n    XrDuration timeout;\n} XrSpaceComponentStatusSetInfoFB;\n\ntypedef struct XrSpaceComponentStatusFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 enabled;\n    XrBool32 changePending;\n} XrSpaceComponentStatusFB;\n\ntypedef struct XrUuidEXT {\n    uint8_t data[XR_UUID_SIZE_EXT];\n} XrUuidEXT;\n\ntypedef struct XrEventDataSpatialAnchorCreateCompleteFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAsyncRequestIdFB requestId;\n    XrResult result;\n    XrSpace space;\n    XrUuidEXT uuid;\n} XrEventDataSpatialAnchorCreateCompleteFB;\n\ntypedef struct XrEventDataSpaceSetStatusCompleteFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAsyncRequestIdFB requestId;\n    XrResult result;\n    XrSpace space;\n    XrUuidEXT uuid;\n    XrSpaceComponentTypeFB componentType;\n    XrBool32 enabled;\n} XrEventDataSpaceSetStatusCompleteFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFB)(XrSession session,\n                                                          const XrSpatialAnchorCreateInfoFB *info,\n                                                          XrAsyncRequestIdFB *requestId);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpaceUuidFB)(XrSpace space, XrUuidEXT *uuid);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateSpaceSupportedComponentsFB)(XrSpace space,\n                                                                        uint32_t componentTypeCapacityInput,\n                                                                        uint32_t *componentTypeCountOutput,\n                                                                        XrSpaceComponentTypeFB *componentTypes);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetSpaceComponentStatusFB)(XrSpace space,\n                                                              const XrSpaceComponentStatusSetInfoFB *info,\n                                                              XrAsyncRequestIdFB *requestId);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpaceComponentStatusFB)(XrSpace space,\n                                                              XrSpaceComponentTypeFB componentType,\n                                                              XrSpaceComponentStatusFB *status);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorFB(\n    XrSession                                   session,\n    const XrSpatialAnchorCreateInfoFB*          info,\n    XrAsyncRequestIdFB*                         requestId);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceUuidFB(\n    XrSpace                                     space,\n    XrUuidEXT*                                  uuid);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSpaceSupportedComponentsFB(\n    XrSpace                                     space,\n    uint32_t                                    componentTypeCapacityInput,\n    uint32_t*                                   componentTypeCountOutput,\n    XrSpaceComponentTypeFB*                     componentTypes);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetSpaceComponentStatusFB(\n    XrSpace                                     space,\n    const XrSpaceComponentStatusSetInfoFB*      info,\n    XrAsyncRequestIdFB*                         requestId);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceComponentStatusFB(\n    XrSpace                                     space,\n    XrSpaceComponentTypeFB                      componentType,\n    XrSpaceComponentStatusFB*                   status);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_foveation 1\nXR_DEFINE_HANDLE(XrFoveationProfileFB)\n#define XR_FB_foveation_SPEC_VERSION      1\n#define XR_FB_FOVEATION_EXTENSION_NAME    \"XR_FB_foveation\"\ntypedef XrFlags64 XrSwapchainCreateFoveationFlagsFB;\n\n// Flag bits for XrSwapchainCreateFoveationFlagsFB\nstatic const XrSwapchainCreateFoveationFlagsFB XR_SWAPCHAIN_CREATE_FOVEATION_SCALED_BIN_BIT_FB = 0x00000001;\nstatic const XrSwapchainCreateFoveationFlagsFB XR_SWAPCHAIN_CREATE_FOVEATION_FRAGMENT_DENSITY_MAP_BIT_FB = 0x00000002;\n\ntypedef XrFlags64 XrSwapchainStateFoveationFlagsFB;\n\n// Flag bits for XrSwapchainStateFoveationFlagsFB\n\ntypedef struct XrFoveationProfileCreateInfoFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n} XrFoveationProfileCreateInfoFB;\n\n// XrSwapchainCreateInfoFoveationFB extends XrSwapchainCreateInfo\ntypedef struct XrSwapchainCreateInfoFoveationFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                   next;\n    XrSwapchainCreateFoveationFlagsFB flags;\n} XrSwapchainCreateInfoFoveationFB;\n\ntypedef struct XrSwapchainStateFoveationFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                  next;\n    XrSwapchainStateFoveationFlagsFB flags;\n    XrFoveationProfileFB profile;\n} XrSwapchainStateFoveationFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateFoveationProfileFB)(XrSession session,\n                                                             const XrFoveationProfileCreateInfoFB *createInfo,\n                                                             XrFoveationProfileFB *profile);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyFoveationProfileFB)(XrFoveationProfileFB profile);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateFoveationProfileFB(\n    XrSession                                   session,\n    const XrFoveationProfileCreateInfoFB*       createInfo,\n    XrFoveationProfileFB*                       profile);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyFoveationProfileFB(\n    XrFoveationProfileFB                        profile);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_foveation_configuration 1\n#define XR_FB_foveation_configuration_SPEC_VERSION 1\n#define XR_FB_FOVEATION_CONFIGURATION_EXTENSION_NAME \"XR_FB_foveation_configuration\"\n\ntypedef enum XrFoveationLevelFB {\n    XR_FOVEATION_LEVEL_NONE_FB = 0,\n    XR_FOVEATION_LEVEL_LOW_FB = 1,\n    XR_FOVEATION_LEVEL_MEDIUM_FB = 2,\n    XR_FOVEATION_LEVEL_HIGH_FB = 3,\n    XR_FOVEATION_LEVEL_MAX_ENUM_FB = 0x7FFFFFFF\n} XrFoveationLevelFB;\n\ntypedef enum XrFoveationDynamicFB {\n    XR_FOVEATION_DYNAMIC_DISABLED_FB = 0,\n    XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB = 1,\n    XR_FOVEATION_DYNAMIC_MAX_ENUM_FB = 0x7FFFFFFF\n} XrFoveationDynamicFB;\n// XrFoveationLevelProfileCreateInfoFB extends XrFoveationProfileCreateInfoFB\ntypedef struct XrFoveationLevelProfileCreateInfoFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS      next;\n    XrFoveationLevelFB level;\n    float verticalOffset;\n    XrFoveationDynamicFB dynamic;\n} XrFoveationLevelProfileCreateInfoFB;\n\n\n#define XR_FB_keyboard_tracking 1\n#define XR_FB_keyboard_tracking_SPEC_VERSION 1\n#define XR_FB_KEYBOARD_TRACKING_EXTENSION_NAME \"XR_FB_keyboard_tracking\"\n#define XR_MAX_KEYBOARD_TRACKING_NAME_SIZE_FB 128\ntypedef XrFlags64 XrKeyboardTrackingFlagsFB;\n\n// Flag bits for XrKeyboardTrackingFlagsFB\nstatic const XrKeyboardTrackingFlagsFB XR_KEYBOARD_TRACKING_EXISTS_BIT_FB = 0x00000001;\nstatic const XrKeyboardTrackingFlagsFB XR_KEYBOARD_TRACKING_LOCAL_BIT_FB = 0x00000002;\nstatic const XrKeyboardTrackingFlagsFB XR_KEYBOARD_TRACKING_REMOTE_BIT_FB = 0x00000004;\nstatic const XrKeyboardTrackingFlagsFB XR_KEYBOARD_TRACKING_CONNECTED_BIT_FB = 0x00000008;\n\ntypedef XrFlags64 XrKeyboardTrackingQueryFlagsFB;\n\n// Flag bits for XrKeyboardTrackingQueryFlagsFB\nstatic const XrKeyboardTrackingQueryFlagsFB XR_KEYBOARD_TRACKING_QUERY_LOCAL_BIT_FB = 0x00000002;\nstatic const XrKeyboardTrackingQueryFlagsFB XR_KEYBOARD_TRACKING_QUERY_REMOTE_BIT_FB = 0x00000004;\n\n// XrSystemKeyboardTrackingPropertiesFB extends XrSystemProperties\ntypedef struct XrSystemKeyboardTrackingPropertiesFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsKeyboardTracking;\n} XrSystemKeyboardTrackingPropertiesFB;\n\ntypedef struct XrKeyboardTrackingDescriptionFB {\n    uint64_t trackedKeyboardId;\n    XrVector3f size;\n    XrKeyboardTrackingFlagsFB flags;\n    char name[XR_MAX_KEYBOARD_TRACKING_NAME_SIZE_FB];\n} XrKeyboardTrackingDescriptionFB;\n\ntypedef struct XrKeyboardSpaceCreateInfoFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint64_t trackedKeyboardId;\n} XrKeyboardSpaceCreateInfoFB;\n\ntypedef struct XrKeyboardTrackingQueryFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                next;\n    XrKeyboardTrackingQueryFlagsFB flags;\n} XrKeyboardTrackingQueryFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrQuerySystemTrackedKeyboardFB)(XrSession session,\n                                                                 const XrKeyboardTrackingQueryFB *queryInfo,\n                                                                 XrKeyboardTrackingDescriptionFB *keyboard);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateKeyboardSpaceFB)(XrSession session,\n                                                          const XrKeyboardSpaceCreateInfoFB *createInfo,\n                                                          XrSpace *keyboardSpace);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrQuerySystemTrackedKeyboardFB(\n    XrSession                                   session,\n    const XrKeyboardTrackingQueryFB*            queryInfo,\n    XrKeyboardTrackingDescriptionFB*            keyboard);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateKeyboardSpaceFB(\n    XrSession                                   session,\n    const XrKeyboardSpaceCreateInfoFB*          createInfo,\n    XrSpace*                                    keyboardSpace);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_triangle_mesh 1\nXR_DEFINE_HANDLE(XrTriangleMeshFB)\n#define XR_FB_triangle_mesh_SPEC_VERSION  2\n#define XR_FB_TRIANGLE_MESH_EXTENSION_NAME \"XR_FB_triangle_mesh\"\n\ntypedef enum XrWindingOrderFB {\n    XR_WINDING_ORDER_UNKNOWN_FB = 0,\n    XR_WINDING_ORDER_CW_FB = 1,\n    XR_WINDING_ORDER_CCW_FB = 2,\n    XR_WINDING_ORDER_MAX_ENUM_FB = 0x7FFFFFFF\n} XrWindingOrderFB;\ntypedef XrFlags64 XrTriangleMeshFlagsFB;\n\n// Flag bits for XrTriangleMeshFlagsFB\nstatic const XrTriangleMeshFlagsFB XR_TRIANGLE_MESH_MUTABLE_BIT_FB = 0x00000001;\n\ntypedef struct XrTriangleMeshCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrTriangleMeshFlagsFB flags;\n    XrWindingOrderFB windingOrder;\n    uint32_t vertexCount;\n    const XrVector3f *vertexBuffer;\n    uint32_t triangleCount;\n    const uint32_t *indexBuffer;\n} XrTriangleMeshCreateInfoFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateTriangleMeshFB)(XrSession session,\n                                                         const XrTriangleMeshCreateInfoFB *createInfo,\n                                                         XrTriangleMeshFB *outTriangleMesh);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyTriangleMeshFB)(XrTriangleMeshFB mesh);\ntypedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshGetVertexBufferFB)(XrTriangleMeshFB mesh,\n                                                                  XrVector3f **outVertexBuffer);\ntypedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshGetIndexBufferFB)(XrTriangleMeshFB mesh,\n                                                                 uint32_t **outIndexBuffer);\ntypedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshBeginUpdateFB)(XrTriangleMeshFB mesh);\ntypedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshEndUpdateFB)(XrTriangleMeshFB mesh,\n                                                            uint32_t vertexCount,\n                                                            uint32_t triangleCount);\ntypedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshBeginVertexBufferUpdateFB)(XrTriangleMeshFB mesh,\n                                                                          uint32_t *outVertexCount);\ntypedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshEndVertexBufferUpdateFB)(XrTriangleMeshFB mesh);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateTriangleMeshFB(\n    XrSession                                   session,\n    const XrTriangleMeshCreateInfoFB*           createInfo,\n    XrTriangleMeshFB*                           outTriangleMesh);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyTriangleMeshFB(\n    XrTriangleMeshFB                            mesh);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshGetVertexBufferFB(\n    XrTriangleMeshFB                            mesh,\n    XrVector3f**                                outVertexBuffer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshGetIndexBufferFB(\n    XrTriangleMeshFB                            mesh,\n    uint32_t**                                  outIndexBuffer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshBeginUpdateFB(\n    XrTriangleMeshFB                            mesh);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshEndUpdateFB(\n    XrTriangleMeshFB                            mesh,\n    uint32_t                                    vertexCount,\n    uint32_t                                    triangleCount);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshBeginVertexBufferUpdateFB(\n    XrTriangleMeshFB                            mesh,\n    uint32_t*                                   outVertexCount);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshEndVertexBufferUpdateFB(\n    XrTriangleMeshFB                            mesh);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_passthrough 1\nXR_DEFINE_HANDLE(XrPassthroughFB)\nXR_DEFINE_HANDLE(XrPassthroughLayerFB)\nXR_DEFINE_HANDLE(XrGeometryInstanceFB)\n#define XR_FB_passthrough_SPEC_VERSION    3\n#define XR_FB_PASSTHROUGH_EXTENSION_NAME  \"XR_FB_passthrough\"\n#define XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB 256\n\ntypedef enum XrPassthroughLayerPurposeFB {\n    XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB = 0,\n    XR_PASSTHROUGH_LAYER_PURPOSE_PROJECTED_FB = 1,\n    XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS_FB = 1000203001,\n    XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB = 1000203002,\n    XR_PASSTHROUGH_LAYER_PURPOSE_MAX_ENUM_FB = 0x7FFFFFFF\n} XrPassthroughLayerPurposeFB;\ntypedef XrFlags64 XrPassthroughCapabilityFlagsFB;\n\n// Flag bits for XrPassthroughCapabilityFlagsFB\nstatic const XrPassthroughCapabilityFlagsFB XR_PASSTHROUGH_CAPABILITY_BIT_FB = 0x00000001;\nstatic const XrPassthroughCapabilityFlagsFB XR_PASSTHROUGH_CAPABILITY_COLOR_BIT_FB = 0x00000002;\nstatic const XrPassthroughCapabilityFlagsFB XR_PASSTHROUGH_CAPABILITY_LAYER_DEPTH_BIT_FB = 0x00000004;\n\ntypedef XrFlags64 XrPassthroughFlagsFB;\n\n// Flag bits for XrPassthroughFlagsFB\nstatic const XrPassthroughFlagsFB XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB = 0x00000001;\nstatic const XrPassthroughFlagsFB XR_PASSTHROUGH_LAYER_DEPTH_BIT_FB = 0x00000002;\n\ntypedef XrFlags64 XrPassthroughStateChangedFlagsFB;\n\n// Flag bits for XrPassthroughStateChangedFlagsFB\nstatic const XrPassthroughStateChangedFlagsFB XR_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT_FB = 0x00000001;\nstatic const XrPassthroughStateChangedFlagsFB XR_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT_FB = 0x00000002;\nstatic const XrPassthroughStateChangedFlagsFB XR_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT_FB = 0x00000004;\nstatic const XrPassthroughStateChangedFlagsFB XR_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT_FB = 0x00000008;\n\n// XrSystemPassthroughPropertiesFB extends XrSystemProperties\ntypedef struct XrSystemPassthroughPropertiesFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrBool32 supportsPassthrough;\n} XrSystemPassthroughPropertiesFB;\n\n// XrSystemPassthroughProperties2FB extends XrSystemProperties\ntypedef struct XrSystemPassthroughProperties2FB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS          next;\n    XrPassthroughCapabilityFlagsFB capabilities;\n} XrSystemPassthroughProperties2FB;\n\ntypedef struct XrPassthroughCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrPassthroughFlagsFB flags;\n} XrPassthroughCreateInfoFB;\n\ntypedef struct XrPassthroughLayerCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS       next;\n    XrPassthroughFB passthrough;\n    XrPassthroughFlagsFB flags;\n    XrPassthroughLayerPurposeFB purpose;\n} XrPassthroughLayerCreateInfoFB;\n\n// XrCompositionLayerPassthroughFB extends XrCompositionLayerBaseHeader\ntypedef struct XrCompositionLayerPassthroughFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrCompositionLayerFlags flags;\n    XrSpace space;\n    XrPassthroughLayerFB layerHandle;\n} XrCompositionLayerPassthroughFB;\n\ntypedef struct XrGeometryInstanceCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrPassthroughLayerFB layer;\n    XrTriangleMeshFB mesh;\n    XrSpace baseSpace;\n    XrPosef pose;\n    XrVector3f scale;\n} XrGeometryInstanceCreateInfoFB;\n\ntypedef struct XrGeometryInstanceTransformFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace baseSpace;\n    XrTime time;\n    XrPosef pose;\n    XrVector3f scale;\n} XrGeometryInstanceTransformFB;\n\ntypedef struct XrPassthroughStyleFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    float textureOpacityFactor;\n    XrColor4f edgeColor;\n} XrPassthroughStyleFB;\n\n// XrPassthroughColorMapMonoToRgbaFB extends XrPassthroughStyleFB\ntypedef struct XrPassthroughColorMapMonoToRgbaFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrColor4f textureColorMap[XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB];\n} XrPassthroughColorMapMonoToRgbaFB;\n\n// XrPassthroughColorMapMonoToMonoFB extends XrPassthroughStyleFB\ntypedef struct XrPassthroughColorMapMonoToMonoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint8_t textureColorMap[XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB];\n} XrPassthroughColorMapMonoToMonoFB;\n\n// XrPassthroughBrightnessContrastSaturationFB extends XrPassthroughStyleFB\ntypedef struct XrPassthroughBrightnessContrastSaturationFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    float brightness;\n    float contrast;\n    float saturation;\n} XrPassthroughBrightnessContrastSaturationFB;\n\ntypedef struct XrEventDataPassthroughStateChangedFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS            next;\n    XrPassthroughStateChangedFlagsFB flags;\n} XrEventDataPassthroughStateChangedFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreatePassthroughFB)(XrSession session,\n                                                        const XrPassthroughCreateInfoFB *createInfo,\n                                                        XrPassthroughFB *outPassthrough);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyPassthroughFB)(XrPassthroughFB passthrough);\ntypedef XrResult (XRAPI_PTR *PFN_xrPassthroughStartFB)(XrPassthroughFB passthrough);\ntypedef XrResult (XRAPI_PTR *PFN_xrPassthroughPauseFB)(XrPassthroughFB passthrough);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreatePassthroughLayerFB)(XrSession session,\n                                                             const XrPassthroughLayerCreateInfoFB *createInfo,\n                                                             XrPassthroughLayerFB *outLayer);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyPassthroughLayerFB)(XrPassthroughLayerFB layer);\ntypedef XrResult (XRAPI_PTR *PFN_xrPassthroughLayerPauseFB)(XrPassthroughLayerFB layer);\ntypedef XrResult (XRAPI_PTR *PFN_xrPassthroughLayerResumeFB)(XrPassthroughLayerFB layer);\ntypedef XrResult (XRAPI_PTR *PFN_xrPassthroughLayerSetStyleFB)(XrPassthroughLayerFB layer,\n                                                               const XrPassthroughStyleFB *style);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateGeometryInstanceFB)(XrSession session,\n                                                             const XrGeometryInstanceCreateInfoFB *createInfo,\n                                                             XrGeometryInstanceFB *outGeometryInstance);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyGeometryInstanceFB)(XrGeometryInstanceFB instance);\ntypedef XrResult (XRAPI_PTR *PFN_xrGeometryInstanceSetTransformFB)(XrGeometryInstanceFB instance,\n                                                                   const XrGeometryInstanceTransformFB *transformation);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreatePassthroughFB(\n    XrSession                                   session,\n    const XrPassthroughCreateInfoFB*            createInfo,\n    XrPassthroughFB*                            outPassthrough);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyPassthroughFB(\n    XrPassthroughFB                             passthrough);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrPassthroughStartFB(\n    XrPassthroughFB                             passthrough);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrPassthroughPauseFB(\n    XrPassthroughFB                             passthrough);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreatePassthroughLayerFB(\n    XrSession                                   session,\n    const XrPassthroughLayerCreateInfoFB*       createInfo,\n    XrPassthroughLayerFB*                       outLayer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyPassthroughLayerFB(\n    XrPassthroughLayerFB                        layer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrPassthroughLayerPauseFB(\n    XrPassthroughLayerFB                        layer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrPassthroughLayerResumeFB(\n    XrPassthroughLayerFB                        layer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrPassthroughLayerSetStyleFB(\n    XrPassthroughLayerFB                        layer,\n    const XrPassthroughStyleFB*                 style);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateGeometryInstanceFB(\n    XrSession                                   session,\n    const XrGeometryInstanceCreateInfoFB*       createInfo,\n    XrGeometryInstanceFB*                       outGeometryInstance);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyGeometryInstanceFB(\n    XrGeometryInstanceFB                        instance);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGeometryInstanceSetTransformFB(\n    XrGeometryInstanceFB                        instance,\n    const XrGeometryInstanceTransformFB*        transformation);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_render_model 1\n\n#define XR_NULL_RENDER_MODEL_KEY_FB 0\n\nXR_DEFINE_ATOM(XrRenderModelKeyFB)\n#define XR_FB_render_model_SPEC_VERSION   4\n#define XR_FB_RENDER_MODEL_EXTENSION_NAME \"XR_FB_render_model\"\n#define XR_MAX_RENDER_MODEL_NAME_SIZE_FB  64\ntypedef XrFlags64 XrRenderModelFlagsFB;\n\n// Flag bits for XrRenderModelFlagsFB\nstatic const XrRenderModelFlagsFB XR_RENDER_MODEL_SUPPORTS_GLTF_2_0_SUBSET_1_BIT_FB = 0x00000001;\nstatic const XrRenderModelFlagsFB XR_RENDER_MODEL_SUPPORTS_GLTF_2_0_SUBSET_2_BIT_FB = 0x00000002;\n\ntypedef struct XrRenderModelPathInfoFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrPath path;\n} XrRenderModelPathInfoFB;\n\ntypedef struct XrRenderModelPropertiesFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS      next;\n    uint32_t vendorId;\n    char modelName[XR_MAX_RENDER_MODEL_NAME_SIZE_FB];\n    XrRenderModelKeyFB modelKey;\n    uint32_t modelVersion;\n    XrRenderModelFlagsFB flags;\n} XrRenderModelPropertiesFB;\n\ntypedef struct XrRenderModelBufferFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t bufferCapacityInput;\n    uint32_t bufferCountOutput;\n    uint8_t *buffer;\n} XrRenderModelBufferFB;\n\ntypedef struct XrRenderModelLoadInfoFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrRenderModelKeyFB modelKey;\n} XrRenderModelLoadInfoFB;\n\n// XrSystemRenderModelPropertiesFB extends XrSystemProperties\ntypedef struct XrSystemRenderModelPropertiesFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsRenderModelLoading;\n} XrSystemRenderModelPropertiesFB;\n\n// XrRenderModelCapabilitiesRequestFB extends XrSystemProperties\ntypedef struct XrRenderModelCapabilitiesRequestFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS      next;\n    XrRenderModelFlagsFB flags;\n} XrRenderModelCapabilitiesRequestFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateRenderModelPathsFB)(XrSession session,\n                                                                uint32_t pathCapacityInput,\n                                                                uint32_t *pathCountOutput,\n                                                                XrRenderModelPathInfoFB *paths);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetRenderModelPropertiesFB)(XrSession session, XrPath path,\n                                                               XrRenderModelPropertiesFB *properties);\ntypedef XrResult (XRAPI_PTR *PFN_xrLoadRenderModelFB)(XrSession session,\n                                                      const XrRenderModelLoadInfoFB *info,\n                                                      XrRenderModelBufferFB *buffer);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateRenderModelPathsFB(\n    XrSession                                   session,\n    uint32_t                                    pathCapacityInput,\n    uint32_t*                                   pathCountOutput,\n    XrRenderModelPathInfoFB*                    paths);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetRenderModelPropertiesFB(\n    XrSession                                   session,\n    XrPath                                      path,\n    XrRenderModelPropertiesFB*                  properties);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrLoadRenderModelFB(\n    XrSession                                   session,\n    const XrRenderModelLoadInfoFB*              info,\n    XrRenderModelBufferFB*                      buffer);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_VARJO_foveated_rendering 1\n#define XR_VARJO_foveated_rendering_SPEC_VERSION 3\n#define XR_VARJO_FOVEATED_RENDERING_EXTENSION_NAME \"XR_VARJO_foveated_rendering\"\n// XrViewLocateFoveatedRenderingVARJO extends XrViewLocateInfo\ntypedef struct XrViewLocateFoveatedRenderingVARJO {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrBool32 foveatedRenderingActive;\n} XrViewLocateFoveatedRenderingVARJO;\n\n// XrFoveatedViewConfigurationViewVARJO extends XrViewConfigurationView\ntypedef struct XrFoveatedViewConfigurationViewVARJO {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 foveatedRenderingActive;\n} XrFoveatedViewConfigurationViewVARJO;\n\n// XrSystemFoveatedRenderingPropertiesVARJO extends XrSystemProperties\ntypedef struct XrSystemFoveatedRenderingPropertiesVARJO {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsFoveatedRendering;\n} XrSystemFoveatedRenderingPropertiesVARJO;\n\n\n#define XR_VARJO_composition_layer_depth_test 1\n#define XR_VARJO_composition_layer_depth_test_SPEC_VERSION 2\n#define XR_VARJO_COMPOSITION_LAYER_DEPTH_TEST_EXTENSION_NAME \"XR_VARJO_composition_layer_depth_test\"\n// XrCompositionLayerDepthTestVARJO extends XrCompositionLayerProjection\ntypedef struct XrCompositionLayerDepthTestVARJO {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    float depthTestRangeNearZ;\n    float depthTestRangeFarZ;\n} XrCompositionLayerDepthTestVARJO;\n\n\n#define XR_VARJO_environment_depth_estimation 1\n#define XR_VARJO_environment_depth_estimation_SPEC_VERSION 1\n#define XR_VARJO_ENVIRONMENT_DEPTH_ESTIMATION_EXTENSION_NAME \"XR_VARJO_environment_depth_estimation\"\ntypedef XrResult (XRAPI_PTR *PFN_xrSetEnvironmentDepthEstimationVARJO)(XrSession session,\n                                                                       XrBool32 enabled);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrSetEnvironmentDepthEstimationVARJO(\n    XrSession                                   session,\n    XrBool32                                    enabled);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_VARJO_marker_tracking 1\n#define XR_VARJO_marker_tracking_SPEC_VERSION 1\n#define XR_VARJO_MARKER_TRACKING_EXTENSION_NAME \"XR_VARJO_marker_tracking\"\n// XrSystemMarkerTrackingPropertiesVARJO extends XrSystemProperties\ntypedef struct XrSystemMarkerTrackingPropertiesVARJO {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsMarkerTracking;\n} XrSystemMarkerTrackingPropertiesVARJO;\n\ntypedef struct XrEventDataMarkerTrackingUpdateVARJO {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint64_t markerId;\n    XrBool32 isActive;\n    XrBool32 isPredicted;\n    XrTime time;\n} XrEventDataMarkerTrackingUpdateVARJO;\n\ntypedef struct XrMarkerSpaceCreateInfoVARJO {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint64_t markerId;\n    XrPosef poseInMarkerSpace;\n} XrMarkerSpaceCreateInfoVARJO;\n\ntypedef XrResult  (XRAPI_PTR *PFN_xrSetMarkerTrackingVARJO)(XrSession session, XrBool32 enabled);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetMarkerTrackingTimeoutVARJO)(XrSession session,\n                                                                  uint64_t markerId,\n                                                                  XrDuration timeout);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetMarkerTrackingPredictionVARJO)(XrSession session,\n                                                                     uint64_t markerId,\n                                                                     XrBool32 enabled);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetMarkerSizeVARJO)(XrSession session, uint64_t markerId,\n                                                       XrExtent2Df *size);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateMarkerSpaceVARJO)(XrSession session,\n                                                           const XrMarkerSpaceCreateInfoVARJO *createInfo,\n                                                           XrSpace *space);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult  XRAPI_CALL xrSetMarkerTrackingVARJO(\n    XrSession                                   session,\n    XrBool32                                    enabled);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetMarkerTrackingTimeoutVARJO(\n    XrSession                                   session,\n    uint64_t                                    markerId,\n    XrDuration                                  timeout);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetMarkerTrackingPredictionVARJO(\n    XrSession                                   session,\n    uint64_t                                    markerId,\n    XrBool32                                    enabled);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetMarkerSizeVARJO(\n    XrSession                                   session,\n    uint64_t                                    markerId,\n    XrExtent2Df*                                size);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateMarkerSpaceVARJO(\n    XrSession                                   session,\n    const XrMarkerSpaceCreateInfoVARJO*         createInfo,\n    XrSpace*                                    space);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_VARJO_view_offset 1\n#define XR_VARJO_view_offset_SPEC_VERSION 1\n#define XR_VARJO_VIEW_OFFSET_EXTENSION_NAME \"XR_VARJO_view_offset\"\ntypedef XrResult  (XRAPI_PTR *PFN_xrSetViewOffsetVARJO)(XrSession session, float offset);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult  XRAPI_CALL xrSetViewOffsetVARJO(\n    XrSession                                   session,\n    float                                       offset);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_ML_ml2_controller_interaction 1\n#define XR_ML_ml2_controller_interaction_SPEC_VERSION 1\n#define XR_ML_ML2_CONTROLLER_INTERACTION_EXTENSION_NAME \"XR_ML_ml2_controller_interaction\"\n\n\n#define XR_ML_frame_end_info 1\n#define XR_ML_frame_end_info_SPEC_VERSION 1\n#define XR_ML_FRAME_END_INFO_EXTENSION_NAME \"XR_ML_frame_end_info\"\ntypedef XrFlags64 XrFrameEndInfoFlagsML;\n\n// Flag bits for XrFrameEndInfoFlagsML\nstatic const XrFrameEndInfoFlagsML XR_FRAME_END_INFO_PROTECTED_BIT_ML = 0x00000001;\nstatic const XrFrameEndInfoFlagsML XR_FRAME_END_INFO_VIGNETTE_BIT_ML = 0x00000002;\n\n// XrFrameEndInfoML extends XrFrameEndInfo\ntypedef struct XrFrameEndInfoML {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    float focusDistance;\n    XrFrameEndInfoFlagsML flags;\n} XrFrameEndInfoML;\n\n\n#define XR_ML_global_dimmer 1\n#define XR_ML_global_dimmer_SPEC_VERSION  1\n#define XR_ML_GLOBAL_DIMMER_EXTENSION_NAME \"XR_ML_global_dimmer\"\ntypedef XrFlags64 XrGlobalDimmerFrameEndInfoFlagsML;\n\n// Flag bits for XrGlobalDimmerFrameEndInfoFlagsML\nstatic const XrGlobalDimmerFrameEndInfoFlagsML XR_GLOBAL_DIMMER_FRAME_END_INFO_ENABLED_BIT_ML = 0x00000001;\n\n// XrGlobalDimmerFrameEndInfoML extends XrFrameEndInfo\ntypedef struct XrGlobalDimmerFrameEndInfoML {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS             next;\n    float dimmerValue;\n    XrGlobalDimmerFrameEndInfoFlagsML flags;\n} XrGlobalDimmerFrameEndInfoML;\n\n\n#define XR_MSFT_spatial_anchor_persistence 1\nXR_DEFINE_HANDLE(XrSpatialAnchorStoreConnectionMSFT)\n#define XR_MAX_SPATIAL_ANCHOR_NAME_SIZE_MSFT 256\n#define XR_MSFT_spatial_anchor_persistence_SPEC_VERSION 2\n#define XR_MSFT_SPATIAL_ANCHOR_PERSISTENCE_EXTENSION_NAME \"XR_MSFT_spatial_anchor_persistence\"\ntypedef struct XrSpatialAnchorPersistenceNameMSFT {\n    char name[XR_MAX_SPATIAL_ANCHOR_NAME_SIZE_MSFT];\n} XrSpatialAnchorPersistenceNameMSFT;\n\ntypedef struct XrSpatialAnchorPersistenceInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS              next;\n    XrSpatialAnchorPersistenceNameMSFT spatialAnchorPersistenceName;\n    XrSpatialAnchorMSFT spatialAnchor;\n} XrSpatialAnchorPersistenceInfoMSFT;\n\ntypedef struct XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS              next;\n    XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore;\n    XrSpatialAnchorPersistenceNameMSFT spatialAnchorPersistenceName;\n} XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorStoreConnectionMSFT)(XrSession session,\n                                                                           XrSpatialAnchorStoreConnectionMSFT *spatialAnchorStore);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialAnchorStoreConnectionMSFT)(\n        XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore);\ntypedef XrResult (XRAPI_PTR *PFN_xrPersistSpatialAnchorMSFT)(\n        XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore,\n        const XrSpatialAnchorPersistenceInfoMSFT *spatialAnchorPersistenceInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumeratePersistedSpatialAnchorNamesMSFT)(\n        XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore,\n        uint32_t spatialAnchorNamesCapacityInput, uint32_t *spatialAnchorNamesCountOutput,\n        XrSpatialAnchorPersistenceNameMSFT *persistedAnchorNames);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFromPersistedNameMSFT)(XrSession session,\n                                                                             const XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT *spatialAnchorCreateInfo,\n                                                                             XrSpatialAnchorMSFT *spatialAnchor);\ntypedef XrResult (XRAPI_PTR *PFN_xrUnpersistSpatialAnchorMSFT)(\n        XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore,\n        const XrSpatialAnchorPersistenceNameMSFT *spatialAnchorPersistenceName);\ntypedef XrResult (XRAPI_PTR *PFN_xrClearSpatialAnchorStoreMSFT)(\n        XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorStoreConnectionMSFT(\n    XrSession                                   session,\n    XrSpatialAnchorStoreConnectionMSFT*         spatialAnchorStore);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroySpatialAnchorStoreConnectionMSFT(\n    XrSpatialAnchorStoreConnectionMSFT          spatialAnchorStore);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrPersistSpatialAnchorMSFT(\n    XrSpatialAnchorStoreConnectionMSFT          spatialAnchorStore,\n    const XrSpatialAnchorPersistenceInfoMSFT*   spatialAnchorPersistenceInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEnumeratePersistedSpatialAnchorNamesMSFT(\n    XrSpatialAnchorStoreConnectionMSFT          spatialAnchorStore,\n    uint32_t                                    spatialAnchorNamesCapacityInput,\n    uint32_t*                                   spatialAnchorNamesCountOutput,\n    XrSpatialAnchorPersistenceNameMSFT*         persistedAnchorNames);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorFromPersistedNameMSFT(\n    XrSession                                   session,\n    const XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT* spatialAnchorCreateInfo,\n    XrSpatialAnchorMSFT*                        spatialAnchor);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrUnpersistSpatialAnchorMSFT(\n    XrSpatialAnchorStoreConnectionMSFT          spatialAnchorStore,\n    const XrSpatialAnchorPersistenceNameMSFT*   spatialAnchorPersistenceName);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrClearSpatialAnchorStoreMSFT(\n    XrSpatialAnchorStoreConnectionMSFT          spatialAnchorStore);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_ULTRALEAP_hand_tracking_forearm 1\n\n#define XR_HAND_FOREARM_JOINT_COUNT_ULTRALEAP 27\n\n#define XR_ULTRALEAP_hand_tracking_forearm_SPEC_VERSION 1\n#define XR_ULTRALEAP_HAND_TRACKING_FOREARM_EXTENSION_NAME \"XR_ULTRALEAP_hand_tracking_forearm\"\n\ntypedef enum XrHandForearmJointULTRALEAP {\n    XR_HAND_FOREARM_JOINT_PALM_ULTRALEAP = 0,\n    XR_HAND_FOREARM_JOINT_WRIST_ULTRALEAP = 1,\n    XR_HAND_FOREARM_JOINT_THUMB_METACARPAL_ULTRALEAP = 2,\n    XR_HAND_FOREARM_JOINT_THUMB_PROXIMAL_ULTRALEAP = 3,\n    XR_HAND_FOREARM_JOINT_THUMB_DISTAL_ULTRALEAP = 4,\n    XR_HAND_FOREARM_JOINT_THUMB_TIP_ULTRALEAP = 5,\n    XR_HAND_FOREARM_JOINT_INDEX_METACARPAL_ULTRALEAP = 6,\n    XR_HAND_FOREARM_JOINT_INDEX_PROXIMAL_ULTRALEAP = 7,\n    XR_HAND_FOREARM_JOINT_INDEX_INTERMEDIATE_ULTRALEAP = 8,\n    XR_HAND_FOREARM_JOINT_INDEX_DISTAL_ULTRALEAP = 9,\n    XR_HAND_FOREARM_JOINT_INDEX_TIP_ULTRALEAP = 10,\n    XR_HAND_FOREARM_JOINT_MIDDLE_METACARPAL_ULTRALEAP = 11,\n    XR_HAND_FOREARM_JOINT_MIDDLE_PROXIMAL_ULTRALEAP = 12,\n    XR_HAND_FOREARM_JOINT_MIDDLE_INTERMEDIATE_ULTRALEAP = 13,\n    XR_HAND_FOREARM_JOINT_MIDDLE_DISTAL_ULTRALEAP = 14,\n    XR_HAND_FOREARM_JOINT_MIDDLE_TIP_ULTRALEAP = 15,\n    XR_HAND_FOREARM_JOINT_RING_METACARPAL_ULTRALEAP = 16,\n    XR_HAND_FOREARM_JOINT_RING_PROXIMAL_ULTRALEAP = 17,\n    XR_HAND_FOREARM_JOINT_RING_INTERMEDIATE_ULTRALEAP = 18,\n    XR_HAND_FOREARM_JOINT_RING_DISTAL_ULTRALEAP = 19,\n    XR_HAND_FOREARM_JOINT_RING_TIP_ULTRALEAP = 20,\n    XR_HAND_FOREARM_JOINT_LITTLE_METACARPAL_ULTRALEAP = 21,\n    XR_HAND_FOREARM_JOINT_LITTLE_PROXIMAL_ULTRALEAP = 22,\n    XR_HAND_FOREARM_JOINT_LITTLE_INTERMEDIATE_ULTRALEAP = 23,\n    XR_HAND_FOREARM_JOINT_LITTLE_DISTAL_ULTRALEAP = 24,\n    XR_HAND_FOREARM_JOINT_LITTLE_TIP_ULTRALEAP = 25,\n    XR_HAND_FOREARM_JOINT_ELBOW_ULTRALEAP = 26,\n    XR_HAND_FOREARM_JOINT_MAX_ENUM_ULTRALEAP = 0x7FFFFFFF\n} XrHandForearmJointULTRALEAP;\n\n\n#define XR_FB_spatial_entity_query 1\n#define XR_FB_spatial_entity_query_SPEC_VERSION 1\n#define XR_FB_SPATIAL_ENTITY_QUERY_EXTENSION_NAME \"XR_FB_spatial_entity_query\"\n\ntypedef enum XrSpaceQueryActionFB {\n    XR_SPACE_QUERY_ACTION_LOAD_FB = 0,\n    XR_SPACE_QUERY_ACTION_MAX_ENUM_FB = 0x7FFFFFFF\n} XrSpaceQueryActionFB;\n\ntypedef enum XrSpaceStorageLocationFB {\n    XR_SPACE_STORAGE_LOCATION_INVALID_FB = 0,\n    XR_SPACE_STORAGE_LOCATION_LOCAL_FB = 1,\n    XR_SPACE_STORAGE_LOCATION_CLOUD_FB = 2,\n    XR_SPACE_STORAGE_LOCATION_MAX_ENUM_FB = 0x7FFFFFFF\n} XrSpaceStorageLocationFB;\ntypedef struct XR_MAY_ALIAS XrSpaceQueryInfoBaseHeaderFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrSpaceQueryInfoBaseHeaderFB;\n\ntypedef struct XR_MAY_ALIAS XrSpaceFilterInfoBaseHeaderFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrSpaceFilterInfoBaseHeaderFB;\n\ntypedef struct XrSpaceQueryInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                next;\n    XrSpaceQueryActionFB queryAction;\n    uint32_t maxResultCount;\n    XrDuration timeout;\n    const XrSpaceFilterInfoBaseHeaderFB *filter;\n    const XrSpaceFilterInfoBaseHeaderFB *excludeFilter;\n} XrSpaceQueryInfoFB;\n\n// XrSpaceStorageLocationFilterInfoFB extends XrSpaceFilterInfoBaseHeaderFB\ntypedef struct XrSpaceStorageLocationFilterInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpaceStorageLocationFB location;\n} XrSpaceStorageLocationFilterInfoFB;\n\ntypedef struct XrSpaceUuidFilterInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t uuidCount;\n    XrUuidEXT *uuids;\n} XrSpaceUuidFilterInfoFB;\n\ntypedef struct XrSpaceComponentFilterInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpaceComponentTypeFB componentType;\n} XrSpaceComponentFilterInfoFB;\n\ntypedef struct XrSpaceQueryResultFB {\n    XrSpace space;\n    XrUuidEXT uuid;\n} XrSpaceQueryResultFB;\n\ntypedef struct XrSpaceQueryResultsFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS       next;\n    uint32_t resultCapacityInput;\n    uint32_t resultCountOutput;\n    XrSpaceQueryResultFB *results;\n} XrSpaceQueryResultsFB;\n\ntypedef struct XrEventDataSpaceQueryResultsAvailableFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAsyncRequestIdFB requestId;\n} XrEventDataSpaceQueryResultsAvailableFB;\n\ntypedef struct XrEventDataSpaceQueryCompleteFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAsyncRequestIdFB requestId;\n    XrResult result;\n} XrEventDataSpaceQueryCompleteFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrQuerySpacesFB)(XrSession session,\n                                                  const XrSpaceQueryInfoBaseHeaderFB *info,\n                                                  XrAsyncRequestIdFB *requestId);\ntypedef XrResult (XRAPI_PTR *PFN_xrRetrieveSpaceQueryResultsFB)(XrSession session,\n                                                                XrAsyncRequestIdFB requestId,\n                                                                XrSpaceQueryResultsFB *results);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrQuerySpacesFB(\n    XrSession                                   session,\n    const XrSpaceQueryInfoBaseHeaderFB*         info,\n    XrAsyncRequestIdFB*                         requestId);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrRetrieveSpaceQueryResultsFB(\n    XrSession                                   session,\n    XrAsyncRequestIdFB                          requestId,\n    XrSpaceQueryResultsFB*                      results);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_spatial_entity_storage 1\n#define XR_FB_spatial_entity_storage_SPEC_VERSION 1\n#define XR_FB_SPATIAL_ENTITY_STORAGE_EXTENSION_NAME \"XR_FB_spatial_entity_storage\"\n\ntypedef enum XrSpacePersistenceModeFB {\n    XR_SPACE_PERSISTENCE_MODE_INVALID_FB = 0,\n    XR_SPACE_PERSISTENCE_MODE_INDEFINITE_FB = 1,\n    XR_SPACE_PERSISTENCE_MODE_MAX_ENUM_FB = 0x7FFFFFFF\n} XrSpacePersistenceModeFB;\ntypedef struct XrSpaceSaveInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace space;\n    XrSpaceStorageLocationFB location;\n    XrSpacePersistenceModeFB persistenceMode;\n} XrSpaceSaveInfoFB;\n\ntypedef struct XrSpaceEraseInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace space;\n    XrSpaceStorageLocationFB location;\n} XrSpaceEraseInfoFB;\n\ntypedef struct XrEventDataSpaceSaveCompleteFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAsyncRequestIdFB requestId;\n    XrResult result;\n    XrSpace space;\n    XrUuidEXT uuid;\n    XrSpaceStorageLocationFB location;\n} XrEventDataSpaceSaveCompleteFB;\n\ntypedef struct XrEventDataSpaceEraseCompleteFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAsyncRequestIdFB requestId;\n    XrResult result;\n    XrSpace space;\n    XrUuidEXT uuid;\n    XrSpaceStorageLocationFB location;\n} XrEventDataSpaceEraseCompleteFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrSaveSpaceFB)(XrSession session, const XrSpaceSaveInfoFB *info,\n                                                XrAsyncRequestIdFB *requestId);\ntypedef XrResult (XRAPI_PTR *PFN_xrEraseSpaceFB)(XrSession session, const XrSpaceEraseInfoFB *info,\n                                                 XrAsyncRequestIdFB *requestId);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrSaveSpaceFB(\n    XrSession                                   session,\n    const XrSpaceSaveInfoFB*                    info,\n    XrAsyncRequestIdFB*                         requestId);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrEraseSpaceFB(\n    XrSession                                   session,\n    const XrSpaceEraseInfoFB*                   info,\n    XrAsyncRequestIdFB*                         requestId);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_touch_controller_pro 1\n#define XR_FB_touch_controller_pro_SPEC_VERSION 1\n#define XR_FB_TOUCH_CONTROLLER_PRO_EXTENSION_NAME \"XR_FB_touch_controller_pro\"\n\n\n#define XR_FB_spatial_entity_sharing 1\nXR_DEFINE_HANDLE(XrSpaceUserFB)\n#define XR_FB_spatial_entity_sharing_SPEC_VERSION 1\n#define XR_FB_SPATIAL_ENTITY_SHARING_EXTENSION_NAME \"XR_FB_spatial_entity_sharing\"\ntypedef struct XrSpaceShareInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t spaceCount;\n    XrSpace *spaces;\n    uint32_t userCount;\n    XrSpaceUserFB *users;\n} XrSpaceShareInfoFB;\n\ntypedef struct XrEventDataSpaceShareCompleteFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAsyncRequestIdFB requestId;\n    XrResult result;\n} XrEventDataSpaceShareCompleteFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrShareSpacesFB)(XrSession session, const XrSpaceShareInfoFB *info,\n                                                  XrAsyncRequestIdFB *requestId);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrShareSpacesFB(\n    XrSession                                   session,\n    const XrSpaceShareInfoFB*                   info,\n    XrAsyncRequestIdFB*                         requestId);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_space_warp 1\n#define XR_FB_space_warp_SPEC_VERSION     2\n#define XR_FB_SPACE_WARP_EXTENSION_NAME   \"XR_FB_space_warp\"\ntypedef XrFlags64 XrCompositionLayerSpaceWarpInfoFlagsFB;\n\n// Flag bits for XrCompositionLayerSpaceWarpInfoFlagsFB\nstatic const XrCompositionLayerSpaceWarpInfoFlagsFB XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB = 0x00000001;\n\n// XrCompositionLayerSpaceWarpInfoFB extends XrCompositionLayerProjectionView\ntypedef struct XrCompositionLayerSpaceWarpInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                  next;\n    XrCompositionLayerSpaceWarpInfoFlagsFB layerFlags;\n    XrSwapchainSubImage motionVectorSubImage;\n    XrPosef appSpaceDeltaPose;\n    XrSwapchainSubImage depthSubImage;\n    float minDepth;\n    float maxDepth;\n    float nearZ;\n    float farZ;\n} XrCompositionLayerSpaceWarpInfoFB;\n\n// XrSystemSpaceWarpPropertiesFB extends XrSystemProperties\ntypedef struct XrSystemSpaceWarpPropertiesFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t recommendedMotionVectorImageRectWidth;\n    uint32_t recommendedMotionVectorImageRectHeight;\n} XrSystemSpaceWarpPropertiesFB;\n\n\n#define XR_FB_haptic_amplitude_envelope 1\n\n#define XR_MAX_HAPTIC_AMPLITUDE_ENVELOPE_SAMPLES_FB 4000u\n\n#define XR_FB_haptic_amplitude_envelope_SPEC_VERSION 1\n#define XR_FB_HAPTIC_AMPLITUDE_ENVELOPE_EXTENSION_NAME \"XR_FB_haptic_amplitude_envelope\"\ntypedef struct XrHapticAmplitudeEnvelopeVibrationFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrDuration duration;\n    uint32_t amplitudeCount;\n    const float *amplitudes;\n} XrHapticAmplitudeEnvelopeVibrationFB;\n\n\n#define XR_FB_scene 1\n#define XR_FB_scene_SPEC_VERSION          3\n#define XR_FB_SCENE_EXTENSION_NAME        \"XR_FB_scene\"\ntypedef XrFlags64 XrSemanticLabelsSupportFlagsFB;\n\n// Flag bits for XrSemanticLabelsSupportFlagsFB\nstatic const XrSemanticLabelsSupportFlagsFB XR_SEMANTIC_LABELS_SUPPORT_MULTIPLE_SEMANTIC_LABELS_BIT_FB = 0x00000001;\nstatic const XrSemanticLabelsSupportFlagsFB XR_SEMANTIC_LABELS_SUPPORT_ACCEPT_DESK_TO_TABLE_MIGRATION_BIT_FB = 0x00000002;\n\ntypedef struct XrExtent3DfFB {\n    float width;\n    float height;\n    float depth;\n} XrExtent3DfFB;\n\ntypedef struct XrOffset3DfFB {\n    float x;\n    float y;\n    float z;\n} XrOffset3DfFB;\n\ntypedef struct XrRect3DfFB {\n    XrOffset3DfFB offset;\n    XrExtent3DfFB extent;\n} XrRect3DfFB;\n\ntypedef struct XrSemanticLabelsFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t bufferCapacityInput;\n    uint32_t bufferCountOutput;\n    char *buffer;\n} XrSemanticLabelsFB;\n\ntypedef struct XrRoomLayoutFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrUuidEXT floorUuid;\n    XrUuidEXT ceilingUuid;\n    uint32_t wallUuidCapacityInput;\n    uint32_t wallUuidCountOutput;\n    XrUuidEXT *wallUuids;\n} XrRoomLayoutFB;\n\ntypedef struct XrBoundary2DFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t vertexCapacityInput;\n    uint32_t vertexCountOutput;\n    XrVector2f *vertices;\n} XrBoundary2DFB;\n\ntypedef struct XrSemanticLabelsSupportInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS          next;\n    XrSemanticLabelsSupportFlagsFB flags;\n    const char *recognizedLabels;\n} XrSemanticLabelsSupportInfoFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpaceBoundingBox2DFB)(XrSession session, XrSpace space,\n                                                            XrRect2Df *boundingBox2DOutput);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpaceBoundingBox3DFB)(XrSession session, XrSpace space,\n                                                            XrRect3DfFB *boundingBox3DOutput);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpaceSemanticLabelsFB)(XrSession session, XrSpace space,\n                                                             XrSemanticLabelsFB *semanticLabelsOutput);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpaceBoundary2DFB)(XrSession session, XrSpace space,\n                                                         XrBoundary2DFB *boundary2DOutput);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpaceRoomLayoutFB)(XrSession session, XrSpace space,\n                                                         XrRoomLayoutFB *roomLayoutOutput);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceBoundingBox2DFB(\n    XrSession                                   session,\n    XrSpace                                     space,\n    XrRect2Df*                                  boundingBox2DOutput);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceBoundingBox3DFB(\n    XrSession                                   session,\n    XrSpace                                     space,\n    XrRect3DfFB*                                boundingBox3DOutput);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceSemanticLabelsFB(\n    XrSession                                   session,\n    XrSpace                                     space,\n    XrSemanticLabelsFB*                         semanticLabelsOutput);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceBoundary2DFB(\n    XrSession                                   session,\n    XrSpace                                     space,\n    XrBoundary2DFB*                             boundary2DOutput);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceRoomLayoutFB(\n    XrSession                                   session,\n    XrSpace                                     space,\n    XrRoomLayoutFB*                             roomLayoutOutput);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_EXT_palm_pose 1\n#define XR_EXT_palm_pose_SPEC_VERSION     2\n#define XR_EXT_PALM_POSE_EXTENSION_NAME   \"XR_EXT_palm_pose\"\n\n\n#define XR_ALMALENCE_digital_lens_control 1\n#define XR_ALMALENCE_digital_lens_control_SPEC_VERSION 1\n#define XR_ALMALENCE_DIGITAL_LENS_CONTROL_EXTENSION_NAME \"XR_ALMALENCE_digital_lens_control\"\ntypedef XrFlags64 XrDigitalLensControlFlagsALMALENCE;\n\n// Flag bits for XrDigitalLensControlFlagsALMALENCE\nstatic const XrDigitalLensControlFlagsALMALENCE XR_DIGITAL_LENS_CONTROL_PROCESSING_DISABLE_BIT_ALMALENCE = 0x00000001;\n\ntypedef struct XrDigitalLensControlALMALENCE {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS              next;\n    XrDigitalLensControlFlagsALMALENCE flags;\n} XrDigitalLensControlALMALENCE;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrSetDigitalLensControlALMALENCE)(XrSession session,\n                                                                   const XrDigitalLensControlALMALENCE *digitalLensControl);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrSetDigitalLensControlALMALENCE(\n    XrSession                                   session,\n    const XrDigitalLensControlALMALENCE*        digitalLensControl);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_scene_capture 1\n#define XR_FB_scene_capture_SPEC_VERSION  1\n#define XR_FB_SCENE_CAPTURE_EXTENSION_NAME \"XR_FB_scene_capture\"\ntypedef struct XrEventDataSceneCaptureCompleteFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAsyncRequestIdFB requestId;\n    XrResult result;\n} XrEventDataSceneCaptureCompleteFB;\n\ntypedef struct XrSceneCaptureRequestInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t requestByteCount;\n    const char *request;\n} XrSceneCaptureRequestInfoFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrRequestSceneCaptureFB)(XrSession session,\n                                                          const XrSceneCaptureRequestInfoFB *info,\n                                                          XrAsyncRequestIdFB *requestId);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrRequestSceneCaptureFB(\n    XrSession                                   session,\n    const XrSceneCaptureRequestInfoFB*          info,\n    XrAsyncRequestIdFB*                         requestId);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_spatial_entity_container 1\n#define XR_FB_spatial_entity_container_SPEC_VERSION 2\n#define XR_FB_SPATIAL_ENTITY_CONTAINER_EXTENSION_NAME \"XR_FB_spatial_entity_container\"\ntypedef struct XrSpaceContainerFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t uuidCapacityInput;\n    uint32_t uuidCountOutput;\n    XrUuidEXT *uuids;\n} XrSpaceContainerFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpaceContainerFB)(XrSession session, XrSpace space,\n                                                        XrSpaceContainerFB *spaceContainerOutput);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceContainerFB(\n    XrSession                                   session,\n    XrSpace                                     space,\n    XrSpaceContainerFB*                         spaceContainerOutput);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_META_foveation_eye_tracked 1\n#define XR_FOVEATION_CENTER_SIZE_META     2\n#define XR_META_foveation_eye_tracked_SPEC_VERSION 1\n#define XR_META_FOVEATION_EYE_TRACKED_EXTENSION_NAME \"XR_META_foveation_eye_tracked\"\ntypedef XrFlags64 XrFoveationEyeTrackedProfileCreateFlagsMETA;\n\n// Flag bits for XrFoveationEyeTrackedProfileCreateFlagsMETA\n\ntypedef XrFlags64 XrFoveationEyeTrackedStateFlagsMETA;\n\n// Flag bits for XrFoveationEyeTrackedStateFlagsMETA\nstatic const XrFoveationEyeTrackedStateFlagsMETA XR_FOVEATION_EYE_TRACKED_STATE_VALID_BIT_META = 0x00000001;\n\n// XrFoveationEyeTrackedProfileCreateInfoMETA extends XrFoveationLevelProfileCreateInfoFB\ntypedef struct XrFoveationEyeTrackedProfileCreateInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                       next;\n    XrFoveationEyeTrackedProfileCreateFlagsMETA flags;\n} XrFoveationEyeTrackedProfileCreateInfoMETA;\n\ntypedef struct XrFoveationEyeTrackedStateMETA {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                     next;\n    XrVector2f foveationCenter[XR_FOVEATION_CENTER_SIZE_META];\n    XrFoveationEyeTrackedStateFlagsMETA flags;\n} XrFoveationEyeTrackedStateMETA;\n\n// XrSystemFoveationEyeTrackedPropertiesMETA extends XrSystemProperties\ntypedef struct XrSystemFoveationEyeTrackedPropertiesMETA {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsFoveationEyeTracked;\n} XrSystemFoveationEyeTrackedPropertiesMETA;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetFoveationEyeTrackedStateMETA)(XrSession session,\n                                                                    XrFoveationEyeTrackedStateMETA *foveationState);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrGetFoveationEyeTrackedStateMETA(\n    XrSession                                   session,\n    XrFoveationEyeTrackedStateMETA*             foveationState);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_face_tracking 1\n\n#define XR_FACE_EXPRESSSION_SET_DEFAULT_FB XR_FACE_EXPRESSION_SET_DEFAULT_FB\n\nXR_DEFINE_HANDLE(XrFaceTrackerFB)\n#define XR_FB_face_tracking_SPEC_VERSION  1\n#define XR_FB_FACE_TRACKING_EXTENSION_NAME \"XR_FB_face_tracking\"\n\ntypedef enum XrFaceExpressionFB {\n    XR_FACE_EXPRESSION_BROW_LOWERER_L_FB = 0,\n    XR_FACE_EXPRESSION_BROW_LOWERER_R_FB = 1,\n    XR_FACE_EXPRESSION_CHEEK_PUFF_L_FB = 2,\n    XR_FACE_EXPRESSION_CHEEK_PUFF_R_FB = 3,\n    XR_FACE_EXPRESSION_CHEEK_RAISER_L_FB = 4,\n    XR_FACE_EXPRESSION_CHEEK_RAISER_R_FB = 5,\n    XR_FACE_EXPRESSION_CHEEK_SUCK_L_FB = 6,\n    XR_FACE_EXPRESSION_CHEEK_SUCK_R_FB = 7,\n    XR_FACE_EXPRESSION_CHIN_RAISER_B_FB = 8,\n    XR_FACE_EXPRESSION_CHIN_RAISER_T_FB = 9,\n    XR_FACE_EXPRESSION_DIMPLER_L_FB = 10,\n    XR_FACE_EXPRESSION_DIMPLER_R_FB = 11,\n    XR_FACE_EXPRESSION_EYES_CLOSED_L_FB = 12,\n    XR_FACE_EXPRESSION_EYES_CLOSED_R_FB = 13,\n    XR_FACE_EXPRESSION_EYES_LOOK_DOWN_L_FB = 14,\n    XR_FACE_EXPRESSION_EYES_LOOK_DOWN_R_FB = 15,\n    XR_FACE_EXPRESSION_EYES_LOOK_LEFT_L_FB = 16,\n    XR_FACE_EXPRESSION_EYES_LOOK_LEFT_R_FB = 17,\n    XR_FACE_EXPRESSION_EYES_LOOK_RIGHT_L_FB = 18,\n    XR_FACE_EXPRESSION_EYES_LOOK_RIGHT_R_FB = 19,\n    XR_FACE_EXPRESSION_EYES_LOOK_UP_L_FB = 20,\n    XR_FACE_EXPRESSION_EYES_LOOK_UP_R_FB = 21,\n    XR_FACE_EXPRESSION_INNER_BROW_RAISER_L_FB = 22,\n    XR_FACE_EXPRESSION_INNER_BROW_RAISER_R_FB = 23,\n    XR_FACE_EXPRESSION_JAW_DROP_FB = 24,\n    XR_FACE_EXPRESSION_JAW_SIDEWAYS_LEFT_FB = 25,\n    XR_FACE_EXPRESSION_JAW_SIDEWAYS_RIGHT_FB = 26,\n    XR_FACE_EXPRESSION_JAW_THRUST_FB = 27,\n    XR_FACE_EXPRESSION_LID_TIGHTENER_L_FB = 28,\n    XR_FACE_EXPRESSION_LID_TIGHTENER_R_FB = 29,\n    XR_FACE_EXPRESSION_LIP_CORNER_DEPRESSOR_L_FB = 30,\n    XR_FACE_EXPRESSION_LIP_CORNER_DEPRESSOR_R_FB = 31,\n    XR_FACE_EXPRESSION_LIP_CORNER_PULLER_L_FB = 32,\n    XR_FACE_EXPRESSION_LIP_CORNER_PULLER_R_FB = 33,\n    XR_FACE_EXPRESSION_LIP_FUNNELER_LB_FB = 34,\n    XR_FACE_EXPRESSION_LIP_FUNNELER_LT_FB = 35,\n    XR_FACE_EXPRESSION_LIP_FUNNELER_RB_FB = 36,\n    XR_FACE_EXPRESSION_LIP_FUNNELER_RT_FB = 37,\n    XR_FACE_EXPRESSION_LIP_PRESSOR_L_FB = 38,\n    XR_FACE_EXPRESSION_LIP_PRESSOR_R_FB = 39,\n    XR_FACE_EXPRESSION_LIP_PUCKER_L_FB = 40,\n    XR_FACE_EXPRESSION_LIP_PUCKER_R_FB = 41,\n    XR_FACE_EXPRESSION_LIP_STRETCHER_L_FB = 42,\n    XR_FACE_EXPRESSION_LIP_STRETCHER_R_FB = 43,\n    XR_FACE_EXPRESSION_LIP_SUCK_LB_FB = 44,\n    XR_FACE_EXPRESSION_LIP_SUCK_LT_FB = 45,\n    XR_FACE_EXPRESSION_LIP_SUCK_RB_FB = 46,\n    XR_FACE_EXPRESSION_LIP_SUCK_RT_FB = 47,\n    XR_FACE_EXPRESSION_LIP_TIGHTENER_L_FB = 48,\n    XR_FACE_EXPRESSION_LIP_TIGHTENER_R_FB = 49,\n    XR_FACE_EXPRESSION_LIPS_TOWARD_FB = 50,\n    XR_FACE_EXPRESSION_LOWER_LIP_DEPRESSOR_L_FB = 51,\n    XR_FACE_EXPRESSION_LOWER_LIP_DEPRESSOR_R_FB = 52,\n    XR_FACE_EXPRESSION_MOUTH_LEFT_FB = 53,\n    XR_FACE_EXPRESSION_MOUTH_RIGHT_FB = 54,\n    XR_FACE_EXPRESSION_NOSE_WRINKLER_L_FB = 55,\n    XR_FACE_EXPRESSION_NOSE_WRINKLER_R_FB = 56,\n    XR_FACE_EXPRESSION_OUTER_BROW_RAISER_L_FB = 57,\n    XR_FACE_EXPRESSION_OUTER_BROW_RAISER_R_FB = 58,\n    XR_FACE_EXPRESSION_UPPER_LID_RAISER_L_FB = 59,\n    XR_FACE_EXPRESSION_UPPER_LID_RAISER_R_FB = 60,\n    XR_FACE_EXPRESSION_UPPER_LIP_RAISER_L_FB = 61,\n    XR_FACE_EXPRESSION_UPPER_LIP_RAISER_R_FB = 62,\n    XR_FACE_EXPRESSION_COUNT_FB = 63,\n    XR_FACE_EXPRESSION_MAX_ENUM_FB = 0x7FFFFFFF\n} XrFaceExpressionFB;\n\ntypedef enum XrFaceExpressionSetFB {\n    XR_FACE_EXPRESSION_SET_DEFAULT_FB = 0,\n    XR_FACE_EXPRESSION_SET_MAX_ENUM_FB = 0x7FFFFFFF\n} XrFaceExpressionSetFB;\n\ntypedef enum XrFaceConfidenceFB {\n    XR_FACE_CONFIDENCE_LOWER_FACE_FB = 0,\n    XR_FACE_CONFIDENCE_UPPER_FACE_FB = 1,\n    XR_FACE_CONFIDENCE_COUNT_FB = 2,\n    XR_FACE_CONFIDENCE_MAX_ENUM_FB = 0x7FFFFFFF\n} XrFaceConfidenceFB;\n// XrSystemFaceTrackingPropertiesFB extends XrSystemProperties\ntypedef struct XrSystemFaceTrackingPropertiesFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsFaceTracking;\n} XrSystemFaceTrackingPropertiesFB;\n\ntypedef struct XrFaceTrackerCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrFaceExpressionSetFB faceExpressionSet;\n} XrFaceTrackerCreateInfoFB;\n\ntypedef struct XrFaceExpressionInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrTime time;\n} XrFaceExpressionInfoFB;\n\ntypedef struct XrFaceExpressionStatusFB {\n    XrBool32 isValid;\n    XrBool32 isEyeFollowingBlendshapesValid;\n} XrFaceExpressionStatusFB;\n\ntypedef struct XrFaceExpressionWeightsFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS          next;\n    uint32_t weightCount;\n    float *weights;\n    uint32_t confidenceCount;\n    float *confidences;\n    XrFaceExpressionStatusFB status;\n    XrTime time;\n} XrFaceExpressionWeightsFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateFaceTrackerFB)(XrSession session,\n                                                        const XrFaceTrackerCreateInfoFB *createInfo,\n                                                        XrFaceTrackerFB *faceTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyFaceTrackerFB)(XrFaceTrackerFB faceTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetFaceExpressionWeightsFB)(XrFaceTrackerFB faceTracker,\n                                                               const XrFaceExpressionInfoFB *expressionInfo,\n                                                               XrFaceExpressionWeightsFB *expressionWeights);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateFaceTrackerFB(\n    XrSession                                   session,\n    const XrFaceTrackerCreateInfoFB*            createInfo,\n    XrFaceTrackerFB*                            faceTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyFaceTrackerFB(\n    XrFaceTrackerFB                             faceTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetFaceExpressionWeightsFB(\n    XrFaceTrackerFB                             faceTracker,\n    const XrFaceExpressionInfoFB*               expressionInfo,\n    XrFaceExpressionWeightsFB*                  expressionWeights);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_eye_tracking_social 1\nXR_DEFINE_HANDLE(XrEyeTrackerFB)\n#define XR_FB_eye_tracking_social_SPEC_VERSION 1\n#define XR_FB_EYE_TRACKING_SOCIAL_EXTENSION_NAME \"XR_FB_eye_tracking_social\"\n\ntypedef enum XrEyePositionFB {\n    XR_EYE_POSITION_LEFT_FB = 0,\n    XR_EYE_POSITION_RIGHT_FB = 1,\n    XR_EYE_POSITION_COUNT_FB = 2,\n    XR_EYE_POSITION_MAX_ENUM_FB = 0x7FFFFFFF\n} XrEyePositionFB;\ntypedef struct XrEyeGazeFB {\n    XrBool32 isValid;\n    XrPosef gazePose;\n    float gazeConfidence;\n} XrEyeGazeFB;\n\ntypedef struct XrEyeTrackerCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrEyeTrackerCreateInfoFB;\n\ntypedef struct XrEyeGazesInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace baseSpace;\n    XrTime time;\n} XrEyeGazesInfoFB;\n\n// XrSystemEyeTrackingPropertiesFB extends XrSystemProperties\ntypedef struct XrSystemEyeTrackingPropertiesFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsEyeTracking;\n} XrSystemEyeTrackingPropertiesFB;\n\ntypedef struct XrEyeGazesFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrEyeGazeFB gaze[XR_EYE_POSITION_COUNT_FB];\n    XrTime time;\n} XrEyeGazesFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateEyeTrackerFB)(XrSession session,\n                                                       const XrEyeTrackerCreateInfoFB *createInfo,\n                                                       XrEyeTrackerFB *eyeTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyEyeTrackerFB)(XrEyeTrackerFB eyeTracker);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetEyeGazesFB)(XrEyeTrackerFB eyeTracker,\n                                                  const XrEyeGazesInfoFB *gazeInfo,\n                                                  XrEyeGazesFB *eyeGazes);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateEyeTrackerFB(\n    XrSession                                   session,\n    const XrEyeTrackerCreateInfoFB*             createInfo,\n    XrEyeTrackerFB*                             eyeTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyEyeTrackerFB(\n    XrEyeTrackerFB                              eyeTracker);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetEyeGazesFB(\n    XrEyeTrackerFB                              eyeTracker,\n    const XrEyeGazesInfoFB*                     gazeInfo,\n    XrEyeGazesFB*                               eyeGazes);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_passthrough_keyboard_hands 1\n#define XR_FB_passthrough_keyboard_hands_SPEC_VERSION 2\n#define XR_FB_PASSTHROUGH_KEYBOARD_HANDS_EXTENSION_NAME \"XR_FB_passthrough_keyboard_hands\"\ntypedef struct XrPassthroughKeyboardHandsIntensityFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    float leftHandIntensity;\n    float rightHandIntensity;\n} XrPassthroughKeyboardHandsIntensityFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrPassthroughLayerSetKeyboardHandsIntensityFB)(\n        XrPassthroughLayerFB layer, const XrPassthroughKeyboardHandsIntensityFB *intensity);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrPassthroughLayerSetKeyboardHandsIntensityFB(\n    XrPassthroughLayerFB                        layer,\n    const XrPassthroughKeyboardHandsIntensityFB* intensity);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_composition_layer_settings 1\n#define XR_FB_composition_layer_settings_SPEC_VERSION 1\n#define XR_FB_COMPOSITION_LAYER_SETTINGS_EXTENSION_NAME \"XR_FB_composition_layer_settings\"\ntypedef XrFlags64 XrCompositionLayerSettingsFlagsFB;\n\n// Flag bits for XrCompositionLayerSettingsFlagsFB\nstatic const XrCompositionLayerSettingsFlagsFB XR_COMPOSITION_LAYER_SETTINGS_NORMAL_SUPER_SAMPLING_BIT_FB = 0x00000001;\nstatic const XrCompositionLayerSettingsFlagsFB XR_COMPOSITION_LAYER_SETTINGS_QUALITY_SUPER_SAMPLING_BIT_FB = 0x00000002;\nstatic const XrCompositionLayerSettingsFlagsFB XR_COMPOSITION_LAYER_SETTINGS_NORMAL_SHARPENING_BIT_FB = 0x00000004;\nstatic const XrCompositionLayerSettingsFlagsFB XR_COMPOSITION_LAYER_SETTINGS_QUALITY_SHARPENING_BIT_FB = 0x00000008;\n\n// XrCompositionLayerSettingsFB extends XrCompositionLayerBaseHeader\ntypedef struct XrCompositionLayerSettingsFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS             next;\n    XrCompositionLayerSettingsFlagsFB layerFlags;\n} XrCompositionLayerSettingsFB;\n\n\n#define XR_FB_touch_controller_proximity 1\n#define XR_FB_touch_controller_proximity_SPEC_VERSION 1\n#define XR_FB_TOUCH_CONTROLLER_PROXIMITY_EXTENSION_NAME \"XR_FB_touch_controller_proximity\"\n\n\n#define XR_FB_haptic_pcm 1\n\n#define XR_MAX_HAPTIC_PCM_BUFFER_SIZE_FB 4000\n\n#define XR_FB_haptic_pcm_SPEC_VERSION     1\n#define XR_FB_HAPTIC_PCM_EXTENSION_NAME   \"XR_FB_haptic_pcm\"\ntypedef struct XrHapticPcmVibrationFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t bufferSize;\n    const float *buffer;\n    float sampleRate;\n    XrBool32 append;\n    uint32_t *samplesConsumed;\n} XrHapticPcmVibrationFB;\n\ntypedef struct XrDevicePcmSampleRateStateFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    float sampleRate;\n} XrDevicePcmSampleRateStateFB;\n\ntypedef XrDevicePcmSampleRateStateFB XrDevicePcmSampleRateGetInfoFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetDeviceSampleRateFB)(XrSession session,\n                                                          const XrHapticActionInfo *hapticActionInfo,\n                                                          XrDevicePcmSampleRateGetInfoFB *deviceSampleRate);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrGetDeviceSampleRateFB(\n    XrSession                                   session,\n    const XrHapticActionInfo*                   hapticActionInfo,\n    XrDevicePcmSampleRateGetInfoFB*             deviceSampleRate);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_composition_layer_depth_test 1\n#define XR_FB_composition_layer_depth_test_SPEC_VERSION 1\n#define XR_FB_COMPOSITION_LAYER_DEPTH_TEST_EXTENSION_NAME \"XR_FB_composition_layer_depth_test\"\n\ntypedef enum XrCompareOpFB {\n    XR_COMPARE_OP_NEVER_FB = 0,\n    XR_COMPARE_OP_LESS_FB = 1,\n    XR_COMPARE_OP_EQUAL_FB = 2,\n    XR_COMPARE_OP_LESS_OR_EQUAL_FB = 3,\n    XR_COMPARE_OP_GREATER_FB = 4,\n    XR_COMPARE_OP_NOT_EQUAL_FB = 5,\n    XR_COMPARE_OP_GREATER_OR_EQUAL_FB = 6,\n    XR_COMPARE_OP_ALWAYS_FB = 7,\n    XR_COMPARE_OP_MAX_ENUM_FB = 0x7FFFFFFF\n} XrCompareOpFB;\n// XrCompositionLayerDepthTestFB extends XrCompositionLayerBaseHeader\ntypedef struct XrCompositionLayerDepthTestFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrBool32 depthMask;\n    XrCompareOpFB compareOp;\n} XrCompositionLayerDepthTestFB;\n\n\n#define XR_META_local_dimming 1\n#define XR_META_local_dimming_SPEC_VERSION 1\n#define XR_META_LOCAL_DIMMING_EXTENSION_NAME \"XR_META_local_dimming\"\n\ntypedef enum XrLocalDimmingModeMETA {\n    XR_LOCAL_DIMMING_MODE_OFF_META = 0,\n    XR_LOCAL_DIMMING_MODE_ON_META = 1,\n    XR_LOCAL_DIMMING_MODE_MAX_ENUM_META = 0x7FFFFFFF\n} XrLocalDimmingModeMETA;\n// XrLocalDimmingFrameEndInfoMETA extends XrFrameEndInfo\ntypedef struct XrLocalDimmingFrameEndInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrLocalDimmingModeMETA localDimmingMode;\n} XrLocalDimmingFrameEndInfoMETA;\n\n\n#define XR_META_virtual_keyboard 1\nXR_DEFINE_HANDLE(XrVirtualKeyboardMETA)\n#define XR_MAX_VIRTUAL_KEYBOARD_COMMIT_TEXT_SIZE_META 3992\n#define XR_META_virtual_keyboard_SPEC_VERSION 1\n#define XR_META_VIRTUAL_KEYBOARD_EXTENSION_NAME \"XR_META_virtual_keyboard\"\n\ntypedef enum XrVirtualKeyboardLocationTypeMETA {\n    XR_VIRTUAL_KEYBOARD_LOCATION_TYPE_CUSTOM_META = 0,\n    XR_VIRTUAL_KEYBOARD_LOCATION_TYPE_FAR_META = 1,\n    XR_VIRTUAL_KEYBOARD_LOCATION_TYPE_DIRECT_META = 2,\n    XR_VIRTUAL_KEYBOARD_LOCATION_TYPE_MAX_ENUM_META = 0x7FFFFFFF\n} XrVirtualKeyboardLocationTypeMETA;\n\ntypedef enum XrVirtualKeyboardInputSourceMETA {\n    XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_CONTROLLER_RAY_LEFT_META = 1,\n    XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_CONTROLLER_RAY_RIGHT_META = 2,\n    XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_HAND_RAY_LEFT_META = 3,\n    XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_HAND_RAY_RIGHT_META = 4,\n    XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_CONTROLLER_DIRECT_LEFT_META = 5,\n    XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_CONTROLLER_DIRECT_RIGHT_META = 6,\n    XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_HAND_DIRECT_INDEX_TIP_LEFT_META = 7,\n    XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_HAND_DIRECT_INDEX_TIP_RIGHT_META = 8,\n    XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_MAX_ENUM_META = 0x7FFFFFFF\n} XrVirtualKeyboardInputSourceMETA;\ntypedef XrFlags64 XrVirtualKeyboardInputStateFlagsMETA;\n\n// Flag bits for XrVirtualKeyboardInputStateFlagsMETA\nstatic const XrVirtualKeyboardInputStateFlagsMETA XR_VIRTUAL_KEYBOARD_INPUT_STATE_PRESSED_BIT_META = 0x00000001;\n\n// XrSystemVirtualKeyboardPropertiesMETA extends XrSystemProperties\ntypedef struct XrSystemVirtualKeyboardPropertiesMETA {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsVirtualKeyboard;\n} XrSystemVirtualKeyboardPropertiesMETA;\n\ntypedef struct XrVirtualKeyboardCreateInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n} XrVirtualKeyboardCreateInfoMETA;\n\ntypedef struct XrVirtualKeyboardSpaceCreateInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS             next;\n    XrVirtualKeyboardLocationTypeMETA locationType;\n    XrSpace space;\n    XrPosef poseInSpace;\n} XrVirtualKeyboardSpaceCreateInfoMETA;\n\ntypedef struct XrVirtualKeyboardLocationInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS             next;\n    XrVirtualKeyboardLocationTypeMETA locationType;\n    XrSpace space;\n    XrPosef poseInSpace;\n    float scale;\n} XrVirtualKeyboardLocationInfoMETA;\n\ntypedef struct XrVirtualKeyboardModelVisibilitySetInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrBool32 visible;\n} XrVirtualKeyboardModelVisibilitySetInfoMETA;\n\ntypedef struct XrVirtualKeyboardAnimationStateMETA {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    int32_t animationIndex;\n    float fraction;\n} XrVirtualKeyboardAnimationStateMETA;\n\ntypedef struct XrVirtualKeyboardModelAnimationStatesMETA {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                      next;\n    uint32_t stateCapacityInput;\n    uint32_t stateCountOutput;\n    XrVirtualKeyboardAnimationStateMETA *states;\n} XrVirtualKeyboardModelAnimationStatesMETA;\n\ntypedef struct XrVirtualKeyboardTextureDataMETA {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t textureWidth;\n    uint32_t textureHeight;\n    uint32_t bufferCapacityInput;\n    uint32_t bufferCountOutput;\n    uint8_t *buffer;\n} XrVirtualKeyboardTextureDataMETA;\n\ntypedef struct XrVirtualKeyboardInputInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                next;\n    XrVirtualKeyboardInputSourceMETA inputSource;\n    XrSpace inputSpace;\n    XrPosef inputPoseInSpace;\n    XrVirtualKeyboardInputStateFlagsMETA inputState;\n} XrVirtualKeyboardInputInfoMETA;\n\ntypedef struct XrVirtualKeyboardTextContextChangeInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    const char *textContext;\n} XrVirtualKeyboardTextContextChangeInfoMETA;\n\ntypedef struct XrEventDataVirtualKeyboardCommitTextMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrVirtualKeyboardMETA keyboard;\n    char text[XR_MAX_VIRTUAL_KEYBOARD_COMMIT_TEXT_SIZE_META];\n} XrEventDataVirtualKeyboardCommitTextMETA;\n\ntypedef struct XrEventDataVirtualKeyboardBackspaceMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrVirtualKeyboardMETA keyboard;\n} XrEventDataVirtualKeyboardBackspaceMETA;\n\ntypedef struct XrEventDataVirtualKeyboardEnterMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrVirtualKeyboardMETA keyboard;\n} XrEventDataVirtualKeyboardEnterMETA;\n\ntypedef struct XrEventDataVirtualKeyboardShownMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrVirtualKeyboardMETA keyboard;\n} XrEventDataVirtualKeyboardShownMETA;\n\ntypedef struct XrEventDataVirtualKeyboardHiddenMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrVirtualKeyboardMETA keyboard;\n} XrEventDataVirtualKeyboardHiddenMETA;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateVirtualKeyboardMETA)(XrSession session,\n                                                              const XrVirtualKeyboardCreateInfoMETA *createInfo,\n                                                              XrVirtualKeyboardMETA *keyboard);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyVirtualKeyboardMETA)(XrVirtualKeyboardMETA keyboard);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateVirtualKeyboardSpaceMETA)(XrSession session,\n                                                                   XrVirtualKeyboardMETA keyboard,\n                                                                   const XrVirtualKeyboardSpaceCreateInfoMETA *createInfo,\n                                                                   XrSpace *keyboardSpace);\ntypedef XrResult (XRAPI_PTR *PFN_xrSuggestVirtualKeyboardLocationMETA)(\n        XrVirtualKeyboardMETA keyboard, const XrVirtualKeyboardLocationInfoMETA *locationInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVirtualKeyboardScaleMETA)(XrVirtualKeyboardMETA keyboard,\n                                                                float *scale);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetVirtualKeyboardModelVisibilityMETA)(\n        XrVirtualKeyboardMETA keyboard,\n        const XrVirtualKeyboardModelVisibilitySetInfoMETA *modelVisibility);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVirtualKeyboardModelAnimationStatesMETA)(\n        XrVirtualKeyboardMETA keyboard, XrVirtualKeyboardModelAnimationStatesMETA *animationStates);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVirtualKeyboardDirtyTexturesMETA)(\n        XrVirtualKeyboardMETA keyboard, uint32_t textureIdCapacityInput,\n        uint32_t *textureIdCountOutput, uint64_t *textureIds);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVirtualKeyboardTextureDataMETA)(\n        XrVirtualKeyboardMETA keyboard, uint64_t textureId,\n        XrVirtualKeyboardTextureDataMETA *textureData);\ntypedef XrResult (XRAPI_PTR *PFN_xrSendVirtualKeyboardInputMETA)(XrVirtualKeyboardMETA keyboard,\n                                                                 const XrVirtualKeyboardInputInfoMETA *info,\n                                                                 XrPosef *interactorRootPose);\ntypedef XrResult (XRAPI_PTR *PFN_xrChangeVirtualKeyboardTextContextMETA)(\n        XrVirtualKeyboardMETA keyboard,\n        const XrVirtualKeyboardTextContextChangeInfoMETA *changeInfo);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateVirtualKeyboardMETA(\n    XrSession                                   session,\n    const XrVirtualKeyboardCreateInfoMETA*      createInfo,\n    XrVirtualKeyboardMETA*                      keyboard);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyVirtualKeyboardMETA(\n    XrVirtualKeyboardMETA                       keyboard);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateVirtualKeyboardSpaceMETA(\n    XrSession                                   session,\n    XrVirtualKeyboardMETA                       keyboard,\n    const XrVirtualKeyboardSpaceCreateInfoMETA* createInfo,\n    XrSpace*                                    keyboardSpace);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSuggestVirtualKeyboardLocationMETA(\n    XrVirtualKeyboardMETA                       keyboard,\n    const XrVirtualKeyboardLocationInfoMETA*    locationInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVirtualKeyboardScaleMETA(\n    XrVirtualKeyboardMETA                       keyboard,\n    float*                                      scale);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetVirtualKeyboardModelVisibilityMETA(\n    XrVirtualKeyboardMETA                       keyboard,\n    const XrVirtualKeyboardModelVisibilitySetInfoMETA* modelVisibility);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVirtualKeyboardModelAnimationStatesMETA(\n    XrVirtualKeyboardMETA                       keyboard,\n    XrVirtualKeyboardModelAnimationStatesMETA*  animationStates);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVirtualKeyboardDirtyTexturesMETA(\n    XrVirtualKeyboardMETA                       keyboard,\n    uint32_t                                    textureIdCapacityInput,\n    uint32_t*                                   textureIdCountOutput,\n    uint64_t*                                   textureIds);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVirtualKeyboardTextureDataMETA(\n    XrVirtualKeyboardMETA                       keyboard,\n    uint64_t                                    textureId,\n    XrVirtualKeyboardTextureDataMETA*           textureData);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSendVirtualKeyboardInputMETA(\n    XrVirtualKeyboardMETA                       keyboard,\n    const XrVirtualKeyboardInputInfoMETA*       info,\n    XrPosef*                                    interactorRootPose);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrChangeVirtualKeyboardTextContextMETA(\n    XrVirtualKeyboardMETA                       keyboard,\n    const XrVirtualKeyboardTextContextChangeInfoMETA* changeInfo);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_OCULUS_external_camera 1\n#define XR_MAX_EXTERNAL_CAMERA_NAME_SIZE_OCULUS 32\n#define XR_OCULUS_external_camera_SPEC_VERSION 1\n#define XR_OCULUS_EXTERNAL_CAMERA_EXTENSION_NAME \"XR_OCULUS_external_camera\"\n\ntypedef enum XrExternalCameraAttachedToDeviceOCULUS {\n    XR_EXTERNAL_CAMERA_ATTACHED_TO_DEVICE_NONE_OCULUS = 0,\n    XR_EXTERNAL_CAMERA_ATTACHED_TO_DEVICE_HMD_OCULUS = 1,\n    XR_EXTERNAL_CAMERA_ATTACHED_TO_DEVICE_LTOUCH_OCULUS = 2,\n    XR_EXTERNAL_CAMERA_ATTACHED_TO_DEVICE_RTOUCH_OCULUS = 3,\n    XR_EXTERNAL_CAMERA_ATTACHED_TO_DEVICE_MAX_ENUM_OCULUS = 0x7FFFFFFF\n} XrExternalCameraAttachedToDeviceOCULUS;\ntypedef XrFlags64 XrExternalCameraStatusFlagsOCULUS;\n\n// Flag bits for XrExternalCameraStatusFlagsOCULUS\nstatic const XrExternalCameraStatusFlagsOCULUS XR_EXTERNAL_CAMERA_STATUS_CONNECTED_BIT_OCULUS = 0x00000001;\nstatic const XrExternalCameraStatusFlagsOCULUS XR_EXTERNAL_CAMERA_STATUS_CALIBRATING_BIT_OCULUS = 0x00000002;\nstatic const XrExternalCameraStatusFlagsOCULUS XR_EXTERNAL_CAMERA_STATUS_CALIBRATION_FAILED_BIT_OCULUS = 0x00000004;\nstatic const XrExternalCameraStatusFlagsOCULUS XR_EXTERNAL_CAMERA_STATUS_CALIBRATED_BIT_OCULUS = 0x00000008;\nstatic const XrExternalCameraStatusFlagsOCULUS XR_EXTERNAL_CAMERA_STATUS_CAPTURING_BIT_OCULUS = 0x00000010;\n\ntypedef struct XrExternalCameraIntrinsicsOCULUS {\n    XrTime lastChangeTime;\n    XrFovf fov;\n    float virtualNearPlaneDistance;\n    float virtualFarPlaneDistance;\n    XrExtent2Di imageSensorPixelResolution;\n} XrExternalCameraIntrinsicsOCULUS;\n\ntypedef struct XrExternalCameraExtrinsicsOCULUS {\n    XrTime lastChangeTime;\n    XrExternalCameraStatusFlagsOCULUS cameraStatusFlags;\n    XrExternalCameraAttachedToDeviceOCULUS attachedToDevice;\n    XrPosef relativePose;\n} XrExternalCameraExtrinsicsOCULUS;\n\ntypedef struct XrExternalCameraOCULUS {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS            next;\n    char name[XR_MAX_EXTERNAL_CAMERA_NAME_SIZE_OCULUS];\n    XrExternalCameraIntrinsicsOCULUS intrinsics;\n    XrExternalCameraExtrinsicsOCULUS extrinsics;\n} XrExternalCameraOCULUS;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumerateExternalCamerasOCULUS)(XrSession session,\n                                                                   uint32_t cameraCapacityInput,\n                                                                   uint32_t *cameraCountOutput,\n                                                                   XrExternalCameraOCULUS *cameras);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateExternalCamerasOCULUS(\n    XrSession                                   session,\n    uint32_t                                    cameraCapacityInput,\n    uint32_t*                                   cameraCountOutput,\n    XrExternalCameraOCULUS*                     cameras);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_META_performance_metrics 1\n#define XR_META_performance_metrics_SPEC_VERSION 2\n#define XR_META_PERFORMANCE_METRICS_EXTENSION_NAME \"XR_META_performance_metrics\"\n\ntypedef enum XrPerformanceMetricsCounterUnitMETA {\n    XR_PERFORMANCE_METRICS_COUNTER_UNIT_GENERIC_META = 0,\n    XR_PERFORMANCE_METRICS_COUNTER_UNIT_PERCENTAGE_META = 1,\n    XR_PERFORMANCE_METRICS_COUNTER_UNIT_MILLISECONDS_META = 2,\n    XR_PERFORMANCE_METRICS_COUNTER_UNIT_BYTES_META = 3,\n    XR_PERFORMANCE_METRICS_COUNTER_UNIT_HERTZ_META = 4,\n    XR_PERFORMANCE_METRICS_COUNTER_UNIT_MAX_ENUM_META = 0x7FFFFFFF\n} XrPerformanceMetricsCounterUnitMETA;\ntypedef XrFlags64 XrPerformanceMetricsCounterFlagsMETA;\n\n// Flag bits for XrPerformanceMetricsCounterFlagsMETA\nstatic const XrPerformanceMetricsCounterFlagsMETA XR_PERFORMANCE_METRICS_COUNTER_ANY_VALUE_VALID_BIT_META = 0x00000001;\nstatic const XrPerformanceMetricsCounterFlagsMETA XR_PERFORMANCE_METRICS_COUNTER_UINT_VALUE_VALID_BIT_META = 0x00000002;\nstatic const XrPerformanceMetricsCounterFlagsMETA XR_PERFORMANCE_METRICS_COUNTER_FLOAT_VALUE_VALID_BIT_META = 0x00000004;\n\ntypedef struct XrPerformanceMetricsStateMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrBool32 enabled;\n} XrPerformanceMetricsStateMETA;\n\ntypedef struct XrPerformanceMetricsCounterMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                next;\n    XrPerformanceMetricsCounterFlagsMETA counterFlags;\n    XrPerformanceMetricsCounterUnitMETA counterUnit;\n    uint32_t uintValue;\n    float floatValue;\n} XrPerformanceMetricsCounterMETA;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrEnumeratePerformanceMetricsCounterPathsMETA)(XrInstance instance,\n                                                                                uint32_t counterPathCapacityInput,\n                                                                                uint32_t *counterPathCountOutput,\n                                                                                XrPath *counterPaths);\ntypedef XrResult (XRAPI_PTR *PFN_xrSetPerformanceMetricsStateMETA)(XrSession session,\n                                                                   const XrPerformanceMetricsStateMETA *state);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetPerformanceMetricsStateMETA)(XrSession session,\n                                                                   XrPerformanceMetricsStateMETA *state);\ntypedef XrResult (XRAPI_PTR *PFN_xrQueryPerformanceMetricsCounterMETA)(XrSession session,\n                                                                       XrPath counterPath,\n                                                                       XrPerformanceMetricsCounterMETA *counter);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrEnumeratePerformanceMetricsCounterPathsMETA(\n    XrInstance                                  instance,\n    uint32_t                                    counterPathCapacityInput,\n    uint32_t*                                   counterPathCountOutput,\n    XrPath*                                     counterPaths);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrSetPerformanceMetricsStateMETA(\n    XrSession                                   session,\n    const XrPerformanceMetricsStateMETA*        state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetPerformanceMetricsStateMETA(\n    XrSession                                   session,\n    XrPerformanceMetricsStateMETA*              state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrQueryPerformanceMetricsCounterMETA(\n    XrSession                                   session,\n    XrPath                                      counterPath,\n    XrPerformanceMetricsCounterMETA*            counter);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_spatial_entity_storage_batch 1\n#define XR_FB_spatial_entity_storage_batch_SPEC_VERSION 1\n#define XR_FB_SPATIAL_ENTITY_STORAGE_BATCH_EXTENSION_NAME \"XR_FB_spatial_entity_storage_batch\"\ntypedef struct XrSpaceListSaveInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t spaceCount;\n    XrSpace *spaces;\n    XrSpaceStorageLocationFB location;\n} XrSpaceListSaveInfoFB;\n\ntypedef struct XrEventDataSpaceListSaveCompleteFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrAsyncRequestIdFB requestId;\n    XrResult result;\n} XrEventDataSpaceListSaveCompleteFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrSaveSpaceListFB)(XrSession session,\n                                                    const XrSpaceListSaveInfoFB *info,\n                                                    XrAsyncRequestIdFB *requestId);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrSaveSpaceListFB(\n    XrSession                                   session,\n    const XrSpaceListSaveInfoFB*                info,\n    XrAsyncRequestIdFB*                         requestId);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_FB_spatial_entity_user 1\ntypedef uint64_t XrSpaceUserIdFB;\n#define XR_FB_spatial_entity_user_SPEC_VERSION 1\n#define XR_FB_SPATIAL_ENTITY_USER_EXTENSION_NAME \"XR_FB_spatial_entity_user\"\ntypedef struct XrSpaceUserCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpaceUserIdFB userId;\n} XrSpaceUserCreateInfoFB;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSpaceUserFB)(XrSession session,\n                                                      const XrSpaceUserCreateInfoFB *info,\n                                                      XrSpaceUserFB *user);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetSpaceUserIdFB)(XrSpaceUserFB user, XrSpaceUserIdFB *userId);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroySpaceUserFB)(XrSpaceUserFB user);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpaceUserFB(\n    XrSession                                   session,\n    const XrSpaceUserCreateInfoFB*              info,\n    XrSpaceUserFB*                              user);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceUserIdFB(\n    XrSpaceUserFB                               user,\n    XrSpaceUserIdFB*                            userId);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroySpaceUserFB(\n    XrSpaceUserFB                               user);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_META_headset_id 1\n#define XR_META_headset_id_SPEC_VERSION   1\n#define XR_META_HEADSET_ID_EXTENSION_NAME \"XR_META_headset_id\"\n// XrSystemHeadsetIdPropertiesMETA extends XrSystemProperties\ntypedef struct XrSystemHeadsetIdPropertiesMETA {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrUuidEXT id;\n} XrSystemHeadsetIdPropertiesMETA;\n\n\n#define XR_META_passthrough_color_lut 1\nXR_DEFINE_HANDLE(XrPassthroughColorLutMETA)\n#define XR_META_passthrough_color_lut_SPEC_VERSION 1\n#define XR_META_PASSTHROUGH_COLOR_LUT_EXTENSION_NAME \"XR_META_passthrough_color_lut\"\n\ntypedef enum XrPassthroughColorLutChannelsMETA {\n    XR_PASSTHROUGH_COLOR_LUT_CHANNELS_RGB_META = 1,\n    XR_PASSTHROUGH_COLOR_LUT_CHANNELS_RGBA_META = 2,\n    XR_PASSTHROUGH_COLOR_LUT_CHANNELS_MAX_ENUM_META = 0x7FFFFFFF\n} XrPassthroughColorLutChannelsMETA;\ntypedef struct XrPassthroughColorLutDataMETA {\n    uint32_t bufferSize;\n    const uint8_t *buffer;\n} XrPassthroughColorLutDataMETA;\n\ntypedef struct XrPassthroughColorLutCreateInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS             next;\n    XrPassthroughColorLutChannelsMETA channels;\n    uint32_t resolution;\n    XrPassthroughColorLutDataMETA data;\n} XrPassthroughColorLutCreateInfoMETA;\n\ntypedef struct XrPassthroughColorLutUpdateInfoMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS         next;\n    XrPassthroughColorLutDataMETA data;\n} XrPassthroughColorLutUpdateInfoMETA;\n\n// XrPassthroughColorMapLutMETA extends XrPassthroughStyleFB\ntypedef struct XrPassthroughColorMapLutMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS     next;\n    XrPassthroughColorLutMETA colorLut;\n    float weight;\n} XrPassthroughColorMapLutMETA;\n\n// XrPassthroughColorMapInterpolatedLutMETA extends XrPassthroughStyleFB\ntypedef struct XrPassthroughColorMapInterpolatedLutMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS     next;\n    XrPassthroughColorLutMETA sourceColorLut;\n    XrPassthroughColorLutMETA targetColorLut;\n    float weight;\n} XrPassthroughColorMapInterpolatedLutMETA;\n\n// XrSystemPassthroughColorLutPropertiesMETA extends XrSystemProperties\ntypedef struct XrSystemPassthroughColorLutPropertiesMETA {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t maxColorLutResolution;\n} XrSystemPassthroughColorLutPropertiesMETA;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreatePassthroughColorLutMETA)(XrPassthroughFB passthrough,\n                                                                  const XrPassthroughColorLutCreateInfoMETA *createInfo,\n                                                                  XrPassthroughColorLutMETA *colorLut);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyPassthroughColorLutMETA)(\n        XrPassthroughColorLutMETA colorLut);\ntypedef XrResult (XRAPI_PTR *PFN_xrUpdatePassthroughColorLutMETA)(\n        XrPassthroughColorLutMETA colorLut, const XrPassthroughColorLutUpdateInfoMETA *updateInfo);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreatePassthroughColorLutMETA(\n    XrPassthroughFB                             passthrough,\n    const XrPassthroughColorLutCreateInfoMETA*  createInfo,\n    XrPassthroughColorLutMETA*                  colorLut);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyPassthroughColorLutMETA(\n    XrPassthroughColorLutMETA                   colorLut);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrUpdatePassthroughColorLutMETA(\n    XrPassthroughColorLutMETA                   colorLut,\n    const XrPassthroughColorLutUpdateInfoMETA*  updateInfo);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_EXT_uuid 1\n#define XR_EXT_uuid_SPEC_VERSION          1\n#define XR_EXT_UUID_EXTENSION_NAME        \"XR_EXT_uuid\"\n\n\n#define XR_EXT_hand_interaction 1\n#define XR_EXT_hand_interaction_SPEC_VERSION 1\n#define XR_EXT_HAND_INTERACTION_EXTENSION_NAME \"XR_EXT_hand_interaction\"\n\n\n#define XR_QCOM_tracking_optimization_settings 1\n#define XR_QCOM_tracking_optimization_settings_SPEC_VERSION 1\n#define XR_QCOM_TRACKING_OPTIMIZATION_SETTINGS_EXTENSION_NAME \"XR_QCOM_tracking_optimization_settings\"\n\ntypedef enum XrTrackingOptimizationSettingsDomainQCOM {\n    XR_TRACKING_OPTIMIZATION_SETTINGS_DOMAIN_ALL_QCOM = 1,\n    XR_TRACKING_OPTIMIZATION_SETTINGS_DOMAIN_MAX_ENUM_QCOM = 0x7FFFFFFF\n} XrTrackingOptimizationSettingsDomainQCOM;\n\ntypedef enum XrTrackingOptimizationSettingsHintQCOM {\n    XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_NONE_QCOM = 0,\n    XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_LONG_RANGE_PRIORIZATION_QCOM = 1,\n    XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_CLOSE_RANGE_PRIORIZATION_QCOM = 2,\n    XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_LOW_POWER_PRIORIZATION_QCOM = 3,\n    XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_HIGH_POWER_PRIORIZATION_QCOM = 4,\n    XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_MAX_ENUM_QCOM = 0x7FFFFFFF\n} XrTrackingOptimizationSettingsHintQCOM;\ntypedef XrResult (XRAPI_PTR *PFN_xrSetTrackingOptimizationSettingsHintQCOM)(XrSession session,\n                                                                            XrTrackingOptimizationSettingsDomainQCOM domain,\n                                                                            XrTrackingOptimizationSettingsHintQCOM hint);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrSetTrackingOptimizationSettingsHintQCOM(\n    XrSession                                   session,\n    XrTrackingOptimizationSettingsDomainQCOM    domain,\n    XrTrackingOptimizationSettingsHintQCOM      hint);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_HTC_passthrough 1\nXR_DEFINE_HANDLE(XrPassthroughHTC)\n#define XR_HTC_passthrough_SPEC_VERSION   1\n#define XR_HTC_PASSTHROUGH_EXTENSION_NAME \"XR_HTC_passthrough\"\n\ntypedef enum XrPassthroughFormHTC {\n    XR_PASSTHROUGH_FORM_PLANAR_HTC = 0,\n    XR_PASSTHROUGH_FORM_PROJECTED_HTC = 1,\n    XR_PASSTHROUGH_FORM_MAX_ENUM_HTC = 0x7FFFFFFF\n} XrPassthroughFormHTC;\ntypedef struct XrPassthroughCreateInfoHTC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrPassthroughFormHTC form;\n} XrPassthroughCreateInfoHTC;\n\ntypedef struct XrPassthroughColorHTC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    float alpha;\n} XrPassthroughColorHTC;\n\n// XrPassthroughMeshTransformInfoHTC extends XrCompositionLayerPassthroughHTC\ntypedef struct XrPassthroughMeshTransformInfoHTC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    uint32_t vertexCount;\n    const XrVector3f *vertices;\n    uint32_t indexCount;\n    const uint32_t *indices;\n    XrSpace baseSpace;\n    XrTime time;\n    XrPosef pose;\n    XrVector3f scale;\n} XrPassthroughMeshTransformInfoHTC;\n\ntypedef struct XrCompositionLayerPassthroughHTC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrCompositionLayerFlags layerFlags;\n    XrSpace space;\n    XrPassthroughHTC passthrough;\n    XrPassthroughColorHTC color;\n} XrCompositionLayerPassthroughHTC;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreatePassthroughHTC)(XrSession session,\n                                                         const XrPassthroughCreateInfoHTC *createInfo,\n                                                         XrPassthroughHTC *passthrough);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyPassthroughHTC)(XrPassthroughHTC passthrough);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrCreatePassthroughHTC(\n    XrSession                                   session,\n    const XrPassthroughCreateInfoHTC*           createInfo,\n    XrPassthroughHTC*                           passthrough);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyPassthroughHTC(\n    XrPassthroughHTC                            passthrough);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_HTC_foveation 1\n#define XR_HTC_foveation_SPEC_VERSION     1\n#define XR_HTC_FOVEATION_EXTENSION_NAME   \"XR_HTC_foveation\"\n\ntypedef enum XrFoveationModeHTC {\n    XR_FOVEATION_MODE_DISABLE_HTC = 0,\n    XR_FOVEATION_MODE_FIXED_HTC = 1,\n    XR_FOVEATION_MODE_DYNAMIC_HTC = 2,\n    XR_FOVEATION_MODE_CUSTOM_HTC = 3,\n    XR_FOVEATION_MODE_MAX_ENUM_HTC = 0x7FFFFFFF\n} XrFoveationModeHTC;\n\ntypedef enum XrFoveationLevelHTC {\n    XR_FOVEATION_LEVEL_NONE_HTC = 0,\n    XR_FOVEATION_LEVEL_LOW_HTC = 1,\n    XR_FOVEATION_LEVEL_MEDIUM_HTC = 2,\n    XR_FOVEATION_LEVEL_HIGH_HTC = 3,\n    XR_FOVEATION_LEVEL_MAX_ENUM_HTC = 0x7FFFFFFF\n} XrFoveationLevelHTC;\ntypedef XrFlags64 XrFoveationDynamicFlagsHTC;\n\n// Flag bits for XrFoveationDynamicFlagsHTC\nstatic const XrFoveationDynamicFlagsHTC XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_BIT_HTC = 0x00000001;\nstatic const XrFoveationDynamicFlagsHTC XR_FOVEATION_DYNAMIC_CLEAR_FOV_ENABLED_BIT_HTC = 0x00000002;\nstatic const XrFoveationDynamicFlagsHTC XR_FOVEATION_DYNAMIC_FOCAL_CENTER_OFFSET_ENABLED_BIT_HTC = 0x00000004;\n\ntypedef struct XrFoveationApplyInfoHTC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrFoveationModeHTC mode;\n    uint32_t subImageCount;\n    XrSwapchainSubImage *subImages;\n} XrFoveationApplyInfoHTC;\n\ntypedef struct XrFoveationConfigurationHTC {\n    XrFoveationLevelHTC level;\n    float clearFovDegree;\n    XrVector2f focalCenterOffset;\n} XrFoveationConfigurationHTC;\n\n// XrFoveationDynamicModeInfoHTC extends XrFoveationApplyInfoHTC\ntypedef struct XrFoveationDynamicModeInfoHTC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS      next;\n    XrFoveationDynamicFlagsHTC dynamicFlags;\n} XrFoveationDynamicModeInfoHTC;\n\n// XrFoveationCustomModeInfoHTC extends XrFoveationApplyInfoHTC\ntypedef struct XrFoveationCustomModeInfoHTC {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS              next;\n    uint32_t configCount;\n    const XrFoveationConfigurationHTC *configs;\n} XrFoveationCustomModeInfoHTC;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrApplyFoveationHTC)(XrSession session,\n                                                      const XrFoveationApplyInfoHTC *applyInfo);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrApplyFoveationHTC(\n    XrSession                                   session,\n    const XrFoveationApplyInfoHTC*              applyInfo);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_EXT_active_action_set_priority 1\n#define XR_EXT_active_action_set_priority_SPEC_VERSION 1\n#define XR_EXT_ACTIVE_ACTION_SET_PRIORITY_EXTENSION_NAME \"XR_EXT_active_action_set_priority\"\ntypedef struct XrActiveActionSetPriorityEXT {\n    XrActionSet actionSet;\n    uint32_t priorityOverride;\n} XrActiveActionSetPriorityEXT;\n\n// XrActiveActionSetPrioritiesEXT extends XrActionsSyncInfo\ntypedef struct XrActiveActionSetPrioritiesEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS               next;\n    uint32_t actionSetPriorityCount;\n    const XrActiveActionSetPriorityEXT *actionSetPriorities;\n} XrActiveActionSetPrioritiesEXT;\n\n\n#define XR_MNDX_force_feedback_curl 1\n#define XR_MNDX_force_feedback_curl_SPEC_VERSION 1\n#define XR_MNDX_FORCE_FEEDBACK_CURL_EXTENSION_NAME \"XR_MNDX_force_feedback_curl\"\n\ntypedef enum XrForceFeedbackCurlLocationMNDX {\n    XR_FORCE_FEEDBACK_CURL_LOCATION_THUMB_CURL_MNDX = 0,\n    XR_FORCE_FEEDBACK_CURL_LOCATION_INDEX_CURL_MNDX = 1,\n    XR_FORCE_FEEDBACK_CURL_LOCATION_MIDDLE_CURL_MNDX = 2,\n    XR_FORCE_FEEDBACK_CURL_LOCATION_RING_CURL_MNDX = 3,\n    XR_FORCE_FEEDBACK_CURL_LOCATION_LITTLE_CURL_MNDX = 4,\n    XR_FORCE_FEEDBACK_CURL_LOCATION_MAX_ENUM_MNDX = 0x7FFFFFFF\n} XrForceFeedbackCurlLocationMNDX;\n// XrSystemForceFeedbackCurlPropertiesMNDX extends XrSystemProperties\ntypedef struct XrSystemForceFeedbackCurlPropertiesMNDX {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrBool32 supportsForceFeedbackCurl;\n} XrSystemForceFeedbackCurlPropertiesMNDX;\n\ntypedef struct XrForceFeedbackCurlApplyLocationMNDX {\n    XrForceFeedbackCurlLocationMNDX location;\n    float value;\n} XrForceFeedbackCurlApplyLocationMNDX;\n\ntypedef struct XrForceFeedbackCurlApplyLocationsMNDX {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                 next;\n    uint32_t locationCount;\n    XrForceFeedbackCurlApplyLocationMNDX *locations;\n} XrForceFeedbackCurlApplyLocationsMNDX;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrApplyForceFeedbackCurlMNDX)(XrHandTrackerEXT handTracker,\n                                                               const XrForceFeedbackCurlApplyLocationsMNDX *locations);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\n                                                                                                                        XRAPI_ATTR XrResult XRAPI_CALL xrApplyForceFeedbackCurlMNDX(\n    XrHandTrackerEXT                            handTracker,\n    const XrForceFeedbackCurlApplyLocationsMNDX* locations);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_BD_controller_interaction 1\n#define XR_BD_controller_interaction_SPEC_VERSION 1\n#define XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME \"XR_BD_controller_interaction\"\n\n\n#define XR_EXT_local_floor 1\n#define XR_EXT_local_floor_SPEC_VERSION   1\n#define XR_EXT_LOCAL_FLOOR_EXTENSION_NAME \"XR_EXT_local_floor\"\n\n\n#define XR_EXT_hand_tracking_data_source 1\n#define XR_EXT_hand_tracking_data_source_SPEC_VERSION 1\n#define XR_EXT_HAND_TRACKING_DATA_SOURCE_EXTENSION_NAME \"XR_EXT_hand_tracking_data_source\"\n\ntypedef enum XrHandTrackingDataSourceEXT {\n    XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT = 1,\n    XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT = 2,\n    XR_HAND_TRACKING_DATA_SOURCE_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrHandTrackingDataSourceEXT;\n// XrHandTrackingDataSourceInfoEXT extends XrHandTrackerCreateInfoEXT\ntypedef struct XrHandTrackingDataSourceInfoEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS        next;\n    uint32_t requestedDataSourceCount;\n    XrHandTrackingDataSourceEXT *requestedDataSources;\n} XrHandTrackingDataSourceInfoEXT;\n\n// XrHandTrackingDataSourceStateEXT extends XrHandJointLocationsEXT\ntypedef struct XrHandTrackingDataSourceStateEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS             next;\n    XrBool32 isActive;\n    XrHandTrackingDataSourceEXT dataSource;\n} XrHandTrackingDataSourceStateEXT;\n\n\n#define XR_EXT_plane_detection 1\nXR_DEFINE_HANDLE(XrPlaneDetectorEXT)\n#define XR_EXT_plane_detection_SPEC_VERSION 1\n#define XR_EXT_PLANE_DETECTION_EXTENSION_NAME \"XR_EXT_plane_detection\"\n\ntypedef enum XrPlaneDetectorOrientationEXT {\n    XR_PLANE_DETECTOR_ORIENTATION_HORIZONTAL_UPWARD_EXT = 0,\n    XR_PLANE_DETECTOR_ORIENTATION_HORIZONTAL_DOWNWARD_EXT = 1,\n    XR_PLANE_DETECTOR_ORIENTATION_VERTICAL_EXT = 2,\n    XR_PLANE_DETECTOR_ORIENTATION_ARBITRARY_EXT = 3,\n    XR_PLANE_DETECTOR_ORIENTATION_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrPlaneDetectorOrientationEXT;\n\ntypedef enum XrPlaneDetectorSemanticTypeEXT {\n    XR_PLANE_DETECTOR_SEMANTIC_TYPE_UNDEFINED_EXT = 0,\n    XR_PLANE_DETECTOR_SEMANTIC_TYPE_CEILING_EXT = 1,\n    XR_PLANE_DETECTOR_SEMANTIC_TYPE_FLOOR_EXT = 2,\n    XR_PLANE_DETECTOR_SEMANTIC_TYPE_WALL_EXT = 3,\n    XR_PLANE_DETECTOR_SEMANTIC_TYPE_PLATFORM_EXT = 4,\n    XR_PLANE_DETECTOR_SEMANTIC_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrPlaneDetectorSemanticTypeEXT;\n\ntypedef enum XrPlaneDetectionStateEXT {\n    XR_PLANE_DETECTION_STATE_NONE_EXT = 0,\n    XR_PLANE_DETECTION_STATE_PENDING_EXT = 1,\n    XR_PLANE_DETECTION_STATE_DONE_EXT = 2,\n    XR_PLANE_DETECTION_STATE_ERROR_EXT = 3,\n    XR_PLANE_DETECTION_STATE_FATAL_EXT = 4,\n    XR_PLANE_DETECTION_STATE_MAX_ENUM_EXT = 0x7FFFFFFF\n} XrPlaneDetectionStateEXT;\ntypedef XrFlags64 XrPlaneDetectionCapabilityFlagsEXT;\n\n// Flag bits for XrPlaneDetectionCapabilityFlagsEXT\nstatic const XrPlaneDetectionCapabilityFlagsEXT XR_PLANE_DETECTION_CAPABILITY_PLANE_DETECTION_BIT_EXT = 0x00000001;\nstatic const XrPlaneDetectionCapabilityFlagsEXT XR_PLANE_DETECTION_CAPABILITY_PLANE_HOLES_BIT_EXT = 0x00000002;\nstatic const XrPlaneDetectionCapabilityFlagsEXT XR_PLANE_DETECTION_CAPABILITY_SEMANTIC_CEILING_BIT_EXT = 0x00000004;\nstatic const XrPlaneDetectionCapabilityFlagsEXT XR_PLANE_DETECTION_CAPABILITY_SEMANTIC_FLOOR_BIT_EXT = 0x00000008;\nstatic const XrPlaneDetectionCapabilityFlagsEXT XR_PLANE_DETECTION_CAPABILITY_SEMANTIC_WALL_BIT_EXT = 0x00000010;\nstatic const XrPlaneDetectionCapabilityFlagsEXT XR_PLANE_DETECTION_CAPABILITY_SEMANTIC_PLATFORM_BIT_EXT = 0x00000020;\nstatic const XrPlaneDetectionCapabilityFlagsEXT XR_PLANE_DETECTION_CAPABILITY_ORIENTATION_BIT_EXT = 0x00000040;\n\ntypedef XrFlags64 XrPlaneDetectorFlagsEXT;\n\n// Flag bits for XrPlaneDetectorFlagsEXT\nstatic const XrPlaneDetectorFlagsEXT XR_PLANE_DETECTOR_ENABLE_CONTOUR_BIT_EXT = 0x00000001;\n\n// XrSystemPlaneDetectionPropertiesEXT extends XrSystemProperties\ntypedef struct XrSystemPlaneDetectionPropertiesEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                    next;\n    XrPlaneDetectionCapabilityFlagsEXT supportedFeatures;\n} XrSystemPlaneDetectionPropertiesEXT;\n\ntypedef struct XrPlaneDetectorCreateInfoEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrPlaneDetectorFlagsEXT flags;\n} XrPlaneDetectorCreateInfoEXT;\n\ntypedef struct XrExtent3DfEXT {\n    float width;\n    float height;\n    float depth;\n} XrExtent3DfEXT;\n\ntypedef struct XrPlaneDetectorBeginInfoEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS                 next;\n    XrSpace baseSpace;\n    XrTime time;\n    uint32_t orientationCount;\n    const XrPlaneDetectorOrientationEXT *orientations;\n    uint32_t semanticTypeCount;\n    const XrPlaneDetectorSemanticTypeEXT *semanticTypes;\n    uint32_t maxPlanes;\n    float minArea;\n    XrPosef boundingBoxPose;\n    XrExtent3DfEXT boundingBoxExtent;\n} XrPlaneDetectorBeginInfoEXT;\n\ntypedef struct XrPlaneDetectorGetInfoEXT {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    XrSpace baseSpace;\n    XrTime time;\n} XrPlaneDetectorGetInfoEXT;\n\ntypedef struct XrPlaneDetectorLocationEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS                next;\n    uint64_t planeId;\n    XrSpaceLocationFlags locationFlags;\n    XrPosef pose;\n    XrExtent2Df extents;\n    XrPlaneDetectorOrientationEXT orientation;\n    XrPlaneDetectorSemanticTypeEXT semanticType;\n    uint32_t polygonBufferCount;\n} XrPlaneDetectorLocationEXT;\n\ntypedef struct XrPlaneDetectorLocationsEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS             next;\n    uint32_t planeLocationCapacityInput;\n    uint32_t planeLocationCountOutput;\n    XrPlaneDetectorLocationEXT *planeLocations;\n} XrPlaneDetectorLocationsEXT;\n\ntypedef struct XrPlaneDetectorPolygonBufferEXT {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t vertexCapacityInput;\n    uint32_t vertexCountOutput;\n    XrVector2f *vertices;\n} XrPlaneDetectorPolygonBufferEXT;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreatePlaneDetectorEXT)(XrSession session,\n                                                           const XrPlaneDetectorCreateInfoEXT *createInfo,\n                                                           XrPlaneDetectorEXT *planeDetector);\ntypedef XrResult (XRAPI_PTR *PFN_xrDestroyPlaneDetectorEXT)(XrPlaneDetectorEXT planeDetector);\ntypedef XrResult (XRAPI_PTR *PFN_xrBeginPlaneDetectionEXT)(XrPlaneDetectorEXT planeDetector,\n                                                           const XrPlaneDetectorBeginInfoEXT *beginInfo);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetPlaneDetectionStateEXT)(XrPlaneDetectorEXT planeDetector,\n                                                              XrPlaneDetectionStateEXT *state);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetPlaneDetectionsEXT)(XrPlaneDetectorEXT planeDetector,\n                                                          const XrPlaneDetectorGetInfoEXT *info,\n                                                          XrPlaneDetectorLocationsEXT *locations);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetPlanePolygonBufferEXT)(XrPlaneDetectorEXT planeDetector,\n                                                             uint64_t planeId,\n                                                             uint32_t polygonBufferIndex,\n                                                             XrPlaneDetectorPolygonBufferEXT *polygonBuffer);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrCreatePlaneDetectorEXT(\n    XrSession                                   session,\n    const XrPlaneDetectorCreateInfoEXT*         createInfo,\n    XrPlaneDetectorEXT*                         planeDetector);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrDestroyPlaneDetectorEXT(\n    XrPlaneDetectorEXT                          planeDetector);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrBeginPlaneDetectionEXT(\n    XrPlaneDetectorEXT                          planeDetector,\n    const XrPlaneDetectorBeginInfoEXT*          beginInfo);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetPlaneDetectionStateEXT(\n    XrPlaneDetectorEXT                          planeDetector,\n    XrPlaneDetectionStateEXT*                   state);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetPlaneDetectionsEXT(\n    XrPlaneDetectorEXT                          planeDetector,\n    const XrPlaneDetectorGetInfoEXT*            info,\n    XrPlaneDetectorLocationsEXT*                locations);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetPlanePolygonBufferEXT(\n    XrPlaneDetectorEXT                          planeDetector,\n    uint64_t                                    planeId,\n    uint32_t                                    polygonBufferIndex,\n    XrPlaneDetectorPolygonBufferEXT*            polygonBuffer);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n\n\n#define XR_OPPO_controller_interaction 1\n#define XR_OPPO_controller_interaction_SPEC_VERSION 1\n#define XR_OPPO_CONTROLLER_INTERACTION_EXTENSION_NAME \"XR_OPPO_controller_interaction\"\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/openxr/openxr_platform.h",
    "content": "#ifndef OPENXR_PLATFORM_H_\n#define OPENXR_PLATFORM_H_ 1\n\n/*\n** Copyright 2017-2023 The Khronos Group Inc.\n**\n** SPDX-License-Identifier: Apache-2.0 OR MIT\n*/\n\n/*\n** This header is generated from the Khronos OpenXR XML API Registry.\n**\n*/\n\n#include \"openxr.h\"\n\n#ifdef XR_USE_PLATFORM_ANDROID\n\n#include <jni.h>\n#include \"EGL/egl.h\"\n#include \"GLES/gl.h\"\n\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n#ifdef XR_USE_PLATFORM_ANDROID\n\n#define XR_KHR_android_thread_settings 1\n#define XR_KHR_android_thread_settings_SPEC_VERSION 5\n#define XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME \"XR_KHR_android_thread_settings\"\n\ntypedef enum XrAndroidThreadTypeKHR {\n    XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR = 1,\n    XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR = 2,\n    XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR = 3,\n    XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR = 4,\n    XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF\n} XrAndroidThreadTypeKHR;\ntypedef XrResult (XRAPI_PTR *PFN_xrSetAndroidApplicationThreadKHR)(XrSession session,\n                                                                   XrAndroidThreadTypeKHR threadType,\n                                                                   uint32_t threadId);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrSetAndroidApplicationThreadKHR(\n    XrSession                                   session,\n    XrAndroidThreadTypeKHR                      threadType,\n    uint32_t                                    threadId);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_PLATFORM_ANDROID */\n\n#ifdef XR_USE_PLATFORM_ANDROID\n\n#define XR_KHR_android_surface_swapchain 1\n#define XR_KHR_android_surface_swapchain_SPEC_VERSION 4\n#define XR_KHR_ANDROID_SURFACE_SWAPCHAIN_EXTENSION_NAME \"XR_KHR_android_surface_swapchain\"\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchainAndroidSurfaceKHR)(XrSession session,\n                                                                     const XrSwapchainCreateInfo *info,\n                                                                     XrSwapchain *swapchain,\n                                                                     jobject *surface);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchainAndroidSurfaceKHR(\n    XrSession                                   session,\n    const XrSwapchainCreateInfo*                info,\n    XrSwapchain*                                swapchain,\n    jobject*                                    surface);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_PLATFORM_ANDROID */\n\n#ifdef XR_USE_PLATFORM_ANDROID\n\n#define XR_KHR_android_create_instance 1\n#define XR_KHR_android_create_instance_SPEC_VERSION 3\n#define XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME \"XR_KHR_android_create_instance\"\n// XrInstanceCreateInfoAndroidKHR extends XrInstanceCreateInfo\ntypedef struct XrInstanceCreateInfoAndroidKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    void *XR_MAY_ALIAS          applicationVM;\n    void *XR_MAY_ALIAS          applicationActivity;\n} XrInstanceCreateInfoAndroidKHR;\n\n#endif /* XR_USE_PLATFORM_ANDROID */\n\n#ifdef XR_USE_GRAPHICS_API_VULKAN\n\n#define XR_KHR_vulkan_swapchain_format_list 1\n#define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 4\n#define XR_KHR_VULKAN_SWAPCHAIN_FORMAT_LIST_EXTENSION_NAME \"XR_KHR_vulkan_swapchain_format_list\"\ntypedef struct XrVulkanSwapchainFormatListCreateInfoKHR {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    uint32_t                    viewFormatCount;\n    const VkFormat*             viewFormats;\n} XrVulkanSwapchainFormatListCreateInfoKHR;\n\n#endif /* XR_USE_GRAPHICS_API_VULKAN */\n\n#ifdef XR_USE_GRAPHICS_API_OPENGL\n\n#define XR_KHR_opengl_enable 1\n#define XR_KHR_opengl_enable_SPEC_VERSION 10\n#define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME \"XR_KHR_opengl_enable\"\n#ifdef XR_USE_PLATFORM_WIN32\n// XrGraphicsBindingOpenGLWin32KHR extends XrSessionCreateInfo\ntypedef struct XrGraphicsBindingOpenGLWin32KHR {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    HDC                         hDC;\n    HGLRC                       hGLRC;\n} XrGraphicsBindingOpenGLWin32KHR;\n#endif // XR_USE_PLATFORM_WIN32\n\n#ifdef XR_USE_PLATFORM_XLIB\n// XrGraphicsBindingOpenGLXlibKHR extends XrSessionCreateInfo\ntypedef struct XrGraphicsBindingOpenGLXlibKHR {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    Display*                    xDisplay;\n    uint32_t                    visualid;\n    GLXFBConfig                 glxFBConfig;\n    GLXDrawable                 glxDrawable;\n    GLXContext                  glxContext;\n} XrGraphicsBindingOpenGLXlibKHR;\n#endif // XR_USE_PLATFORM_XLIB\n\n#ifdef XR_USE_PLATFORM_XCB\n// XrGraphicsBindingOpenGLXcbKHR extends XrSessionCreateInfo\ntypedef struct XrGraphicsBindingOpenGLXcbKHR {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    xcb_connection_t*           connection;\n    uint32_t                    screenNumber;\n    xcb_glx_fbconfig_t          fbconfigid;\n    xcb_visualid_t              visualid;\n    xcb_glx_drawable_t          glxDrawable;\n    xcb_glx_context_t           glxContext;\n} XrGraphicsBindingOpenGLXcbKHR;\n#endif // XR_USE_PLATFORM_XCB\n\n#ifdef XR_USE_PLATFORM_WAYLAND\n// XrGraphicsBindingOpenGLWaylandKHR extends XrSessionCreateInfo\ntypedef struct XrGraphicsBindingOpenGLWaylandKHR {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    struct wl_display*          display;\n} XrGraphicsBindingOpenGLWaylandKHR;\n#endif // XR_USE_PLATFORM_WAYLAND\n\ntypedef struct XrSwapchainImageOpenGLKHR {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t image;\n} XrSwapchainImageOpenGLKHR;\n\ntypedef struct XrGraphicsRequirementsOpenGLKHR {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrVersion minApiVersionSupported;\n    XrVersion maxApiVersionSupported;\n} XrGraphicsRequirementsOpenGLKHR;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance instance,\n                                                                     XrSystemId systemId,\n                                                                     XrGraphicsRequirementsOpenGLKHR *graphicsRequirements);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    XrGraphicsRequirementsOpenGLKHR*            graphicsRequirements);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_GRAPHICS_API_OPENGL */\n\n#ifdef XR_USE_GRAPHICS_API_OPENGL_ES\n\n#define XR_KHR_opengl_es_enable 1\n#define XR_KHR_opengl_es_enable_SPEC_VERSION 8\n#define XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME \"XR_KHR_opengl_es_enable\"\n#ifdef XR_USE_PLATFORM_ANDROID\n// XrGraphicsBindingOpenGLESAndroidKHR extends XrSessionCreateInfo\ntypedef struct XrGraphicsBindingOpenGLESAndroidKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    EGLDisplay display;\n    EGLConfig config;\n    EGLContext context;\n} XrGraphicsBindingOpenGLESAndroidKHR;\n#endif // XR_USE_PLATFORM_ANDROID\n\ntypedef struct XrSwapchainImageOpenGLESKHR {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t image;\n} XrSwapchainImageOpenGLESKHR;\n\ntypedef struct XrGraphicsRequirementsOpenGLESKHR {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    XrVersion minApiVersionSupported;\n    XrVersion maxApiVersionSupported;\n} XrGraphicsRequirementsOpenGLESKHR;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLESGraphicsRequirementsKHR)(XrInstance instance,\n                                                                       XrSystemId systemId,\n                                                                       XrGraphicsRequirementsOpenGLESKHR *graphicsRequirements);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    XrGraphicsRequirementsOpenGLESKHR*          graphicsRequirements);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */\n\n#ifdef XR_USE_GRAPHICS_API_VULKAN\n\n#define XR_KHR_vulkan_enable 1\n#define XR_KHR_vulkan_enable_SPEC_VERSION 8\n#define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME \"XR_KHR_vulkan_enable\"\n// XrGraphicsBindingVulkanKHR extends XrSessionCreateInfo\ntypedef struct XrGraphicsBindingVulkanKHR {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    VkInstance                  instance;\n    VkPhysicalDevice            physicalDevice;\n    VkDevice                    device;\n    uint32_t                    queueFamilyIndex;\n    uint32_t                    queueIndex;\n} XrGraphicsBindingVulkanKHR;\n\ntypedef struct XrSwapchainImageVulkanKHR {\n    XrStructureType       type;\n    void* XR_MAY_ALIAS    next;\n    VkImage               image;\n} XrSwapchainImageVulkanKHR;\n\ntypedef struct XrGraphicsRequirementsVulkanKHR {\n    XrStructureType       type;\n    void* XR_MAY_ALIAS    next;\n    XrVersion             minApiVersionSupported;\n    XrVersion             maxApiVersionSupported;\n} XrGraphicsRequirementsVulkanKHR;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    uint32_t                                    bufferCapacityInput,\n    uint32_t*                                   bufferCountOutput,\n    char*                                       buffer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    uint32_t                                    bufferCapacityInput,\n    uint32_t*                                   bufferCountOutput,\n    char*                                       buffer);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    VkInstance                                  vkInstance,\n    VkPhysicalDevice*                           vkPhysicalDevice);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    XrGraphicsRequirementsVulkanKHR*            graphicsRequirements);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_GRAPHICS_API_VULKAN */\n\n#ifdef XR_USE_GRAPHICS_API_D3D11\n\n#define XR_KHR_D3D11_enable 1\n#define XR_KHR_D3D11_enable_SPEC_VERSION  9\n#define XR_KHR_D3D11_ENABLE_EXTENSION_NAME \"XR_KHR_D3D11_enable\"\n// XrGraphicsBindingD3D11KHR extends XrSessionCreateInfo\ntypedef struct XrGraphicsBindingD3D11KHR {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    ID3D11Device*               device;\n} XrGraphicsBindingD3D11KHR;\n\ntypedef struct XrSwapchainImageD3D11KHR {\n     XrStructureType      type;\n    void* XR_MAY_ALIAS    next;\n    ID3D11Texture2D*      texture;\n} XrSwapchainImageD3D11KHR;\n\ntypedef struct XrGraphicsRequirementsD3D11KHR {\n    XrStructureType       type;\n    void* XR_MAY_ALIAS    next;\n    LUID                  adapterLuid;\n    D3D_FEATURE_LEVEL     minFeatureLevel;\n} XrGraphicsRequirementsD3D11KHR;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR* graphicsRequirements);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    XrGraphicsRequirementsD3D11KHR*             graphicsRequirements);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_GRAPHICS_API_D3D11 */\n\n#ifdef XR_USE_GRAPHICS_API_D3D12\n\n#define XR_KHR_D3D12_enable 1\n#define XR_KHR_D3D12_enable_SPEC_VERSION  9\n#define XR_KHR_D3D12_ENABLE_EXTENSION_NAME \"XR_KHR_D3D12_enable\"\n// XrGraphicsBindingD3D12KHR extends XrSessionCreateInfo\ntypedef struct XrGraphicsBindingD3D12KHR {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    ID3D12Device*               device;\n    ID3D12CommandQueue*         queue;\n} XrGraphicsBindingD3D12KHR;\n\ntypedef struct XrSwapchainImageD3D12KHR {\n     XrStructureType      type;\n    void* XR_MAY_ALIAS    next;\n    ID3D12Resource*       texture;\n} XrSwapchainImageD3D12KHR;\n\ntypedef struct XrGraphicsRequirementsD3D12KHR {\n    XrStructureType       type;\n    void* XR_MAY_ALIAS    next;\n    LUID                  adapterLuid;\n    D3D_FEATURE_LEVEL     minFeatureLevel;\n} XrGraphicsRequirementsD3D12KHR;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR* graphicsRequirements);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    XrGraphicsRequirementsD3D12KHR*             graphicsRequirements);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_GRAPHICS_API_D3D12 */\n\n#ifdef XR_USE_PLATFORM_WIN32\n\n#define XR_KHR_win32_convert_performance_counter_time 1\n#define XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION 1\n#define XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME \"XR_KHR_win32_convert_performance_counter_time\"\ntypedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time);\ntypedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime   time, LARGE_INTEGER* performanceCounter);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(\n    XrInstance                                  instance,\n    const LARGE_INTEGER*                        performanceCounter,\n    XrTime*                                     time);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(\n    XrInstance                                  instance,\n    XrTime                                      time,\n    LARGE_INTEGER*                              performanceCounter);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_PLATFORM_WIN32 */\n\n#ifdef XR_USE_TIMESPEC\n\n#define XR_KHR_convert_timespec_time 1\n#define XR_KHR_convert_timespec_time_SPEC_VERSION 1\n#define XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME \"XR_KHR_convert_timespec_time\"\ntypedef XrResult (XRAPI_PTR *PFN_xrConvertTimespecTimeToTimeKHR)(XrInstance instance, const struct timespec* timespecTime, XrTime* time);\ntypedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime   time, struct timespec* timespecTime);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(\n    XrInstance                                  instance,\n    const struct timespec*                      timespecTime,\n    XrTime*                                     time);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(\n    XrInstance                                  instance,\n    XrTime                                      time,\n    struct timespec*                            timespecTime);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_TIMESPEC */\n\n#ifdef XR_USE_PLATFORM_ANDROID\n\n#define XR_KHR_loader_init_android 1\n#define XR_KHR_loader_init_android_SPEC_VERSION 1\n#define XR_KHR_LOADER_INIT_ANDROID_EXTENSION_NAME \"XR_KHR_loader_init_android\"\ntypedef struct XrLoaderInitInfoAndroidKHR {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS    next;\n    void *XR_MAY_ALIAS          applicationVM;\n    void *XR_MAY_ALIAS          applicationContext;\n} XrLoaderInitInfoAndroidKHR;\n\n#endif /* XR_USE_PLATFORM_ANDROID */\n\n#ifdef XR_USE_GRAPHICS_API_VULKAN\n\n#define XR_KHR_vulkan_enable2 1\n#define XR_KHR_vulkan_enable2_SPEC_VERSION 2\n#define XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME \"XR_KHR_vulkan_enable2\"\ntypedef XrFlags64 XrVulkanInstanceCreateFlagsKHR;\n\n// Flag bits for XrVulkanInstanceCreateFlagsKHR\n\ntypedef XrFlags64 XrVulkanDeviceCreateFlagsKHR;\n\n// Flag bits for XrVulkanDeviceCreateFlagsKHR\n\ntypedef struct XrVulkanInstanceCreateInfoKHR {\n    XrStructureType                   type;\n    const void* XR_MAY_ALIAS          next;\n    XrSystemId                        systemId;\n    XrVulkanInstanceCreateFlagsKHR    createFlags;\n    PFN_vkGetInstanceProcAddr         pfnGetInstanceProcAddr;\n    const VkInstanceCreateInfo*       vulkanCreateInfo;\n    const VkAllocationCallbacks*      vulkanAllocator;\n} XrVulkanInstanceCreateInfoKHR;\n\ntypedef struct XrVulkanDeviceCreateInfoKHR {\n    XrStructureType                 type;\n    const void* XR_MAY_ALIAS        next;\n    XrSystemId                      systemId;\n    XrVulkanDeviceCreateFlagsKHR    createFlags;\n    PFN_vkGetInstanceProcAddr       pfnGetInstanceProcAddr;\n    VkPhysicalDevice                vulkanPhysicalDevice;\n    const VkDeviceCreateInfo*       vulkanCreateInfo;\n    const VkAllocationCallbacks*    vulkanAllocator;\n} XrVulkanDeviceCreateInfoKHR;\n\ntypedef XrGraphicsBindingVulkanKHR XrGraphicsBindingVulkan2KHR;\n\ntypedef struct XrVulkanGraphicsDeviceGetInfoKHR {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    XrSystemId                  systemId;\n    VkInstance                  vulkanInstance;\n} XrVulkanGraphicsDeviceGetInfoKHR;\n\ntypedef XrSwapchainImageVulkanKHR XrSwapchainImageVulkan2KHR;\n\ntypedef XrGraphicsRequirementsVulkanKHR XrGraphicsRequirementsVulkan2KHR;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanInstanceKHR)(XrInstance instance, const XrVulkanInstanceCreateInfoKHR* createInfo, VkInstance* vulkanInstance, VkResult* vulkanResult);\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanDeviceKHR)(XrInstance instance, const XrVulkanDeviceCreateInfoKHR* createInfo, VkDevice* vulkanDevice, VkResult* vulkanResult);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDevice2KHR)(XrInstance instance, const XrVulkanGraphicsDeviceGetInfoKHR* getInfo, VkPhysicalDevice* vulkanPhysicalDevice);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirements2KHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanInstanceKHR(\n    XrInstance                                  instance,\n    const XrVulkanInstanceCreateInfoKHR*        createInfo,\n    VkInstance*                                 vulkanInstance,\n    VkResult*                                   vulkanResult);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanDeviceKHR(\n    XrInstance                                  instance,\n    const XrVulkanDeviceCreateInfoKHR*          createInfo,\n    VkDevice*                                   vulkanDevice,\n    VkResult*                                   vulkanResult);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDevice2KHR(\n    XrInstance                                  instance,\n    const XrVulkanGraphicsDeviceGetInfoKHR*     getInfo,\n    VkPhysicalDevice*                           vulkanPhysicalDevice);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirements2KHR(\n    XrInstance                                  instance,\n    XrSystemId                                  systemId,\n    XrGraphicsRequirementsVulkanKHR*            graphicsRequirements);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_GRAPHICS_API_VULKAN */\n\n#ifdef XR_USE_PLATFORM_EGL\n\n#define XR_MNDX_egl_enable 1\n#define XR_MNDX_egl_enable_SPEC_VERSION   1\n#define XR_MNDX_EGL_ENABLE_EXTENSION_NAME \"XR_MNDX_egl_enable\"\n// XrGraphicsBindingEGLMNDX extends XrSessionCreateInfo\ntypedef struct XrGraphicsBindingEGLMNDX {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    PFNEGLGETPROCADDRESSPROC    getProcAddress;\n    EGLDisplay                  display;\n    EGLConfig                   config;\n    EGLContext                  context;\n} XrGraphicsBindingEGLMNDX;\n\n#endif /* XR_USE_PLATFORM_EGL */\n\n#ifdef XR_USE_PLATFORM_WIN32\n\n#define XR_MSFT_perception_anchor_interop 1\n#define XR_MSFT_perception_anchor_interop_SPEC_VERSION 1\n#define XR_MSFT_PERCEPTION_ANCHOR_INTEROP_EXTENSION_NAME \"XR_MSFT_perception_anchor_interop\"\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFromPerceptionAnchorMSFT)(XrSession session, IUnknown* perceptionAnchor, XrSpatialAnchorMSFT* anchor);\ntypedef XrResult (XRAPI_PTR *PFN_xrTryGetPerceptionAnchorFromSpatialAnchorMSFT)(XrSession session, XrSpatialAnchorMSFT anchor, IUnknown** perceptionAnchor);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorFromPerceptionAnchorMSFT(\n    XrSession                                   session,\n    IUnknown*                                   perceptionAnchor,\n    XrSpatialAnchorMSFT*                        anchor);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrTryGetPerceptionAnchorFromSpatialAnchorMSFT(\n    XrSession                                   session,\n    XrSpatialAnchorMSFT                         anchor,\n    IUnknown**                                  perceptionAnchor);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_PLATFORM_WIN32 */\n\n#ifdef XR_USE_PLATFORM_WIN32\n\n#define XR_MSFT_holographic_window_attachment 1\n#define XR_MSFT_holographic_window_attachment_SPEC_VERSION 1\n#define XR_MSFT_HOLOGRAPHIC_WINDOW_ATTACHMENT_EXTENSION_NAME \"XR_MSFT_holographic_window_attachment\"\n#ifdef XR_USE_PLATFORM_WIN32\n// XrHolographicWindowAttachmentMSFT extends XrSessionCreateInfo\ntypedef struct XrHolographicWindowAttachmentMSFT {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    IUnknown*                   holographicSpace;\n    IUnknown*                   coreWindow;\n} XrHolographicWindowAttachmentMSFT;\n#endif // XR_USE_PLATFORM_WIN32\n\n#endif /* XR_USE_PLATFORM_WIN32 */\n\n#ifdef XR_USE_PLATFORM_ANDROID\n\n#define XR_FB_android_surface_swapchain_create 1\n#define XR_FB_android_surface_swapchain_create_SPEC_VERSION 1\n#define XR_FB_ANDROID_SURFACE_SWAPCHAIN_CREATE_EXTENSION_NAME \"XR_FB_android_surface_swapchain_create\"\ntypedef XrFlags64 XrAndroidSurfaceSwapchainFlagsFB;\n\n// Flag bits for XrAndroidSurfaceSwapchainFlagsFB\nstatic const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_SYNCHRONOUS_BIT_FB = 0x00000001;\nstatic const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_USE_TIMESTAMPS_BIT_FB = 0x00000002;\n\n#ifdef XR_USE_PLATFORM_ANDROID\n// XrAndroidSurfaceSwapchainCreateInfoFB extends XrSwapchainCreateInfo\ntypedef struct XrAndroidSurfaceSwapchainCreateInfoFB {\n    XrStructureType type;\n    const void *XR_MAY_ALIAS            next;\n    XrAndroidSurfaceSwapchainFlagsFB createFlags;\n} XrAndroidSurfaceSwapchainCreateInfoFB;\n#endif // XR_USE_PLATFORM_ANDROID\n\n#endif /* XR_USE_PLATFORM_ANDROID */\n\n#ifdef XR_USE_PLATFORM_ML\n\n#define XR_ML_compat 1\n#define XR_ML_compat_SPEC_VERSION         1\n#define XR_ML_COMPAT_EXTENSION_NAME       \"XR_ML_compat\"\ntypedef struct XrCoordinateSpaceCreateInfoML {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    MLCoordinateFrameUID        cfuid;\n    XrPosef                     poseInCoordinateSpace;\n} XrCoordinateSpaceCreateInfoML;\n\ntypedef XrResult (XRAPI_PTR *PFN_xrCreateSpaceFromCoordinateFrameUIDML)(XrSession session, const XrCoordinateSpaceCreateInfoML *createInfo, XrSpace* space);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrCreateSpaceFromCoordinateFrameUIDML(\n    XrSession                                   session,\n    const XrCoordinateSpaceCreateInfoML *       createInfo,\n    XrSpace*                                    space);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_PLATFORM_ML */\n\n#ifdef XR_USE_PLATFORM_WIN32\n\n#define XR_OCULUS_audio_device_guid 1\n#define XR_OCULUS_audio_device_guid_SPEC_VERSION 1\n#define XR_OCULUS_AUDIO_DEVICE_GUID_EXTENSION_NAME \"XR_OCULUS_audio_device_guid\"\n#define XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS 128\ntypedef XrResult (XRAPI_PTR *PFN_xrGetAudioOutputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);\ntypedef XrResult (XRAPI_PTR *PFN_xrGetAudioInputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);\n\n#ifndef XR_NO_PROTOTYPES\n#ifdef XR_EXTENSION_PROTOTYPES\nXRAPI_ATTR XrResult XRAPI_CALL xrGetAudioOutputDeviceGuidOculus(\n    XrInstance                                  instance,\n    wchar_t                                     buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);\n\nXRAPI_ATTR XrResult XRAPI_CALL xrGetAudioInputDeviceGuidOculus(\n    XrInstance                                  instance,\n    wchar_t                                     buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);\n#endif /* XR_EXTENSION_PROTOTYPES */\n#endif /* !XR_NO_PROTOTYPES */\n#endif /* XR_USE_PLATFORM_WIN32 */\n\n#ifdef XR_USE_GRAPHICS_API_VULKAN\n\n#define XR_FB_foveation_vulkan 1\n#define XR_FB_foveation_vulkan_SPEC_VERSION 1\n#define XR_FB_FOVEATION_VULKAN_EXTENSION_NAME \"XR_FB_foveation_vulkan\"\n// XrSwapchainImageFoveationVulkanFB extends XrSwapchainImageVulkanKHR\ntypedef struct XrSwapchainImageFoveationVulkanFB {\n    XrStructureType       type;\n    void* XR_MAY_ALIAS    next;\n    VkImage               image;\n    uint32_t              width;\n    uint32_t              height;\n} XrSwapchainImageFoveationVulkanFB;\n\n#endif /* XR_USE_GRAPHICS_API_VULKAN */\n\n#ifdef XR_USE_PLATFORM_ANDROID\n\n#define XR_FB_swapchain_update_state_android_surface 1\n#define XR_FB_swapchain_update_state_android_surface_SPEC_VERSION 1\n#define XR_FB_SWAPCHAIN_UPDATE_STATE_ANDROID_SURFACE_EXTENSION_NAME \"XR_FB_swapchain_update_state_android_surface\"\n#ifdef XR_USE_PLATFORM_ANDROID\ntypedef struct XrSwapchainStateAndroidSurfaceDimensionsFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    uint32_t width;\n    uint32_t height;\n} XrSwapchainStateAndroidSurfaceDimensionsFB;\n#endif // XR_USE_PLATFORM_ANDROID\n\n#endif /* XR_USE_PLATFORM_ANDROID */\n\n#ifdef XR_USE_GRAPHICS_API_OPENGL_ES\n\n#define XR_FB_swapchain_update_state_opengl_es 1\n#define XR_FB_swapchain_update_state_opengl_es_SPEC_VERSION 1\n#define XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME \"XR_FB_swapchain_update_state_opengl_es\"\n#ifdef XR_USE_GRAPHICS_API_OPENGL_ES\ntypedef struct XrSwapchainStateSamplerOpenGLESFB {\n    XrStructureType type;\n    void *XR_MAY_ALIAS    next;\n    EGLenum minFilter;\n    EGLenum magFilter;\n    EGLenum wrapModeS;\n    EGLenum wrapModeT;\n    EGLenum swizzleRed;\n    EGLenum swizzleGreen;\n    EGLenum swizzleBlue;\n    EGLenum swizzleAlpha;\n    float maxAnisotropy;\n    XrColor4f borderColor;\n} XrSwapchainStateSamplerOpenGLESFB;\n#endif // XR_USE_GRAPHICS_API_OPENGL_ES\n\n#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */\n\n#ifdef XR_USE_GRAPHICS_API_VULKAN\n\n#define XR_FB_swapchain_update_state_vulkan 1\n#define XR_FB_swapchain_update_state_vulkan_SPEC_VERSION 1\n#define XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME \"XR_FB_swapchain_update_state_vulkan\"\n#ifdef XR_USE_GRAPHICS_API_VULKAN\ntypedef struct XrSwapchainStateSamplerVulkanFB {\n    XrStructureType         type;\n    void* XR_MAY_ALIAS      next;\n    VkFilter                minFilter;\n    VkFilter                magFilter;\n    VkSamplerMipmapMode     mipmapMode;\n    VkSamplerAddressMode    wrapModeS;\n    VkSamplerAddressMode    wrapModeT;\n    VkComponentSwizzle      swizzleRed;\n    VkComponentSwizzle      swizzleGreen;\n    VkComponentSwizzle      swizzleBlue;\n    VkComponentSwizzle      swizzleAlpha;\n    float                   maxAnisotropy;\n    XrColor4f               borderColor;\n} XrSwapchainStateSamplerVulkanFB;\n#endif // XR_USE_GRAPHICS_API_VULKAN\n\n#endif /* XR_USE_GRAPHICS_API_VULKAN */\n\n#ifdef XR_USE_GRAPHICS_API_VULKAN\n\n#define XR_META_vulkan_swapchain_create_info 1\n#define XR_META_vulkan_swapchain_create_info_SPEC_VERSION 1\n#define XR_META_VULKAN_SWAPCHAIN_CREATE_INFO_EXTENSION_NAME \"XR_META_vulkan_swapchain_create_info\"\n// XrVulkanSwapchainCreateInfoMETA extends XrSwapchainCreateInfo\ntypedef struct XrVulkanSwapchainCreateInfoMETA {\n    XrStructureType             type;\n    const void* XR_MAY_ALIAS    next;\n    VkImageCreateFlags          additionalCreateFlags;\n    VkImageUsageFlags           additionalUsageFlags;\n} XrVulkanSwapchainCreateInfoMETA;\n\n#endif /* XR_USE_GRAPHICS_API_VULKAN */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/openxr/openxr_platform_defines.h",
    "content": "/*\n** Copyright (c) 2017-2023, The Khronos Group Inc.\n**\n** SPDX-License-Identifier: Apache-2.0 OR MIT\n*/\n\n#ifndef OPENXR_PLATFORM_DEFINES_H_\n#define OPENXR_PLATFORM_DEFINES_H_ 1\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Platform-specific calling convention macros.\n *\n * Platforms should define these so that OpenXR clients call OpenXR functions\n * with the same calling conventions that the OpenXR implementation expects.\n *\n * XRAPI_ATTR - Placed before the return type in function declarations.\n *              Useful for C++11 and GCC/Clang-style function attribute syntax.\n * XRAPI_CALL - Placed after the return type in function declarations.\n *              Useful for MSVC-style calling convention syntax.\n * XRAPI_PTR  - Placed between the '(' and '*' in function pointer types.\n *\n * Function declaration:  XRAPI_ATTR void XRAPI_CALL xrFunction(void);\n * Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void);\n */\n#if defined(_WIN32)\n#define XRAPI_ATTR\n// On Windows, functions use the stdcall convention\n#define XRAPI_CALL __stdcall\n#define XRAPI_PTR XRAPI_CALL\n#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7\n#error \"API not supported for the 'armeabi' NDK ABI\"\n#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)\n// On Android 32-bit ARM targets, functions use the \"hardfloat\"\n// calling convention, i.e. float parameters are passed in registers. This\n// is true even if the rest of the application passes floats on the stack,\n// as it does by default when compiling for the armeabi-v7a NDK ABI.\n#define XRAPI_ATTR __attribute__((pcs(\"aapcs-vfp\")))\n#define XRAPI_CALL\n#define XRAPI_PTR XRAPI_ATTR\n#else\n// On other platforms, use the default calling convention\n#define XRAPI_ATTR\n#define XRAPI_CALL\n#define XRAPI_PTR\n#endif\n\n#include <stddef.h>\n\n#if !defined(XR_NO_STDINT_H)\n#if defined(_MSC_VER) && (_MSC_VER < 1600)\ntypedef signed __int8 int8_t;\ntypedef unsigned __int8 uint8_t;\ntypedef signed __int16 int16_t;\ntypedef unsigned __int16 uint16_t;\ntypedef signed __int32 int32_t;\ntypedef unsigned __int32 uint32_t;\ntypedef signed __int64 int64_t;\ntypedef unsigned __int64 uint64_t;\n#else\n#include <stdint.h>\n#endif\n#endif  // !defined( XR_NO_STDINT_H )\n\n// XR_PTR_SIZE (in bytes)\n#if (defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(__powerpc64__))\n#define XR_PTR_SIZE 8\n#else\n#define XR_PTR_SIZE 4\n#endif\n\n// Needed so we can use clang __has_feature portably.\n#if !defined(XR_COMPILER_HAS_FEATURE)\n#if defined(__clang__)\n#define XR_COMPILER_HAS_FEATURE(x) __has_feature(x)\n#else\n#define XR_COMPILER_HAS_FEATURE(x) 0\n#endif\n#endif\n\n// Identifies if the current compiler has C++11 support enabled.\n// Does not by itself identify if any given C++11 feature is present.\n#if !defined(XR_CPP11_ENABLED) && defined(__cplusplus)\n#if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)\n#define XR_CPP11_ENABLED 1\n#elif defined(_MSC_VER) && (_MSC_VER >= 1600)\n#define XR_CPP11_ENABLED 1\n#elif (__cplusplus >= 201103L) // 201103 is the first C++11 version.\n#define XR_CPP11_ENABLED 1\n#endif\n#endif\n\n// Identifies if the current compiler supports C++11 nullptr.\n#if !defined(XR_CPP_NULLPTR_SUPPORTED)\n#if defined(XR_CPP11_ENABLED) && \\\n    ((defined(__clang__) && XR_COMPILER_HAS_FEATURE(cxx_nullptr)) || \\\n     (defined(__GNUC__) && (((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006)) || \\\n     (defined(_MSC_VER) && (_MSC_VER >= 1600)) || \\\n     (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))\n#define XR_CPP_NULLPTR_SUPPORTED 1\n#endif\n#endif\n\n#if !defined(XR_CPP_NULLPTR_SUPPORTED)\n#define XR_CPP_NULLPTR_SUPPORTED 0\n#endif  // !defined(XR_CPP_NULLPTR_SUPPORTED)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/openxr/openxr_reflection.h",
    "content": "#ifndef OPENXR_REFLECTION_H_\n#define OPENXR_REFLECTION_H_ 1\n\n/*\n** Copyright (c) 2017-2023, The Khronos Group Inc.\n**\n** SPDX-License-Identifier: Apache-2.0 OR MIT\n*/\n\n/*\n** This header is generated from the Khronos OpenXR XML API Registry.\n**\n*/\n\n#include \"openxr.h\"\n\n/*\nThis file contains expansion macros (X Macros) for OpenXR enumerations and structures.\nExample of how to use expansion macros to make an enum-to-string function:\n*/\n#define XR_ENUM_CASE_STR(name, val) case name: return #name;\n#define XR_ENUM_STR(enumType)                         \\\n    constexpr const char* XrEnumStr(enumType e) {     \\\n        switch (e) {                                  \\\n            XR_LIST_ENUM_##enumType(XR_ENUM_CASE_STR) \\\n            default: return \"Unknown\";                \\\n        }                                             \\\n    }                                                 \\\n\n#define XR_LIST_ENUM_XrResult(_) \\\n    _(XR_SUCCESS, 0) \\\n    _(XR_TIMEOUT_EXPIRED, 1) \\\n    _(XR_SESSION_LOSS_PENDING, 3) \\\n    _(XR_EVENT_UNAVAILABLE, 4) \\\n    _(XR_SPACE_BOUNDS_UNAVAILABLE, 7) \\\n    _(XR_SESSION_NOT_FOCUSED, 8) \\\n    _(XR_FRAME_DISCARDED, 9) \\\n    _(XR_ERROR_VALIDATION_FAILURE, -1) \\\n    _(XR_ERROR_RUNTIME_FAILURE, -2) \\\n    _(XR_ERROR_OUT_OF_MEMORY, -3) \\\n    _(XR_ERROR_API_VERSION_UNSUPPORTED, -4) \\\n    _(XR_ERROR_INITIALIZATION_FAILED, -6) \\\n    _(XR_ERROR_FUNCTION_UNSUPPORTED, -7) \\\n    _(XR_ERROR_FEATURE_UNSUPPORTED, -8) \\\n    _(XR_ERROR_EXTENSION_NOT_PRESENT, -9) \\\n    _(XR_ERROR_LIMIT_REACHED, -10) \\\n    _(XR_ERROR_SIZE_INSUFFICIENT, -11) \\\n    _(XR_ERROR_HANDLE_INVALID, -12) \\\n    _(XR_ERROR_INSTANCE_LOST, -13) \\\n    _(XR_ERROR_SESSION_RUNNING, -14) \\\n    _(XR_ERROR_SESSION_NOT_RUNNING, -16) \\\n    _(XR_ERROR_SESSION_LOST, -17) \\\n    _(XR_ERROR_SYSTEM_INVALID, -18) \\\n    _(XR_ERROR_PATH_INVALID, -19) \\\n    _(XR_ERROR_PATH_COUNT_EXCEEDED, -20) \\\n    _(XR_ERROR_PATH_FORMAT_INVALID, -21) \\\n    _(XR_ERROR_PATH_UNSUPPORTED, -22) \\\n    _(XR_ERROR_LAYER_INVALID, -23) \\\n    _(XR_ERROR_LAYER_LIMIT_EXCEEDED, -24) \\\n    _(XR_ERROR_SWAPCHAIN_RECT_INVALID, -25) \\\n    _(XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED, -26) \\\n    _(XR_ERROR_ACTION_TYPE_MISMATCH, -27) \\\n    _(XR_ERROR_SESSION_NOT_READY, -28) \\\n    _(XR_ERROR_SESSION_NOT_STOPPING, -29) \\\n    _(XR_ERROR_TIME_INVALID, -30) \\\n    _(XR_ERROR_REFERENCE_SPACE_UNSUPPORTED, -31) \\\n    _(XR_ERROR_FILE_ACCESS_ERROR, -32) \\\n    _(XR_ERROR_FILE_CONTENTS_INVALID, -33) \\\n    _(XR_ERROR_FORM_FACTOR_UNSUPPORTED, -34) \\\n    _(XR_ERROR_FORM_FACTOR_UNAVAILABLE, -35) \\\n    _(XR_ERROR_API_LAYER_NOT_PRESENT, -36) \\\n    _(XR_ERROR_CALL_ORDER_INVALID, -37) \\\n    _(XR_ERROR_GRAPHICS_DEVICE_INVALID, -38) \\\n    _(XR_ERROR_POSE_INVALID, -39) \\\n    _(XR_ERROR_INDEX_OUT_OF_RANGE, -40) \\\n    _(XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED, -41) \\\n    _(XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED, -42) \\\n    _(XR_ERROR_NAME_DUPLICATED, -44) \\\n    _(XR_ERROR_NAME_INVALID, -45) \\\n    _(XR_ERROR_ACTIONSET_NOT_ATTACHED, -46) \\\n    _(XR_ERROR_ACTIONSETS_ALREADY_ATTACHED, -47) \\\n    _(XR_ERROR_LOCALIZED_NAME_DUPLICATED, -48) \\\n    _(XR_ERROR_LOCALIZED_NAME_INVALID, -49) \\\n    _(XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING, -50) \\\n    _(XR_ERROR_RUNTIME_UNAVAILABLE, -51) \\\n    _(XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR, -1000003000) \\\n    _(XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR, -1000003001) \\\n    _(XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT, -1000039001) \\\n    _(XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT, -1000053000) \\\n    _(XR_ERROR_CONTROLLER_MODEL_KEY_INVALID_MSFT, -1000055000) \\\n    _(XR_ERROR_REPROJECTION_MODE_UNSUPPORTED_MSFT, -1000066000) \\\n    _(XR_ERROR_COMPUTE_NEW_SCENE_NOT_COMPLETED_MSFT, -1000097000) \\\n    _(XR_ERROR_SCENE_COMPONENT_ID_INVALID_MSFT, -1000097001) \\\n    _(XR_ERROR_SCENE_COMPONENT_TYPE_MISMATCH_MSFT, -1000097002) \\\n    _(XR_ERROR_SCENE_MESH_BUFFER_ID_INVALID_MSFT, -1000097003) \\\n    _(XR_ERROR_SCENE_COMPUTE_FEATURE_INCOMPATIBLE_MSFT, -1000097004) \\\n    _(XR_ERROR_SCENE_COMPUTE_CONSISTENCY_MISMATCH_MSFT, -1000097005) \\\n    _(XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB, -1000101000) \\\n    _(XR_ERROR_COLOR_SPACE_UNSUPPORTED_FB, -1000108000) \\\n    _(XR_ERROR_SPACE_COMPONENT_NOT_SUPPORTED_FB, -1000113000) \\\n    _(XR_ERROR_SPACE_COMPONENT_NOT_ENABLED_FB, -1000113001) \\\n    _(XR_ERROR_SPACE_COMPONENT_STATUS_PENDING_FB, -1000113002) \\\n    _(XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB, -1000113003) \\\n    _(XR_ERROR_UNEXPECTED_STATE_PASSTHROUGH_FB, -1000118000) \\\n    _(XR_ERROR_FEATURE_ALREADY_CREATED_PASSTHROUGH_FB, -1000118001) \\\n    _(XR_ERROR_FEATURE_REQUIRED_PASSTHROUGH_FB, -1000118002) \\\n    _(XR_ERROR_NOT_PERMITTED_PASSTHROUGH_FB, -1000118003) \\\n    _(XR_ERROR_INSUFFICIENT_RESOURCES_PASSTHROUGH_FB, -1000118004) \\\n    _(XR_ERROR_UNKNOWN_PASSTHROUGH_FB, -1000118050) \\\n    _(XR_ERROR_RENDER_MODEL_KEY_INVALID_FB, -1000119000) \\\n    _(XR_RENDER_MODEL_UNAVAILABLE_FB, 1000119020) \\\n    _(XR_ERROR_MARKER_NOT_TRACKED_VARJO, -1000124000) \\\n    _(XR_ERROR_MARKER_ID_INVALID_VARJO, -1000124001) \\\n    _(XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT, -1000142001) \\\n    _(XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT, -1000142002) \\\n    _(XR_ERROR_SPACE_MAPPING_INSUFFICIENT_FB, -1000169000) \\\n    _(XR_ERROR_SPACE_LOCALIZATION_FAILED_FB, -1000169001) \\\n    _(XR_ERROR_SPACE_NETWORK_TIMEOUT_FB, -1000169002) \\\n    _(XR_ERROR_SPACE_NETWORK_REQUEST_FAILED_FB, -1000169003) \\\n    _(XR_ERROR_SPACE_CLOUD_STORAGE_DISABLED_FB, -1000169004) \\\n    _(XR_ERROR_PASSTHROUGH_COLOR_LUT_BUFFER_SIZE_MISMATCH_META, -1000266000) \\\n    _(XR_ERROR_HINT_ALREADY_SET_QCOM, -1000306000) \\\n    _(XR_ERROR_SPACE_NOT_LOCATABLE_EXT, -1000429000) \\\n    _(XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT, -1000429001) \\\n    _(XR_RESULT_MAX_ENUM, 0x7FFFFFFF)\n\nXR_ENUM_STR(XrResult);\n\n#define XR_LIST_ENUM_XrStructureType(_) \\\n    _(XR_TYPE_UNKNOWN, 0) \\\n    _(XR_TYPE_API_LAYER_PROPERTIES, 1) \\\n    _(XR_TYPE_EXTENSION_PROPERTIES, 2) \\\n    _(XR_TYPE_INSTANCE_CREATE_INFO, 3) \\\n    _(XR_TYPE_SYSTEM_GET_INFO, 4) \\\n    _(XR_TYPE_SYSTEM_PROPERTIES, 5) \\\n    _(XR_TYPE_VIEW_LOCATE_INFO, 6) \\\n    _(XR_TYPE_VIEW, 7) \\\n    _(XR_TYPE_SESSION_CREATE_INFO, 8) \\\n    _(XR_TYPE_SWAPCHAIN_CREATE_INFO, 9) \\\n    _(XR_TYPE_SESSION_BEGIN_INFO, 10) \\\n    _(XR_TYPE_VIEW_STATE, 11) \\\n    _(XR_TYPE_FRAME_END_INFO, 12) \\\n    _(XR_TYPE_HAPTIC_VIBRATION, 13) \\\n    _(XR_TYPE_EVENT_DATA_BUFFER, 16) \\\n    _(XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING, 17) \\\n    _(XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED, 18) \\\n    _(XR_TYPE_ACTION_STATE_BOOLEAN, 23) \\\n    _(XR_TYPE_ACTION_STATE_FLOAT, 24) \\\n    _(XR_TYPE_ACTION_STATE_VECTOR2F, 25) \\\n    _(XR_TYPE_ACTION_STATE_POSE, 27) \\\n    _(XR_TYPE_ACTION_SET_CREATE_INFO, 28) \\\n    _(XR_TYPE_ACTION_CREATE_INFO, 29) \\\n    _(XR_TYPE_INSTANCE_PROPERTIES, 32) \\\n    _(XR_TYPE_FRAME_WAIT_INFO, 33) \\\n    _(XR_TYPE_COMPOSITION_LAYER_PROJECTION, 35) \\\n    _(XR_TYPE_COMPOSITION_LAYER_QUAD, 36) \\\n    _(XR_TYPE_REFERENCE_SPACE_CREATE_INFO, 37) \\\n    _(XR_TYPE_ACTION_SPACE_CREATE_INFO, 38) \\\n    _(XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING, 40) \\\n    _(XR_TYPE_VIEW_CONFIGURATION_VIEW, 41) \\\n    _(XR_TYPE_SPACE_LOCATION, 42) \\\n    _(XR_TYPE_SPACE_VELOCITY, 43) \\\n    _(XR_TYPE_FRAME_STATE, 44) \\\n    _(XR_TYPE_VIEW_CONFIGURATION_PROPERTIES, 45) \\\n    _(XR_TYPE_FRAME_BEGIN_INFO, 46) \\\n    _(XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW, 48) \\\n    _(XR_TYPE_EVENT_DATA_EVENTS_LOST, 49) \\\n    _(XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING, 51) \\\n    _(XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED, 52) \\\n    _(XR_TYPE_INTERACTION_PROFILE_STATE, 53) \\\n    _(XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, 55) \\\n    _(XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO, 56) \\\n    _(XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, 57) \\\n    _(XR_TYPE_ACTION_STATE_GET_INFO, 58) \\\n    _(XR_TYPE_HAPTIC_ACTION_INFO, 59) \\\n    _(XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO, 60) \\\n    _(XR_TYPE_ACTIONS_SYNC_INFO, 61) \\\n    _(XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO, 62) \\\n    _(XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO, 63) \\\n    _(XR_TYPE_COMPOSITION_LAYER_CUBE_KHR, 1000006000) \\\n    _(XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, 1000008000) \\\n    _(XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR, 1000010000) \\\n    _(XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR, 1000014000) \\\n    _(XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT, 1000015000) \\\n    _(XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR, 1000017000) \\\n    _(XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR, 1000018000) \\\n    _(XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 1000019000) \\\n    _(XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, 1000019001) \\\n    _(XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, 1000019002) \\\n    _(XR_TYPE_DEBUG_UTILS_LABEL_EXT, 1000019003) \\\n    _(XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, 1000023000) \\\n    _(XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR, 1000023001) \\\n    _(XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR, 1000023002) \\\n    _(XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR, 1000023003) \\\n    _(XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR, 1000023004) \\\n    _(XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR, 1000023005) \\\n    _(XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR, 1000024001) \\\n    _(XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR, 1000024002) \\\n    _(XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR, 1000024003) \\\n    _(XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR, 1000025000) \\\n    _(XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR, 1000025001) \\\n    _(XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR, 1000025002) \\\n    _(XR_TYPE_GRAPHICS_BINDING_D3D11_KHR, 1000027000) \\\n    _(XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR, 1000027001) \\\n    _(XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR, 1000027002) \\\n    _(XR_TYPE_GRAPHICS_BINDING_D3D12_KHR, 1000028000) \\\n    _(XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR, 1000028001) \\\n    _(XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR, 1000028002) \\\n    _(XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT, 1000030000) \\\n    _(XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT, 1000030001) \\\n    _(XR_TYPE_VISIBILITY_MASK_KHR, 1000031000) \\\n    _(XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR, 1000031001) \\\n    _(XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX, 1000033000) \\\n    _(XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX, 1000033003) \\\n    _(XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR, 1000034000) \\\n    _(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT, 1000039000) \\\n    _(XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT, 1000039001) \\\n    _(XR_TYPE_COMPOSITION_LAYER_IMAGE_LAYOUT_FB, 1000040000) \\\n    _(XR_TYPE_COMPOSITION_LAYER_ALPHA_BLEND_FB, 1000041001) \\\n    _(XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT, 1000046000) \\\n    _(XR_TYPE_GRAPHICS_BINDING_EGL_MNDX, 1000048004) \\\n    _(XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT, 1000049000) \\\n    _(XR_TYPE_SPATIAL_GRAPH_STATIC_NODE_BINDING_CREATE_INFO_MSFT, 1000049001) \\\n    _(XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_GET_INFO_MSFT, 1000049002) \\\n    _(XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_MSFT, 1000049003) \\\n    _(XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT, 1000051000) \\\n    _(XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT, 1000051001) \\\n    _(XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT, 1000051002) \\\n    _(XR_TYPE_HAND_JOINT_LOCATIONS_EXT, 1000051003) \\\n    _(XR_TYPE_HAND_JOINT_VELOCITIES_EXT, 1000051004) \\\n    _(XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT, 1000052000) \\\n    _(XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT, 1000052001) \\\n    _(XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT, 1000052002) \\\n    _(XR_TYPE_HAND_MESH_MSFT, 1000052003) \\\n    _(XR_TYPE_HAND_POSE_TYPE_INFO_MSFT, 1000052004) \\\n    _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT, 1000053000) \\\n    _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT, 1000053001) \\\n    _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT, 1000053002) \\\n    _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT, 1000053003) \\\n    _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT, 1000053004) \\\n    _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT, 1000053005) \\\n    _(XR_TYPE_CONTROLLER_MODEL_KEY_STATE_MSFT, 1000055000) \\\n    _(XR_TYPE_CONTROLLER_MODEL_NODE_PROPERTIES_MSFT, 1000055001) \\\n    _(XR_TYPE_CONTROLLER_MODEL_PROPERTIES_MSFT, 1000055002) \\\n    _(XR_TYPE_CONTROLLER_MODEL_NODE_STATE_MSFT, 1000055003) \\\n    _(XR_TYPE_CONTROLLER_MODEL_STATE_MSFT, 1000055004) \\\n    _(XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC, 1000059000) \\\n    _(XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT, 1000063000) \\\n    _(XR_TYPE_COMPOSITION_LAYER_REPROJECTION_INFO_MSFT, 1000066000) \\\n    _(XR_TYPE_COMPOSITION_LAYER_REPROJECTION_PLANE_OVERRIDE_MSFT, 1000066001) \\\n    _(XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB, 1000070000) \\\n    _(XR_TYPE_COMPOSITION_LAYER_SECURE_CONTENT_FB, 1000072000) \\\n    _(XR_TYPE_BODY_TRACKER_CREATE_INFO_FB, 1000076001) \\\n    _(XR_TYPE_BODY_JOINTS_LOCATE_INFO_FB, 1000076002) \\\n    _(XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_FB, 1000076004) \\\n    _(XR_TYPE_BODY_JOINT_LOCATIONS_FB, 1000076005) \\\n    _(XR_TYPE_BODY_SKELETON_FB, 1000076006) \\\n    _(XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT, 1000078000) \\\n    _(XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE, 1000079000) \\\n    _(XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT, 1000080000) \\\n    _(XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR, 1000089000) \\\n    _(XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR, 1000090000) \\\n    _(XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR, 1000090001) \\\n    _(XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR, 1000090003) \\\n    _(XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR, 1000091000) \\\n    _(XR_TYPE_SCENE_OBSERVER_CREATE_INFO_MSFT, 1000097000) \\\n    _(XR_TYPE_SCENE_CREATE_INFO_MSFT, 1000097001) \\\n    _(XR_TYPE_NEW_SCENE_COMPUTE_INFO_MSFT, 1000097002) \\\n    _(XR_TYPE_VISUAL_MESH_COMPUTE_LOD_INFO_MSFT, 1000097003) \\\n    _(XR_TYPE_SCENE_COMPONENTS_MSFT, 1000097004) \\\n    _(XR_TYPE_SCENE_COMPONENTS_GET_INFO_MSFT, 1000097005) \\\n    _(XR_TYPE_SCENE_COMPONENT_LOCATIONS_MSFT, 1000097006) \\\n    _(XR_TYPE_SCENE_COMPONENTS_LOCATE_INFO_MSFT, 1000097007) \\\n    _(XR_TYPE_SCENE_OBJECTS_MSFT, 1000097008) \\\n    _(XR_TYPE_SCENE_COMPONENT_PARENT_FILTER_INFO_MSFT, 1000097009) \\\n    _(XR_TYPE_SCENE_OBJECT_TYPES_FILTER_INFO_MSFT, 1000097010) \\\n    _(XR_TYPE_SCENE_PLANES_MSFT, 1000097011) \\\n    _(XR_TYPE_SCENE_PLANE_ALIGNMENT_FILTER_INFO_MSFT, 1000097012) \\\n    _(XR_TYPE_SCENE_MESHES_MSFT, 1000097013) \\\n    _(XR_TYPE_SCENE_MESH_BUFFERS_GET_INFO_MSFT, 1000097014) \\\n    _(XR_TYPE_SCENE_MESH_BUFFERS_MSFT, 1000097015) \\\n    _(XR_TYPE_SCENE_MESH_VERTEX_BUFFER_MSFT, 1000097016) \\\n    _(XR_TYPE_SCENE_MESH_INDICES_UINT32_MSFT, 1000097017) \\\n    _(XR_TYPE_SCENE_MESH_INDICES_UINT16_MSFT, 1000097018) \\\n    _(XR_TYPE_SERIALIZED_SCENE_FRAGMENT_DATA_GET_INFO_MSFT, 1000098000) \\\n    _(XR_TYPE_SCENE_DESERIALIZE_INFO_MSFT, 1000098001) \\\n    _(XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB, 1000101000) \\\n    _(XR_TYPE_VIVE_TRACKER_PATHS_HTCX, 1000103000) \\\n    _(XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX, 1000103001) \\\n    _(XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC, 1000104000) \\\n    _(XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC, 1000104001) \\\n    _(XR_TYPE_FACIAL_EXPRESSIONS_HTC, 1000104002) \\\n    _(XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB, 1000108000) \\\n    _(XR_TYPE_HAND_TRACKING_MESH_FB, 1000110001) \\\n    _(XR_TYPE_HAND_TRACKING_SCALE_FB, 1000110003) \\\n    _(XR_TYPE_HAND_TRACKING_AIM_STATE_FB, 1000111001) \\\n    _(XR_TYPE_HAND_TRACKING_CAPSULES_STATE_FB, 1000112000) \\\n    _(XR_TYPE_SYSTEM_SPATIAL_ENTITY_PROPERTIES_FB, 1000113004) \\\n    _(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_FB, 1000113003) \\\n    _(XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB, 1000113007) \\\n    _(XR_TYPE_SPACE_COMPONENT_STATUS_FB, 1000113001) \\\n    _(XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB, 1000113005) \\\n    _(XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB, 1000113006) \\\n    _(XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB, 1000114000) \\\n    _(XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB, 1000114001) \\\n    _(XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB, 1000114002) \\\n    _(XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB, 1000115000) \\\n    _(XR_TYPE_KEYBOARD_SPACE_CREATE_INFO_FB, 1000116009) \\\n    _(XR_TYPE_KEYBOARD_TRACKING_QUERY_FB, 1000116004) \\\n    _(XR_TYPE_SYSTEM_KEYBOARD_TRACKING_PROPERTIES_FB, 1000116002) \\\n    _(XR_TYPE_TRIANGLE_MESH_CREATE_INFO_FB, 1000117001) \\\n    _(XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB, 1000118000) \\\n    _(XR_TYPE_PASSTHROUGH_CREATE_INFO_FB, 1000118001) \\\n    _(XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB, 1000118002) \\\n    _(XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB, 1000118003) \\\n    _(XR_TYPE_GEOMETRY_INSTANCE_CREATE_INFO_FB, 1000118004) \\\n    _(XR_TYPE_GEOMETRY_INSTANCE_TRANSFORM_FB, 1000118005) \\\n    _(XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB, 1000118006) \\\n    _(XR_TYPE_PASSTHROUGH_STYLE_FB, 1000118020) \\\n    _(XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB, 1000118021) \\\n    _(XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB, 1000118022) \\\n    _(XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB, 1000118023) \\\n    _(XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB, 1000118030) \\\n    _(XR_TYPE_RENDER_MODEL_PATH_INFO_FB, 1000119000) \\\n    _(XR_TYPE_RENDER_MODEL_PROPERTIES_FB, 1000119001) \\\n    _(XR_TYPE_RENDER_MODEL_BUFFER_FB, 1000119002) \\\n    _(XR_TYPE_RENDER_MODEL_LOAD_INFO_FB, 1000119003) \\\n    _(XR_TYPE_SYSTEM_RENDER_MODEL_PROPERTIES_FB, 1000119004) \\\n    _(XR_TYPE_RENDER_MODEL_CAPABILITIES_REQUEST_FB, 1000119005) \\\n    _(XR_TYPE_BINDING_MODIFICATIONS_KHR, 1000120000) \\\n    _(XR_TYPE_VIEW_LOCATE_FOVEATED_RENDERING_VARJO, 1000121000) \\\n    _(XR_TYPE_FOVEATED_VIEW_CONFIGURATION_VIEW_VARJO, 1000121001) \\\n    _(XR_TYPE_SYSTEM_FOVEATED_RENDERING_PROPERTIES_VARJO, 1000121002) \\\n    _(XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_VARJO, 1000122000) \\\n    _(XR_TYPE_SYSTEM_MARKER_TRACKING_PROPERTIES_VARJO, 1000124000) \\\n    _(XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO, 1000124001) \\\n    _(XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO, 1000124002) \\\n    _(XR_TYPE_FRAME_END_INFO_ML, 1000135000) \\\n    _(XR_TYPE_GLOBAL_DIMMER_FRAME_END_INFO_ML, 1000136000) \\\n    _(XR_TYPE_COORDINATE_SPACE_CREATE_INFO_ML, 1000137000) \\\n    _(XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT, 1000142000) \\\n    _(XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT, 1000142001) \\\n    _(XR_TYPE_SPACE_QUERY_INFO_FB, 1000156001) \\\n    _(XR_TYPE_SPACE_QUERY_RESULTS_FB, 1000156002) \\\n    _(XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB, 1000156003) \\\n    _(XR_TYPE_SPACE_UUID_FILTER_INFO_FB, 1000156054) \\\n    _(XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB, 1000156052) \\\n    _(XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB, 1000156103) \\\n    _(XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB, 1000156104) \\\n    _(XR_TYPE_SPACE_SAVE_INFO_FB, 1000158000) \\\n    _(XR_TYPE_SPACE_ERASE_INFO_FB, 1000158001) \\\n    _(XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB, 1000158106) \\\n    _(XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB, 1000158107) \\\n    _(XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB, 1000160000) \\\n    _(XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB, 1000161000) \\\n    _(XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB, 1000162000) \\\n    _(XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB, 1000163000) \\\n    _(XR_TYPE_SPACE_SHARE_INFO_FB, 1000169001) \\\n    _(XR_TYPE_EVENT_DATA_SPACE_SHARE_COMPLETE_FB, 1000169002) \\\n    _(XR_TYPE_COMPOSITION_LAYER_SPACE_WARP_INFO_FB, 1000171000) \\\n    _(XR_TYPE_SYSTEM_SPACE_WARP_PROPERTIES_FB, 1000171001) \\\n    _(XR_TYPE_HAPTIC_AMPLITUDE_ENVELOPE_VIBRATION_FB, 1000173001) \\\n    _(XR_TYPE_SEMANTIC_LABELS_FB, 1000175000) \\\n    _(XR_TYPE_ROOM_LAYOUT_FB, 1000175001) \\\n    _(XR_TYPE_BOUNDARY_2D_FB, 1000175002) \\\n    _(XR_TYPE_SEMANTIC_LABELS_SUPPORT_INFO_FB, 1000175010) \\\n    _(XR_TYPE_DIGITAL_LENS_CONTROL_ALMALENCE, 1000196000) \\\n    _(XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB, 1000198001) \\\n    _(XR_TYPE_SCENE_CAPTURE_REQUEST_INFO_FB, 1000198050) \\\n    _(XR_TYPE_SPACE_CONTAINER_FB, 1000199000) \\\n    _(XR_TYPE_FOVEATION_EYE_TRACKED_PROFILE_CREATE_INFO_META, 1000200000) \\\n    _(XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META, 1000200001) \\\n    _(XR_TYPE_SYSTEM_FOVEATION_EYE_TRACKED_PROPERTIES_META, 1000200002) \\\n    _(XR_TYPE_SYSTEM_FACE_TRACKING_PROPERTIES_FB, 1000201004) \\\n    _(XR_TYPE_FACE_TRACKER_CREATE_INFO_FB, 1000201005) \\\n    _(XR_TYPE_FACE_EXPRESSION_INFO_FB, 1000201002) \\\n    _(XR_TYPE_FACE_EXPRESSION_WEIGHTS_FB, 1000201006) \\\n    _(XR_TYPE_EYE_TRACKER_CREATE_INFO_FB, 1000202001) \\\n    _(XR_TYPE_EYE_GAZES_INFO_FB, 1000202002) \\\n    _(XR_TYPE_EYE_GAZES_FB, 1000202003) \\\n    _(XR_TYPE_SYSTEM_EYE_TRACKING_PROPERTIES_FB, 1000202004) \\\n    _(XR_TYPE_PASSTHROUGH_KEYBOARD_HANDS_INTENSITY_FB, 1000203002) \\\n    _(XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB, 1000204000) \\\n    _(XR_TYPE_HAPTIC_PCM_VIBRATION_FB, 1000209001) \\\n    _(XR_TYPE_DEVICE_PCM_SAMPLE_RATE_STATE_FB, 1000209002) \\\n    _(XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_FB, 1000212000) \\\n    _(XR_TYPE_LOCAL_DIMMING_FRAME_END_INFO_META, 1000216000) \\\n    _(XR_TYPE_SYSTEM_VIRTUAL_KEYBOARD_PROPERTIES_META, 1000219001) \\\n    _(XR_TYPE_VIRTUAL_KEYBOARD_CREATE_INFO_META, 1000219002) \\\n    _(XR_TYPE_VIRTUAL_KEYBOARD_SPACE_CREATE_INFO_META, 1000219003) \\\n    _(XR_TYPE_VIRTUAL_KEYBOARD_LOCATION_INFO_META, 1000219004) \\\n    _(XR_TYPE_VIRTUAL_KEYBOARD_MODEL_VISIBILITY_SET_INFO_META, 1000219005) \\\n    _(XR_TYPE_VIRTUAL_KEYBOARD_ANIMATION_STATE_META, 1000219006) \\\n    _(XR_TYPE_VIRTUAL_KEYBOARD_MODEL_ANIMATION_STATES_META, 1000219007) \\\n    _(XR_TYPE_VIRTUAL_KEYBOARD_TEXTURE_DATA_META, 1000219009) \\\n    _(XR_TYPE_VIRTUAL_KEYBOARD_INPUT_INFO_META, 1000219010) \\\n    _(XR_TYPE_VIRTUAL_KEYBOARD_TEXT_CONTEXT_CHANGE_INFO_META, 1000219011) \\\n    _(XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_COMMIT_TEXT_META, 1000219014) \\\n    _(XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_BACKSPACE_META, 1000219015) \\\n    _(XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_ENTER_META, 1000219016) \\\n    _(XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_SHOWN_META, 1000219017) \\\n    _(XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_HIDDEN_META, 1000219018) \\\n    _(XR_TYPE_EXTERNAL_CAMERA_OCULUS, 1000226000) \\\n    _(XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META, 1000227000) \\\n    _(XR_TYPE_PERFORMANCE_METRICS_STATE_META, 1000232001) \\\n    _(XR_TYPE_PERFORMANCE_METRICS_COUNTER_META, 1000232002) \\\n    _(XR_TYPE_SPACE_LIST_SAVE_INFO_FB, 1000238000) \\\n    _(XR_TYPE_EVENT_DATA_SPACE_LIST_SAVE_COMPLETE_FB, 1000238001) \\\n    _(XR_TYPE_SPACE_USER_CREATE_INFO_FB, 1000241001) \\\n    _(XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META, 1000245000) \\\n    _(XR_TYPE_SYSTEM_PASSTHROUGH_COLOR_LUT_PROPERTIES_META, 1000266000) \\\n    _(XR_TYPE_PASSTHROUGH_COLOR_LUT_CREATE_INFO_META, 1000266001) \\\n    _(XR_TYPE_PASSTHROUGH_COLOR_LUT_UPDATE_INFO_META, 1000266002) \\\n    _(XR_TYPE_PASSTHROUGH_COLOR_MAP_LUT_META, 1000266100) \\\n    _(XR_TYPE_PASSTHROUGH_COLOR_MAP_INTERPOLATED_LUT_META, 1000266101) \\\n    _(XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC, 1000317001) \\\n    _(XR_TYPE_PASSTHROUGH_COLOR_HTC, 1000317002) \\\n    _(XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC, 1000317003) \\\n    _(XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC, 1000317004) \\\n    _(XR_TYPE_FOVEATION_APPLY_INFO_HTC, 1000318000) \\\n    _(XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC, 1000318001) \\\n    _(XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC, 1000318002) \\\n    _(XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT, 1000373000) \\\n    _(XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX, 1000375000) \\\n    _(XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX, 1000375001) \\\n    _(XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT, 1000428000) \\\n    _(XR_TYPE_HAND_TRACKING_DATA_SOURCE_STATE_EXT, 1000428001) \\\n    _(XR_TYPE_PLANE_DETECTOR_CREATE_INFO_EXT, 1000429001) \\\n    _(XR_TYPE_PLANE_DETECTOR_BEGIN_INFO_EXT, 1000429002) \\\n    _(XR_TYPE_PLANE_DETECTOR_GET_INFO_EXT, 1000429003) \\\n    _(XR_TYPE_PLANE_DETECTOR_LOCATIONS_EXT, 1000429004) \\\n    _(XR_TYPE_PLANE_DETECTOR_LOCATION_EXT, 1000429005) \\\n    _(XR_TYPE_PLANE_DETECTOR_POLYGON_BUFFER_EXT, 1000429006) \\\n    _(XR_TYPE_SYSTEM_PLANE_DETECTION_PROPERTIES_EXT, 1000429007) \\\n    _(XR_STRUCTURE_TYPE_MAX_ENUM, 0x7FFFFFFF)\n\nXR_ENUM_STR(XrStructureType);\n\n#define XR_LIST_ENUM_XrFormFactor(_) \\\n    _(XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY, 1) \\\n    _(XR_FORM_FACTOR_HANDHELD_DISPLAY, 2) \\\n    _(XR_FORM_FACTOR_MAX_ENUM, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrViewConfigurationType(_) \\\n    _(XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO, 1) \\\n    _(XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 2) \\\n    _(XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO, 1000037000) \\\n    _(XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT, 1000054000) \\\n    _(XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM, 0x7FFFFFFF)\n\nXR_ENUM_STR(XrViewConfigurationType);\n\n#define XR_LIST_ENUM_XrEnvironmentBlendMode(_) \\\n    _(XR_ENVIRONMENT_BLEND_MODE_OPAQUE, 1) \\\n    _(XR_ENVIRONMENT_BLEND_MODE_ADDITIVE, 2) \\\n    _(XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND, 3) \\\n    _(XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrReferenceSpaceType(_) \\\n    _(XR_REFERENCE_SPACE_TYPE_VIEW, 1) \\\n    _(XR_REFERENCE_SPACE_TYPE_LOCAL, 2) \\\n    _(XR_REFERENCE_SPACE_TYPE_STAGE, 3) \\\n    _(XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT, 1000038000) \\\n    _(XR_REFERENCE_SPACE_TYPE_COMBINED_EYE_VARJO, 1000121000) \\\n    _(XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT, 1000426000) \\\n    _(XR_REFERENCE_SPACE_TYPE_MAX_ENUM, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrActionType(_) \\\n    _(XR_ACTION_TYPE_BOOLEAN_INPUT, 1) \\\n    _(XR_ACTION_TYPE_FLOAT_INPUT, 2) \\\n    _(XR_ACTION_TYPE_VECTOR2F_INPUT, 3) \\\n    _(XR_ACTION_TYPE_POSE_INPUT, 4) \\\n    _(XR_ACTION_TYPE_VIBRATION_OUTPUT, 100) \\\n    _(XR_ACTION_TYPE_MAX_ENUM, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrEyeVisibility(_) \\\n    _(XR_EYE_VISIBILITY_BOTH, 0) \\\n    _(XR_EYE_VISIBILITY_LEFT, 1) \\\n    _(XR_EYE_VISIBILITY_RIGHT, 2) \\\n    _(XR_EYE_VISIBILITY_MAX_ENUM, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSessionState(_) \\\n    _(XR_SESSION_STATE_UNKNOWN, 0) \\\n    _(XR_SESSION_STATE_IDLE, 1) \\\n    _(XR_SESSION_STATE_READY, 2) \\\n    _(XR_SESSION_STATE_SYNCHRONIZED, 3) \\\n    _(XR_SESSION_STATE_VISIBLE, 4) \\\n    _(XR_SESSION_STATE_FOCUSED, 5) \\\n    _(XR_SESSION_STATE_STOPPING, 6) \\\n    _(XR_SESSION_STATE_LOSS_PENDING, 7) \\\n    _(XR_SESSION_STATE_EXITING, 8) \\\n    _(XR_SESSION_STATE_MAX_ENUM, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrObjectType(_) \\\n    _(XR_OBJECT_TYPE_UNKNOWN, 0) \\\n    _(XR_OBJECT_TYPE_INSTANCE, 1) \\\n    _(XR_OBJECT_TYPE_SESSION, 2) \\\n    _(XR_OBJECT_TYPE_SWAPCHAIN, 3) \\\n    _(XR_OBJECT_TYPE_SPACE, 4) \\\n    _(XR_OBJECT_TYPE_ACTION_SET, 5) \\\n    _(XR_OBJECT_TYPE_ACTION, 6) \\\n    _(XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT, 1000019000) \\\n    _(XR_OBJECT_TYPE_SPATIAL_ANCHOR_MSFT, 1000039000) \\\n    _(XR_OBJECT_TYPE_SPATIAL_GRAPH_NODE_BINDING_MSFT, 1000049000) \\\n    _(XR_OBJECT_TYPE_HAND_TRACKER_EXT, 1000051000) \\\n    _(XR_OBJECT_TYPE_BODY_TRACKER_FB, 1000076000) \\\n    _(XR_OBJECT_TYPE_SCENE_OBSERVER_MSFT, 1000097000) \\\n    _(XR_OBJECT_TYPE_SCENE_MSFT, 1000097001) \\\n    _(XR_OBJECT_TYPE_FACIAL_TRACKER_HTC, 1000104000) \\\n    _(XR_OBJECT_TYPE_FOVEATION_PROFILE_FB, 1000114000) \\\n    _(XR_OBJECT_TYPE_TRIANGLE_MESH_FB, 1000117000) \\\n    _(XR_OBJECT_TYPE_PASSTHROUGH_FB, 1000118000) \\\n    _(XR_OBJECT_TYPE_PASSTHROUGH_LAYER_FB, 1000118002) \\\n    _(XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB, 1000118004) \\\n    _(XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT, 1000142000) \\\n    _(XR_OBJECT_TYPE_FACE_TRACKER_FB, 1000201000) \\\n    _(XR_OBJECT_TYPE_EYE_TRACKER_FB, 1000202000) \\\n    _(XR_OBJECT_TYPE_VIRTUAL_KEYBOARD_META, 1000219000) \\\n    _(XR_OBJECT_TYPE_SPACE_USER_FB, 1000241000) \\\n    _(XR_OBJECT_TYPE_PASSTHROUGH_COLOR_LUT_META, 1000266000) \\\n    _(XR_OBJECT_TYPE_PASSTHROUGH_HTC, 1000317000) \\\n    _(XR_OBJECT_TYPE_PLANE_DETECTOR_EXT, 1000429000) \\\n    _(XR_OBJECT_TYPE_MAX_ENUM, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrAndroidThreadTypeKHR(_) \\\n    _(XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, 1) \\\n    _(XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR, 2) \\\n    _(XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR, 3) \\\n    _(XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR, 4) \\\n    _(XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrVisibilityMaskTypeKHR(_) \\\n    _(XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR, 1) \\\n    _(XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR, 2) \\\n    _(XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR, 3) \\\n    _(XR_VISIBILITY_MASK_TYPE_MAX_ENUM_KHR, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPerfSettingsDomainEXT(_) \\\n    _(XR_PERF_SETTINGS_DOMAIN_CPU_EXT, 1) \\\n    _(XR_PERF_SETTINGS_DOMAIN_GPU_EXT, 2) \\\n    _(XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPerfSettingsSubDomainEXT(_) \\\n    _(XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT, 1) \\\n    _(XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT, 2) \\\n    _(XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT, 3) \\\n    _(XR_PERF_SETTINGS_SUB_DOMAIN_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPerfSettingsLevelEXT(_) \\\n    _(XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT, 0) \\\n    _(XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT, 25) \\\n    _(XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT, 50) \\\n    _(XR_PERF_SETTINGS_LEVEL_BOOST_EXT, 75) \\\n    _(XR_PERF_SETTINGS_LEVEL_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPerfSettingsNotificationLevelEXT(_) \\\n    _(XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT, 0) \\\n    _(XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT, 25) \\\n    _(XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT, 75) \\\n    _(XR_PERF_SETTINGS_NOTIFICATION_LEVEL_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrBlendFactorFB(_) \\\n    _(XR_BLEND_FACTOR_ZERO_FB, 0) \\\n    _(XR_BLEND_FACTOR_ONE_FB, 1) \\\n    _(XR_BLEND_FACTOR_SRC_ALPHA_FB, 2) \\\n    _(XR_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA_FB, 3) \\\n    _(XR_BLEND_FACTOR_DST_ALPHA_FB, 4) \\\n    _(XR_BLEND_FACTOR_ONE_MINUS_DST_ALPHA_FB, 5) \\\n    _(XR_BLEND_FACTOR_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSpatialGraphNodeTypeMSFT(_) \\\n    _(XR_SPATIAL_GRAPH_NODE_TYPE_STATIC_MSFT, 1) \\\n    _(XR_SPATIAL_GRAPH_NODE_TYPE_DYNAMIC_MSFT, 2) \\\n    _(XR_SPATIAL_GRAPH_NODE_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrHandEXT(_) \\\n    _(XR_HAND_LEFT_EXT, 1) \\\n    _(XR_HAND_RIGHT_EXT, 2) \\\n    _(XR_HAND_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrHandJointEXT(_) \\\n    _(XR_HAND_JOINT_PALM_EXT, 0) \\\n    _(XR_HAND_JOINT_WRIST_EXT, 1) \\\n    _(XR_HAND_JOINT_THUMB_METACARPAL_EXT, 2) \\\n    _(XR_HAND_JOINT_THUMB_PROXIMAL_EXT, 3) \\\n    _(XR_HAND_JOINT_THUMB_DISTAL_EXT, 4) \\\n    _(XR_HAND_JOINT_THUMB_TIP_EXT, 5) \\\n    _(XR_HAND_JOINT_INDEX_METACARPAL_EXT, 6) \\\n    _(XR_HAND_JOINT_INDEX_PROXIMAL_EXT, 7) \\\n    _(XR_HAND_JOINT_INDEX_INTERMEDIATE_EXT, 8) \\\n    _(XR_HAND_JOINT_INDEX_DISTAL_EXT, 9) \\\n    _(XR_HAND_JOINT_INDEX_TIP_EXT, 10) \\\n    _(XR_HAND_JOINT_MIDDLE_METACARPAL_EXT, 11) \\\n    _(XR_HAND_JOINT_MIDDLE_PROXIMAL_EXT, 12) \\\n    _(XR_HAND_JOINT_MIDDLE_INTERMEDIATE_EXT, 13) \\\n    _(XR_HAND_JOINT_MIDDLE_DISTAL_EXT, 14) \\\n    _(XR_HAND_JOINT_MIDDLE_TIP_EXT, 15) \\\n    _(XR_HAND_JOINT_RING_METACARPAL_EXT, 16) \\\n    _(XR_HAND_JOINT_RING_PROXIMAL_EXT, 17) \\\n    _(XR_HAND_JOINT_RING_INTERMEDIATE_EXT, 18) \\\n    _(XR_HAND_JOINT_RING_DISTAL_EXT, 19) \\\n    _(XR_HAND_JOINT_RING_TIP_EXT, 20) \\\n    _(XR_HAND_JOINT_LITTLE_METACARPAL_EXT, 21) \\\n    _(XR_HAND_JOINT_LITTLE_PROXIMAL_EXT, 22) \\\n    _(XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT, 23) \\\n    _(XR_HAND_JOINT_LITTLE_DISTAL_EXT, 24) \\\n    _(XR_HAND_JOINT_LITTLE_TIP_EXT, 25) \\\n    _(XR_HAND_JOINT_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrHandJointSetEXT(_) \\\n    _(XR_HAND_JOINT_SET_DEFAULT_EXT, 0) \\\n    _(XR_HAND_JOINT_SET_HAND_WITH_FOREARM_ULTRALEAP, 1000149000) \\\n    _(XR_HAND_JOINT_SET_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrHandPoseTypeMSFT(_) \\\n    _(XR_HAND_POSE_TYPE_TRACKED_MSFT, 0) \\\n    _(XR_HAND_POSE_TYPE_REFERENCE_OPEN_PALM_MSFT, 1) \\\n    _(XR_HAND_POSE_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrReprojectionModeMSFT(_) \\\n    _(XR_REPROJECTION_MODE_DEPTH_MSFT, 1) \\\n    _(XR_REPROJECTION_MODE_PLANAR_FROM_DEPTH_MSFT, 2) \\\n    _(XR_REPROJECTION_MODE_PLANAR_MANUAL_MSFT, 3) \\\n    _(XR_REPROJECTION_MODE_ORIENTATION_ONLY_MSFT, 4) \\\n    _(XR_REPROJECTION_MODE_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrBodyJointFB(_) \\\n    _(XR_BODY_JOINT_ROOT_FB, 0) \\\n    _(XR_BODY_JOINT_HIPS_FB, 1) \\\n    _(XR_BODY_JOINT_SPINE_LOWER_FB, 2) \\\n    _(XR_BODY_JOINT_SPINE_MIDDLE_FB, 3) \\\n    _(XR_BODY_JOINT_SPINE_UPPER_FB, 4) \\\n    _(XR_BODY_JOINT_CHEST_FB, 5) \\\n    _(XR_BODY_JOINT_NECK_FB, 6) \\\n    _(XR_BODY_JOINT_HEAD_FB, 7) \\\n    _(XR_BODY_JOINT_LEFT_SHOULDER_FB, 8) \\\n    _(XR_BODY_JOINT_LEFT_SCAPULA_FB, 9) \\\n    _(XR_BODY_JOINT_LEFT_ARM_UPPER_FB, 10) \\\n    _(XR_BODY_JOINT_LEFT_ARM_LOWER_FB, 11) \\\n    _(XR_BODY_JOINT_LEFT_HAND_WRIST_TWIST_FB, 12) \\\n    _(XR_BODY_JOINT_RIGHT_SHOULDER_FB, 13) \\\n    _(XR_BODY_JOINT_RIGHT_SCAPULA_FB, 14) \\\n    _(XR_BODY_JOINT_RIGHT_ARM_UPPER_FB, 15) \\\n    _(XR_BODY_JOINT_RIGHT_ARM_LOWER_FB, 16) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_WRIST_TWIST_FB, 17) \\\n    _(XR_BODY_JOINT_LEFT_HAND_PALM_FB, 18) \\\n    _(XR_BODY_JOINT_LEFT_HAND_WRIST_FB, 19) \\\n    _(XR_BODY_JOINT_LEFT_HAND_THUMB_METACARPAL_FB, 20) \\\n    _(XR_BODY_JOINT_LEFT_HAND_THUMB_PROXIMAL_FB, 21) \\\n    _(XR_BODY_JOINT_LEFT_HAND_THUMB_DISTAL_FB, 22) \\\n    _(XR_BODY_JOINT_LEFT_HAND_THUMB_TIP_FB, 23) \\\n    _(XR_BODY_JOINT_LEFT_HAND_INDEX_METACARPAL_FB, 24) \\\n    _(XR_BODY_JOINT_LEFT_HAND_INDEX_PROXIMAL_FB, 25) \\\n    _(XR_BODY_JOINT_LEFT_HAND_INDEX_INTERMEDIATE_FB, 26) \\\n    _(XR_BODY_JOINT_LEFT_HAND_INDEX_DISTAL_FB, 27) \\\n    _(XR_BODY_JOINT_LEFT_HAND_INDEX_TIP_FB, 28) \\\n    _(XR_BODY_JOINT_LEFT_HAND_MIDDLE_METACARPAL_FB, 29) \\\n    _(XR_BODY_JOINT_LEFT_HAND_MIDDLE_PROXIMAL_FB, 30) \\\n    _(XR_BODY_JOINT_LEFT_HAND_MIDDLE_INTERMEDIATE_FB, 31) \\\n    _(XR_BODY_JOINT_LEFT_HAND_MIDDLE_DISTAL_FB, 32) \\\n    _(XR_BODY_JOINT_LEFT_HAND_MIDDLE_TIP_FB, 33) \\\n    _(XR_BODY_JOINT_LEFT_HAND_RING_METACARPAL_FB, 34) \\\n    _(XR_BODY_JOINT_LEFT_HAND_RING_PROXIMAL_FB, 35) \\\n    _(XR_BODY_JOINT_LEFT_HAND_RING_INTERMEDIATE_FB, 36) \\\n    _(XR_BODY_JOINT_LEFT_HAND_RING_DISTAL_FB, 37) \\\n    _(XR_BODY_JOINT_LEFT_HAND_RING_TIP_FB, 38) \\\n    _(XR_BODY_JOINT_LEFT_HAND_LITTLE_METACARPAL_FB, 39) \\\n    _(XR_BODY_JOINT_LEFT_HAND_LITTLE_PROXIMAL_FB, 40) \\\n    _(XR_BODY_JOINT_LEFT_HAND_LITTLE_INTERMEDIATE_FB, 41) \\\n    _(XR_BODY_JOINT_LEFT_HAND_LITTLE_DISTAL_FB, 42) \\\n    _(XR_BODY_JOINT_LEFT_HAND_LITTLE_TIP_FB, 43) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_PALM_FB, 44) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_WRIST_FB, 45) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_THUMB_METACARPAL_FB, 46) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_THUMB_PROXIMAL_FB, 47) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_THUMB_DISTAL_FB, 48) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_THUMB_TIP_FB, 49) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_INDEX_METACARPAL_FB, 50) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_INDEX_PROXIMAL_FB, 51) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_INDEX_INTERMEDIATE_FB, 52) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_INDEX_DISTAL_FB, 53) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_INDEX_TIP_FB, 54) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_MIDDLE_METACARPAL_FB, 55) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_MIDDLE_PROXIMAL_FB, 56) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_MIDDLE_INTERMEDIATE_FB, 57) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_MIDDLE_DISTAL_FB, 58) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_MIDDLE_TIP_FB, 59) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_RING_METACARPAL_FB, 60) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_RING_PROXIMAL_FB, 61) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_RING_INTERMEDIATE_FB, 62) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_RING_DISTAL_FB, 63) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_RING_TIP_FB, 64) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_LITTLE_METACARPAL_FB, 65) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_LITTLE_PROXIMAL_FB, 66) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_LITTLE_INTERMEDIATE_FB, 67) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_LITTLE_DISTAL_FB, 68) \\\n    _(XR_BODY_JOINT_RIGHT_HAND_LITTLE_TIP_FB, 69) \\\n    _(XR_BODY_JOINT_COUNT_FB, 70) \\\n    _(XR_BODY_JOINT_NONE_FB, -1) \\\n    _(XR_BODY_JOINT_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrBodyJointSetFB(_) \\\n    _(XR_BODY_JOINT_SET_DEFAULT_FB, 0) \\\n    _(XR_BODY_JOINT_SET_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrHandJointsMotionRangeEXT(_) \\\n    _(XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT, 1) \\\n    _(XR_HAND_JOINTS_MOTION_RANGE_CONFORMING_TO_CONTROLLER_EXT, 2) \\\n    _(XR_HAND_JOINTS_MOTION_RANGE_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSceneComputeFeatureMSFT(_) \\\n    _(XR_SCENE_COMPUTE_FEATURE_PLANE_MSFT, 1) \\\n    _(XR_SCENE_COMPUTE_FEATURE_PLANE_MESH_MSFT, 2) \\\n    _(XR_SCENE_COMPUTE_FEATURE_VISUAL_MESH_MSFT, 3) \\\n    _(XR_SCENE_COMPUTE_FEATURE_COLLIDER_MESH_MSFT, 4) \\\n    _(XR_SCENE_COMPUTE_FEATURE_SERIALIZE_SCENE_MSFT, 1000098000) \\\n    _(XR_SCENE_COMPUTE_FEATURE_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSceneComputeConsistencyMSFT(_) \\\n    _(XR_SCENE_COMPUTE_CONSISTENCY_SNAPSHOT_COMPLETE_MSFT, 1) \\\n    _(XR_SCENE_COMPUTE_CONSISTENCY_SNAPSHOT_INCOMPLETE_FAST_MSFT, 2) \\\n    _(XR_SCENE_COMPUTE_CONSISTENCY_OCCLUSION_OPTIMIZED_MSFT, 3) \\\n    _(XR_SCENE_COMPUTE_CONSISTENCY_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrMeshComputeLodMSFT(_) \\\n    _(XR_MESH_COMPUTE_LOD_COARSE_MSFT, 1) \\\n    _(XR_MESH_COMPUTE_LOD_MEDIUM_MSFT, 2) \\\n    _(XR_MESH_COMPUTE_LOD_FINE_MSFT, 3) \\\n    _(XR_MESH_COMPUTE_LOD_UNLIMITED_MSFT, 4) \\\n    _(XR_MESH_COMPUTE_LOD_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSceneComponentTypeMSFT(_) \\\n    _(XR_SCENE_COMPONENT_TYPE_INVALID_MSFT, -1) \\\n    _(XR_SCENE_COMPONENT_TYPE_OBJECT_MSFT, 1) \\\n    _(XR_SCENE_COMPONENT_TYPE_PLANE_MSFT, 2) \\\n    _(XR_SCENE_COMPONENT_TYPE_VISUAL_MESH_MSFT, 3) \\\n    _(XR_SCENE_COMPONENT_TYPE_COLLIDER_MESH_MSFT, 4) \\\n    _(XR_SCENE_COMPONENT_TYPE_SERIALIZED_SCENE_FRAGMENT_MSFT, 1000098000) \\\n    _(XR_SCENE_COMPONENT_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSceneObjectTypeMSFT(_) \\\n    _(XR_SCENE_OBJECT_TYPE_UNCATEGORIZED_MSFT, -1) \\\n    _(XR_SCENE_OBJECT_TYPE_BACKGROUND_MSFT, 1) \\\n    _(XR_SCENE_OBJECT_TYPE_WALL_MSFT, 2) \\\n    _(XR_SCENE_OBJECT_TYPE_FLOOR_MSFT, 3) \\\n    _(XR_SCENE_OBJECT_TYPE_CEILING_MSFT, 4) \\\n    _(XR_SCENE_OBJECT_TYPE_PLATFORM_MSFT, 5) \\\n    _(XR_SCENE_OBJECT_TYPE_INFERRED_MSFT, 6) \\\n    _(XR_SCENE_OBJECT_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrScenePlaneAlignmentTypeMSFT(_) \\\n    _(XR_SCENE_PLANE_ALIGNMENT_TYPE_NON_ORTHOGONAL_MSFT, 0) \\\n    _(XR_SCENE_PLANE_ALIGNMENT_TYPE_HORIZONTAL_MSFT, 1) \\\n    _(XR_SCENE_PLANE_ALIGNMENT_TYPE_VERTICAL_MSFT, 2) \\\n    _(XR_SCENE_PLANE_ALIGNMENT_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSceneComputeStateMSFT(_) \\\n    _(XR_SCENE_COMPUTE_STATE_NONE_MSFT, 0) \\\n    _(XR_SCENE_COMPUTE_STATE_UPDATING_MSFT, 1) \\\n    _(XR_SCENE_COMPUTE_STATE_COMPLETED_MSFT, 2) \\\n    _(XR_SCENE_COMPUTE_STATE_COMPLETED_WITH_ERROR_MSFT, 3) \\\n    _(XR_SCENE_COMPUTE_STATE_MAX_ENUM_MSFT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrEyeExpressionHTC(_) \\\n    _(XR_EYE_EXPRESSION_LEFT_BLINK_HTC, 0) \\\n    _(XR_EYE_EXPRESSION_LEFT_WIDE_HTC, 1) \\\n    _(XR_EYE_EXPRESSION_RIGHT_BLINK_HTC, 2) \\\n    _(XR_EYE_EXPRESSION_RIGHT_WIDE_HTC, 3) \\\n    _(XR_EYE_EXPRESSION_LEFT_SQUEEZE_HTC, 4) \\\n    _(XR_EYE_EXPRESSION_RIGHT_SQUEEZE_HTC, 5) \\\n    _(XR_EYE_EXPRESSION_LEFT_DOWN_HTC, 6) \\\n    _(XR_EYE_EXPRESSION_RIGHT_DOWN_HTC, 7) \\\n    _(XR_EYE_EXPRESSION_LEFT_OUT_HTC, 8) \\\n    _(XR_EYE_EXPRESSION_RIGHT_IN_HTC, 9) \\\n    _(XR_EYE_EXPRESSION_LEFT_IN_HTC, 10) \\\n    _(XR_EYE_EXPRESSION_RIGHT_OUT_HTC, 11) \\\n    _(XR_EYE_EXPRESSION_LEFT_UP_HTC, 12) \\\n    _(XR_EYE_EXPRESSION_RIGHT_UP_HTC, 13) \\\n    _(XR_EYE_EXPRESSION_MAX_ENUM_HTC, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrLipExpressionHTC(_) \\\n    _(XR_LIP_EXPRESSION_JAW_RIGHT_HTC, 0) \\\n    _(XR_LIP_EXPRESSION_JAW_LEFT_HTC, 1) \\\n    _(XR_LIP_EXPRESSION_JAW_FORWARD_HTC, 2) \\\n    _(XR_LIP_EXPRESSION_JAW_OPEN_HTC, 3) \\\n    _(XR_LIP_EXPRESSION_MOUTH_APE_SHAPE_HTC, 4) \\\n    _(XR_LIP_EXPRESSION_MOUTH_UPPER_RIGHT_HTC, 5) \\\n    _(XR_LIP_EXPRESSION_MOUTH_UPPER_LEFT_HTC, 6) \\\n    _(XR_LIP_EXPRESSION_MOUTH_LOWER_RIGHT_HTC, 7) \\\n    _(XR_LIP_EXPRESSION_MOUTH_LOWER_LEFT_HTC, 8) \\\n    _(XR_LIP_EXPRESSION_MOUTH_UPPER_OVERTURN_HTC, 9) \\\n    _(XR_LIP_EXPRESSION_MOUTH_LOWER_OVERTURN_HTC, 10) \\\n    _(XR_LIP_EXPRESSION_MOUTH_POUT_HTC, 11) \\\n    _(XR_LIP_EXPRESSION_MOUTH_SMILE_RIGHT_HTC, 12) \\\n    _(XR_LIP_EXPRESSION_MOUTH_SMILE_LEFT_HTC, 13) \\\n    _(XR_LIP_EXPRESSION_MOUTH_SAD_RIGHT_HTC, 14) \\\n    _(XR_LIP_EXPRESSION_MOUTH_SAD_LEFT_HTC, 15) \\\n    _(XR_LIP_EXPRESSION_CHEEK_PUFF_RIGHT_HTC, 16) \\\n    _(XR_LIP_EXPRESSION_CHEEK_PUFF_LEFT_HTC, 17) \\\n    _(XR_LIP_EXPRESSION_CHEEK_SUCK_HTC, 18) \\\n    _(XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC, 19) \\\n    _(XR_LIP_EXPRESSION_MOUTH_UPPER_UPLEFT_HTC, 20) \\\n    _(XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNRIGHT_HTC, 21) \\\n    _(XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNLEFT_HTC, 22) \\\n    _(XR_LIP_EXPRESSION_MOUTH_UPPER_INSIDE_HTC, 23) \\\n    _(XR_LIP_EXPRESSION_MOUTH_LOWER_INSIDE_HTC, 24) \\\n    _(XR_LIP_EXPRESSION_MOUTH_LOWER_OVERLAY_HTC, 25) \\\n    _(XR_LIP_EXPRESSION_TONGUE_LONGSTEP1_HTC, 26) \\\n    _(XR_LIP_EXPRESSION_TONGUE_LEFT_HTC, 27) \\\n    _(XR_LIP_EXPRESSION_TONGUE_RIGHT_HTC, 28) \\\n    _(XR_LIP_EXPRESSION_TONGUE_UP_HTC, 29) \\\n    _(XR_LIP_EXPRESSION_TONGUE_DOWN_HTC, 30) \\\n    _(XR_LIP_EXPRESSION_TONGUE_ROLL_HTC, 31) \\\n    _(XR_LIP_EXPRESSION_TONGUE_LONGSTEP2_HTC, 32) \\\n    _(XR_LIP_EXPRESSION_TONGUE_UPRIGHT_MORPH_HTC, 33) \\\n    _(XR_LIP_EXPRESSION_TONGUE_UPLEFT_MORPH_HTC, 34) \\\n    _(XR_LIP_EXPRESSION_TONGUE_DOWNRIGHT_MORPH_HTC, 35) \\\n    _(XR_LIP_EXPRESSION_TONGUE_DOWNLEFT_MORPH_HTC, 36) \\\n    _(XR_LIP_EXPRESSION_MAX_ENUM_HTC, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrFacialTrackingTypeHTC(_) \\\n    _(XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC, 1) \\\n    _(XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC, 2) \\\n    _(XR_FACIAL_TRACKING_TYPE_MAX_ENUM_HTC, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrColorSpaceFB(_) \\\n    _(XR_COLOR_SPACE_UNMANAGED_FB, 0) \\\n    _(XR_COLOR_SPACE_REC2020_FB, 1) \\\n    _(XR_COLOR_SPACE_REC709_FB, 2) \\\n    _(XR_COLOR_SPACE_RIFT_CV1_FB, 3) \\\n    _(XR_COLOR_SPACE_RIFT_S_FB, 4) \\\n    _(XR_COLOR_SPACE_QUEST_FB, 5) \\\n    _(XR_COLOR_SPACE_P3_FB, 6) \\\n    _(XR_COLOR_SPACE_ADOBE_RGB_FB, 7) \\\n    _(XR_COLOR_SPACE_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSpaceComponentTypeFB(_) \\\n    _(XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB, 0) \\\n    _(XR_SPACE_COMPONENT_TYPE_STORABLE_FB, 1) \\\n    _(XR_SPACE_COMPONENT_TYPE_SHARABLE_FB, 2) \\\n    _(XR_SPACE_COMPONENT_TYPE_BOUNDED_2D_FB, 3) \\\n    _(XR_SPACE_COMPONENT_TYPE_BOUNDED_3D_FB, 4) \\\n    _(XR_SPACE_COMPONENT_TYPE_SEMANTIC_LABELS_FB, 5) \\\n    _(XR_SPACE_COMPONENT_TYPE_ROOM_LAYOUT_FB, 6) \\\n    _(XR_SPACE_COMPONENT_TYPE_SPACE_CONTAINER_FB, 7) \\\n    _(XR_SPACE_COMPONENT_TYPE_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrFoveationLevelFB(_) \\\n    _(XR_FOVEATION_LEVEL_NONE_FB, 0) \\\n    _(XR_FOVEATION_LEVEL_LOW_FB, 1) \\\n    _(XR_FOVEATION_LEVEL_MEDIUM_FB, 2) \\\n    _(XR_FOVEATION_LEVEL_HIGH_FB, 3) \\\n    _(XR_FOVEATION_LEVEL_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrFoveationDynamicFB(_) \\\n    _(XR_FOVEATION_DYNAMIC_DISABLED_FB, 0) \\\n    _(XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB, 1) \\\n    _(XR_FOVEATION_DYNAMIC_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrWindingOrderFB(_) \\\n    _(XR_WINDING_ORDER_UNKNOWN_FB, 0) \\\n    _(XR_WINDING_ORDER_CW_FB, 1) \\\n    _(XR_WINDING_ORDER_CCW_FB, 2) \\\n    _(XR_WINDING_ORDER_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPassthroughLayerPurposeFB(_) \\\n    _(XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB, 0) \\\n    _(XR_PASSTHROUGH_LAYER_PURPOSE_PROJECTED_FB, 1) \\\n    _(XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS_FB, 1000203001) \\\n    _(XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB, 1000203002) \\\n    _(XR_PASSTHROUGH_LAYER_PURPOSE_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrHandForearmJointULTRALEAP(_) \\\n    _(XR_HAND_FOREARM_JOINT_PALM_ULTRALEAP, 0) \\\n    _(XR_HAND_FOREARM_JOINT_WRIST_ULTRALEAP, 1) \\\n    _(XR_HAND_FOREARM_JOINT_THUMB_METACARPAL_ULTRALEAP, 2) \\\n    _(XR_HAND_FOREARM_JOINT_THUMB_PROXIMAL_ULTRALEAP, 3) \\\n    _(XR_HAND_FOREARM_JOINT_THUMB_DISTAL_ULTRALEAP, 4) \\\n    _(XR_HAND_FOREARM_JOINT_THUMB_TIP_ULTRALEAP, 5) \\\n    _(XR_HAND_FOREARM_JOINT_INDEX_METACARPAL_ULTRALEAP, 6) \\\n    _(XR_HAND_FOREARM_JOINT_INDEX_PROXIMAL_ULTRALEAP, 7) \\\n    _(XR_HAND_FOREARM_JOINT_INDEX_INTERMEDIATE_ULTRALEAP, 8) \\\n    _(XR_HAND_FOREARM_JOINT_INDEX_DISTAL_ULTRALEAP, 9) \\\n    _(XR_HAND_FOREARM_JOINT_INDEX_TIP_ULTRALEAP, 10) \\\n    _(XR_HAND_FOREARM_JOINT_MIDDLE_METACARPAL_ULTRALEAP, 11) \\\n    _(XR_HAND_FOREARM_JOINT_MIDDLE_PROXIMAL_ULTRALEAP, 12) \\\n    _(XR_HAND_FOREARM_JOINT_MIDDLE_INTERMEDIATE_ULTRALEAP, 13) \\\n    _(XR_HAND_FOREARM_JOINT_MIDDLE_DISTAL_ULTRALEAP, 14) \\\n    _(XR_HAND_FOREARM_JOINT_MIDDLE_TIP_ULTRALEAP, 15) \\\n    _(XR_HAND_FOREARM_JOINT_RING_METACARPAL_ULTRALEAP, 16) \\\n    _(XR_HAND_FOREARM_JOINT_RING_PROXIMAL_ULTRALEAP, 17) \\\n    _(XR_HAND_FOREARM_JOINT_RING_INTERMEDIATE_ULTRALEAP, 18) \\\n    _(XR_HAND_FOREARM_JOINT_RING_DISTAL_ULTRALEAP, 19) \\\n    _(XR_HAND_FOREARM_JOINT_RING_TIP_ULTRALEAP, 20) \\\n    _(XR_HAND_FOREARM_JOINT_LITTLE_METACARPAL_ULTRALEAP, 21) \\\n    _(XR_HAND_FOREARM_JOINT_LITTLE_PROXIMAL_ULTRALEAP, 22) \\\n    _(XR_HAND_FOREARM_JOINT_LITTLE_INTERMEDIATE_ULTRALEAP, 23) \\\n    _(XR_HAND_FOREARM_JOINT_LITTLE_DISTAL_ULTRALEAP, 24) \\\n    _(XR_HAND_FOREARM_JOINT_LITTLE_TIP_ULTRALEAP, 25) \\\n    _(XR_HAND_FOREARM_JOINT_ELBOW_ULTRALEAP, 26) \\\n    _(XR_HAND_FOREARM_JOINT_MAX_ENUM_ULTRALEAP, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSpaceQueryActionFB(_) \\\n    _(XR_SPACE_QUERY_ACTION_LOAD_FB, 0) \\\n    _(XR_SPACE_QUERY_ACTION_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSpaceStorageLocationFB(_) \\\n    _(XR_SPACE_STORAGE_LOCATION_INVALID_FB, 0) \\\n    _(XR_SPACE_STORAGE_LOCATION_LOCAL_FB, 1) \\\n    _(XR_SPACE_STORAGE_LOCATION_CLOUD_FB, 2) \\\n    _(XR_SPACE_STORAGE_LOCATION_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrSpacePersistenceModeFB(_) \\\n    _(XR_SPACE_PERSISTENCE_MODE_INVALID_FB, 0) \\\n    _(XR_SPACE_PERSISTENCE_MODE_INDEFINITE_FB, 1) \\\n    _(XR_SPACE_PERSISTENCE_MODE_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrFaceExpressionFB(_) \\\n    _(XR_FACE_EXPRESSION_BROW_LOWERER_L_FB, 0) \\\n    _(XR_FACE_EXPRESSION_BROW_LOWERER_R_FB, 1) \\\n    _(XR_FACE_EXPRESSION_CHEEK_PUFF_L_FB, 2) \\\n    _(XR_FACE_EXPRESSION_CHEEK_PUFF_R_FB, 3) \\\n    _(XR_FACE_EXPRESSION_CHEEK_RAISER_L_FB, 4) \\\n    _(XR_FACE_EXPRESSION_CHEEK_RAISER_R_FB, 5) \\\n    _(XR_FACE_EXPRESSION_CHEEK_SUCK_L_FB, 6) \\\n    _(XR_FACE_EXPRESSION_CHEEK_SUCK_R_FB, 7) \\\n    _(XR_FACE_EXPRESSION_CHIN_RAISER_B_FB, 8) \\\n    _(XR_FACE_EXPRESSION_CHIN_RAISER_T_FB, 9) \\\n    _(XR_FACE_EXPRESSION_DIMPLER_L_FB, 10) \\\n    _(XR_FACE_EXPRESSION_DIMPLER_R_FB, 11) \\\n    _(XR_FACE_EXPRESSION_EYES_CLOSED_L_FB, 12) \\\n    _(XR_FACE_EXPRESSION_EYES_CLOSED_R_FB, 13) \\\n    _(XR_FACE_EXPRESSION_EYES_LOOK_DOWN_L_FB, 14) \\\n    _(XR_FACE_EXPRESSION_EYES_LOOK_DOWN_R_FB, 15) \\\n    _(XR_FACE_EXPRESSION_EYES_LOOK_LEFT_L_FB, 16) \\\n    _(XR_FACE_EXPRESSION_EYES_LOOK_LEFT_R_FB, 17) \\\n    _(XR_FACE_EXPRESSION_EYES_LOOK_RIGHT_L_FB, 18) \\\n    _(XR_FACE_EXPRESSION_EYES_LOOK_RIGHT_R_FB, 19) \\\n    _(XR_FACE_EXPRESSION_EYES_LOOK_UP_L_FB, 20) \\\n    _(XR_FACE_EXPRESSION_EYES_LOOK_UP_R_FB, 21) \\\n    _(XR_FACE_EXPRESSION_INNER_BROW_RAISER_L_FB, 22) \\\n    _(XR_FACE_EXPRESSION_INNER_BROW_RAISER_R_FB, 23) \\\n    _(XR_FACE_EXPRESSION_JAW_DROP_FB, 24) \\\n    _(XR_FACE_EXPRESSION_JAW_SIDEWAYS_LEFT_FB, 25) \\\n    _(XR_FACE_EXPRESSION_JAW_SIDEWAYS_RIGHT_FB, 26) \\\n    _(XR_FACE_EXPRESSION_JAW_THRUST_FB, 27) \\\n    _(XR_FACE_EXPRESSION_LID_TIGHTENER_L_FB, 28) \\\n    _(XR_FACE_EXPRESSION_LID_TIGHTENER_R_FB, 29) \\\n    _(XR_FACE_EXPRESSION_LIP_CORNER_DEPRESSOR_L_FB, 30) \\\n    _(XR_FACE_EXPRESSION_LIP_CORNER_DEPRESSOR_R_FB, 31) \\\n    _(XR_FACE_EXPRESSION_LIP_CORNER_PULLER_L_FB, 32) \\\n    _(XR_FACE_EXPRESSION_LIP_CORNER_PULLER_R_FB, 33) \\\n    _(XR_FACE_EXPRESSION_LIP_FUNNELER_LB_FB, 34) \\\n    _(XR_FACE_EXPRESSION_LIP_FUNNELER_LT_FB, 35) \\\n    _(XR_FACE_EXPRESSION_LIP_FUNNELER_RB_FB, 36) \\\n    _(XR_FACE_EXPRESSION_LIP_FUNNELER_RT_FB, 37) \\\n    _(XR_FACE_EXPRESSION_LIP_PRESSOR_L_FB, 38) \\\n    _(XR_FACE_EXPRESSION_LIP_PRESSOR_R_FB, 39) \\\n    _(XR_FACE_EXPRESSION_LIP_PUCKER_L_FB, 40) \\\n    _(XR_FACE_EXPRESSION_LIP_PUCKER_R_FB, 41) \\\n    _(XR_FACE_EXPRESSION_LIP_STRETCHER_L_FB, 42) \\\n    _(XR_FACE_EXPRESSION_LIP_STRETCHER_R_FB, 43) \\\n    _(XR_FACE_EXPRESSION_LIP_SUCK_LB_FB, 44) \\\n    _(XR_FACE_EXPRESSION_LIP_SUCK_LT_FB, 45) \\\n    _(XR_FACE_EXPRESSION_LIP_SUCK_RB_FB, 46) \\\n    _(XR_FACE_EXPRESSION_LIP_SUCK_RT_FB, 47) \\\n    _(XR_FACE_EXPRESSION_LIP_TIGHTENER_L_FB, 48) \\\n    _(XR_FACE_EXPRESSION_LIP_TIGHTENER_R_FB, 49) \\\n    _(XR_FACE_EXPRESSION_LIPS_TOWARD_FB, 50) \\\n    _(XR_FACE_EXPRESSION_LOWER_LIP_DEPRESSOR_L_FB, 51) \\\n    _(XR_FACE_EXPRESSION_LOWER_LIP_DEPRESSOR_R_FB, 52) \\\n    _(XR_FACE_EXPRESSION_MOUTH_LEFT_FB, 53) \\\n    _(XR_FACE_EXPRESSION_MOUTH_RIGHT_FB, 54) \\\n    _(XR_FACE_EXPRESSION_NOSE_WRINKLER_L_FB, 55) \\\n    _(XR_FACE_EXPRESSION_NOSE_WRINKLER_R_FB, 56) \\\n    _(XR_FACE_EXPRESSION_OUTER_BROW_RAISER_L_FB, 57) \\\n    _(XR_FACE_EXPRESSION_OUTER_BROW_RAISER_R_FB, 58) \\\n    _(XR_FACE_EXPRESSION_UPPER_LID_RAISER_L_FB, 59) \\\n    _(XR_FACE_EXPRESSION_UPPER_LID_RAISER_R_FB, 60) \\\n    _(XR_FACE_EXPRESSION_UPPER_LIP_RAISER_L_FB, 61) \\\n    _(XR_FACE_EXPRESSION_UPPER_LIP_RAISER_R_FB, 62) \\\n    _(XR_FACE_EXPRESSION_COUNT_FB, 63) \\\n    _(XR_FACE_EXPRESSION_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrFaceExpressionSetFB(_) \\\n    _(XR_FACE_EXPRESSION_SET_DEFAULT_FB, 0) \\\n    _(XR_FACE_EXPRESSION_SET_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrFaceConfidenceFB(_) \\\n    _(XR_FACE_CONFIDENCE_LOWER_FACE_FB, 0) \\\n    _(XR_FACE_CONFIDENCE_UPPER_FACE_FB, 1) \\\n    _(XR_FACE_CONFIDENCE_COUNT_FB, 2) \\\n    _(XR_FACE_CONFIDENCE_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrEyePositionFB(_) \\\n    _(XR_EYE_POSITION_LEFT_FB, 0) \\\n    _(XR_EYE_POSITION_RIGHT_FB, 1) \\\n    _(XR_EYE_POSITION_COUNT_FB, 2) \\\n    _(XR_EYE_POSITION_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrCompareOpFB(_) \\\n    _(XR_COMPARE_OP_NEVER_FB, 0) \\\n    _(XR_COMPARE_OP_LESS_FB, 1) \\\n    _(XR_COMPARE_OP_EQUAL_FB, 2) \\\n    _(XR_COMPARE_OP_LESS_OR_EQUAL_FB, 3) \\\n    _(XR_COMPARE_OP_GREATER_FB, 4) \\\n    _(XR_COMPARE_OP_NOT_EQUAL_FB, 5) \\\n    _(XR_COMPARE_OP_GREATER_OR_EQUAL_FB, 6) \\\n    _(XR_COMPARE_OP_ALWAYS_FB, 7) \\\n    _(XR_COMPARE_OPFB_MAX_ENUM_FB, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrLocalDimmingModeMETA(_) \\\n    _(XR_LOCAL_DIMMING_MODE_OFF_META, 0) \\\n    _(XR_LOCAL_DIMMING_MODE_ON_META, 1) \\\n    _(XR_LOCAL_DIMMING_MODE_MAX_ENUM_META, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrVirtualKeyboardLocationTypeMETA(_) \\\n    _(XR_VIRTUAL_KEYBOARD_LOCATION_TYPE_CUSTOM_META, 0) \\\n    _(XR_VIRTUAL_KEYBOARD_LOCATION_TYPE_FAR_META, 1) \\\n    _(XR_VIRTUAL_KEYBOARD_LOCATION_TYPE_DIRECT_META, 2) \\\n    _(XR_VIRTUAL_KEYBOARD_LOCATION_TYPE_MAX_ENUM_META, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrVirtualKeyboardInputSourceMETA(_) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_CONTROLLER_RAY_LEFT_META, 1) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_CONTROLLER_RAY_RIGHT_META, 2) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_HAND_RAY_LEFT_META, 3) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_HAND_RAY_RIGHT_META, 4) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_CONTROLLER_DIRECT_LEFT_META, 5) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_CONTROLLER_DIRECT_RIGHT_META, 6) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_HAND_DIRECT_INDEX_TIP_LEFT_META, 7) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_HAND_DIRECT_INDEX_TIP_RIGHT_META, 8) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_SOURCE_MAX_ENUM_META, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrExternalCameraAttachedToDeviceOCULUS(_) \\\n    _(XR_EXTERNAL_CAMERA_ATTACHED_TO_DEVICE_NONE_OCULUS, 0) \\\n    _(XR_EXTERNAL_CAMERA_ATTACHED_TO_DEVICE_HMD_OCULUS, 1) \\\n    _(XR_EXTERNAL_CAMERA_ATTACHED_TO_DEVICE_LTOUCH_OCULUS, 2) \\\n    _(XR_EXTERNAL_CAMERA_ATTACHED_TO_DEVICE_RTOUCH_OCULUS, 3) \\\n    _(XR_EXTERNAL_CAMERA_ATTACHED_TODEVICE_MAX_ENUM_OCULUS, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPerformanceMetricsCounterUnitMETA(_) \\\n    _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_GENERIC_META, 0) \\\n    _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_PERCENTAGE_META, 1) \\\n    _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_MILLISECONDS_META, 2) \\\n    _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_BYTES_META, 3) \\\n    _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_HERTZ_META, 4) \\\n    _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_MAX_ENUM_META, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPassthroughColorLutChannelsMETA(_) \\\n    _(XR_PASSTHROUGH_COLOR_LUT_CHANNELS_RGB_META, 1) \\\n    _(XR_PASSTHROUGH_COLOR_LUT_CHANNELS_RGBA_META, 2) \\\n    _(XR_PASSTHROUGH_COLOR_LUT_CHANNELS_MAX_ENUM_META, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrTrackingOptimizationSettingsDomainQCOM(_) \\\n    _(XR_TRACKING_OPTIMIZATION_SETTINGS_DOMAIN_ALL_QCOM, 1) \\\n    _(XR_TRACKING_OPTIMIZATION_SETTINGS_DOMAIN_MAX_ENUM_QCOM, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrTrackingOptimizationSettingsHintQCOM(_) \\\n    _(XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_NONE_QCOM, 0) \\\n    _(XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_LONG_RANGE_PRIORIZATION_QCOM, 1) \\\n    _(XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_CLOSE_RANGE_PRIORIZATION_QCOM, 2) \\\n    _(XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_LOW_POWER_PRIORIZATION_QCOM, 3) \\\n    _(XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_HIGH_POWER_PRIORIZATION_QCOM, 4) \\\n    _(XR_TRACKING_OPTIMIZATION_SETTINGS_HINT_MAX_ENUM_QCOM, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPassthroughFormHTC(_) \\\n    _(XR_PASSTHROUGH_FORM_PLANAR_HTC, 0) \\\n    _(XR_PASSTHROUGH_FORM_PROJECTED_HTC, 1) \\\n    _(XR_PASSTHROUGH_FORM_MAX_ENUM_HTC, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrFoveationModeHTC(_) \\\n    _(XR_FOVEATION_MODE_DISABLE_HTC, 0) \\\n    _(XR_FOVEATION_MODE_FIXED_HTC, 1) \\\n    _(XR_FOVEATION_MODE_DYNAMIC_HTC, 2) \\\n    _(XR_FOVEATION_MODE_CUSTOM_HTC, 3) \\\n    _(XR_FOVEATION_MODE_MAX_ENUM_HTC, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrFoveationLevelHTC(_) \\\n    _(XR_FOVEATION_LEVEL_NONE_HTC, 0) \\\n    _(XR_FOVEATION_LEVEL_LOW_HTC, 1) \\\n    _(XR_FOVEATION_LEVEL_MEDIUM_HTC, 2) \\\n    _(XR_FOVEATION_LEVEL_HIGH_HTC, 3) \\\n    _(XR_FOVEATION_LEVEL_MAX_ENUM_HTC, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrForceFeedbackCurlLocationMNDX(_) \\\n    _(XR_FORCE_FEEDBACK_CURL_LOCATION_THUMB_CURL_MNDX, 0) \\\n    _(XR_FORCE_FEEDBACK_CURL_LOCATION_INDEX_CURL_MNDX, 1) \\\n    _(XR_FORCE_FEEDBACK_CURL_LOCATION_MIDDLE_CURL_MNDX, 2) \\\n    _(XR_FORCE_FEEDBACK_CURL_LOCATION_RING_CURL_MNDX, 3) \\\n    _(XR_FORCE_FEEDBACK_CURL_LOCATION_LITTLE_CURL_MNDX, 4) \\\n    _(XR_FORCE_FEEDBACK_CURL_LOCATION_MAX_ENUM_MNDX, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrHandTrackingDataSourceEXT(_) \\\n    _(XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT, 1) \\\n    _(XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT, 2) \\\n    _(XR_HAND_TRACKING_DATA_SOURCE_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPlaneDetectorOrientationEXT(_) \\\n    _(XR_PLANE_DETECTOR_ORIENTATION_HORIZONTAL_UPWARD_EXT, 0) \\\n    _(XR_PLANE_DETECTOR_ORIENTATION_HORIZONTAL_DOWNWARD_EXT, 1) \\\n    _(XR_PLANE_DETECTOR_ORIENTATION_VERTICAL_EXT, 2) \\\n    _(XR_PLANE_DETECTOR_ORIENTATION_ARBITRARY_EXT, 3) \\\n    _(XR_PLANE_DETECTOR_ORIENTATION_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPlaneDetectorSemanticTypeEXT(_) \\\n    _(XR_PLANE_DETECTOR_SEMANTIC_TYPE_UNDEFINED_EXT, 0) \\\n    _(XR_PLANE_DETECTOR_SEMANTIC_TYPE_CEILING_EXT, 1) \\\n    _(XR_PLANE_DETECTOR_SEMANTIC_TYPE_FLOOR_EXT, 2) \\\n    _(XR_PLANE_DETECTOR_SEMANTIC_TYPE_WALL_EXT, 3) \\\n    _(XR_PLANE_DETECTOR_SEMANTIC_TYPE_PLATFORM_EXT, 4) \\\n    _(XR_PLANE_DETECTOR_SEMANTIC_TYPE_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_ENUM_XrPlaneDetectionStateEXT(_) \\\n    _(XR_PLANE_DETECTION_STATE_NONE_EXT, 0) \\\n    _(XR_PLANE_DETECTION_STATE_PENDING_EXT, 1) \\\n    _(XR_PLANE_DETECTION_STATE_DONE_EXT, 2) \\\n    _(XR_PLANE_DETECTION_STATE_ERROR_EXT, 3) \\\n    _(XR_PLANE_DETECTION_STATE_FATAL_EXT, 4) \\\n    _(XR_PLANE_DETECTION_STATE_MAX_ENUM_EXT, 0x7FFFFFFF)\n\n#define XR_LIST_BITS_XrInstanceCreateFlags(_)\n\n#define XR_LIST_BITS_XrSessionCreateFlags(_)\n\n#define XR_LIST_BITS_XrSpaceVelocityFlags(_) \\\n    _(XR_SPACE_VELOCITY_LINEAR_VALID_BIT, 0x00000001) \\\n    _(XR_SPACE_VELOCITY_ANGULAR_VALID_BIT, 0x00000002) \\\n\n#define XR_LIST_BITS_XrSpaceLocationFlags(_) \\\n    _(XR_SPACE_LOCATION_ORIENTATION_VALID_BIT, 0x00000001) \\\n    _(XR_SPACE_LOCATION_POSITION_VALID_BIT, 0x00000002) \\\n    _(XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT, 0x00000004) \\\n    _(XR_SPACE_LOCATION_POSITION_TRACKED_BIT, 0x00000008) \\\n\n#define XR_LIST_BITS_XrSwapchainCreateFlags(_) \\\n    _(XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT, 0x00000001) \\\n    _(XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT, 0x00000002) \\\n\n#define XR_LIST_BITS_XrSwapchainUsageFlags(_) \\\n    _(XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, 0x00000001) \\\n    _(XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0x00000002) \\\n    _(XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT, 0x00000004) \\\n    _(XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT, 0x00000008) \\\n    _(XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT, 0x00000010) \\\n    _(XR_SWAPCHAIN_USAGE_SAMPLED_BIT, 0x00000020) \\\n    _(XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT, 0x00000040) \\\n    _(XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND, 0x00000080) \\\n    _(XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_KHR, XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND) \\\n\n#define XR_LIST_BITS_XrCompositionLayerFlags(_) \\\n    _(XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT, 0x00000001) \\\n    _(XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT, 0x00000002) \\\n    _(XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT, 0x00000004) \\\n\n#define XR_LIST_BITS_XrViewStateFlags(_) \\\n    _(XR_VIEW_STATE_ORIENTATION_VALID_BIT, 0x00000001) \\\n    _(XR_VIEW_STATE_POSITION_VALID_BIT, 0x00000002) \\\n    _(XR_VIEW_STATE_ORIENTATION_TRACKED_BIT, 0x00000004) \\\n    _(XR_VIEW_STATE_POSITION_TRACKED_BIT, 0x00000008) \\\n\n#define XR_LIST_BITS_XrInputSourceLocalizedNameFlags(_) \\\n    _(XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT, 0x00000001) \\\n    _(XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT, 0x00000002) \\\n    _(XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT, 0x00000004) \\\n\n#define XR_LIST_BITS_XrVulkanInstanceCreateFlagsKHR(_)\n\n#define XR_LIST_BITS_XrVulkanDeviceCreateFlagsKHR(_)\n\n#define XR_LIST_BITS_XrDebugUtilsMessageSeverityFlagsEXT(_) \\\n    _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, 0x00000001) \\\n    _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, 0x00000010) \\\n    _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, 0x00000100) \\\n    _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 0x00001000) \\\n\n#define XR_LIST_BITS_XrDebugUtilsMessageTypeFlagsEXT(_) \\\n    _(XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 0x00000001) \\\n    _(XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, 0x00000002) \\\n    _(XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, 0x00000004) \\\n    _(XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT, 0x00000008) \\\n\n#define XR_LIST_BITS_XrOverlaySessionCreateFlagsEXTX(_)\n\n#define XR_LIST_BITS_XrOverlayMainSessionFlagsEXTX(_) \\\n    _(XR_OVERLAY_MAIN_SESSION_ENABLED_COMPOSITION_LAYER_INFO_DEPTH_BIT_EXTX, 0x00000001) \\\n\n#define XR_LIST_BITS_XrCompositionLayerImageLayoutFlagsFB(_) \\\n    _(XR_COMPOSITION_LAYER_IMAGE_LAYOUT_VERTICAL_FLIP_BIT_FB, 0x00000001) \\\n\n#define XR_LIST_BITS_XrAndroidSurfaceSwapchainFlagsFB(_) \\\n    _(XR_ANDROID_SURFACE_SWAPCHAIN_SYNCHRONOUS_BIT_FB, 0x00000001) \\\n    _(XR_ANDROID_SURFACE_SWAPCHAIN_USE_TIMESTAMPS_BIT_FB, 0x00000002) \\\n\n#define XR_LIST_BITS_XrCompositionLayerSecureContentFlagsFB(_) \\\n    _(XR_COMPOSITION_LAYER_SECURE_CONTENT_EXCLUDE_LAYER_BIT_FB, 0x00000001) \\\n    _(XR_COMPOSITION_LAYER_SECURE_CONTENT_REPLACE_LAYER_BIT_FB, 0x00000002) \\\n\n#define XR_LIST_BITS_XrHandTrackingAimFlagsFB(_) \\\n    _(XR_HAND_TRACKING_AIM_COMPUTED_BIT_FB, 0x00000001) \\\n    _(XR_HAND_TRACKING_AIM_VALID_BIT_FB, 0x00000002) \\\n    _(XR_HAND_TRACKING_AIM_INDEX_PINCHING_BIT_FB, 0x00000004) \\\n    _(XR_HAND_TRACKING_AIM_MIDDLE_PINCHING_BIT_FB, 0x00000008) \\\n    _(XR_HAND_TRACKING_AIM_RING_PINCHING_BIT_FB, 0x00000010) \\\n    _(XR_HAND_TRACKING_AIM_LITTLE_PINCHING_BIT_FB, 0x00000020) \\\n    _(XR_HAND_TRACKING_AIM_SYSTEM_GESTURE_BIT_FB, 0x00000040) \\\n    _(XR_HAND_TRACKING_AIM_DOMINANT_HAND_BIT_FB, 0x00000080) \\\n    _(XR_HAND_TRACKING_AIM_MENU_PRESSED_BIT_FB, 0x00000100) \\\n\n#define XR_LIST_BITS_XrSwapchainCreateFoveationFlagsFB(_) \\\n    _(XR_SWAPCHAIN_CREATE_FOVEATION_SCALED_BIN_BIT_FB, 0x00000001) \\\n    _(XR_SWAPCHAIN_CREATE_FOVEATION_FRAGMENT_DENSITY_MAP_BIT_FB, 0x00000002) \\\n\n#define XR_LIST_BITS_XrSwapchainStateFoveationFlagsFB(_)\n\n#define XR_LIST_BITS_XrKeyboardTrackingFlagsFB(_) \\\n    _(XR_KEYBOARD_TRACKING_EXISTS_BIT_FB, 0x00000001) \\\n    _(XR_KEYBOARD_TRACKING_LOCAL_BIT_FB, 0x00000002) \\\n    _(XR_KEYBOARD_TRACKING_REMOTE_BIT_FB, 0x00000004) \\\n    _(XR_KEYBOARD_TRACKING_CONNECTED_BIT_FB, 0x00000008) \\\n\n#define XR_LIST_BITS_XrKeyboardTrackingQueryFlagsFB(_) \\\n    _(XR_KEYBOARD_TRACKING_QUERY_LOCAL_BIT_FB, 0x00000002) \\\n    _(XR_KEYBOARD_TRACKING_QUERY_REMOTE_BIT_FB, 0x00000004) \\\n\n#define XR_LIST_BITS_XrTriangleMeshFlagsFB(_) \\\n    _(XR_TRIANGLE_MESH_MUTABLE_BIT_FB, 0x00000001) \\\n\n#define XR_LIST_BITS_XrPassthroughCapabilityFlagsFB(_) \\\n    _(XR_PASSTHROUGH_CAPABILITY_BIT_FB, 0x00000001) \\\n    _(XR_PASSTHROUGH_CAPABILITY_COLOR_BIT_FB, 0x00000002) \\\n    _(XR_PASSTHROUGH_CAPABILITY_LAYER_DEPTH_BIT_FB, 0x00000004) \\\n\n#define XR_LIST_BITS_XrPassthroughFlagsFB(_) \\\n    _(XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB, 0x00000001) \\\n    _(XR_PASSTHROUGH_LAYER_DEPTH_BIT_FB, 0x00000002) \\\n\n#define XR_LIST_BITS_XrPassthroughStateChangedFlagsFB(_) \\\n    _(XR_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT_FB, 0x00000001) \\\n    _(XR_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT_FB, 0x00000002) \\\n    _(XR_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT_FB, 0x00000004) \\\n    _(XR_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT_FB, 0x00000008) \\\n\n#define XR_LIST_BITS_XrRenderModelFlagsFB(_) \\\n    _(XR_RENDER_MODEL_SUPPORTS_GLTF_2_0_SUBSET_1_BIT_FB, 0x00000001) \\\n    _(XR_RENDER_MODEL_SUPPORTS_GLTF_2_0_SUBSET_2_BIT_FB, 0x00000002) \\\n\n#define XR_LIST_BITS_XrFrameEndInfoFlagsML(_) \\\n    _(XR_FRAME_END_INFO_PROTECTED_BIT_ML, 0x00000001) \\\n    _(XR_FRAME_END_INFO_VIGNETTE_BIT_ML, 0x00000002) \\\n\n#define XR_LIST_BITS_XrGlobalDimmerFrameEndInfoFlagsML(_) \\\n    _(XR_GLOBAL_DIMMER_FRAME_END_INFO_ENABLED_BIT_ML, 0x00000001) \\\n\n#define XR_LIST_BITS_XrCompositionLayerSpaceWarpInfoFlagsFB(_) \\\n    _(XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0x00000001) \\\n\n#define XR_LIST_BITS_XrSemanticLabelsSupportFlagsFB(_) \\\n    _(XR_SEMANTIC_LABELS_SUPPORT_MULTIPLE_SEMANTIC_LABELS_BIT_FB, 0x00000001) \\\n    _(XR_SEMANTIC_LABELS_SUPPORT_ACCEPT_DESK_TO_TABLE_MIGRATION_BIT_FB, 0x00000002) \\\n\n#define XR_LIST_BITS_XrDigitalLensControlFlagsALMALENCE(_) \\\n    _(XR_DIGITAL_LENS_CONTROL_PROCESSING_DISABLE_BIT_ALMALENCE, 0x00000001) \\\n\n#define XR_LIST_BITS_XrFoveationEyeTrackedProfileCreateFlagsMETA(_)\n\n#define XR_LIST_BITS_XrFoveationEyeTrackedStateFlagsMETA(_) \\\n    _(XR_FOVEATION_EYE_TRACKED_STATE_VALID_BIT_META, 0x00000001) \\\n\n#define XR_LIST_BITS_XrCompositionLayerSettingsFlagsFB(_) \\\n    _(XR_COMPOSITION_LAYER_SETTINGS_NORMAL_SUPER_SAMPLING_BIT_FB, 0x00000001) \\\n    _(XR_COMPOSITION_LAYER_SETTINGS_QUALITY_SUPER_SAMPLING_BIT_FB, 0x00000002) \\\n    _(XR_COMPOSITION_LAYER_SETTINGS_NORMAL_SHARPENING_BIT_FB, 0x00000004) \\\n    _(XR_COMPOSITION_LAYER_SETTINGS_QUALITY_SHARPENING_BIT_FB, 0x00000008) \\\n\n#define XR_LIST_BITS_XrVirtualKeyboardInputStateFlagsMETA(_) \\\n    _(XR_VIRTUAL_KEYBOARD_INPUT_STATE_PRESSED_BIT_META, 0x00000001) \\\n\n#define XR_LIST_BITS_XrExternalCameraStatusFlagsOCULUS(_) \\\n    _(XR_EXTERNAL_CAMERA_STATUS_CONNECTED_BIT_OCULUS, 0x00000001) \\\n    _(XR_EXTERNAL_CAMERA_STATUS_CALIBRATING_BIT_OCULUS, 0x00000002) \\\n    _(XR_EXTERNAL_CAMERA_STATUS_CALIBRATION_FAILED_BIT_OCULUS, 0x00000004) \\\n    _(XR_EXTERNAL_CAMERA_STATUS_CALIBRATED_BIT_OCULUS, 0x00000008) \\\n    _(XR_EXTERNAL_CAMERA_STATUS_CAPTURING_BIT_OCULUS, 0x00000010) \\\n\n#define XR_LIST_BITS_XrPerformanceMetricsCounterFlagsMETA(_) \\\n    _(XR_PERFORMANCE_METRICS_COUNTER_ANY_VALUE_VALID_BIT_META, 0x00000001) \\\n    _(XR_PERFORMANCE_METRICS_COUNTER_UINT_VALUE_VALID_BIT_META, 0x00000002) \\\n    _(XR_PERFORMANCE_METRICS_COUNTER_FLOAT_VALUE_VALID_BIT_META, 0x00000004) \\\n\n#define XR_LIST_BITS_XrFoveationDynamicFlagsHTC(_) \\\n    _(XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_BIT_HTC, 0x00000001) \\\n    _(XR_FOVEATION_DYNAMIC_CLEAR_FOV_ENABLED_BIT_HTC, 0x00000002) \\\n    _(XR_FOVEATION_DYNAMIC_FOCAL_CENTER_OFFSET_ENABLED_BIT_HTC, 0x00000004) \\\n\n#define XR_LIST_BITS_XrPlaneDetectionCapabilityFlagsEXT(_) \\\n    _(XR_PLANE_DETECTION_CAPABILITY_PLANE_DETECTION_BIT_EXT, 0x00000001) \\\n    _(XR_PLANE_DETECTION_CAPABILITY_PLANE_HOLES_BIT_EXT, 0x00000002) \\\n    _(XR_PLANE_DETECTION_CAPABILITY_SEMANTIC_CEILING_BIT_EXT, 0x00000004) \\\n    _(XR_PLANE_DETECTION_CAPABILITY_SEMANTIC_FLOOR_BIT_EXT, 0x00000008) \\\n    _(XR_PLANE_DETECTION_CAPABILITY_SEMANTIC_WALL_BIT_EXT, 0x00000010) \\\n    _(XR_PLANE_DETECTION_CAPABILITY_SEMANTIC_PLATFORM_BIT_EXT, 0x00000020) \\\n    _(XR_PLANE_DETECTION_CAPABILITY_ORIENTATION_BIT_EXT, 0x00000040) \\\n\n#define XR_LIST_BITS_XrPlaneDetectorFlagsEXT(_) \\\n    _(XR_PLANE_DETECTOR_ENABLE_CONTOUR_BIT_EXT, 0x00000001) \\\n\n/// Calls your macro with the name of each member of XrApiLayerProperties, in order.\n#define XR_LIST_STRUCT_XrApiLayerProperties(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerName) \\\n    _(specVersion) \\\n    _(layerVersion) \\\n    _(description) \\\n\n/// Calls your macro with the name of each member of XrExtensionProperties, in order.\n#define XR_LIST_STRUCT_XrExtensionProperties(_) \\\n    _(type) \\\n    _(next) \\\n    _(extensionName) \\\n    _(extensionVersion) \\\n\n/// Calls your macro with the name of each member of XrApplicationInfo, in order.\n#define XR_LIST_STRUCT_XrApplicationInfo(_) \\\n    _(applicationName) \\\n    _(applicationVersion) \\\n    _(engineName) \\\n    _(engineVersion) \\\n    _(apiVersion) \\\n\n/// Calls your macro with the name of each member of XrInstanceCreateInfo, in order.\n#define XR_LIST_STRUCT_XrInstanceCreateInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(createFlags) \\\n    _(applicationInfo) \\\n    _(enabledApiLayerCount) \\\n    _(enabledApiLayerNames) \\\n    _(enabledExtensionCount) \\\n    _(enabledExtensionNames) \\\n\n/// Calls your macro with the name of each member of XrInstanceProperties, in order.\n#define XR_LIST_STRUCT_XrInstanceProperties(_) \\\n    _(type) \\\n    _(next) \\\n    _(runtimeVersion) \\\n    _(runtimeName) \\\n\n/// Calls your macro with the name of each member of XrEventDataBuffer, in order.\n#define XR_LIST_STRUCT_XrEventDataBuffer(_) \\\n    _(type) \\\n    _(next) \\\n    _(varying) \\\n\n/// Calls your macro with the name of each member of XrSystemGetInfo, in order.\n#define XR_LIST_STRUCT_XrSystemGetInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(formFactor) \\\n\n/// Calls your macro with the name of each member of XrSystemGraphicsProperties, in order.\n#define XR_LIST_STRUCT_XrSystemGraphicsProperties(_) \\\n    _(maxSwapchainImageHeight) \\\n    _(maxSwapchainImageWidth) \\\n    _(maxLayerCount) \\\n\n/// Calls your macro with the name of each member of XrSystemTrackingProperties, in order.\n#define XR_LIST_STRUCT_XrSystemTrackingProperties(_) \\\n    _(orientationTracking) \\\n    _(positionTracking) \\\n\n/// Calls your macro with the name of each member of XrSystemProperties, in order.\n#define XR_LIST_STRUCT_XrSystemProperties(_) \\\n    _(type) \\\n    _(next) \\\n    _(systemId) \\\n    _(vendorId) \\\n    _(systemName) \\\n    _(graphicsProperties) \\\n    _(trackingProperties) \\\n\n/// Calls your macro with the name of each member of XrSessionCreateInfo, in order.\n#define XR_LIST_STRUCT_XrSessionCreateInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(createFlags) \\\n    _(systemId) \\\n\n/// Calls your macro with the name of each member of XrVector3f, in order.\n#define XR_LIST_STRUCT_XrVector3f(_) \\\n    _(x) \\\n    _(y) \\\n    _(z) \\\n\n/// Calls your macro with the name of each member of XrSpaceVelocity, in order.\n#define XR_LIST_STRUCT_XrSpaceVelocity(_) \\\n    _(type) \\\n    _(next) \\\n    _(velocityFlags) \\\n    _(linearVelocity) \\\n    _(angularVelocity) \\\n\n/// Calls your macro with the name of each member of XrQuaternionf, in order.\n#define XR_LIST_STRUCT_XrQuaternionf(_) \\\n    _(x) \\\n    _(y) \\\n    _(z) \\\n    _(w) \\\n\n/// Calls your macro with the name of each member of XrPosef, in order.\n#define XR_LIST_STRUCT_XrPosef(_) \\\n    _(orientation) \\\n    _(position) \\\n\n/// Calls your macro with the name of each member of XrReferenceSpaceCreateInfo, in order.\n#define XR_LIST_STRUCT_XrReferenceSpaceCreateInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(referenceSpaceType) \\\n    _(poseInReferenceSpace) \\\n\n/// Calls your macro with the name of each member of XrExtent2Df, in order.\n#define XR_LIST_STRUCT_XrExtent2Df(_) \\\n    _(width) \\\n    _(height) \\\n\n/// Calls your macro with the name of each member of XrActionSpaceCreateInfo, in order.\n#define XR_LIST_STRUCT_XrActionSpaceCreateInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(action) \\\n    _(subactionPath) \\\n    _(poseInActionSpace) \\\n\n/// Calls your macro with the name of each member of XrSpaceLocation, in order.\n#define XR_LIST_STRUCT_XrSpaceLocation(_) \\\n    _(type) \\\n    _(next) \\\n    _(locationFlags) \\\n    _(pose) \\\n\n/// Calls your macro with the name of each member of XrViewConfigurationProperties, in order.\n#define XR_LIST_STRUCT_XrViewConfigurationProperties(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewConfigurationType) \\\n    _(fovMutable) \\\n\n/// Calls your macro with the name of each member of XrViewConfigurationView, in order.\n#define XR_LIST_STRUCT_XrViewConfigurationView(_) \\\n    _(type) \\\n    _(next) \\\n    _(recommendedImageRectWidth) \\\n    _(maxImageRectWidth) \\\n    _(recommendedImageRectHeight) \\\n    _(maxImageRectHeight) \\\n    _(recommendedSwapchainSampleCount) \\\n    _(maxSwapchainSampleCount) \\\n\n/// Calls your macro with the name of each member of XrSwapchainCreateInfo, in order.\n#define XR_LIST_STRUCT_XrSwapchainCreateInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(createFlags) \\\n    _(usageFlags) \\\n    _(format) \\\n    _(sampleCount) \\\n    _(width) \\\n    _(height) \\\n    _(faceCount) \\\n    _(arraySize) \\\n    _(mipCount) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageBaseHeader, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageBaseHeader(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageAcquireInfo, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageAcquireInfo(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageWaitInfo, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageWaitInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(timeout) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageReleaseInfo, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageReleaseInfo(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSessionBeginInfo, in order.\n#define XR_LIST_STRUCT_XrSessionBeginInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(primaryViewConfigurationType) \\\n\n/// Calls your macro with the name of each member of XrFrameWaitInfo, in order.\n#define XR_LIST_STRUCT_XrFrameWaitInfo(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrFrameState, in order.\n#define XR_LIST_STRUCT_XrFrameState(_) \\\n    _(type) \\\n    _(next) \\\n    _(predictedDisplayTime) \\\n    _(predictedDisplayPeriod) \\\n    _(shouldRender) \\\n\n/// Calls your macro with the name of each member of XrFrameBeginInfo, in order.\n#define XR_LIST_STRUCT_XrFrameBeginInfo(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerBaseHeader, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerBaseHeader(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n    _(space) \\\n\n/// Calls your macro with the name of each member of XrFrameEndInfo, in order.\n#define XR_LIST_STRUCT_XrFrameEndInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(displayTime) \\\n    _(environmentBlendMode) \\\n    _(layerCount) \\\n    _(layers) \\\n\n/// Calls your macro with the name of each member of XrViewLocateInfo, in order.\n#define XR_LIST_STRUCT_XrViewLocateInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewConfigurationType) \\\n    _(displayTime) \\\n    _(space) \\\n\n/// Calls your macro with the name of each member of XrViewState, in order.\n#define XR_LIST_STRUCT_XrViewState(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewStateFlags) \\\n\n/// Calls your macro with the name of each member of XrFovf, in order.\n#define XR_LIST_STRUCT_XrFovf(_) \\\n    _(angleLeft) \\\n    _(angleRight) \\\n    _(angleUp) \\\n    _(angleDown) \\\n\n/// Calls your macro with the name of each member of XrView, in order.\n#define XR_LIST_STRUCT_XrView(_) \\\n    _(type) \\\n    _(next) \\\n    _(pose) \\\n    _(fov) \\\n\n/// Calls your macro with the name of each member of XrActionSetCreateInfo, in order.\n#define XR_LIST_STRUCT_XrActionSetCreateInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(actionSetName) \\\n    _(localizedActionSetName) \\\n    _(priority) \\\n\n/// Calls your macro with the name of each member of XrActionCreateInfo, in order.\n#define XR_LIST_STRUCT_XrActionCreateInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(actionName) \\\n    _(actionType) \\\n    _(countSubactionPaths) \\\n    _(subactionPaths) \\\n    _(localizedActionName) \\\n\n/// Calls your macro with the name of each member of XrActionSuggestedBinding, in order.\n#define XR_LIST_STRUCT_XrActionSuggestedBinding(_) \\\n    _(action) \\\n    _(binding) \\\n\n/// Calls your macro with the name of each member of XrInteractionProfileSuggestedBinding, in order.\n#define XR_LIST_STRUCT_XrInteractionProfileSuggestedBinding(_) \\\n    _(type) \\\n    _(next) \\\n    _(interactionProfile) \\\n    _(countSuggestedBindings) \\\n    _(suggestedBindings) \\\n\n/// Calls your macro with the name of each member of XrSessionActionSetsAttachInfo, in order.\n#define XR_LIST_STRUCT_XrSessionActionSetsAttachInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(countActionSets) \\\n    _(actionSets) \\\n\n/// Calls your macro with the name of each member of XrInteractionProfileState, in order.\n#define XR_LIST_STRUCT_XrInteractionProfileState(_) \\\n    _(type) \\\n    _(next) \\\n    _(interactionProfile) \\\n\n/// Calls your macro with the name of each member of XrActionStateGetInfo, in order.\n#define XR_LIST_STRUCT_XrActionStateGetInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(action) \\\n    _(subactionPath) \\\n\n/// Calls your macro with the name of each member of XrActionStateBoolean, in order.\n#define XR_LIST_STRUCT_XrActionStateBoolean(_) \\\n    _(type) \\\n    _(next) \\\n    _(currentState) \\\n    _(changedSinceLastSync) \\\n    _(lastChangeTime) \\\n    _(isActive) \\\n\n/// Calls your macro with the name of each member of XrActionStateFloat, in order.\n#define XR_LIST_STRUCT_XrActionStateFloat(_) \\\n    _(type) \\\n    _(next) \\\n    _(currentState) \\\n    _(changedSinceLastSync) \\\n    _(lastChangeTime) \\\n    _(isActive) \\\n\n/// Calls your macro with the name of each member of XrVector2f, in order.\n#define XR_LIST_STRUCT_XrVector2f(_) \\\n    _(x) \\\n    _(y) \\\n\n/// Calls your macro with the name of each member of XrActionStateVector2f, in order.\n#define XR_LIST_STRUCT_XrActionStateVector2f(_) \\\n    _(type) \\\n    _(next) \\\n    _(currentState) \\\n    _(changedSinceLastSync) \\\n    _(lastChangeTime) \\\n    _(isActive) \\\n\n/// Calls your macro with the name of each member of XrActionStatePose, in order.\n#define XR_LIST_STRUCT_XrActionStatePose(_) \\\n    _(type) \\\n    _(next) \\\n    _(isActive) \\\n\n/// Calls your macro with the name of each member of XrActiveActionSet, in order.\n#define XR_LIST_STRUCT_XrActiveActionSet(_) \\\n    _(actionSet) \\\n    _(subactionPath) \\\n\n/// Calls your macro with the name of each member of XrActionsSyncInfo, in order.\n#define XR_LIST_STRUCT_XrActionsSyncInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(countActiveActionSets) \\\n    _(activeActionSets) \\\n\n/// Calls your macro with the name of each member of XrBoundSourcesForActionEnumerateInfo, in order.\n#define XR_LIST_STRUCT_XrBoundSourcesForActionEnumerateInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(action) \\\n\n/// Calls your macro with the name of each member of XrInputSourceLocalizedNameGetInfo, in order.\n#define XR_LIST_STRUCT_XrInputSourceLocalizedNameGetInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(sourcePath) \\\n    _(whichComponents) \\\n\n/// Calls your macro with the name of each member of XrHapticActionInfo, in order.\n#define XR_LIST_STRUCT_XrHapticActionInfo(_) \\\n    _(type) \\\n    _(next) \\\n    _(action) \\\n    _(subactionPath) \\\n\n/// Calls your macro with the name of each member of XrHapticBaseHeader, in order.\n#define XR_LIST_STRUCT_XrHapticBaseHeader(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrBaseInStructure, in order.\n#define XR_LIST_STRUCT_XrBaseInStructure(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrBaseOutStructure, in order.\n#define XR_LIST_STRUCT_XrBaseOutStructure(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrOffset2Di, in order.\n#define XR_LIST_STRUCT_XrOffset2Di(_) \\\n    _(x) \\\n    _(y) \\\n\n/// Calls your macro with the name of each member of XrExtent2Di, in order.\n#define XR_LIST_STRUCT_XrExtent2Di(_) \\\n    _(width) \\\n    _(height) \\\n\n/// Calls your macro with the name of each member of XrRect2Di, in order.\n#define XR_LIST_STRUCT_XrRect2Di(_) \\\n    _(offset) \\\n    _(extent) \\\n\n/// Calls your macro with the name of each member of XrSwapchainSubImage, in order.\n#define XR_LIST_STRUCT_XrSwapchainSubImage(_) \\\n    _(swapchain) \\\n    _(imageRect) \\\n    _(imageArrayIndex) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerProjectionView, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerProjectionView(_) \\\n    _(type) \\\n    _(next) \\\n    _(pose) \\\n    _(fov) \\\n    _(subImage) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerProjection, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerProjection(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n    _(space) \\\n    _(viewCount) \\\n    _(views) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerQuad, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerQuad(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n    _(space) \\\n    _(eyeVisibility) \\\n    _(subImage) \\\n    _(pose) \\\n    _(size) \\\n\n/// Calls your macro with the name of each member of XrEventDataBaseHeader, in order.\n#define XR_LIST_STRUCT_XrEventDataBaseHeader(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrEventDataEventsLost, in order.\n#define XR_LIST_STRUCT_XrEventDataEventsLost(_) \\\n    _(type) \\\n    _(next) \\\n    _(lostEventCount) \\\n\n/// Calls your macro with the name of each member of XrEventDataInstanceLossPending, in order.\n#define XR_LIST_STRUCT_XrEventDataInstanceLossPending(_) \\\n    _(type) \\\n    _(next) \\\n    _(lossTime) \\\n\n/// Calls your macro with the name of each member of XrEventDataSessionStateChanged, in order.\n#define XR_LIST_STRUCT_XrEventDataSessionStateChanged(_) \\\n    _(type) \\\n    _(next) \\\n    _(session) \\\n    _(state) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrEventDataReferenceSpaceChangePending, in order.\n#define XR_LIST_STRUCT_XrEventDataReferenceSpaceChangePending(_) \\\n    _(type) \\\n    _(next) \\\n    _(session) \\\n    _(referenceSpaceType) \\\n    _(changeTime) \\\n    _(poseValid) \\\n    _(poseInPreviousSpace) \\\n\n/// Calls your macro with the name of each member of XrEventDataInteractionProfileChanged, in order.\n#define XR_LIST_STRUCT_XrEventDataInteractionProfileChanged(_) \\\n    _(type) \\\n    _(next) \\\n    _(session) \\\n\n/// Calls your macro with the name of each member of XrHapticVibration, in order.\n#define XR_LIST_STRUCT_XrHapticVibration(_) \\\n    _(type) \\\n    _(next) \\\n    _(duration) \\\n    _(frequency) \\\n    _(amplitude) \\\n\n/// Calls your macro with the name of each member of XrOffset2Df, in order.\n#define XR_LIST_STRUCT_XrOffset2Df(_) \\\n    _(x) \\\n    _(y) \\\n\n/// Calls your macro with the name of each member of XrRect2Df, in order.\n#define XR_LIST_STRUCT_XrRect2Df(_) \\\n    _(offset) \\\n    _(extent) \\\n\n/// Calls your macro with the name of each member of XrVector4f, in order.\n#define XR_LIST_STRUCT_XrVector4f(_) \\\n    _(x) \\\n    _(y) \\\n    _(z) \\\n    _(w) \\\n\n/// Calls your macro with the name of each member of XrColor4f, in order.\n#define XR_LIST_STRUCT_XrColor4f(_) \\\n    _(r) \\\n    _(g) \\\n    _(b) \\\n    _(a) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerCubeKHR, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerCubeKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n    _(space) \\\n    _(eyeVisibility) \\\n    _(swapchain) \\\n    _(imageArrayIndex) \\\n    _(orientation) \\\n\n/// Calls your macro with the name of each member of XrInstanceCreateInfoAndroidKHR, in order.\n#define XR_LIST_STRUCT_XrInstanceCreateInfoAndroidKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(applicationVM) \\\n    _(applicationActivity) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerDepthInfoKHR, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerDepthInfoKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(subImage) \\\n    _(minDepth) \\\n    _(maxDepth) \\\n    _(nearZ) \\\n    _(farZ) \\\n\n/// Calls your macro with the name of each member of XrVulkanSwapchainFormatListCreateInfoKHR, in order.\n#define XR_LIST_STRUCT_XrVulkanSwapchainFormatListCreateInfoKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewFormatCount) \\\n    _(viewFormats) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerCylinderKHR, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerCylinderKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n    _(space) \\\n    _(eyeVisibility) \\\n    _(subImage) \\\n    _(pose) \\\n    _(radius) \\\n    _(centralAngle) \\\n    _(aspectRatio) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerEquirectKHR, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerEquirectKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n    _(space) \\\n    _(eyeVisibility) \\\n    _(subImage) \\\n    _(pose) \\\n    _(radius) \\\n    _(scale) \\\n    _(bias) \\\n\n/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLWin32KHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWin32KHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(hDC) \\\n    _(hGLRC) \\\n\n/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLXlibKHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXlibKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(xDisplay) \\\n    _(visualid) \\\n    _(glxFBConfig) \\\n    _(glxDrawable) \\\n    _(glxContext) \\\n\n/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLXcbKHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXcbKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(connection) \\\n    _(screenNumber) \\\n    _(fbconfigid) \\\n    _(visualid) \\\n    _(glxDrawable) \\\n    _(glxContext) \\\n\n/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLWaylandKHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWaylandKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(display) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageOpenGLKHR, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageOpenGLKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(image) \\\n\n/// Calls your macro with the name of each member of XrGraphicsRequirementsOpenGLKHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(minApiVersionSupported) \\\n    _(maxApiVersionSupported) \\\n\n/// Calls your macro with the name of each member of XrGraphicsBindingOpenGLESAndroidKHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLESAndroidKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(display) \\\n    _(config) \\\n    _(context) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageOpenGLESKHR, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageOpenGLESKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(image) \\\n\n/// Calls your macro with the name of each member of XrGraphicsRequirementsOpenGLESKHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLESKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(minApiVersionSupported) \\\n    _(maxApiVersionSupported) \\\n\n/// Calls your macro with the name of each member of XrGraphicsBindingVulkanKHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsBindingVulkanKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(instance) \\\n    _(physicalDevice) \\\n    _(device) \\\n    _(queueFamilyIndex) \\\n    _(queueIndex) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageVulkanKHR, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageVulkanKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(image) \\\n\n/// Calls your macro with the name of each member of XrGraphicsRequirementsVulkanKHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsRequirementsVulkanKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(minApiVersionSupported) \\\n    _(maxApiVersionSupported) \\\n\n/// Calls your macro with the name of each member of XrGraphicsBindingD3D11KHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsBindingD3D11KHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(device) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageD3D11KHR, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageD3D11KHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(texture) \\\n\n/// Calls your macro with the name of each member of XrGraphicsRequirementsD3D11KHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsRequirementsD3D11KHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(adapterLuid) \\\n    _(minFeatureLevel) \\\n\n/// Calls your macro with the name of each member of XrGraphicsBindingD3D12KHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsBindingD3D12KHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(device) \\\n    _(queue) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageD3D12KHR, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageD3D12KHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(texture) \\\n\n/// Calls your macro with the name of each member of XrGraphicsRequirementsD3D12KHR, in order.\n#define XR_LIST_STRUCT_XrGraphicsRequirementsD3D12KHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(adapterLuid) \\\n    _(minFeatureLevel) \\\n\n/// Calls your macro with the name of each member of XrVisibilityMaskKHR, in order.\n#define XR_LIST_STRUCT_XrVisibilityMaskKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(vertexCapacityInput) \\\n    _(vertexCountOutput) \\\n    _(vertices) \\\n    _(indexCapacityInput) \\\n    _(indexCountOutput) \\\n    _(indices) \\\n\n/// Calls your macro with the name of each member of XrEventDataVisibilityMaskChangedKHR, in order.\n#define XR_LIST_STRUCT_XrEventDataVisibilityMaskChangedKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(session) \\\n    _(viewConfigurationType) \\\n    _(viewIndex) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerColorScaleBiasKHR, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerColorScaleBiasKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(colorScale) \\\n    _(colorBias) \\\n\n/// Calls your macro with the name of each member of XrLoaderInitInfoBaseHeaderKHR, in order.\n#define XR_LIST_STRUCT_XrLoaderInitInfoBaseHeaderKHR(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrLoaderInitInfoAndroidKHR, in order.\n#define XR_LIST_STRUCT_XrLoaderInitInfoAndroidKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(applicationVM) \\\n    _(applicationContext) \\\n\n/// Calls your macro with the name of each member of XrVulkanInstanceCreateInfoKHR, in order.\n#define XR_LIST_STRUCT_XrVulkanInstanceCreateInfoKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(systemId) \\\n    _(createFlags) \\\n    _(pfnGetInstanceProcAddr) \\\n    _(vulkanCreateInfo) \\\n    _(vulkanAllocator) \\\n\n/// Calls your macro with the name of each member of XrVulkanDeviceCreateInfoKHR, in order.\n#define XR_LIST_STRUCT_XrVulkanDeviceCreateInfoKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(systemId) \\\n    _(createFlags) \\\n    _(pfnGetInstanceProcAddr) \\\n    _(vulkanPhysicalDevice) \\\n    _(vulkanCreateInfo) \\\n    _(vulkanAllocator) \\\n\n/// Calls your macro with the name of each member of XrVulkanGraphicsDeviceGetInfoKHR, in order.\n#define XR_LIST_STRUCT_XrVulkanGraphicsDeviceGetInfoKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(systemId) \\\n    _(vulkanInstance) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerEquirect2KHR, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerEquirect2KHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n    _(space) \\\n    _(eyeVisibility) \\\n    _(subImage) \\\n    _(pose) \\\n    _(radius) \\\n    _(centralHorizontalAngle) \\\n    _(upperVerticalAngle) \\\n    _(lowerVerticalAngle) \\\n\n/// Calls your macro with the name of each member of XrBindingModificationBaseHeaderKHR, in order.\n#define XR_LIST_STRUCT_XrBindingModificationBaseHeaderKHR(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrBindingModificationsKHR, in order.\n#define XR_LIST_STRUCT_XrBindingModificationsKHR(_) \\\n    _(type) \\\n    _(next) \\\n    _(bindingModificationCount) \\\n    _(bindingModifications) \\\n\n/// Calls your macro with the name of each member of XrEventDataPerfSettingsEXT, in order.\n#define XR_LIST_STRUCT_XrEventDataPerfSettingsEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(domain) \\\n    _(subDomain) \\\n    _(fromLevel) \\\n    _(toLevel) \\\n\n/// Calls your macro with the name of each member of XrDebugUtilsObjectNameInfoEXT, in order.\n#define XR_LIST_STRUCT_XrDebugUtilsObjectNameInfoEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(objectType) \\\n    _(objectHandle) \\\n    _(objectName) \\\n\n/// Calls your macro with the name of each member of XrDebugUtilsLabelEXT, in order.\n#define XR_LIST_STRUCT_XrDebugUtilsLabelEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(labelName) \\\n\n/// Calls your macro with the name of each member of XrDebugUtilsMessengerCallbackDataEXT, in order.\n#define XR_LIST_STRUCT_XrDebugUtilsMessengerCallbackDataEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(messageId) \\\n    _(functionName) \\\n    _(message) \\\n    _(objectCount) \\\n    _(objects) \\\n    _(sessionLabelCount) \\\n    _(sessionLabels) \\\n\n/// Calls your macro with the name of each member of XrDebugUtilsMessengerCreateInfoEXT, in order.\n#define XR_LIST_STRUCT_XrDebugUtilsMessengerCreateInfoEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(messageSeverities) \\\n    _(messageTypes) \\\n    _(userCallback) \\\n    _(userData) \\\n\n/// Calls your macro with the name of each member of XrSystemEyeGazeInteractionPropertiesEXT, in order.\n#define XR_LIST_STRUCT_XrSystemEyeGazeInteractionPropertiesEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsEyeGazeInteraction) \\\n\n/// Calls your macro with the name of each member of XrEyeGazeSampleTimeEXT, in order.\n#define XR_LIST_STRUCT_XrEyeGazeSampleTimeEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrSessionCreateInfoOverlayEXTX, in order.\n#define XR_LIST_STRUCT_XrSessionCreateInfoOverlayEXTX(_) \\\n    _(type) \\\n    _(next) \\\n    _(createFlags) \\\n    _(sessionLayersPlacement) \\\n\n/// Calls your macro with the name of each member of XrEventDataMainSessionVisibilityChangedEXTX, in order.\n#define XR_LIST_STRUCT_XrEventDataMainSessionVisibilityChangedEXTX(_) \\\n    _(type) \\\n    _(next) \\\n    _(visible) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrSpatialAnchorCreateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSpatialAnchorCreateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(space) \\\n    _(pose) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrSpatialAnchorSpaceCreateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSpatialAnchorSpaceCreateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(anchor) \\\n    _(poseInAnchorSpace) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerImageLayoutFB, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerImageLayoutFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerAlphaBlendFB, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerAlphaBlendFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(srcFactorColor) \\\n    _(dstFactorColor) \\\n    _(srcFactorAlpha) \\\n    _(dstFactorAlpha) \\\n\n/// Calls your macro with the name of each member of XrViewConfigurationDepthRangeEXT, in order.\n#define XR_LIST_STRUCT_XrViewConfigurationDepthRangeEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(recommendedNearZ) \\\n    _(minNearZ) \\\n    _(recommendedFarZ) \\\n    _(maxFarZ) \\\n\n/// Calls your macro with the name of each member of XrGraphicsBindingEGLMNDX, in order.\n#define XR_LIST_STRUCT_XrGraphicsBindingEGLMNDX(_) \\\n    _(type) \\\n    _(next) \\\n    _(getProcAddress) \\\n    _(display) \\\n    _(config) \\\n    _(context) \\\n\n/// Calls your macro with the name of each member of XrSpatialGraphNodeSpaceCreateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSpatialGraphNodeSpaceCreateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(nodeType) \\\n    _(nodeId) \\\n    _(pose) \\\n\n/// Calls your macro with the name of each member of XrSpatialGraphStaticNodeBindingCreateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSpatialGraphStaticNodeBindingCreateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(space) \\\n    _(poseInSpace) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrSpatialGraphNodeBindingPropertiesGetInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSpatialGraphNodeBindingPropertiesGetInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSpatialGraphNodeBindingPropertiesMSFT, in order.\n#define XR_LIST_STRUCT_XrSpatialGraphNodeBindingPropertiesMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(nodeId) \\\n    _(poseInNodeSpace) \\\n\n/// Calls your macro with the name of each member of XrSystemHandTrackingPropertiesEXT, in order.\n#define XR_LIST_STRUCT_XrSystemHandTrackingPropertiesEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsHandTracking) \\\n\n/// Calls your macro with the name of each member of XrHandTrackerCreateInfoEXT, in order.\n#define XR_LIST_STRUCT_XrHandTrackerCreateInfoEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(hand) \\\n    _(handJointSet) \\\n\n/// Calls your macro with the name of each member of XrHandJointsLocateInfoEXT, in order.\n#define XR_LIST_STRUCT_XrHandJointsLocateInfoEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(baseSpace) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrHandJointLocationEXT, in order.\n#define XR_LIST_STRUCT_XrHandJointLocationEXT(_) \\\n    _(locationFlags) \\\n    _(pose) \\\n    _(radius) \\\n\n/// Calls your macro with the name of each member of XrHandJointVelocityEXT, in order.\n#define XR_LIST_STRUCT_XrHandJointVelocityEXT(_) \\\n    _(velocityFlags) \\\n    _(linearVelocity) \\\n    _(angularVelocity) \\\n\n/// Calls your macro with the name of each member of XrHandJointLocationsEXT, in order.\n#define XR_LIST_STRUCT_XrHandJointLocationsEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(isActive) \\\n    _(jointCount) \\\n    _(jointLocations) \\\n\n/// Calls your macro with the name of each member of XrHandJointVelocitiesEXT, in order.\n#define XR_LIST_STRUCT_XrHandJointVelocitiesEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(jointCount) \\\n    _(jointVelocities) \\\n\n/// Calls your macro with the name of each member of XrSystemHandTrackingMeshPropertiesMSFT, in order.\n#define XR_LIST_STRUCT_XrSystemHandTrackingMeshPropertiesMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsHandTrackingMesh) \\\n    _(maxHandMeshIndexCount) \\\n    _(maxHandMeshVertexCount) \\\n\n/// Calls your macro with the name of each member of XrHandMeshSpaceCreateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrHandMeshSpaceCreateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(handPoseType) \\\n    _(poseInHandMeshSpace) \\\n\n/// Calls your macro with the name of each member of XrHandMeshUpdateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrHandMeshUpdateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(time) \\\n    _(handPoseType) \\\n\n/// Calls your macro with the name of each member of XrHandMeshIndexBufferMSFT, in order.\n#define XR_LIST_STRUCT_XrHandMeshIndexBufferMSFT(_) \\\n    _(indexBufferKey) \\\n    _(indexCapacityInput) \\\n    _(indexCountOutput) \\\n    _(indices) \\\n\n/// Calls your macro with the name of each member of XrHandMeshVertexMSFT, in order.\n#define XR_LIST_STRUCT_XrHandMeshVertexMSFT(_) \\\n    _(position) \\\n    _(normal) \\\n\n/// Calls your macro with the name of each member of XrHandMeshVertexBufferMSFT, in order.\n#define XR_LIST_STRUCT_XrHandMeshVertexBufferMSFT(_) \\\n    _(vertexUpdateTime) \\\n    _(vertexCapacityInput) \\\n    _(vertexCountOutput) \\\n    _(vertices) \\\n\n/// Calls your macro with the name of each member of XrHandMeshMSFT, in order.\n#define XR_LIST_STRUCT_XrHandMeshMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(isActive) \\\n    _(indexBufferChanged) \\\n    _(vertexBufferChanged) \\\n    _(indexBuffer) \\\n    _(vertexBuffer) \\\n\n/// Calls your macro with the name of each member of XrHandPoseTypeInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrHandPoseTypeInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(handPoseType) \\\n\n/// Calls your macro with the name of each member of XrSecondaryViewConfigurationSessionBeginInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSecondaryViewConfigurationSessionBeginInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewConfigurationCount) \\\n    _(enabledViewConfigurationTypes) \\\n\n/// Calls your macro with the name of each member of XrSecondaryViewConfigurationStateMSFT, in order.\n#define XR_LIST_STRUCT_XrSecondaryViewConfigurationStateMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewConfigurationType) \\\n    _(active) \\\n\n/// Calls your macro with the name of each member of XrSecondaryViewConfigurationFrameStateMSFT, in order.\n#define XR_LIST_STRUCT_XrSecondaryViewConfigurationFrameStateMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewConfigurationCount) \\\n    _(viewConfigurationStates) \\\n\n/// Calls your macro with the name of each member of XrSecondaryViewConfigurationLayerInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSecondaryViewConfigurationLayerInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewConfigurationType) \\\n    _(environmentBlendMode) \\\n    _(layerCount) \\\n    _(layers) \\\n\n/// Calls your macro with the name of each member of XrSecondaryViewConfigurationFrameEndInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSecondaryViewConfigurationFrameEndInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewConfigurationCount) \\\n    _(viewConfigurationLayersInfo) \\\n\n/// Calls your macro with the name of each member of XrSecondaryViewConfigurationSwapchainCreateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSecondaryViewConfigurationSwapchainCreateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(viewConfigurationType) \\\n\n/// Calls your macro with the name of each member of XrControllerModelKeyStateMSFT, in order.\n#define XR_LIST_STRUCT_XrControllerModelKeyStateMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(modelKey) \\\n\n/// Calls your macro with the name of each member of XrControllerModelNodePropertiesMSFT, in order.\n#define XR_LIST_STRUCT_XrControllerModelNodePropertiesMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(parentNodeName) \\\n    _(nodeName) \\\n\n/// Calls your macro with the name of each member of XrControllerModelPropertiesMSFT, in order.\n#define XR_LIST_STRUCT_XrControllerModelPropertiesMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(nodeCapacityInput) \\\n    _(nodeCountOutput) \\\n    _(nodeProperties) \\\n\n/// Calls your macro with the name of each member of XrControllerModelNodeStateMSFT, in order.\n#define XR_LIST_STRUCT_XrControllerModelNodeStateMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(nodePose) \\\n\n/// Calls your macro with the name of each member of XrControllerModelStateMSFT, in order.\n#define XR_LIST_STRUCT_XrControllerModelStateMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(nodeCapacityInput) \\\n    _(nodeCountOutput) \\\n    _(nodeStates) \\\n\n/// Calls your macro with the name of each member of XrViewConfigurationViewFovEPIC, in order.\n#define XR_LIST_STRUCT_XrViewConfigurationViewFovEPIC(_) \\\n    _(type) \\\n    _(next) \\\n    _(recommendedFov) \\\n    _(maxMutableFov) \\\n\n/// Calls your macro with the name of each member of XrHolographicWindowAttachmentMSFT, in order.\n#define XR_LIST_STRUCT_XrHolographicWindowAttachmentMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(holographicSpace) \\\n    _(coreWindow) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerReprojectionInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerReprojectionInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(reprojectionMode) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerReprojectionPlaneOverrideMSFT, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerReprojectionPlaneOverrideMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(position) \\\n    _(normal) \\\n    _(velocity) \\\n\n/// Calls your macro with the name of each member of XrAndroidSurfaceSwapchainCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrAndroidSurfaceSwapchainCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(createFlags) \\\n\n/// Calls your macro with the name of each member of XrSwapchainStateBaseHeaderFB, in order.\n#define XR_LIST_STRUCT_XrSwapchainStateBaseHeaderFB(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerSecureContentFB, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerSecureContentFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrBodyJointLocationFB, in order.\n#define XR_LIST_STRUCT_XrBodyJointLocationFB(_) \\\n    _(locationFlags) \\\n    _(pose) \\\n\n/// Calls your macro with the name of each member of XrSystemBodyTrackingPropertiesFB, in order.\n#define XR_LIST_STRUCT_XrSystemBodyTrackingPropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsBodyTracking) \\\n\n/// Calls your macro with the name of each member of XrBodyTrackerCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrBodyTrackerCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(bodyJointSet) \\\n\n/// Calls your macro with the name of each member of XrBodySkeletonJointFB, in order.\n#define XR_LIST_STRUCT_XrBodySkeletonJointFB(_) \\\n    _(joint) \\\n    _(parentJoint) \\\n    _(pose) \\\n\n/// Calls your macro with the name of each member of XrBodySkeletonFB, in order.\n#define XR_LIST_STRUCT_XrBodySkeletonFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(jointCount) \\\n    _(joints) \\\n\n/// Calls your macro with the name of each member of XrBodyJointsLocateInfoFB, in order.\n#define XR_LIST_STRUCT_XrBodyJointsLocateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(baseSpace) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrBodyJointLocationsFB, in order.\n#define XR_LIST_STRUCT_XrBodyJointLocationsFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(isActive) \\\n    _(confidence) \\\n    _(jointCount) \\\n    _(jointLocations) \\\n    _(skeletonChangedCount) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrInteractionProfileDpadBindingEXT, in order.\n#define XR_LIST_STRUCT_XrInteractionProfileDpadBindingEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(binding) \\\n    _(actionSet) \\\n    _(forceThreshold) \\\n    _(forceThresholdReleased) \\\n    _(centerRegion) \\\n    _(wedgeAngle) \\\n    _(isSticky) \\\n    _(onHaptic) \\\n    _(offHaptic) \\\n\n/// Calls your macro with the name of each member of XrInteractionProfileAnalogThresholdVALVE, in order.\n#define XR_LIST_STRUCT_XrInteractionProfileAnalogThresholdVALVE(_) \\\n    _(type) \\\n    _(next) \\\n    _(action) \\\n    _(binding) \\\n    _(onThreshold) \\\n    _(offThreshold) \\\n    _(onHaptic) \\\n    _(offHaptic) \\\n\n/// Calls your macro with the name of each member of XrHandJointsMotionRangeInfoEXT, in order.\n#define XR_LIST_STRUCT_XrHandJointsMotionRangeInfoEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(handJointsMotionRange) \\\n\n/// Calls your macro with the name of each member of XrUuidMSFT, in order.\n#define XR_LIST_STRUCT_XrUuidMSFT(_) \\\n    _(bytes) \\\n\n/// Calls your macro with the name of each member of XrSceneObserverCreateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneObserverCreateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSceneCreateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneCreateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSceneSphereBoundMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneSphereBoundMSFT(_) \\\n    _(center) \\\n    _(radius) \\\n\n/// Calls your macro with the name of each member of XrSceneOrientedBoxBoundMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneOrientedBoxBoundMSFT(_) \\\n    _(pose) \\\n    _(extents) \\\n\n/// Calls your macro with the name of each member of XrSceneFrustumBoundMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneFrustumBoundMSFT(_) \\\n    _(pose) \\\n    _(fov) \\\n    _(farDistance) \\\n\n/// Calls your macro with the name of each member of XrSceneBoundsMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneBoundsMSFT(_) \\\n    _(space) \\\n    _(time) \\\n    _(sphereCount) \\\n    _(spheres) \\\n    _(boxCount) \\\n    _(boxes) \\\n    _(frustumCount) \\\n    _(frustums) \\\n\n/// Calls your macro with the name of each member of XrNewSceneComputeInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrNewSceneComputeInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestedFeatureCount) \\\n    _(requestedFeatures) \\\n    _(consistency) \\\n    _(bounds) \\\n\n/// Calls your macro with the name of each member of XrVisualMeshComputeLodInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrVisualMeshComputeLodInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(lod) \\\n\n/// Calls your macro with the name of each member of XrSceneComponentMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneComponentMSFT(_) \\\n    _(componentType) \\\n    _(id) \\\n    _(parentId) \\\n    _(updateTime) \\\n\n/// Calls your macro with the name of each member of XrSceneComponentsMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneComponentsMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(componentCapacityInput) \\\n    _(componentCountOutput) \\\n    _(components) \\\n\n/// Calls your macro with the name of each member of XrSceneComponentsGetInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneComponentsGetInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(componentType) \\\n\n/// Calls your macro with the name of each member of XrSceneComponentLocationMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneComponentLocationMSFT(_) \\\n    _(flags) \\\n    _(pose) \\\n\n/// Calls your macro with the name of each member of XrSceneComponentLocationsMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneComponentLocationsMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(locationCount) \\\n    _(locations) \\\n\n/// Calls your macro with the name of each member of XrSceneComponentsLocateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneComponentsLocateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(baseSpace) \\\n    _(time) \\\n    _(componentIdCount) \\\n    _(componentIds) \\\n\n/// Calls your macro with the name of each member of XrSceneObjectMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneObjectMSFT(_) \\\n    _(objectType) \\\n\n/// Calls your macro with the name of each member of XrSceneObjectsMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneObjectsMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(sceneObjectCount) \\\n    _(sceneObjects) \\\n\n/// Calls your macro with the name of each member of XrSceneComponentParentFilterInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneComponentParentFilterInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(parentId) \\\n\n/// Calls your macro with the name of each member of XrSceneObjectTypesFilterInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneObjectTypesFilterInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(objectTypeCount) \\\n    _(objectTypes) \\\n\n/// Calls your macro with the name of each member of XrScenePlaneMSFT, in order.\n#define XR_LIST_STRUCT_XrScenePlaneMSFT(_) \\\n    _(alignment) \\\n    _(size) \\\n    _(meshBufferId) \\\n    _(supportsIndicesUint16) \\\n\n/// Calls your macro with the name of each member of XrScenePlanesMSFT, in order.\n#define XR_LIST_STRUCT_XrScenePlanesMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(scenePlaneCount) \\\n    _(scenePlanes) \\\n\n/// Calls your macro with the name of each member of XrScenePlaneAlignmentFilterInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrScenePlaneAlignmentFilterInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(alignmentCount) \\\n    _(alignments) \\\n\n/// Calls your macro with the name of each member of XrSceneMeshMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneMeshMSFT(_) \\\n    _(meshBufferId) \\\n    _(supportsIndicesUint16) \\\n\n/// Calls your macro with the name of each member of XrSceneMeshesMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneMeshesMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(sceneMeshCount) \\\n    _(sceneMeshes) \\\n\n/// Calls your macro with the name of each member of XrSceneMeshBuffersGetInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneMeshBuffersGetInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(meshBufferId) \\\n\n/// Calls your macro with the name of each member of XrSceneMeshBuffersMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneMeshBuffersMSFT(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSceneMeshVertexBufferMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneMeshVertexBufferMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(vertexCapacityInput) \\\n    _(vertexCountOutput) \\\n    _(vertices) \\\n\n/// Calls your macro with the name of each member of XrSceneMeshIndicesUint32MSFT, in order.\n#define XR_LIST_STRUCT_XrSceneMeshIndicesUint32MSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(indexCapacityInput) \\\n    _(indexCountOutput) \\\n    _(indices) \\\n\n/// Calls your macro with the name of each member of XrSceneMeshIndicesUint16MSFT, in order.\n#define XR_LIST_STRUCT_XrSceneMeshIndicesUint16MSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(indexCapacityInput) \\\n    _(indexCountOutput) \\\n    _(indices) \\\n\n/// Calls your macro with the name of each member of XrSerializedSceneFragmentDataGetInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSerializedSceneFragmentDataGetInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(sceneFragmentId) \\\n\n/// Calls your macro with the name of each member of XrDeserializeSceneFragmentMSFT, in order.\n#define XR_LIST_STRUCT_XrDeserializeSceneFragmentMSFT(_) \\\n    _(bufferSize) \\\n    _(buffer) \\\n\n/// Calls your macro with the name of each member of XrSceneDeserializeInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSceneDeserializeInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(fragmentCount) \\\n    _(fragments) \\\n\n/// Calls your macro with the name of each member of XrEventDataDisplayRefreshRateChangedFB, in order.\n#define XR_LIST_STRUCT_XrEventDataDisplayRefreshRateChangedFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(fromDisplayRefreshRate) \\\n    _(toDisplayRefreshRate) \\\n\n/// Calls your macro with the name of each member of XrViveTrackerPathsHTCX, in order.\n#define XR_LIST_STRUCT_XrViveTrackerPathsHTCX(_) \\\n    _(type) \\\n    _(next) \\\n    _(persistentPath) \\\n    _(rolePath) \\\n\n/// Calls your macro with the name of each member of XrEventDataViveTrackerConnectedHTCX, in order.\n#define XR_LIST_STRUCT_XrEventDataViveTrackerConnectedHTCX(_) \\\n    _(type) \\\n    _(next) \\\n    _(paths) \\\n\n/// Calls your macro with the name of each member of XrSystemFacialTrackingPropertiesHTC, in order.\n#define XR_LIST_STRUCT_XrSystemFacialTrackingPropertiesHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportEyeFacialTracking) \\\n    _(supportLipFacialTracking) \\\n\n/// Calls your macro with the name of each member of XrFacialExpressionsHTC, in order.\n#define XR_LIST_STRUCT_XrFacialExpressionsHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(isActive) \\\n    _(sampleTime) \\\n    _(expressionCount) \\\n    _(expressionWeightings) \\\n\n/// Calls your macro with the name of each member of XrFacialTrackerCreateInfoHTC, in order.\n#define XR_LIST_STRUCT_XrFacialTrackerCreateInfoHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(facialTrackingType) \\\n\n/// Calls your macro with the name of each member of XrSystemColorSpacePropertiesFB, in order.\n#define XR_LIST_STRUCT_XrSystemColorSpacePropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(colorSpace) \\\n\n/// Calls your macro with the name of each member of XrVector4sFB, in order.\n#define XR_LIST_STRUCT_XrVector4sFB(_) \\\n    _(x) \\\n    _(y) \\\n    _(z) \\\n    _(w) \\\n\n/// Calls your macro with the name of each member of XrHandTrackingMeshFB, in order.\n#define XR_LIST_STRUCT_XrHandTrackingMeshFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(jointCapacityInput) \\\n    _(jointCountOutput) \\\n    _(jointBindPoses) \\\n    _(jointRadii) \\\n    _(jointParents) \\\n    _(vertexCapacityInput) \\\n    _(vertexCountOutput) \\\n    _(vertexPositions) \\\n    _(vertexNormals) \\\n    _(vertexUVs) \\\n    _(vertexBlendIndices) \\\n    _(vertexBlendWeights) \\\n    _(indexCapacityInput) \\\n    _(indexCountOutput) \\\n    _(indices) \\\n\n/// Calls your macro with the name of each member of XrHandTrackingScaleFB, in order.\n#define XR_LIST_STRUCT_XrHandTrackingScaleFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(sensorOutput) \\\n    _(currentOutput) \\\n    _(overrideHandScale) \\\n    _(overrideValueInput) \\\n\n/// Calls your macro with the name of each member of XrHandTrackingAimStateFB, in order.\n#define XR_LIST_STRUCT_XrHandTrackingAimStateFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(status) \\\n    _(aimPose) \\\n    _(pinchStrengthIndex) \\\n    _(pinchStrengthMiddle) \\\n    _(pinchStrengthRing) \\\n    _(pinchStrengthLittle) \\\n\n/// Calls your macro with the name of each member of XrHandCapsuleFB, in order.\n#define XR_LIST_STRUCT_XrHandCapsuleFB(_) \\\n    _(points) \\\n    _(radius) \\\n    _(joint) \\\n\n/// Calls your macro with the name of each member of XrHandTrackingCapsulesStateFB, in order.\n#define XR_LIST_STRUCT_XrHandTrackingCapsulesStateFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(capsules) \\\n\n/// Calls your macro with the name of each member of XrSystemSpatialEntityPropertiesFB, in order.\n#define XR_LIST_STRUCT_XrSystemSpatialEntityPropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsSpatialEntity) \\\n\n/// Calls your macro with the name of each member of XrSpatialAnchorCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpatialAnchorCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(space) \\\n    _(poseInSpace) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrSpaceComponentStatusSetInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceComponentStatusSetInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(componentType) \\\n    _(enabled) \\\n    _(timeout) \\\n\n/// Calls your macro with the name of each member of XrSpaceComponentStatusFB, in order.\n#define XR_LIST_STRUCT_XrSpaceComponentStatusFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(enabled) \\\n    _(changePending) \\\n\n/// Calls your macro with the name of each member of XrUuidEXT, in order.\n#define XR_LIST_STRUCT_XrUuidEXT(_) \\\n    _(data) \\\n\n/// Calls your macro with the name of each member of XrEventDataSpatialAnchorCreateCompleteFB, in order.\n#define XR_LIST_STRUCT_XrEventDataSpatialAnchorCreateCompleteFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestId) \\\n    _(result) \\\n    _(space) \\\n    _(uuid) \\\n\n/// Calls your macro with the name of each member of XrEventDataSpaceSetStatusCompleteFB, in order.\n#define XR_LIST_STRUCT_XrEventDataSpaceSetStatusCompleteFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestId) \\\n    _(result) \\\n    _(space) \\\n    _(uuid) \\\n    _(componentType) \\\n    _(enabled) \\\n\n/// Calls your macro with the name of each member of XrFoveationProfileCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrFoveationProfileCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSwapchainCreateInfoFoveationFB, in order.\n#define XR_LIST_STRUCT_XrSwapchainCreateInfoFoveationFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrSwapchainStateFoveationFB, in order.\n#define XR_LIST_STRUCT_XrSwapchainStateFoveationFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n    _(profile) \\\n\n/// Calls your macro with the name of each member of XrFoveationLevelProfileCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrFoveationLevelProfileCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(level) \\\n    _(verticalOffset) \\\n    _(dynamic) \\\n\n/// Calls your macro with the name of each member of XrSystemKeyboardTrackingPropertiesFB, in order.\n#define XR_LIST_STRUCT_XrSystemKeyboardTrackingPropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsKeyboardTracking) \\\n\n/// Calls your macro with the name of each member of XrKeyboardTrackingDescriptionFB, in order.\n#define XR_LIST_STRUCT_XrKeyboardTrackingDescriptionFB(_) \\\n    _(trackedKeyboardId) \\\n    _(size) \\\n    _(flags) \\\n    _(name) \\\n\n/// Calls your macro with the name of each member of XrKeyboardSpaceCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrKeyboardSpaceCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(trackedKeyboardId) \\\n\n/// Calls your macro with the name of each member of XrKeyboardTrackingQueryFB, in order.\n#define XR_LIST_STRUCT_XrKeyboardTrackingQueryFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrTriangleMeshCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrTriangleMeshCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n    _(windingOrder) \\\n    _(vertexCount) \\\n    _(vertexBuffer) \\\n    _(triangleCount) \\\n    _(indexBuffer) \\\n\n/// Calls your macro with the name of each member of XrSystemPassthroughPropertiesFB, in order.\n#define XR_LIST_STRUCT_XrSystemPassthroughPropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsPassthrough) \\\n\n/// Calls your macro with the name of each member of XrSystemPassthroughProperties2FB, in order.\n#define XR_LIST_STRUCT_XrSystemPassthroughProperties2FB(_) \\\n    _(type) \\\n    _(next) \\\n    _(capabilities) \\\n\n/// Calls your macro with the name of each member of XrPassthroughCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrPassthroughCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrPassthroughLayerCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrPassthroughLayerCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(passthrough) \\\n    _(flags) \\\n    _(purpose) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerPassthroughFB, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerPassthroughFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n    _(space) \\\n    _(layerHandle) \\\n\n/// Calls your macro with the name of each member of XrGeometryInstanceCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrGeometryInstanceCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(layer) \\\n    _(mesh) \\\n    _(baseSpace) \\\n    _(pose) \\\n    _(scale) \\\n\n/// Calls your macro with the name of each member of XrGeometryInstanceTransformFB, in order.\n#define XR_LIST_STRUCT_XrGeometryInstanceTransformFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(baseSpace) \\\n    _(time) \\\n    _(pose) \\\n    _(scale) \\\n\n/// Calls your macro with the name of each member of XrPassthroughStyleFB, in order.\n#define XR_LIST_STRUCT_XrPassthroughStyleFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(textureOpacityFactor) \\\n    _(edgeColor) \\\n\n/// Calls your macro with the name of each member of XrPassthroughColorMapMonoToRgbaFB, in order.\n#define XR_LIST_STRUCT_XrPassthroughColorMapMonoToRgbaFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(textureColorMap) \\\n\n/// Calls your macro with the name of each member of XrPassthroughColorMapMonoToMonoFB, in order.\n#define XR_LIST_STRUCT_XrPassthroughColorMapMonoToMonoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(textureColorMap) \\\n\n/// Calls your macro with the name of each member of XrPassthroughBrightnessContrastSaturationFB, in order.\n#define XR_LIST_STRUCT_XrPassthroughBrightnessContrastSaturationFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(brightness) \\\n    _(contrast) \\\n    _(saturation) \\\n\n/// Calls your macro with the name of each member of XrEventDataPassthroughStateChangedFB, in order.\n#define XR_LIST_STRUCT_XrEventDataPassthroughStateChangedFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrRenderModelPathInfoFB, in order.\n#define XR_LIST_STRUCT_XrRenderModelPathInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(path) \\\n\n/// Calls your macro with the name of each member of XrRenderModelPropertiesFB, in order.\n#define XR_LIST_STRUCT_XrRenderModelPropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(vendorId) \\\n    _(modelName) \\\n    _(modelKey) \\\n    _(modelVersion) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrRenderModelBufferFB, in order.\n#define XR_LIST_STRUCT_XrRenderModelBufferFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(bufferCapacityInput) \\\n    _(bufferCountOutput) \\\n    _(buffer) \\\n\n/// Calls your macro with the name of each member of XrRenderModelLoadInfoFB, in order.\n#define XR_LIST_STRUCT_XrRenderModelLoadInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(modelKey) \\\n\n/// Calls your macro with the name of each member of XrSystemRenderModelPropertiesFB, in order.\n#define XR_LIST_STRUCT_XrSystemRenderModelPropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsRenderModelLoading) \\\n\n/// Calls your macro with the name of each member of XrRenderModelCapabilitiesRequestFB, in order.\n#define XR_LIST_STRUCT_XrRenderModelCapabilitiesRequestFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrViewLocateFoveatedRenderingVARJO, in order.\n#define XR_LIST_STRUCT_XrViewLocateFoveatedRenderingVARJO(_) \\\n    _(type) \\\n    _(next) \\\n    _(foveatedRenderingActive) \\\n\n/// Calls your macro with the name of each member of XrFoveatedViewConfigurationViewVARJO, in order.\n#define XR_LIST_STRUCT_XrFoveatedViewConfigurationViewVARJO(_) \\\n    _(type) \\\n    _(next) \\\n    _(foveatedRenderingActive) \\\n\n/// Calls your macro with the name of each member of XrSystemFoveatedRenderingPropertiesVARJO, in order.\n#define XR_LIST_STRUCT_XrSystemFoveatedRenderingPropertiesVARJO(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsFoveatedRendering) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerDepthTestVARJO, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerDepthTestVARJO(_) \\\n    _(type) \\\n    _(next) \\\n    _(depthTestRangeNearZ) \\\n    _(depthTestRangeFarZ) \\\n\n/// Calls your macro with the name of each member of XrSystemMarkerTrackingPropertiesVARJO, in order.\n#define XR_LIST_STRUCT_XrSystemMarkerTrackingPropertiesVARJO(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsMarkerTracking) \\\n\n/// Calls your macro with the name of each member of XrEventDataMarkerTrackingUpdateVARJO, in order.\n#define XR_LIST_STRUCT_XrEventDataMarkerTrackingUpdateVARJO(_) \\\n    _(type) \\\n    _(next) \\\n    _(markerId) \\\n    _(isActive) \\\n    _(isPredicted) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrMarkerSpaceCreateInfoVARJO, in order.\n#define XR_LIST_STRUCT_XrMarkerSpaceCreateInfoVARJO(_) \\\n    _(type) \\\n    _(next) \\\n    _(markerId) \\\n    _(poseInMarkerSpace) \\\n\n/// Calls your macro with the name of each member of XrFrameEndInfoML, in order.\n#define XR_LIST_STRUCT_XrFrameEndInfoML(_) \\\n    _(type) \\\n    _(next) \\\n    _(focusDistance) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrGlobalDimmerFrameEndInfoML, in order.\n#define XR_LIST_STRUCT_XrGlobalDimmerFrameEndInfoML(_) \\\n    _(type) \\\n    _(next) \\\n    _(dimmerValue) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrCoordinateSpaceCreateInfoML, in order.\n#define XR_LIST_STRUCT_XrCoordinateSpaceCreateInfoML(_) \\\n    _(type) \\\n    _(next) \\\n    _(cfuid) \\\n    _(poseInCoordinateSpace) \\\n\n/// Calls your macro with the name of each member of XrSpatialAnchorPersistenceNameMSFT, in order.\n#define XR_LIST_STRUCT_XrSpatialAnchorPersistenceNameMSFT(_) \\\n    _(name) \\\n\n/// Calls your macro with the name of each member of XrSpatialAnchorPersistenceInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSpatialAnchorPersistenceInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(spatialAnchorPersistenceName) \\\n    _(spatialAnchor) \\\n\n/// Calls your macro with the name of each member of XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, in order.\n#define XR_LIST_STRUCT_XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT(_) \\\n    _(type) \\\n    _(next) \\\n    _(spatialAnchorStore) \\\n    _(spatialAnchorPersistenceName) \\\n\n/// Calls your macro with the name of each member of XrSpaceQueryInfoBaseHeaderFB, in order.\n#define XR_LIST_STRUCT_XrSpaceQueryInfoBaseHeaderFB(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSpaceFilterInfoBaseHeaderFB, in order.\n#define XR_LIST_STRUCT_XrSpaceFilterInfoBaseHeaderFB(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrSpaceQueryInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceQueryInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(queryAction) \\\n    _(maxResultCount) \\\n    _(timeout) \\\n    _(filter) \\\n    _(excludeFilter) \\\n\n/// Calls your macro with the name of each member of XrSpaceStorageLocationFilterInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceStorageLocationFilterInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(location) \\\n\n/// Calls your macro with the name of each member of XrSpaceUuidFilterInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceUuidFilterInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(uuidCount) \\\n    _(uuids) \\\n\n/// Calls your macro with the name of each member of XrSpaceComponentFilterInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceComponentFilterInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(componentType) \\\n\n/// Calls your macro with the name of each member of XrSpaceQueryResultFB, in order.\n#define XR_LIST_STRUCT_XrSpaceQueryResultFB(_) \\\n    _(space) \\\n    _(uuid) \\\n\n/// Calls your macro with the name of each member of XrSpaceQueryResultsFB, in order.\n#define XR_LIST_STRUCT_XrSpaceQueryResultsFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(resultCapacityInput) \\\n    _(resultCountOutput) \\\n    _(results) \\\n\n/// Calls your macro with the name of each member of XrEventDataSpaceQueryResultsAvailableFB, in order.\n#define XR_LIST_STRUCT_XrEventDataSpaceQueryResultsAvailableFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestId) \\\n\n/// Calls your macro with the name of each member of XrEventDataSpaceQueryCompleteFB, in order.\n#define XR_LIST_STRUCT_XrEventDataSpaceQueryCompleteFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestId) \\\n    _(result) \\\n\n/// Calls your macro with the name of each member of XrSpaceSaveInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceSaveInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(space) \\\n    _(location) \\\n    _(persistenceMode) \\\n\n/// Calls your macro with the name of each member of XrSpaceEraseInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceEraseInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(space) \\\n    _(location) \\\n\n/// Calls your macro with the name of each member of XrEventDataSpaceSaveCompleteFB, in order.\n#define XR_LIST_STRUCT_XrEventDataSpaceSaveCompleteFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestId) \\\n    _(result) \\\n    _(space) \\\n    _(uuid) \\\n    _(location) \\\n\n/// Calls your macro with the name of each member of XrEventDataSpaceEraseCompleteFB, in order.\n#define XR_LIST_STRUCT_XrEventDataSpaceEraseCompleteFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestId) \\\n    _(result) \\\n    _(space) \\\n    _(uuid) \\\n    _(location) \\\n\n/// Calls your macro with the name of each member of XrSwapchainImageFoveationVulkanFB, in order.\n#define XR_LIST_STRUCT_XrSwapchainImageFoveationVulkanFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(image) \\\n    _(width) \\\n    _(height) \\\n\n/// Calls your macro with the name of each member of XrSwapchainStateAndroidSurfaceDimensionsFB, in order.\n#define XR_LIST_STRUCT_XrSwapchainStateAndroidSurfaceDimensionsFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(width) \\\n    _(height) \\\n\n/// Calls your macro with the name of each member of XrSwapchainStateSamplerOpenGLESFB, in order.\n#define XR_LIST_STRUCT_XrSwapchainStateSamplerOpenGLESFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(minFilter) \\\n    _(magFilter) \\\n    _(wrapModeS) \\\n    _(wrapModeT) \\\n    _(swizzleRed) \\\n    _(swizzleGreen) \\\n    _(swizzleBlue) \\\n    _(swizzleAlpha) \\\n    _(maxAnisotropy) \\\n    _(borderColor) \\\n\n/// Calls your macro with the name of each member of XrSwapchainStateSamplerVulkanFB, in order.\n#define XR_LIST_STRUCT_XrSwapchainStateSamplerVulkanFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(minFilter) \\\n    _(magFilter) \\\n    _(mipmapMode) \\\n    _(wrapModeS) \\\n    _(wrapModeT) \\\n    _(swizzleRed) \\\n    _(swizzleGreen) \\\n    _(swizzleBlue) \\\n    _(swizzleAlpha) \\\n    _(maxAnisotropy) \\\n    _(borderColor) \\\n\n/// Calls your macro with the name of each member of XrSpaceShareInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceShareInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(spaceCount) \\\n    _(spaces) \\\n    _(userCount) \\\n    _(users) \\\n\n/// Calls your macro with the name of each member of XrEventDataSpaceShareCompleteFB, in order.\n#define XR_LIST_STRUCT_XrEventDataSpaceShareCompleteFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestId) \\\n    _(result) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerSpaceWarpInfoFB, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerSpaceWarpInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n    _(motionVectorSubImage) \\\n    _(appSpaceDeltaPose) \\\n    _(depthSubImage) \\\n    _(minDepth) \\\n    _(maxDepth) \\\n    _(nearZ) \\\n    _(farZ) \\\n\n/// Calls your macro with the name of each member of XrSystemSpaceWarpPropertiesFB, in order.\n#define XR_LIST_STRUCT_XrSystemSpaceWarpPropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(recommendedMotionVectorImageRectWidth) \\\n    _(recommendedMotionVectorImageRectHeight) \\\n\n/// Calls your macro with the name of each member of XrHapticAmplitudeEnvelopeVibrationFB, in order.\n#define XR_LIST_STRUCT_XrHapticAmplitudeEnvelopeVibrationFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(duration) \\\n    _(amplitudeCount) \\\n    _(amplitudes) \\\n\n/// Calls your macro with the name of each member of XrExtent3DfFB, in order.\n#define XR_LIST_STRUCT_XrExtent3DfFB(_) \\\n    _(width) \\\n    _(height) \\\n    _(depth) \\\n\n/// Calls your macro with the name of each member of XrOffset3DfFB, in order.\n#define XR_LIST_STRUCT_XrOffset3DfFB(_) \\\n    _(x) \\\n    _(y) \\\n    _(z) \\\n\n/// Calls your macro with the name of each member of XrRect3DfFB, in order.\n#define XR_LIST_STRUCT_XrRect3DfFB(_) \\\n    _(offset) \\\n    _(extent) \\\n\n/// Calls your macro with the name of each member of XrSemanticLabelsFB, in order.\n#define XR_LIST_STRUCT_XrSemanticLabelsFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(bufferCapacityInput) \\\n    _(bufferCountOutput) \\\n    _(buffer) \\\n\n/// Calls your macro with the name of each member of XrRoomLayoutFB, in order.\n#define XR_LIST_STRUCT_XrRoomLayoutFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(floorUuid) \\\n    _(ceilingUuid) \\\n    _(wallUuidCapacityInput) \\\n    _(wallUuidCountOutput) \\\n    _(wallUuids) \\\n\n/// Calls your macro with the name of each member of XrBoundary2DFB, in order.\n#define XR_LIST_STRUCT_XrBoundary2DFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(vertexCapacityInput) \\\n    _(vertexCountOutput) \\\n    _(vertices) \\\n\n/// Calls your macro with the name of each member of XrSemanticLabelsSupportInfoFB, in order.\n#define XR_LIST_STRUCT_XrSemanticLabelsSupportInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n    _(recognizedLabels) \\\n\n/// Calls your macro with the name of each member of XrDigitalLensControlALMALENCE, in order.\n#define XR_LIST_STRUCT_XrDigitalLensControlALMALENCE(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrEventDataSceneCaptureCompleteFB, in order.\n#define XR_LIST_STRUCT_XrEventDataSceneCaptureCompleteFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestId) \\\n    _(result) \\\n\n/// Calls your macro with the name of each member of XrSceneCaptureRequestInfoFB, in order.\n#define XR_LIST_STRUCT_XrSceneCaptureRequestInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestByteCount) \\\n    _(request) \\\n\n/// Calls your macro with the name of each member of XrSpaceContainerFB, in order.\n#define XR_LIST_STRUCT_XrSpaceContainerFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(uuidCapacityInput) \\\n    _(uuidCountOutput) \\\n    _(uuids) \\\n\n/// Calls your macro with the name of each member of XrFoveationEyeTrackedProfileCreateInfoMETA, in order.\n#define XR_LIST_STRUCT_XrFoveationEyeTrackedProfileCreateInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrFoveationEyeTrackedStateMETA, in order.\n#define XR_LIST_STRUCT_XrFoveationEyeTrackedStateMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(foveationCenter) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrSystemFoveationEyeTrackedPropertiesMETA, in order.\n#define XR_LIST_STRUCT_XrSystemFoveationEyeTrackedPropertiesMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsFoveationEyeTracked) \\\n\n/// Calls your macro with the name of each member of XrSystemFaceTrackingPropertiesFB, in order.\n#define XR_LIST_STRUCT_XrSystemFaceTrackingPropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsFaceTracking) \\\n\n/// Calls your macro with the name of each member of XrFaceTrackerCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrFaceTrackerCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(faceExpressionSet) \\\n\n/// Calls your macro with the name of each member of XrFaceExpressionInfoFB, in order.\n#define XR_LIST_STRUCT_XrFaceExpressionInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrFaceExpressionStatusFB, in order.\n#define XR_LIST_STRUCT_XrFaceExpressionStatusFB(_) \\\n    _(isValid) \\\n    _(isEyeFollowingBlendshapesValid) \\\n\n/// Calls your macro with the name of each member of XrFaceExpressionWeightsFB, in order.\n#define XR_LIST_STRUCT_XrFaceExpressionWeightsFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(weightCount) \\\n    _(weights) \\\n    _(confidenceCount) \\\n    _(confidences) \\\n    _(status) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrEyeGazeFB, in order.\n#define XR_LIST_STRUCT_XrEyeGazeFB(_) \\\n    _(isValid) \\\n    _(gazePose) \\\n    _(gazeConfidence) \\\n\n/// Calls your macro with the name of each member of XrEyeTrackerCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrEyeTrackerCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrEyeGazesInfoFB, in order.\n#define XR_LIST_STRUCT_XrEyeGazesInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(baseSpace) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrSystemEyeTrackingPropertiesFB, in order.\n#define XR_LIST_STRUCT_XrSystemEyeTrackingPropertiesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsEyeTracking) \\\n\n/// Calls your macro with the name of each member of XrEyeGazesFB, in order.\n#define XR_LIST_STRUCT_XrEyeGazesFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(gaze) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrPassthroughKeyboardHandsIntensityFB, in order.\n#define XR_LIST_STRUCT_XrPassthroughKeyboardHandsIntensityFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(leftHandIntensity) \\\n    _(rightHandIntensity) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerSettingsFB, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerSettingsFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n\n/// Calls your macro with the name of each member of XrHapticPcmVibrationFB, in order.\n#define XR_LIST_STRUCT_XrHapticPcmVibrationFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(bufferSize) \\\n    _(buffer) \\\n    _(sampleRate) \\\n    _(append) \\\n    _(samplesConsumed) \\\n\n/// Calls your macro with the name of each member of XrDevicePcmSampleRateStateFB, in order.\n#define XR_LIST_STRUCT_XrDevicePcmSampleRateStateFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(sampleRate) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerDepthTestFB, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerDepthTestFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(depthMask) \\\n    _(compareOp) \\\n\n/// Calls your macro with the name of each member of XrLocalDimmingFrameEndInfoMETA, in order.\n#define XR_LIST_STRUCT_XrLocalDimmingFrameEndInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(localDimmingMode) \\\n\n/// Calls your macro with the name of each member of XrSystemVirtualKeyboardPropertiesMETA, in order.\n#define XR_LIST_STRUCT_XrSystemVirtualKeyboardPropertiesMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsVirtualKeyboard) \\\n\n/// Calls your macro with the name of each member of XrVirtualKeyboardCreateInfoMETA, in order.\n#define XR_LIST_STRUCT_XrVirtualKeyboardCreateInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n\n/// Calls your macro with the name of each member of XrVirtualKeyboardSpaceCreateInfoMETA, in order.\n#define XR_LIST_STRUCT_XrVirtualKeyboardSpaceCreateInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(locationType) \\\n    _(space) \\\n    _(poseInSpace) \\\n\n/// Calls your macro with the name of each member of XrVirtualKeyboardLocationInfoMETA, in order.\n#define XR_LIST_STRUCT_XrVirtualKeyboardLocationInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(locationType) \\\n    _(space) \\\n    _(poseInSpace) \\\n    _(scale) \\\n\n/// Calls your macro with the name of each member of XrVirtualKeyboardModelVisibilitySetInfoMETA, in order.\n#define XR_LIST_STRUCT_XrVirtualKeyboardModelVisibilitySetInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(visible) \\\n\n/// Calls your macro with the name of each member of XrVirtualKeyboardAnimationStateMETA, in order.\n#define XR_LIST_STRUCT_XrVirtualKeyboardAnimationStateMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(animationIndex) \\\n    _(fraction) \\\n\n/// Calls your macro with the name of each member of XrVirtualKeyboardModelAnimationStatesMETA, in order.\n#define XR_LIST_STRUCT_XrVirtualKeyboardModelAnimationStatesMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(stateCapacityInput) \\\n    _(stateCountOutput) \\\n    _(states) \\\n\n/// Calls your macro with the name of each member of XrVirtualKeyboardTextureDataMETA, in order.\n#define XR_LIST_STRUCT_XrVirtualKeyboardTextureDataMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(textureWidth) \\\n    _(textureHeight) \\\n    _(bufferCapacityInput) \\\n    _(bufferCountOutput) \\\n    _(buffer) \\\n\n/// Calls your macro with the name of each member of XrVirtualKeyboardInputInfoMETA, in order.\n#define XR_LIST_STRUCT_XrVirtualKeyboardInputInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(inputSource) \\\n    _(inputSpace) \\\n    _(inputPoseInSpace) \\\n    _(inputState) \\\n\n/// Calls your macro with the name of each member of XrVirtualKeyboardTextContextChangeInfoMETA, in order.\n#define XR_LIST_STRUCT_XrVirtualKeyboardTextContextChangeInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(textContext) \\\n\n/// Calls your macro with the name of each member of XrEventDataVirtualKeyboardCommitTextMETA, in order.\n#define XR_LIST_STRUCT_XrEventDataVirtualKeyboardCommitTextMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(keyboard) \\\n    _(text) \\\n\n/// Calls your macro with the name of each member of XrEventDataVirtualKeyboardBackspaceMETA, in order.\n#define XR_LIST_STRUCT_XrEventDataVirtualKeyboardBackspaceMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(keyboard) \\\n\n/// Calls your macro with the name of each member of XrEventDataVirtualKeyboardEnterMETA, in order.\n#define XR_LIST_STRUCT_XrEventDataVirtualKeyboardEnterMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(keyboard) \\\n\n/// Calls your macro with the name of each member of XrEventDataVirtualKeyboardShownMETA, in order.\n#define XR_LIST_STRUCT_XrEventDataVirtualKeyboardShownMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(keyboard) \\\n\n/// Calls your macro with the name of each member of XrEventDataVirtualKeyboardHiddenMETA, in order.\n#define XR_LIST_STRUCT_XrEventDataVirtualKeyboardHiddenMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(keyboard) \\\n\n/// Calls your macro with the name of each member of XrExternalCameraIntrinsicsOCULUS, in order.\n#define XR_LIST_STRUCT_XrExternalCameraIntrinsicsOCULUS(_) \\\n    _(lastChangeTime) \\\n    _(fov) \\\n    _(virtualNearPlaneDistance) \\\n    _(virtualFarPlaneDistance) \\\n    _(imageSensorPixelResolution) \\\n\n/// Calls your macro with the name of each member of XrExternalCameraExtrinsicsOCULUS, in order.\n#define XR_LIST_STRUCT_XrExternalCameraExtrinsicsOCULUS(_) \\\n    _(lastChangeTime) \\\n    _(cameraStatusFlags) \\\n    _(attachedToDevice) \\\n    _(relativePose) \\\n\n/// Calls your macro with the name of each member of XrExternalCameraOCULUS, in order.\n#define XR_LIST_STRUCT_XrExternalCameraOCULUS(_) \\\n    _(type) \\\n    _(next) \\\n    _(name) \\\n    _(intrinsics) \\\n    _(extrinsics) \\\n\n/// Calls your macro with the name of each member of XrVulkanSwapchainCreateInfoMETA, in order.\n#define XR_LIST_STRUCT_XrVulkanSwapchainCreateInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(additionalCreateFlags) \\\n    _(additionalUsageFlags) \\\n\n/// Calls your macro with the name of each member of XrPerformanceMetricsStateMETA, in order.\n#define XR_LIST_STRUCT_XrPerformanceMetricsStateMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(enabled) \\\n\n/// Calls your macro with the name of each member of XrPerformanceMetricsCounterMETA, in order.\n#define XR_LIST_STRUCT_XrPerformanceMetricsCounterMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(counterFlags) \\\n    _(counterUnit) \\\n    _(uintValue) \\\n    _(floatValue) \\\n\n/// Calls your macro with the name of each member of XrSpaceListSaveInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceListSaveInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(spaceCount) \\\n    _(spaces) \\\n    _(location) \\\n\n/// Calls your macro with the name of each member of XrEventDataSpaceListSaveCompleteFB, in order.\n#define XR_LIST_STRUCT_XrEventDataSpaceListSaveCompleteFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestId) \\\n    _(result) \\\n\n/// Calls your macro with the name of each member of XrSpaceUserCreateInfoFB, in order.\n#define XR_LIST_STRUCT_XrSpaceUserCreateInfoFB(_) \\\n    _(type) \\\n    _(next) \\\n    _(userId) \\\n\n/// Calls your macro with the name of each member of XrSystemHeadsetIdPropertiesMETA, in order.\n#define XR_LIST_STRUCT_XrSystemHeadsetIdPropertiesMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(id) \\\n\n/// Calls your macro with the name of each member of XrPassthroughColorLutDataMETA, in order.\n#define XR_LIST_STRUCT_XrPassthroughColorLutDataMETA(_) \\\n    _(bufferSize) \\\n    _(buffer) \\\n\n/// Calls your macro with the name of each member of XrPassthroughColorLutCreateInfoMETA, in order.\n#define XR_LIST_STRUCT_XrPassthroughColorLutCreateInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(channels) \\\n    _(resolution) \\\n    _(data) \\\n\n/// Calls your macro with the name of each member of XrPassthroughColorLutUpdateInfoMETA, in order.\n#define XR_LIST_STRUCT_XrPassthroughColorLutUpdateInfoMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(data) \\\n\n/// Calls your macro with the name of each member of XrPassthroughColorMapLutMETA, in order.\n#define XR_LIST_STRUCT_XrPassthroughColorMapLutMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(colorLut) \\\n    _(weight) \\\n\n/// Calls your macro with the name of each member of XrPassthroughColorMapInterpolatedLutMETA, in order.\n#define XR_LIST_STRUCT_XrPassthroughColorMapInterpolatedLutMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(sourceColorLut) \\\n    _(targetColorLut) \\\n    _(weight) \\\n\n/// Calls your macro with the name of each member of XrSystemPassthroughColorLutPropertiesMETA, in order.\n#define XR_LIST_STRUCT_XrSystemPassthroughColorLutPropertiesMETA(_) \\\n    _(type) \\\n    _(next) \\\n    _(maxColorLutResolution) \\\n\n/// Calls your macro with the name of each member of XrPassthroughCreateInfoHTC, in order.\n#define XR_LIST_STRUCT_XrPassthroughCreateInfoHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(form) \\\n\n/// Calls your macro with the name of each member of XrPassthroughColorHTC, in order.\n#define XR_LIST_STRUCT_XrPassthroughColorHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(alpha) \\\n\n/// Calls your macro with the name of each member of XrPassthroughMeshTransformInfoHTC, in order.\n#define XR_LIST_STRUCT_XrPassthroughMeshTransformInfoHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(vertexCount) \\\n    _(vertices) \\\n    _(indexCount) \\\n    _(indices) \\\n    _(baseSpace) \\\n    _(time) \\\n    _(pose) \\\n    _(scale) \\\n\n/// Calls your macro with the name of each member of XrCompositionLayerPassthroughHTC, in order.\n#define XR_LIST_STRUCT_XrCompositionLayerPassthroughHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(layerFlags) \\\n    _(space) \\\n    _(passthrough) \\\n    _(color) \\\n\n/// Calls your macro with the name of each member of XrFoveationApplyInfoHTC, in order.\n#define XR_LIST_STRUCT_XrFoveationApplyInfoHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(mode) \\\n    _(subImageCount) \\\n    _(subImages) \\\n\n/// Calls your macro with the name of each member of XrFoveationConfigurationHTC, in order.\n#define XR_LIST_STRUCT_XrFoveationConfigurationHTC(_) \\\n    _(level) \\\n    _(clearFovDegree) \\\n    _(focalCenterOffset) \\\n\n/// Calls your macro with the name of each member of XrFoveationDynamicModeInfoHTC, in order.\n#define XR_LIST_STRUCT_XrFoveationDynamicModeInfoHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(dynamicFlags) \\\n\n/// Calls your macro with the name of each member of XrFoveationCustomModeInfoHTC, in order.\n#define XR_LIST_STRUCT_XrFoveationCustomModeInfoHTC(_) \\\n    _(type) \\\n    _(next) \\\n    _(configCount) \\\n    _(configs) \\\n\n/// Calls your macro with the name of each member of XrActiveActionSetPriorityEXT, in order.\n#define XR_LIST_STRUCT_XrActiveActionSetPriorityEXT(_) \\\n    _(actionSet) \\\n    _(priorityOverride) \\\n\n/// Calls your macro with the name of each member of XrActiveActionSetPrioritiesEXT, in order.\n#define XR_LIST_STRUCT_XrActiveActionSetPrioritiesEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(actionSetPriorityCount) \\\n    _(actionSetPriorities) \\\n\n/// Calls your macro with the name of each member of XrSystemForceFeedbackCurlPropertiesMNDX, in order.\n#define XR_LIST_STRUCT_XrSystemForceFeedbackCurlPropertiesMNDX(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportsForceFeedbackCurl) \\\n\n/// Calls your macro with the name of each member of XrForceFeedbackCurlApplyLocationMNDX, in order.\n#define XR_LIST_STRUCT_XrForceFeedbackCurlApplyLocationMNDX(_) \\\n    _(location) \\\n    _(value) \\\n\n/// Calls your macro with the name of each member of XrForceFeedbackCurlApplyLocationsMNDX, in order.\n#define XR_LIST_STRUCT_XrForceFeedbackCurlApplyLocationsMNDX(_) \\\n    _(type) \\\n    _(next) \\\n    _(locationCount) \\\n    _(locations) \\\n\n/// Calls your macro with the name of each member of XrHandTrackingDataSourceInfoEXT, in order.\n#define XR_LIST_STRUCT_XrHandTrackingDataSourceInfoEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(requestedDataSourceCount) \\\n    _(requestedDataSources) \\\n\n/// Calls your macro with the name of each member of XrHandTrackingDataSourceStateEXT, in order.\n#define XR_LIST_STRUCT_XrHandTrackingDataSourceStateEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(isActive) \\\n    _(dataSource) \\\n\n/// Calls your macro with the name of each member of XrSystemPlaneDetectionPropertiesEXT, in order.\n#define XR_LIST_STRUCT_XrSystemPlaneDetectionPropertiesEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(supportedFeatures) \\\n\n/// Calls your macro with the name of each member of XrPlaneDetectorCreateInfoEXT, in order.\n#define XR_LIST_STRUCT_XrPlaneDetectorCreateInfoEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(flags) \\\n\n/// Calls your macro with the name of each member of XrExtent3DfEXT, in order.\n#define XR_LIST_STRUCT_XrExtent3DfEXT(_) \\\n    _(width) \\\n    _(height) \\\n    _(depth) \\\n\n/// Calls your macro with the name of each member of XrPlaneDetectorBeginInfoEXT, in order.\n#define XR_LIST_STRUCT_XrPlaneDetectorBeginInfoEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(baseSpace) \\\n    _(time) \\\n    _(orientationCount) \\\n    _(orientations) \\\n    _(semanticTypeCount) \\\n    _(semanticTypes) \\\n    _(maxPlanes) \\\n    _(minArea) \\\n    _(boundingBoxPose) \\\n    _(boundingBoxExtent) \\\n\n/// Calls your macro with the name of each member of XrPlaneDetectorGetInfoEXT, in order.\n#define XR_LIST_STRUCT_XrPlaneDetectorGetInfoEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(baseSpace) \\\n    _(time) \\\n\n/// Calls your macro with the name of each member of XrPlaneDetectorLocationEXT, in order.\n#define XR_LIST_STRUCT_XrPlaneDetectorLocationEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(planeId) \\\n    _(locationFlags) \\\n    _(pose) \\\n    _(extents) \\\n    _(orientation) \\\n    _(semanticType) \\\n    _(polygonBufferCount) \\\n\n/// Calls your macro with the name of each member of XrPlaneDetectorLocationsEXT, in order.\n#define XR_LIST_STRUCT_XrPlaneDetectorLocationsEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(planeLocationCapacityInput) \\\n    _(planeLocationCountOutput) \\\n    _(planeLocations) \\\n\n/// Calls your macro with the name of each member of XrPlaneDetectorPolygonBufferEXT, in order.\n#define XR_LIST_STRUCT_XrPlaneDetectorPolygonBufferEXT(_) \\\n    _(type) \\\n    _(next) \\\n    _(vertexCapacityInput) \\\n    _(vertexCountOutput) \\\n    _(vertices) \\\n\n\n\n/// Calls your macro with the structure type name and the XrStructureType constant for\n/// each known/available structure type, excluding those unavailable due to preprocessor definitions.\n#define XR_LIST_STRUCTURE_TYPES(_) \\\n    XR_LIST_STRUCTURE_TYPES_CORE(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ML(_) \\\n    XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) \\\n\n\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES() - structure types available without any preprocessor definitions\n#define XR_LIST_STRUCTURE_TYPES_CORE(_) \\\n    _(XrApiLayerProperties, XR_TYPE_API_LAYER_PROPERTIES) \\\n    _(XrExtensionProperties, XR_TYPE_EXTENSION_PROPERTIES) \\\n    _(XrInstanceCreateInfo, XR_TYPE_INSTANCE_CREATE_INFO) \\\n    _(XrInstanceProperties, XR_TYPE_INSTANCE_PROPERTIES) \\\n    _(XrEventDataBuffer, XR_TYPE_EVENT_DATA_BUFFER) \\\n    _(XrSystemGetInfo, XR_TYPE_SYSTEM_GET_INFO) \\\n    _(XrSystemProperties, XR_TYPE_SYSTEM_PROPERTIES) \\\n    _(XrSessionCreateInfo, XR_TYPE_SESSION_CREATE_INFO) \\\n    _(XrSpaceVelocity, XR_TYPE_SPACE_VELOCITY) \\\n    _(XrReferenceSpaceCreateInfo, XR_TYPE_REFERENCE_SPACE_CREATE_INFO) \\\n    _(XrActionSpaceCreateInfo, XR_TYPE_ACTION_SPACE_CREATE_INFO) \\\n    _(XrSpaceLocation, XR_TYPE_SPACE_LOCATION) \\\n    _(XrViewConfigurationProperties, XR_TYPE_VIEW_CONFIGURATION_PROPERTIES) \\\n    _(XrViewConfigurationView, XR_TYPE_VIEW_CONFIGURATION_VIEW) \\\n    _(XrSwapchainCreateInfo, XR_TYPE_SWAPCHAIN_CREATE_INFO) \\\n    _(XrSwapchainImageAcquireInfo, XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO) \\\n    _(XrSwapchainImageWaitInfo, XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO) \\\n    _(XrSwapchainImageReleaseInfo, XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO) \\\n    _(XrSessionBeginInfo, XR_TYPE_SESSION_BEGIN_INFO) \\\n    _(XrFrameWaitInfo, XR_TYPE_FRAME_WAIT_INFO) \\\n    _(XrFrameState, XR_TYPE_FRAME_STATE) \\\n    _(XrFrameBeginInfo, XR_TYPE_FRAME_BEGIN_INFO) \\\n    _(XrFrameEndInfo, XR_TYPE_FRAME_END_INFO) \\\n    _(XrViewLocateInfo, XR_TYPE_VIEW_LOCATE_INFO) \\\n    _(XrViewState, XR_TYPE_VIEW_STATE) \\\n    _(XrView, XR_TYPE_VIEW) \\\n    _(XrActionSetCreateInfo, XR_TYPE_ACTION_SET_CREATE_INFO) \\\n    _(XrActionCreateInfo, XR_TYPE_ACTION_CREATE_INFO) \\\n    _(XrInteractionProfileSuggestedBinding, XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING) \\\n    _(XrSessionActionSetsAttachInfo, XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO) \\\n    _(XrInteractionProfileState, XR_TYPE_INTERACTION_PROFILE_STATE) \\\n    _(XrActionStateGetInfo, XR_TYPE_ACTION_STATE_GET_INFO) \\\n    _(XrActionStateBoolean, XR_TYPE_ACTION_STATE_BOOLEAN) \\\n    _(XrActionStateFloat, XR_TYPE_ACTION_STATE_FLOAT) \\\n    _(XrActionStateVector2f, XR_TYPE_ACTION_STATE_VECTOR2F) \\\n    _(XrActionStatePose, XR_TYPE_ACTION_STATE_POSE) \\\n    _(XrActionsSyncInfo, XR_TYPE_ACTIONS_SYNC_INFO) \\\n    _(XrBoundSourcesForActionEnumerateInfo, XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO) \\\n    _(XrInputSourceLocalizedNameGetInfo, XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO) \\\n    _(XrHapticActionInfo, XR_TYPE_HAPTIC_ACTION_INFO) \\\n    _(XrCompositionLayerProjectionView, XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) \\\n    _(XrCompositionLayerProjection, XR_TYPE_COMPOSITION_LAYER_PROJECTION) \\\n    _(XrCompositionLayerQuad, XR_TYPE_COMPOSITION_LAYER_QUAD) \\\n    _(XrEventDataEventsLost, XR_TYPE_EVENT_DATA_EVENTS_LOST) \\\n    _(XrEventDataInstanceLossPending, XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) \\\n    _(XrEventDataSessionStateChanged, XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) \\\n    _(XrEventDataReferenceSpaceChangePending, XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) \\\n    _(XrEventDataInteractionProfileChanged, XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) \\\n    _(XrHapticVibration, XR_TYPE_HAPTIC_VIBRATION) \\\n    _(XrCompositionLayerCubeKHR, XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) \\\n    _(XrCompositionLayerDepthInfoKHR, XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR) \\\n    _(XrCompositionLayerCylinderKHR, XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) \\\n    _(XrCompositionLayerEquirectKHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) \\\n    _(XrVisibilityMaskKHR, XR_TYPE_VISIBILITY_MASK_KHR) \\\n    _(XrEventDataVisibilityMaskChangedKHR, XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) \\\n    _(XrCompositionLayerColorScaleBiasKHR, XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR) \\\n    _(XrCompositionLayerEquirect2KHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR) \\\n    _(XrBindingModificationsKHR, XR_TYPE_BINDING_MODIFICATIONS_KHR) \\\n    _(XrEventDataPerfSettingsEXT, XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) \\\n    _(XrDebugUtilsObjectNameInfoEXT, XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT) \\\n    _(XrDebugUtilsLabelEXT, XR_TYPE_DEBUG_UTILS_LABEL_EXT) \\\n    _(XrDebugUtilsMessengerCallbackDataEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT) \\\n    _(XrDebugUtilsMessengerCreateInfoEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) \\\n    _(XrSystemEyeGazeInteractionPropertiesEXT, XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT) \\\n    _(XrEyeGazeSampleTimeEXT, XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT) \\\n    _(XrSessionCreateInfoOverlayEXTX, XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX) \\\n    _(XrEventDataMainSessionVisibilityChangedEXTX, XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX) \\\n    _(XrSpatialAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT) \\\n    _(XrSpatialAnchorSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT) \\\n    _(XrCompositionLayerImageLayoutFB, XR_TYPE_COMPOSITION_LAYER_IMAGE_LAYOUT_FB) \\\n    _(XrCompositionLayerAlphaBlendFB, XR_TYPE_COMPOSITION_LAYER_ALPHA_BLEND_FB) \\\n    _(XrViewConfigurationDepthRangeEXT, XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT) \\\n    _(XrSpatialGraphNodeSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT) \\\n    _(XrSpatialGraphStaticNodeBindingCreateInfoMSFT, XR_TYPE_SPATIAL_GRAPH_STATIC_NODE_BINDING_CREATE_INFO_MSFT) \\\n    _(XrSpatialGraphNodeBindingPropertiesGetInfoMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_GET_INFO_MSFT) \\\n    _(XrSpatialGraphNodeBindingPropertiesMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_MSFT) \\\n    _(XrSystemHandTrackingPropertiesEXT, XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT) \\\n    _(XrHandTrackerCreateInfoEXT, XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT) \\\n    _(XrHandJointsLocateInfoEXT, XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT) \\\n    _(XrHandJointLocationsEXT, XR_TYPE_HAND_JOINT_LOCATIONS_EXT) \\\n    _(XrHandJointVelocitiesEXT, XR_TYPE_HAND_JOINT_VELOCITIES_EXT) \\\n    _(XrSystemHandTrackingMeshPropertiesMSFT, XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT) \\\n    _(XrHandMeshSpaceCreateInfoMSFT, XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT) \\\n    _(XrHandMeshUpdateInfoMSFT, XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT) \\\n    _(XrHandMeshMSFT, XR_TYPE_HAND_MESH_MSFT) \\\n    _(XrHandPoseTypeInfoMSFT, XR_TYPE_HAND_POSE_TYPE_INFO_MSFT) \\\n    _(XrSecondaryViewConfigurationSessionBeginInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT) \\\n    _(XrSecondaryViewConfigurationStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT) \\\n    _(XrSecondaryViewConfigurationFrameStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT) \\\n    _(XrSecondaryViewConfigurationLayerInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT) \\\n    _(XrSecondaryViewConfigurationFrameEndInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT) \\\n    _(XrSecondaryViewConfigurationSwapchainCreateInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT) \\\n    _(XrControllerModelKeyStateMSFT, XR_TYPE_CONTROLLER_MODEL_KEY_STATE_MSFT) \\\n    _(XrControllerModelNodePropertiesMSFT, XR_TYPE_CONTROLLER_MODEL_NODE_PROPERTIES_MSFT) \\\n    _(XrControllerModelPropertiesMSFT, XR_TYPE_CONTROLLER_MODEL_PROPERTIES_MSFT) \\\n    _(XrControllerModelNodeStateMSFT, XR_TYPE_CONTROLLER_MODEL_NODE_STATE_MSFT) \\\n    _(XrControllerModelStateMSFT, XR_TYPE_CONTROLLER_MODEL_STATE_MSFT) \\\n    _(XrViewConfigurationViewFovEPIC, XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC) \\\n    _(XrCompositionLayerReprojectionInfoMSFT, XR_TYPE_COMPOSITION_LAYER_REPROJECTION_INFO_MSFT) \\\n    _(XrCompositionLayerReprojectionPlaneOverrideMSFT, XR_TYPE_COMPOSITION_LAYER_REPROJECTION_PLANE_OVERRIDE_MSFT) \\\n    _(XrCompositionLayerSecureContentFB, XR_TYPE_COMPOSITION_LAYER_SECURE_CONTENT_FB) \\\n    _(XrSystemBodyTrackingPropertiesFB, XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_FB) \\\n    _(XrBodyTrackerCreateInfoFB, XR_TYPE_BODY_TRACKER_CREATE_INFO_FB) \\\n    _(XrBodySkeletonFB, XR_TYPE_BODY_SKELETON_FB) \\\n    _(XrBodyJointsLocateInfoFB, XR_TYPE_BODY_JOINTS_LOCATE_INFO_FB) \\\n    _(XrBodyJointLocationsFB, XR_TYPE_BODY_JOINT_LOCATIONS_FB) \\\n    _(XrInteractionProfileDpadBindingEXT, XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT) \\\n    _(XrInteractionProfileAnalogThresholdVALVE, XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE) \\\n    _(XrHandJointsMotionRangeInfoEXT, XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT) \\\n    _(XrSceneObserverCreateInfoMSFT, XR_TYPE_SCENE_OBSERVER_CREATE_INFO_MSFT) \\\n    _(XrSceneCreateInfoMSFT, XR_TYPE_SCENE_CREATE_INFO_MSFT) \\\n    _(XrNewSceneComputeInfoMSFT, XR_TYPE_NEW_SCENE_COMPUTE_INFO_MSFT) \\\n    _(XrVisualMeshComputeLodInfoMSFT, XR_TYPE_VISUAL_MESH_COMPUTE_LOD_INFO_MSFT) \\\n    _(XrSceneComponentsMSFT, XR_TYPE_SCENE_COMPONENTS_MSFT) \\\n    _(XrSceneComponentsGetInfoMSFT, XR_TYPE_SCENE_COMPONENTS_GET_INFO_MSFT) \\\n    _(XrSceneComponentLocationsMSFT, XR_TYPE_SCENE_COMPONENT_LOCATIONS_MSFT) \\\n    _(XrSceneComponentsLocateInfoMSFT, XR_TYPE_SCENE_COMPONENTS_LOCATE_INFO_MSFT) \\\n    _(XrSceneObjectsMSFT, XR_TYPE_SCENE_OBJECTS_MSFT) \\\n    _(XrSceneComponentParentFilterInfoMSFT, XR_TYPE_SCENE_COMPONENT_PARENT_FILTER_INFO_MSFT) \\\n    _(XrSceneObjectTypesFilterInfoMSFT, XR_TYPE_SCENE_OBJECT_TYPES_FILTER_INFO_MSFT) \\\n    _(XrScenePlanesMSFT, XR_TYPE_SCENE_PLANES_MSFT) \\\n    _(XrScenePlaneAlignmentFilterInfoMSFT, XR_TYPE_SCENE_PLANE_ALIGNMENT_FILTER_INFO_MSFT) \\\n    _(XrSceneMeshesMSFT, XR_TYPE_SCENE_MESHES_MSFT) \\\n    _(XrSceneMeshBuffersGetInfoMSFT, XR_TYPE_SCENE_MESH_BUFFERS_GET_INFO_MSFT) \\\n    _(XrSceneMeshBuffersMSFT, XR_TYPE_SCENE_MESH_BUFFERS_MSFT) \\\n    _(XrSceneMeshVertexBufferMSFT, XR_TYPE_SCENE_MESH_VERTEX_BUFFER_MSFT) \\\n    _(XrSceneMeshIndicesUint32MSFT, XR_TYPE_SCENE_MESH_INDICES_UINT32_MSFT) \\\n    _(XrSceneMeshIndicesUint16MSFT, XR_TYPE_SCENE_MESH_INDICES_UINT16_MSFT) \\\n    _(XrSerializedSceneFragmentDataGetInfoMSFT, XR_TYPE_SERIALIZED_SCENE_FRAGMENT_DATA_GET_INFO_MSFT) \\\n    _(XrSceneDeserializeInfoMSFT, XR_TYPE_SCENE_DESERIALIZE_INFO_MSFT) \\\n    _(XrEventDataDisplayRefreshRateChangedFB, XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB) \\\n    _(XrViveTrackerPathsHTCX, XR_TYPE_VIVE_TRACKER_PATHS_HTCX) \\\n    _(XrEventDataViveTrackerConnectedHTCX, XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX) \\\n    _(XrSystemFacialTrackingPropertiesHTC, XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC) \\\n    _(XrFacialExpressionsHTC, XR_TYPE_FACIAL_EXPRESSIONS_HTC) \\\n    _(XrFacialTrackerCreateInfoHTC, XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC) \\\n    _(XrSystemColorSpacePropertiesFB, XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB) \\\n    _(XrHandTrackingMeshFB, XR_TYPE_HAND_TRACKING_MESH_FB) \\\n    _(XrHandTrackingScaleFB, XR_TYPE_HAND_TRACKING_SCALE_FB) \\\n    _(XrHandTrackingAimStateFB, XR_TYPE_HAND_TRACKING_AIM_STATE_FB) \\\n    _(XrHandTrackingCapsulesStateFB, XR_TYPE_HAND_TRACKING_CAPSULES_STATE_FB) \\\n    _(XrSystemSpatialEntityPropertiesFB, XR_TYPE_SYSTEM_SPATIAL_ENTITY_PROPERTIES_FB) \\\n    _(XrSpatialAnchorCreateInfoFB, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_FB) \\\n    _(XrSpaceComponentStatusSetInfoFB, XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB) \\\n    _(XrSpaceComponentStatusFB, XR_TYPE_SPACE_COMPONENT_STATUS_FB) \\\n    _(XrEventDataSpatialAnchorCreateCompleteFB, XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB) \\\n    _(XrEventDataSpaceSetStatusCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) \\\n    _(XrFoveationProfileCreateInfoFB, XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB) \\\n    _(XrSwapchainCreateInfoFoveationFB, XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB) \\\n    _(XrSwapchainStateFoveationFB, XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB) \\\n    _(XrFoveationLevelProfileCreateInfoFB, XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB) \\\n    _(XrSystemKeyboardTrackingPropertiesFB, XR_TYPE_SYSTEM_KEYBOARD_TRACKING_PROPERTIES_FB) \\\n    _(XrKeyboardSpaceCreateInfoFB, XR_TYPE_KEYBOARD_SPACE_CREATE_INFO_FB) \\\n    _(XrKeyboardTrackingQueryFB, XR_TYPE_KEYBOARD_TRACKING_QUERY_FB) \\\n    _(XrTriangleMeshCreateInfoFB, XR_TYPE_TRIANGLE_MESH_CREATE_INFO_FB) \\\n    _(XrSystemPassthroughPropertiesFB, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB) \\\n    _(XrSystemPassthroughProperties2FB, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB) \\\n    _(XrPassthroughCreateInfoFB, XR_TYPE_PASSTHROUGH_CREATE_INFO_FB) \\\n    _(XrPassthroughLayerCreateInfoFB, XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB) \\\n    _(XrCompositionLayerPassthroughFB, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB) \\\n    _(XrGeometryInstanceCreateInfoFB, XR_TYPE_GEOMETRY_INSTANCE_CREATE_INFO_FB) \\\n    _(XrGeometryInstanceTransformFB, XR_TYPE_GEOMETRY_INSTANCE_TRANSFORM_FB) \\\n    _(XrPassthroughStyleFB, XR_TYPE_PASSTHROUGH_STYLE_FB) \\\n    _(XrPassthroughColorMapMonoToRgbaFB, XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB) \\\n    _(XrPassthroughColorMapMonoToMonoFB, XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB) \\\n    _(XrPassthroughBrightnessContrastSaturationFB, XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB) \\\n    _(XrEventDataPassthroughStateChangedFB, XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB) \\\n    _(XrRenderModelPathInfoFB, XR_TYPE_RENDER_MODEL_PATH_INFO_FB) \\\n    _(XrRenderModelPropertiesFB, XR_TYPE_RENDER_MODEL_PROPERTIES_FB) \\\n    _(XrRenderModelBufferFB, XR_TYPE_RENDER_MODEL_BUFFER_FB) \\\n    _(XrRenderModelLoadInfoFB, XR_TYPE_RENDER_MODEL_LOAD_INFO_FB) \\\n    _(XrSystemRenderModelPropertiesFB, XR_TYPE_SYSTEM_RENDER_MODEL_PROPERTIES_FB) \\\n    _(XrRenderModelCapabilitiesRequestFB, XR_TYPE_RENDER_MODEL_CAPABILITIES_REQUEST_FB) \\\n    _(XrViewLocateFoveatedRenderingVARJO, XR_TYPE_VIEW_LOCATE_FOVEATED_RENDERING_VARJO) \\\n    _(XrFoveatedViewConfigurationViewVARJO, XR_TYPE_FOVEATED_VIEW_CONFIGURATION_VIEW_VARJO) \\\n    _(XrSystemFoveatedRenderingPropertiesVARJO, XR_TYPE_SYSTEM_FOVEATED_RENDERING_PROPERTIES_VARJO) \\\n    _(XrCompositionLayerDepthTestVARJO, XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_VARJO) \\\n    _(XrSystemMarkerTrackingPropertiesVARJO, XR_TYPE_SYSTEM_MARKER_TRACKING_PROPERTIES_VARJO) \\\n    _(XrEventDataMarkerTrackingUpdateVARJO, XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO) \\\n    _(XrMarkerSpaceCreateInfoVARJO, XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO) \\\n    _(XrFrameEndInfoML, XR_TYPE_FRAME_END_INFO_ML) \\\n    _(XrGlobalDimmerFrameEndInfoML, XR_TYPE_GLOBAL_DIMMER_FRAME_END_INFO_ML) \\\n    _(XrSpatialAnchorPersistenceInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT) \\\n    _(XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT) \\\n    _(XrSpaceQueryInfoFB, XR_TYPE_SPACE_QUERY_INFO_FB) \\\n    _(XrSpaceStorageLocationFilterInfoFB, XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB) \\\n    _(XrSpaceUuidFilterInfoFB, XR_TYPE_SPACE_UUID_FILTER_INFO_FB) \\\n    _(XrSpaceComponentFilterInfoFB, XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB) \\\n    _(XrSpaceQueryResultsFB, XR_TYPE_SPACE_QUERY_RESULTS_FB) \\\n    _(XrEventDataSpaceQueryResultsAvailableFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) \\\n    _(XrEventDataSpaceQueryCompleteFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) \\\n    _(XrSpaceSaveInfoFB, XR_TYPE_SPACE_SAVE_INFO_FB) \\\n    _(XrSpaceEraseInfoFB, XR_TYPE_SPACE_ERASE_INFO_FB) \\\n    _(XrEventDataSpaceSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB) \\\n    _(XrEventDataSpaceEraseCompleteFB, XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB) \\\n    _(XrSpaceShareInfoFB, XR_TYPE_SPACE_SHARE_INFO_FB) \\\n    _(XrEventDataSpaceShareCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SHARE_COMPLETE_FB) \\\n    _(XrCompositionLayerSpaceWarpInfoFB, XR_TYPE_COMPOSITION_LAYER_SPACE_WARP_INFO_FB) \\\n    _(XrSystemSpaceWarpPropertiesFB, XR_TYPE_SYSTEM_SPACE_WARP_PROPERTIES_FB) \\\n    _(XrHapticAmplitudeEnvelopeVibrationFB, XR_TYPE_HAPTIC_AMPLITUDE_ENVELOPE_VIBRATION_FB) \\\n    _(XrSemanticLabelsFB, XR_TYPE_SEMANTIC_LABELS_FB) \\\n    _(XrRoomLayoutFB, XR_TYPE_ROOM_LAYOUT_FB) \\\n    _(XrBoundary2DFB, XR_TYPE_BOUNDARY_2D_FB) \\\n    _(XrSemanticLabelsSupportInfoFB, XR_TYPE_SEMANTIC_LABELS_SUPPORT_INFO_FB) \\\n    _(XrDigitalLensControlALMALENCE, XR_TYPE_DIGITAL_LENS_CONTROL_ALMALENCE) \\\n    _(XrEventDataSceneCaptureCompleteFB, XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB) \\\n    _(XrSceneCaptureRequestInfoFB, XR_TYPE_SCENE_CAPTURE_REQUEST_INFO_FB) \\\n    _(XrSpaceContainerFB, XR_TYPE_SPACE_CONTAINER_FB) \\\n    _(XrFoveationEyeTrackedProfileCreateInfoMETA, XR_TYPE_FOVEATION_EYE_TRACKED_PROFILE_CREATE_INFO_META) \\\n    _(XrFoveationEyeTrackedStateMETA, XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META) \\\n    _(XrSystemFoveationEyeTrackedPropertiesMETA, XR_TYPE_SYSTEM_FOVEATION_EYE_TRACKED_PROPERTIES_META) \\\n    _(XrSystemFaceTrackingPropertiesFB, XR_TYPE_SYSTEM_FACE_TRACKING_PROPERTIES_FB) \\\n    _(XrFaceTrackerCreateInfoFB, XR_TYPE_FACE_TRACKER_CREATE_INFO_FB) \\\n    _(XrFaceExpressionInfoFB, XR_TYPE_FACE_EXPRESSION_INFO_FB) \\\n    _(XrFaceExpressionWeightsFB, XR_TYPE_FACE_EXPRESSION_WEIGHTS_FB) \\\n    _(XrEyeTrackerCreateInfoFB, XR_TYPE_EYE_TRACKER_CREATE_INFO_FB) \\\n    _(XrEyeGazesInfoFB, XR_TYPE_EYE_GAZES_INFO_FB) \\\n    _(XrSystemEyeTrackingPropertiesFB, XR_TYPE_SYSTEM_EYE_TRACKING_PROPERTIES_FB) \\\n    _(XrEyeGazesFB, XR_TYPE_EYE_GAZES_FB) \\\n    _(XrPassthroughKeyboardHandsIntensityFB, XR_TYPE_PASSTHROUGH_KEYBOARD_HANDS_INTENSITY_FB) \\\n    _(XrCompositionLayerSettingsFB, XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB) \\\n    _(XrHapticPcmVibrationFB, XR_TYPE_HAPTIC_PCM_VIBRATION_FB) \\\n    _(XrDevicePcmSampleRateStateFB, XR_TYPE_DEVICE_PCM_SAMPLE_RATE_STATE_FB) \\\n    _(XrCompositionLayerDepthTestFB, XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_FB) \\\n    _(XrLocalDimmingFrameEndInfoMETA, XR_TYPE_LOCAL_DIMMING_FRAME_END_INFO_META) \\\n    _(XrSystemVirtualKeyboardPropertiesMETA, XR_TYPE_SYSTEM_VIRTUAL_KEYBOARD_PROPERTIES_META) \\\n    _(XrVirtualKeyboardCreateInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_CREATE_INFO_META) \\\n    _(XrVirtualKeyboardSpaceCreateInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_SPACE_CREATE_INFO_META) \\\n    _(XrVirtualKeyboardLocationInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_LOCATION_INFO_META) \\\n    _(XrVirtualKeyboardModelVisibilitySetInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_MODEL_VISIBILITY_SET_INFO_META) \\\n    _(XrVirtualKeyboardAnimationStateMETA, XR_TYPE_VIRTUAL_KEYBOARD_ANIMATION_STATE_META) \\\n    _(XrVirtualKeyboardModelAnimationStatesMETA, XR_TYPE_VIRTUAL_KEYBOARD_MODEL_ANIMATION_STATES_META) \\\n    _(XrVirtualKeyboardTextureDataMETA, XR_TYPE_VIRTUAL_KEYBOARD_TEXTURE_DATA_META) \\\n    _(XrVirtualKeyboardInputInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_INPUT_INFO_META) \\\n    _(XrVirtualKeyboardTextContextChangeInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_TEXT_CONTEXT_CHANGE_INFO_META) \\\n    _(XrEventDataVirtualKeyboardCommitTextMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_COMMIT_TEXT_META) \\\n    _(XrEventDataVirtualKeyboardBackspaceMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_BACKSPACE_META) \\\n    _(XrEventDataVirtualKeyboardEnterMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_ENTER_META) \\\n    _(XrEventDataVirtualKeyboardShownMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_SHOWN_META) \\\n    _(XrEventDataVirtualKeyboardHiddenMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_HIDDEN_META) \\\n    _(XrExternalCameraOCULUS, XR_TYPE_EXTERNAL_CAMERA_OCULUS) \\\n    _(XrPerformanceMetricsStateMETA, XR_TYPE_PERFORMANCE_METRICS_STATE_META) \\\n    _(XrPerformanceMetricsCounterMETA, XR_TYPE_PERFORMANCE_METRICS_COUNTER_META) \\\n    _(XrSpaceListSaveInfoFB, XR_TYPE_SPACE_LIST_SAVE_INFO_FB) \\\n    _(XrEventDataSpaceListSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_LIST_SAVE_COMPLETE_FB) \\\n    _(XrSpaceUserCreateInfoFB, XR_TYPE_SPACE_USER_CREATE_INFO_FB) \\\n    _(XrSystemHeadsetIdPropertiesMETA, XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META) \\\n    _(XrPassthroughColorLutCreateInfoMETA, XR_TYPE_PASSTHROUGH_COLOR_LUT_CREATE_INFO_META) \\\n    _(XrPassthroughColorLutUpdateInfoMETA, XR_TYPE_PASSTHROUGH_COLOR_LUT_UPDATE_INFO_META) \\\n    _(XrPassthroughColorMapLutMETA, XR_TYPE_PASSTHROUGH_COLOR_MAP_LUT_META) \\\n    _(XrPassthroughColorMapInterpolatedLutMETA, XR_TYPE_PASSTHROUGH_COLOR_MAP_INTERPOLATED_LUT_META) \\\n    _(XrSystemPassthroughColorLutPropertiesMETA, XR_TYPE_SYSTEM_PASSTHROUGH_COLOR_LUT_PROPERTIES_META) \\\n    _(XrPassthroughCreateInfoHTC, XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC) \\\n    _(XrPassthroughColorHTC, XR_TYPE_PASSTHROUGH_COLOR_HTC) \\\n    _(XrPassthroughMeshTransformInfoHTC, XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC) \\\n    _(XrCompositionLayerPassthroughHTC, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC) \\\n    _(XrFoveationApplyInfoHTC, XR_TYPE_FOVEATION_APPLY_INFO_HTC) \\\n    _(XrFoveationDynamicModeInfoHTC, XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC) \\\n    _(XrFoveationCustomModeInfoHTC, XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC) \\\n    _(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \\\n    _(XrSystemForceFeedbackCurlPropertiesMNDX, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX) \\\n    _(XrForceFeedbackCurlApplyLocationsMNDX, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX) \\\n    _(XrHandTrackingDataSourceInfoEXT, XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT) \\\n    _(XrHandTrackingDataSourceStateEXT, XR_TYPE_HAND_TRACKING_DATA_SOURCE_STATE_EXT) \\\n    _(XrSystemPlaneDetectionPropertiesEXT, XR_TYPE_SYSTEM_PLANE_DETECTION_PROPERTIES_EXT) \\\n    _(XrPlaneDetectorCreateInfoEXT, XR_TYPE_PLANE_DETECTOR_CREATE_INFO_EXT) \\\n    _(XrPlaneDetectorBeginInfoEXT, XR_TYPE_PLANE_DETECTOR_BEGIN_INFO_EXT) \\\n    _(XrPlaneDetectorGetInfoEXT, XR_TYPE_PLANE_DETECTOR_GET_INFO_EXT) \\\n    _(XrPlaneDetectorLocationEXT, XR_TYPE_PLANE_DETECTOR_LOCATION_EXT) \\\n    _(XrPlaneDetectorLocationsEXT, XR_TYPE_PLANE_DETECTOR_LOCATIONS_EXT) \\\n    _(XrPlaneDetectorPolygonBufferEXT, XR_TYPE_PLANE_DETECTOR_POLYGON_BUFFER_EXT) \\\n\n\n#if defined(XR_USE_GRAPHICS_API_D3D11)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_D3D11 is defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \\\n    _(XrGraphicsBindingD3D11KHR, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) \\\n    _(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \\\n    _(XrGraphicsRequirementsD3D11KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_)\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_D3D12)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_D3D12 is defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \\\n    _(XrGraphicsBindingD3D12KHR, XR_TYPE_GRAPHICS_BINDING_D3D12_KHR) \\\n    _(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \\\n    _(XrGraphicsRequirementsD3D12KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_)\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL is defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \\\n    _(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \\\n    _(XrGraphicsRequirementsOpenGLKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_)\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL and XR_USE_PLATFORM_WAYLAND are defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_) \\\n    _(XrGraphicsBindingOpenGLWaylandKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_)\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL and XR_USE_PLATFORM_WIN32 are defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_) \\\n    _(XrGraphicsBindingOpenGLWin32KHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_)\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL and XR_USE_PLATFORM_XCB are defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) \\\n    _(XrGraphicsBindingOpenGLXcbKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_)\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL and XR_USE_PLATFORM_XLIB are defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_) \\\n    _(XrGraphicsBindingOpenGLXlibKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_)\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL_ES is defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) \\\n    _(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \\\n    _(XrGraphicsRequirementsOpenGLESKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR) \\\n    _(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_)\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_OPENGL_ES and XR_USE_PLATFORM_ANDROID are defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) \\\n    _(XrGraphicsBindingOpenGLESAndroidKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_)\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_VULKAN)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_GRAPHICS_API_VULKAN is defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) \\\n    _(XrVulkanSwapchainFormatListCreateInfoKHR, XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR) \\\n    _(XrGraphicsBindingVulkanKHR, XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) \\\n    _(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \\\n    _(XrGraphicsRequirementsVulkanKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR) \\\n    _(XrVulkanInstanceCreateInfoKHR, XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR) \\\n    _(XrVulkanDeviceCreateInfoKHR, XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR) \\\n    _(XrVulkanGraphicsDeviceGetInfoKHR, XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR) \\\n    _(XrSwapchainImageFoveationVulkanFB, XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB) \\\n    _(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \\\n    _(XrVulkanSwapchainCreateInfoMETA, XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_)\n#endif\n\n#if defined(XR_USE_PLATFORM_ANDROID)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_PLATFORM_ANDROID is defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) \\\n    _(XrInstanceCreateInfoAndroidKHR, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR) \\\n    _(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \\\n    _(XrAndroidSurfaceSwapchainCreateInfoFB, XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB) \\\n    _(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_)\n#endif\n\n#if defined(XR_USE_PLATFORM_EGL)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_PLATFORM_EGL is defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) \\\n    _(XrGraphicsBindingEGLMNDX, XR_TYPE_GRAPHICS_BINDING_EGL_MNDX) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_)\n#endif\n\n#if defined(XR_USE_PLATFORM_ML)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_PLATFORM_ML is defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ML(_) \\\n    _(XrCoordinateSpaceCreateInfoML, XR_TYPE_COORDINATE_SPACE_CREATE_INFO_ML) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ML(_)\n#endif\n\n#if defined(XR_USE_PLATFORM_WIN32)\n/// Implementation detail of XR_LIST_STRUCTURE_TYPES()\n/// Structure types available only when XR_USE_PLATFORM_WIN32 is defined\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) \\\n    _(XrHolographicWindowAttachmentMSFT, XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT) \\\n\n#else\n#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_)\n#endif\n\n\n\n/// Calls your macro with the name and extension number of all known\n/// extensions in this version of the spec.\n#define XR_LIST_EXTENSIONS(_) \\\n    _(XR_KHR_android_thread_settings, 4) \\\n    _(XR_KHR_android_surface_swapchain, 5) \\\n    _(XR_KHR_composition_layer_cube, 7) \\\n    _(XR_KHR_android_create_instance, 9) \\\n    _(XR_KHR_composition_layer_depth, 11) \\\n    _(XR_KHR_vulkan_swapchain_format_list, 15) \\\n    _(XR_EXT_performance_settings, 16) \\\n    _(XR_EXT_thermal_query, 17) \\\n    _(XR_KHR_composition_layer_cylinder, 18) \\\n    _(XR_KHR_composition_layer_equirect, 19) \\\n    _(XR_EXT_debug_utils, 20) \\\n    _(XR_KHR_opengl_enable, 24) \\\n    _(XR_KHR_opengl_es_enable, 25) \\\n    _(XR_KHR_vulkan_enable, 26) \\\n    _(XR_KHR_D3D11_enable, 28) \\\n    _(XR_KHR_D3D12_enable, 29) \\\n    _(XR_EXT_eye_gaze_interaction, 31) \\\n    _(XR_KHR_visibility_mask, 32) \\\n    _(XR_EXTX_overlay, 34) \\\n    _(XR_KHR_composition_layer_color_scale_bias, 35) \\\n    _(XR_KHR_win32_convert_performance_counter_time, 36) \\\n    _(XR_KHR_convert_timespec_time, 37) \\\n    _(XR_VARJO_quad_views, 38) \\\n    _(XR_MSFT_unbounded_reference_space, 39) \\\n    _(XR_MSFT_spatial_anchor, 40) \\\n    _(XR_FB_composition_layer_image_layout, 41) \\\n    _(XR_FB_composition_layer_alpha_blend, 42) \\\n    _(XR_MND_headless, 43) \\\n    _(XR_OCULUS_android_session_state_enable, 45) \\\n    _(XR_EXT_view_configuration_depth_range, 47) \\\n    _(XR_EXT_conformance_automation, 48) \\\n    _(XR_MNDX_egl_enable, 49) \\\n    _(XR_MSFT_spatial_graph_bridge, 50) \\\n    _(XR_MSFT_hand_interaction, 51) \\\n    _(XR_EXT_hand_tracking, 52) \\\n    _(XR_MSFT_hand_tracking_mesh, 53) \\\n    _(XR_MSFT_secondary_view_configuration, 54) \\\n    _(XR_MSFT_first_person_observer, 55) \\\n    _(XR_MSFT_controller_model, 56) \\\n    _(XR_MSFT_perception_anchor_interop, 57) \\\n    _(XR_EXT_win32_appcontainer_compatible, 58) \\\n    _(XR_EPIC_view_configuration_fov, 60) \\\n    _(XR_MSFT_holographic_window_attachment, 64) \\\n    _(XR_MSFT_composition_layer_reprojection, 67) \\\n    _(XR_HUAWEI_controller_interaction, 70) \\\n    _(XR_FB_android_surface_swapchain_create, 71) \\\n    _(XR_FB_swapchain_update_state, 72) \\\n    _(XR_FB_composition_layer_secure_content, 73) \\\n    _(XR_FB_body_tracking, 77) \\\n    _(XR_EXT_dpad_binding, 79) \\\n    _(XR_VALVE_analog_threshold, 80) \\\n    _(XR_EXT_hand_joints_motion_range, 81) \\\n    _(XR_KHR_loader_init, 89) \\\n    _(XR_KHR_loader_init_android, 90) \\\n    _(XR_KHR_vulkan_enable2, 91) \\\n    _(XR_KHR_composition_layer_equirect2, 92) \\\n    _(XR_EXT_samsung_odyssey_controller, 95) \\\n    _(XR_EXT_hp_mixed_reality_controller, 96) \\\n    _(XR_MND_swapchain_usage_input_attachment_bit, 97) \\\n    _(XR_MSFT_scene_understanding, 98) \\\n    _(XR_MSFT_scene_understanding_serialization, 99) \\\n    _(XR_FB_display_refresh_rate, 102) \\\n    _(XR_HTC_vive_cosmos_controller_interaction, 103) \\\n    _(XR_HTCX_vive_tracker_interaction, 104) \\\n    _(XR_HTC_facial_tracking, 105) \\\n    _(XR_HTC_vive_focus3_controller_interaction, 106) \\\n    _(XR_HTC_hand_interaction, 107) \\\n    _(XR_HTC_vive_wrist_tracker_interaction, 108) \\\n    _(XR_FB_color_space, 109) \\\n    _(XR_FB_hand_tracking_mesh, 111) \\\n    _(XR_FB_hand_tracking_aim, 112) \\\n    _(XR_FB_hand_tracking_capsules, 113) \\\n    _(XR_FB_spatial_entity, 114) \\\n    _(XR_FB_foveation, 115) \\\n    _(XR_FB_foveation_configuration, 116) \\\n    _(XR_FB_keyboard_tracking, 117) \\\n    _(XR_FB_triangle_mesh, 118) \\\n    _(XR_FB_passthrough, 119) \\\n    _(XR_FB_render_model, 120) \\\n    _(XR_KHR_binding_modification, 121) \\\n    _(XR_VARJO_foveated_rendering, 122) \\\n    _(XR_VARJO_composition_layer_depth_test, 123) \\\n    _(XR_VARJO_environment_depth_estimation, 124) \\\n    _(XR_VARJO_marker_tracking, 125) \\\n    _(XR_VARJO_view_offset, 126) \\\n    _(XR_ML_ml2_controller_interaction, 135) \\\n    _(XR_ML_frame_end_info, 136) \\\n    _(XR_ML_global_dimmer, 137) \\\n    _(XR_ML_compat, 138) \\\n    _(XR_MSFT_spatial_anchor_persistence, 143) \\\n    _(XR_ULTRALEAP_hand_tracking_forearm, 150) \\\n    _(XR_FB_spatial_entity_query, 157) \\\n    _(XR_FB_spatial_entity_storage, 159) \\\n    _(XR_OCULUS_audio_device_guid, 160) \\\n    _(XR_FB_foveation_vulkan, 161) \\\n    _(XR_FB_swapchain_update_state_android_surface, 162) \\\n    _(XR_FB_swapchain_update_state_opengl_es, 163) \\\n    _(XR_FB_swapchain_update_state_vulkan, 164) \\\n    _(XR_KHR_swapchain_usage_input_attachment_bit, 166) \\\n    _(XR_FB_touch_controller_pro, 168) \\\n    _(XR_FB_spatial_entity_sharing, 170) \\\n    _(XR_FB_space_warp, 172) \\\n    _(XR_FB_haptic_amplitude_envelope, 174) \\\n    _(XR_FB_scene, 176) \\\n    _(XR_EXT_palm_pose, 177) \\\n    _(XR_ALMALENCE_digital_lens_control, 197) \\\n    _(XR_FB_scene_capture, 199) \\\n    _(XR_FB_spatial_entity_container, 200) \\\n    _(XR_META_foveation_eye_tracked, 201) \\\n    _(XR_FB_face_tracking, 202) \\\n    _(XR_FB_eye_tracking_social, 203) \\\n    _(XR_FB_passthrough_keyboard_hands, 204) \\\n    _(XR_FB_composition_layer_settings, 205) \\\n    _(XR_FB_touch_controller_proximity, 207) \\\n    _(XR_FB_haptic_pcm, 210) \\\n    _(XR_FB_composition_layer_depth_test, 213) \\\n    _(XR_META_local_dimming, 217) \\\n    _(XR_META_virtual_keyboard, 220) \\\n    _(XR_OCULUS_external_camera, 227) \\\n    _(XR_META_vulkan_swapchain_create_info, 228) \\\n    _(XR_META_performance_metrics, 233) \\\n    _(XR_FB_spatial_entity_storage_batch, 239) \\\n    _(XR_FB_spatial_entity_user, 242) \\\n    _(XR_META_headset_id, 246) \\\n    _(XR_META_passthrough_color_lut, 267) \\\n    _(XR_EXT_uuid, 300) \\\n    _(XR_EXT_hand_interaction, 303) \\\n    _(XR_QCOM_tracking_optimization_settings, 307) \\\n    _(XR_HTC_passthrough, 318) \\\n    _(XR_HTC_foveation, 319) \\\n    _(XR_EXT_active_action_set_priority, 374) \\\n    _(XR_MNDX_force_feedback_curl, 376) \\\n    _(XR_BD_controller_interaction, 385) \\\n    _(XR_EXT_local_floor, 427) \\\n    _(XR_EXT_hand_tracking_data_source, 429) \\\n    _(XR_EXT_plane_detection, 430) \\\n    _(XR_OPPO_controller_interaction, 454) \\\n\n\n#endif\n\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/openxr/openxr_reflection_parent_structs.h",
    "content": "#ifndef OPENXR_REFLECTION_PARENT_STRUCTS_H_\n#define OPENXR_REFLECTION_PARENT_STRUCTS_H_ 1\n\n/*\n** Copyright (c) 2017-2023, The Khronos Group Inc.\n**\n** SPDX-License-Identifier: Apache-2.0 OR MIT\n*/\n\n/*\n** This header is generated from the Khronos OpenXR XML API Registry.\n**\n*/\n\n#include \"openxr.h\"\n\n/*\nThis file contains expansion macros (X Macros) for OpenXR structures that have a parent type.\n*/\n\n\n/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrCompositionLayerBaseHeader\n#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader_CORE(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader()\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader_CORE(_avail, _unavail) \\\n    _avail(XrCompositionLayerProjection, XR_TYPE_COMPOSITION_LAYER_PROJECTION) \\\n    _avail(XrCompositionLayerQuad, XR_TYPE_COMPOSITION_LAYER_QUAD) \\\n    _avail(XrCompositionLayerCubeKHR, XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) \\\n    _avail(XrCompositionLayerCylinderKHR, XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) \\\n    _avail(XrCompositionLayerEquirectKHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) \\\n    _avail(XrCompositionLayerEquirect2KHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR) \\\n    _avail(XrCompositionLayerPassthroughHTC, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC) \\\n\n\n\n\n\n/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrEventDataBaseHeader\n#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader_CORE(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader()\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader_CORE(_avail, _unavail) \\\n    _avail(XrEventDataEventsLost, XR_TYPE_EVENT_DATA_EVENTS_LOST) \\\n    _avail(XrEventDataInstanceLossPending, XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) \\\n    _avail(XrEventDataSessionStateChanged, XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) \\\n    _avail(XrEventDataReferenceSpaceChangePending, XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) \\\n    _avail(XrEventDataInteractionProfileChanged, XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) \\\n    _avail(XrEventDataVisibilityMaskChangedKHR, XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) \\\n    _avail(XrEventDataPerfSettingsEXT, XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) \\\n    _avail(XrEventDataMainSessionVisibilityChangedEXTX, XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX) \\\n    _avail(XrEventDataDisplayRefreshRateChangedFB, XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB) \\\n    _avail(XrEventDataViveTrackerConnectedHTCX, XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX) \\\n    _avail(XrEventDataSpatialAnchorCreateCompleteFB, XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB) \\\n    _avail(XrEventDataSpaceSetStatusCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) \\\n    _avail(XrEventDataMarkerTrackingUpdateVARJO, XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO) \\\n    _avail(XrEventDataSpaceQueryResultsAvailableFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) \\\n    _avail(XrEventDataSpaceQueryCompleteFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) \\\n    _avail(XrEventDataSpaceSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB) \\\n    _avail(XrEventDataSpaceEraseCompleteFB, XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB) \\\n    _avail(XrEventDataSpaceShareCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SHARE_COMPLETE_FB) \\\n    _avail(XrEventDataSpaceListSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_LIST_SAVE_COMPLETE_FB) \\\n\n\n\n\n\n/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrHapticBaseHeader\n#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader_CORE(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader()\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader_CORE(_avail, _unavail) \\\n    _avail(XrHapticVibration, XR_TYPE_HAPTIC_VIBRATION) \\\n    _avail(XrHapticAmplitudeEnvelopeVibrationFB, XR_TYPE_HAPTIC_AMPLITUDE_ENVELOPE_VIBRATION_FB) \\\n    _avail(XrHapticPcmVibrationFB, XR_TYPE_HAPTIC_PCM_VIBRATION_FB) \\\n\n\n\n\n\n/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSwapchainImageBaseHeader\n#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_CORE(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader()\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_CORE(_avail, _unavail) \\\n\n\n#if defined(XR_USE_GRAPHICS_API_D3D11)\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \\\n    _avail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \\\n    _unavail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_D3D12)\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \\\n    _avail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \\\n    _unavail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL)\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \\\n    _avail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \\\n    _unavail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \\\n    _avail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \\\n    _unavail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_VULKAN)\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \\\n    _avail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \\\n    _unavail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \\\n\n#endif\n\n\n\n\n/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrLoaderInitInfoBaseHeaderKHR\n#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_CORE(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR()\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_CORE(_avail, _unavail) \\\n\n\n#if defined(XR_USE_PLATFORM_ANDROID)\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _avail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _unavail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \\\n\n#endif\n\n\n\n\n/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrBindingModificationBaseHeaderKHR\n#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR_CORE(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR()\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR_CORE(_avail, _unavail) \\\n    _avail(XrInteractionProfileDpadBindingEXT, XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT) \\\n    _avail(XrInteractionProfileAnalogThresholdVALVE, XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE) \\\n\n\n\n\n\n/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSwapchainStateBaseHeaderFB\n#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_CORE(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB()\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_CORE(_avail, _unavail) \\\n    _avail(XrSwapchainStateFoveationFB, XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB) \\\n\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \\\n    _avail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \\\n\n#else\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \\\n    _unavail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_VULKAN)\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \\\n    _avail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \\\n\n#else\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \\\n    _unavail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \\\n\n#endif\n\n#if defined(XR_USE_PLATFORM_ANDROID)\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _avail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \\\n\n#else\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _unavail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \\\n\n#endif\n\n\n\n\n/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpaceQueryInfoBaseHeaderFB\n#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB_CORE(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB()\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB_CORE(_avail, _unavail) \\\n    _avail(XrSpaceQueryInfoFB, XR_TYPE_SPACE_QUERY_INFO_FB) \\\n\n\n\n\n\n/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpaceFilterInfoBaseHeaderFB\n#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB_CORE(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB()\n#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB_CORE(_avail, _unavail) \\\n    _avail(XrSpaceUuidFilterInfoFB, XR_TYPE_SPACE_UUID_FILTER_INFO_FB) \\\n    _avail(XrSpaceComponentFilterInfoFB, XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB) \\\n\n\n\n#endif\n\n"
  },
  {
    "path": "modules/rayneoSDKHeaders/openxr/openxr_reflection_structs.h",
    "content": "#ifndef OPENXR_REFLECTION_STRUCTS_H_\n#define OPENXR_REFLECTION_STRUCTS_H_ 1\n\n/*\n** Copyright (c) 2017-2023, The Khronos Group Inc.\n**\n** SPDX-License-Identifier: Apache-2.0 OR MIT\n*/\n\n/*\n** This header is generated from the Khronos OpenXR XML API Registry.\n**\n*/\n\n#include \"openxr.h\"\n\n/*\nThis file contains expansion macros (X Macros) for OpenXR structures.\n*/\n\n\n\n/// Calls one of your macros with the structure type name and the XrStructureType constant for\n/// each known structure type. The first macro (_avail) is called for those that are available,\n/// while the second macro (_unavail) is called for those unavailable due to preprocessor definitions.\n#define XR_LIST_ALL_STRUCTURE_TYPES(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_CORE(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_ML(_avail, _unavail) \\\n    _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_avail, _unavail) \\\n\n\n// Implementation detail of XR_LIST_ALL_STRUCTURE_TYPES()\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_CORE(_avail, _unavail) \\\n    _avail(XrApiLayerProperties, XR_TYPE_API_LAYER_PROPERTIES) \\\n    _avail(XrExtensionProperties, XR_TYPE_EXTENSION_PROPERTIES) \\\n    _avail(XrInstanceCreateInfo, XR_TYPE_INSTANCE_CREATE_INFO) \\\n    _avail(XrInstanceProperties, XR_TYPE_INSTANCE_PROPERTIES) \\\n    _avail(XrEventDataBuffer, XR_TYPE_EVENT_DATA_BUFFER) \\\n    _avail(XrSystemGetInfo, XR_TYPE_SYSTEM_GET_INFO) \\\n    _avail(XrSystemProperties, XR_TYPE_SYSTEM_PROPERTIES) \\\n    _avail(XrSessionCreateInfo, XR_TYPE_SESSION_CREATE_INFO) \\\n    _avail(XrSpaceVelocity, XR_TYPE_SPACE_VELOCITY) \\\n    _avail(XrReferenceSpaceCreateInfo, XR_TYPE_REFERENCE_SPACE_CREATE_INFO) \\\n    _avail(XrActionSpaceCreateInfo, XR_TYPE_ACTION_SPACE_CREATE_INFO) \\\n    _avail(XrSpaceLocation, XR_TYPE_SPACE_LOCATION) \\\n    _avail(XrViewConfigurationProperties, XR_TYPE_VIEW_CONFIGURATION_PROPERTIES) \\\n    _avail(XrViewConfigurationView, XR_TYPE_VIEW_CONFIGURATION_VIEW) \\\n    _avail(XrSwapchainCreateInfo, XR_TYPE_SWAPCHAIN_CREATE_INFO) \\\n    _avail(XrSwapchainImageAcquireInfo, XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO) \\\n    _avail(XrSwapchainImageWaitInfo, XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO) \\\n    _avail(XrSwapchainImageReleaseInfo, XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO) \\\n    _avail(XrSessionBeginInfo, XR_TYPE_SESSION_BEGIN_INFO) \\\n    _avail(XrFrameWaitInfo, XR_TYPE_FRAME_WAIT_INFO) \\\n    _avail(XrFrameState, XR_TYPE_FRAME_STATE) \\\n    _avail(XrFrameBeginInfo, XR_TYPE_FRAME_BEGIN_INFO) \\\n    _avail(XrFrameEndInfo, XR_TYPE_FRAME_END_INFO) \\\n    _avail(XrViewLocateInfo, XR_TYPE_VIEW_LOCATE_INFO) \\\n    _avail(XrViewState, XR_TYPE_VIEW_STATE) \\\n    _avail(XrView, XR_TYPE_VIEW) \\\n    _avail(XrActionSetCreateInfo, XR_TYPE_ACTION_SET_CREATE_INFO) \\\n    _avail(XrActionCreateInfo, XR_TYPE_ACTION_CREATE_INFO) \\\n    _avail(XrInteractionProfileSuggestedBinding, XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING) \\\n    _avail(XrSessionActionSetsAttachInfo, XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO) \\\n    _avail(XrInteractionProfileState, XR_TYPE_INTERACTION_PROFILE_STATE) \\\n    _avail(XrActionStateGetInfo, XR_TYPE_ACTION_STATE_GET_INFO) \\\n    _avail(XrActionStateBoolean, XR_TYPE_ACTION_STATE_BOOLEAN) \\\n    _avail(XrActionStateFloat, XR_TYPE_ACTION_STATE_FLOAT) \\\n    _avail(XrActionStateVector2f, XR_TYPE_ACTION_STATE_VECTOR2F) \\\n    _avail(XrActionStatePose, XR_TYPE_ACTION_STATE_POSE) \\\n    _avail(XrActionsSyncInfo, XR_TYPE_ACTIONS_SYNC_INFO) \\\n    _avail(XrBoundSourcesForActionEnumerateInfo, XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO) \\\n    _avail(XrInputSourceLocalizedNameGetInfo, XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO) \\\n    _avail(XrHapticActionInfo, XR_TYPE_HAPTIC_ACTION_INFO) \\\n    _avail(XrCompositionLayerProjectionView, XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) \\\n    _avail(XrCompositionLayerProjection, XR_TYPE_COMPOSITION_LAYER_PROJECTION) \\\n    _avail(XrCompositionLayerQuad, XR_TYPE_COMPOSITION_LAYER_QUAD) \\\n    _avail(XrEventDataEventsLost, XR_TYPE_EVENT_DATA_EVENTS_LOST) \\\n    _avail(XrEventDataInstanceLossPending, XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) \\\n    _avail(XrEventDataSessionStateChanged, XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) \\\n    _avail(XrEventDataReferenceSpaceChangePending, XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) \\\n    _avail(XrEventDataInteractionProfileChanged, XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) \\\n    _avail(XrHapticVibration, XR_TYPE_HAPTIC_VIBRATION) \\\n    _avail(XrCompositionLayerCubeKHR, XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) \\\n    _avail(XrCompositionLayerDepthInfoKHR, XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR) \\\n    _avail(XrCompositionLayerCylinderKHR, XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) \\\n    _avail(XrCompositionLayerEquirectKHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) \\\n    _avail(XrVisibilityMaskKHR, XR_TYPE_VISIBILITY_MASK_KHR) \\\n    _avail(XrEventDataVisibilityMaskChangedKHR, XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) \\\n    _avail(XrCompositionLayerColorScaleBiasKHR, XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR) \\\n    _avail(XrCompositionLayerEquirect2KHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR) \\\n    _avail(XrBindingModificationsKHR, XR_TYPE_BINDING_MODIFICATIONS_KHR) \\\n    _avail(XrEventDataPerfSettingsEXT, XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) \\\n    _avail(XrDebugUtilsObjectNameInfoEXT, XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT) \\\n    _avail(XrDebugUtilsLabelEXT, XR_TYPE_DEBUG_UTILS_LABEL_EXT) \\\n    _avail(XrDebugUtilsMessengerCallbackDataEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT) \\\n    _avail(XrDebugUtilsMessengerCreateInfoEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) \\\n    _avail(XrSystemEyeGazeInteractionPropertiesEXT, XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT) \\\n    _avail(XrEyeGazeSampleTimeEXT, XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT) \\\n    _avail(XrSessionCreateInfoOverlayEXTX, XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX) \\\n    _avail(XrEventDataMainSessionVisibilityChangedEXTX, XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX) \\\n    _avail(XrSpatialAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT) \\\n    _avail(XrSpatialAnchorSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT) \\\n    _avail(XrCompositionLayerImageLayoutFB, XR_TYPE_COMPOSITION_LAYER_IMAGE_LAYOUT_FB) \\\n    _avail(XrCompositionLayerAlphaBlendFB, XR_TYPE_COMPOSITION_LAYER_ALPHA_BLEND_FB) \\\n    _avail(XrViewConfigurationDepthRangeEXT, XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT) \\\n    _avail(XrSpatialGraphNodeSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT) \\\n    _avail(XrSpatialGraphStaticNodeBindingCreateInfoMSFT, XR_TYPE_SPATIAL_GRAPH_STATIC_NODE_BINDING_CREATE_INFO_MSFT) \\\n    _avail(XrSpatialGraphNodeBindingPropertiesGetInfoMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_GET_INFO_MSFT) \\\n    _avail(XrSpatialGraphNodeBindingPropertiesMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_MSFT) \\\n    _avail(XrSystemHandTrackingPropertiesEXT, XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT) \\\n    _avail(XrHandTrackerCreateInfoEXT, XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT) \\\n    _avail(XrHandJointsLocateInfoEXT, XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT) \\\n    _avail(XrHandJointLocationsEXT, XR_TYPE_HAND_JOINT_LOCATIONS_EXT) \\\n    _avail(XrHandJointVelocitiesEXT, XR_TYPE_HAND_JOINT_VELOCITIES_EXT) \\\n    _avail(XrSystemHandTrackingMeshPropertiesMSFT, XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT) \\\n    _avail(XrHandMeshSpaceCreateInfoMSFT, XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT) \\\n    _avail(XrHandMeshUpdateInfoMSFT, XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT) \\\n    _avail(XrHandMeshMSFT, XR_TYPE_HAND_MESH_MSFT) \\\n    _avail(XrHandPoseTypeInfoMSFT, XR_TYPE_HAND_POSE_TYPE_INFO_MSFT) \\\n    _avail(XrSecondaryViewConfigurationSessionBeginInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT) \\\n    _avail(XrSecondaryViewConfigurationStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT) \\\n    _avail(XrSecondaryViewConfigurationFrameStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT) \\\n    _avail(XrSecondaryViewConfigurationLayerInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT) \\\n    _avail(XrSecondaryViewConfigurationFrameEndInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT) \\\n    _avail(XrSecondaryViewConfigurationSwapchainCreateInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT) \\\n    _avail(XrControllerModelKeyStateMSFT, XR_TYPE_CONTROLLER_MODEL_KEY_STATE_MSFT) \\\n    _avail(XrControllerModelNodePropertiesMSFT, XR_TYPE_CONTROLLER_MODEL_NODE_PROPERTIES_MSFT) \\\n    _avail(XrControllerModelPropertiesMSFT, XR_TYPE_CONTROLLER_MODEL_PROPERTIES_MSFT) \\\n    _avail(XrControllerModelNodeStateMSFT, XR_TYPE_CONTROLLER_MODEL_NODE_STATE_MSFT) \\\n    _avail(XrControllerModelStateMSFT, XR_TYPE_CONTROLLER_MODEL_STATE_MSFT) \\\n    _avail(XrViewConfigurationViewFovEPIC, XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC) \\\n    _avail(XrCompositionLayerReprojectionInfoMSFT, XR_TYPE_COMPOSITION_LAYER_REPROJECTION_INFO_MSFT) \\\n    _avail(XrCompositionLayerReprojectionPlaneOverrideMSFT, XR_TYPE_COMPOSITION_LAYER_REPROJECTION_PLANE_OVERRIDE_MSFT) \\\n    _avail(XrCompositionLayerSecureContentFB, XR_TYPE_COMPOSITION_LAYER_SECURE_CONTENT_FB) \\\n    _avail(XrSystemBodyTrackingPropertiesFB, XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_FB) \\\n    _avail(XrBodyTrackerCreateInfoFB, XR_TYPE_BODY_TRACKER_CREATE_INFO_FB) \\\n    _avail(XrBodySkeletonFB, XR_TYPE_BODY_SKELETON_FB) \\\n    _avail(XrBodyJointsLocateInfoFB, XR_TYPE_BODY_JOINTS_LOCATE_INFO_FB) \\\n    _avail(XrBodyJointLocationsFB, XR_TYPE_BODY_JOINT_LOCATIONS_FB) \\\n    _avail(XrInteractionProfileDpadBindingEXT, XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT) \\\n    _avail(XrInteractionProfileAnalogThresholdVALVE, XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE) \\\n    _avail(XrHandJointsMotionRangeInfoEXT, XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT) \\\n    _avail(XrSceneObserverCreateInfoMSFT, XR_TYPE_SCENE_OBSERVER_CREATE_INFO_MSFT) \\\n    _avail(XrSceneCreateInfoMSFT, XR_TYPE_SCENE_CREATE_INFO_MSFT) \\\n    _avail(XrNewSceneComputeInfoMSFT, XR_TYPE_NEW_SCENE_COMPUTE_INFO_MSFT) \\\n    _avail(XrVisualMeshComputeLodInfoMSFT, XR_TYPE_VISUAL_MESH_COMPUTE_LOD_INFO_MSFT) \\\n    _avail(XrSceneComponentsMSFT, XR_TYPE_SCENE_COMPONENTS_MSFT) \\\n    _avail(XrSceneComponentsGetInfoMSFT, XR_TYPE_SCENE_COMPONENTS_GET_INFO_MSFT) \\\n    _avail(XrSceneComponentLocationsMSFT, XR_TYPE_SCENE_COMPONENT_LOCATIONS_MSFT) \\\n    _avail(XrSceneComponentsLocateInfoMSFT, XR_TYPE_SCENE_COMPONENTS_LOCATE_INFO_MSFT) \\\n    _avail(XrSceneObjectsMSFT, XR_TYPE_SCENE_OBJECTS_MSFT) \\\n    _avail(XrSceneComponentParentFilterInfoMSFT, XR_TYPE_SCENE_COMPONENT_PARENT_FILTER_INFO_MSFT) \\\n    _avail(XrSceneObjectTypesFilterInfoMSFT, XR_TYPE_SCENE_OBJECT_TYPES_FILTER_INFO_MSFT) \\\n    _avail(XrScenePlanesMSFT, XR_TYPE_SCENE_PLANES_MSFT) \\\n    _avail(XrScenePlaneAlignmentFilterInfoMSFT, XR_TYPE_SCENE_PLANE_ALIGNMENT_FILTER_INFO_MSFT) \\\n    _avail(XrSceneMeshesMSFT, XR_TYPE_SCENE_MESHES_MSFT) \\\n    _avail(XrSceneMeshBuffersGetInfoMSFT, XR_TYPE_SCENE_MESH_BUFFERS_GET_INFO_MSFT) \\\n    _avail(XrSceneMeshBuffersMSFT, XR_TYPE_SCENE_MESH_BUFFERS_MSFT) \\\n    _avail(XrSceneMeshVertexBufferMSFT, XR_TYPE_SCENE_MESH_VERTEX_BUFFER_MSFT) \\\n    _avail(XrSceneMeshIndicesUint32MSFT, XR_TYPE_SCENE_MESH_INDICES_UINT32_MSFT) \\\n    _avail(XrSceneMeshIndicesUint16MSFT, XR_TYPE_SCENE_MESH_INDICES_UINT16_MSFT) \\\n    _avail(XrSerializedSceneFragmentDataGetInfoMSFT, XR_TYPE_SERIALIZED_SCENE_FRAGMENT_DATA_GET_INFO_MSFT) \\\n    _avail(XrSceneDeserializeInfoMSFT, XR_TYPE_SCENE_DESERIALIZE_INFO_MSFT) \\\n    _avail(XrEventDataDisplayRefreshRateChangedFB, XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB) \\\n    _avail(XrViveTrackerPathsHTCX, XR_TYPE_VIVE_TRACKER_PATHS_HTCX) \\\n    _avail(XrEventDataViveTrackerConnectedHTCX, XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX) \\\n    _avail(XrSystemFacialTrackingPropertiesHTC, XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC) \\\n    _avail(XrFacialExpressionsHTC, XR_TYPE_FACIAL_EXPRESSIONS_HTC) \\\n    _avail(XrFacialTrackerCreateInfoHTC, XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC) \\\n    _avail(XrSystemColorSpacePropertiesFB, XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB) \\\n    _avail(XrHandTrackingMeshFB, XR_TYPE_HAND_TRACKING_MESH_FB) \\\n    _avail(XrHandTrackingScaleFB, XR_TYPE_HAND_TRACKING_SCALE_FB) \\\n    _avail(XrHandTrackingAimStateFB, XR_TYPE_HAND_TRACKING_AIM_STATE_FB) \\\n    _avail(XrHandTrackingCapsulesStateFB, XR_TYPE_HAND_TRACKING_CAPSULES_STATE_FB) \\\n    _avail(XrSystemSpatialEntityPropertiesFB, XR_TYPE_SYSTEM_SPATIAL_ENTITY_PROPERTIES_FB) \\\n    _avail(XrSpatialAnchorCreateInfoFB, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_FB) \\\n    _avail(XrSpaceComponentStatusSetInfoFB, XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB) \\\n    _avail(XrSpaceComponentStatusFB, XR_TYPE_SPACE_COMPONENT_STATUS_FB) \\\n    _avail(XrEventDataSpatialAnchorCreateCompleteFB, XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB) \\\n    _avail(XrEventDataSpaceSetStatusCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) \\\n    _avail(XrFoveationProfileCreateInfoFB, XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB) \\\n    _avail(XrSwapchainCreateInfoFoveationFB, XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB) \\\n    _avail(XrSwapchainStateFoveationFB, XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB) \\\n    _avail(XrFoveationLevelProfileCreateInfoFB, XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB) \\\n    _avail(XrSystemKeyboardTrackingPropertiesFB, XR_TYPE_SYSTEM_KEYBOARD_TRACKING_PROPERTIES_FB) \\\n    _avail(XrKeyboardSpaceCreateInfoFB, XR_TYPE_KEYBOARD_SPACE_CREATE_INFO_FB) \\\n    _avail(XrKeyboardTrackingQueryFB, XR_TYPE_KEYBOARD_TRACKING_QUERY_FB) \\\n    _avail(XrTriangleMeshCreateInfoFB, XR_TYPE_TRIANGLE_MESH_CREATE_INFO_FB) \\\n    _avail(XrSystemPassthroughPropertiesFB, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB) \\\n    _avail(XrSystemPassthroughProperties2FB, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB) \\\n    _avail(XrPassthroughCreateInfoFB, XR_TYPE_PASSTHROUGH_CREATE_INFO_FB) \\\n    _avail(XrPassthroughLayerCreateInfoFB, XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB) \\\n    _avail(XrCompositionLayerPassthroughFB, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB) \\\n    _avail(XrGeometryInstanceCreateInfoFB, XR_TYPE_GEOMETRY_INSTANCE_CREATE_INFO_FB) \\\n    _avail(XrGeometryInstanceTransformFB, XR_TYPE_GEOMETRY_INSTANCE_TRANSFORM_FB) \\\n    _avail(XrPassthroughStyleFB, XR_TYPE_PASSTHROUGH_STYLE_FB) \\\n    _avail(XrPassthroughColorMapMonoToRgbaFB, XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB) \\\n    _avail(XrPassthroughColorMapMonoToMonoFB, XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB) \\\n    _avail(XrPassthroughBrightnessContrastSaturationFB, XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB) \\\n    _avail(XrEventDataPassthroughStateChangedFB, XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB) \\\n    _avail(XrRenderModelPathInfoFB, XR_TYPE_RENDER_MODEL_PATH_INFO_FB) \\\n    _avail(XrRenderModelPropertiesFB, XR_TYPE_RENDER_MODEL_PROPERTIES_FB) \\\n    _avail(XrRenderModelBufferFB, XR_TYPE_RENDER_MODEL_BUFFER_FB) \\\n    _avail(XrRenderModelLoadInfoFB, XR_TYPE_RENDER_MODEL_LOAD_INFO_FB) \\\n    _avail(XrSystemRenderModelPropertiesFB, XR_TYPE_SYSTEM_RENDER_MODEL_PROPERTIES_FB) \\\n    _avail(XrRenderModelCapabilitiesRequestFB, XR_TYPE_RENDER_MODEL_CAPABILITIES_REQUEST_FB) \\\n    _avail(XrViewLocateFoveatedRenderingVARJO, XR_TYPE_VIEW_LOCATE_FOVEATED_RENDERING_VARJO) \\\n    _avail(XrFoveatedViewConfigurationViewVARJO, XR_TYPE_FOVEATED_VIEW_CONFIGURATION_VIEW_VARJO) \\\n    _avail(XrSystemFoveatedRenderingPropertiesVARJO, XR_TYPE_SYSTEM_FOVEATED_RENDERING_PROPERTIES_VARJO) \\\n    _avail(XrCompositionLayerDepthTestVARJO, XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_VARJO) \\\n    _avail(XrSystemMarkerTrackingPropertiesVARJO, XR_TYPE_SYSTEM_MARKER_TRACKING_PROPERTIES_VARJO) \\\n    _avail(XrEventDataMarkerTrackingUpdateVARJO, XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO) \\\n    _avail(XrMarkerSpaceCreateInfoVARJO, XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO) \\\n    _avail(XrFrameEndInfoML, XR_TYPE_FRAME_END_INFO_ML) \\\n    _avail(XrGlobalDimmerFrameEndInfoML, XR_TYPE_GLOBAL_DIMMER_FRAME_END_INFO_ML) \\\n    _avail(XrSpatialAnchorPersistenceInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT) \\\n    _avail(XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT) \\\n    _avail(XrSpaceQueryInfoFB, XR_TYPE_SPACE_QUERY_INFO_FB) \\\n    _avail(XrSpaceStorageLocationFilterInfoFB, XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB) \\\n    _avail(XrSpaceUuidFilterInfoFB, XR_TYPE_SPACE_UUID_FILTER_INFO_FB) \\\n    _avail(XrSpaceComponentFilterInfoFB, XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB) \\\n    _avail(XrSpaceQueryResultsFB, XR_TYPE_SPACE_QUERY_RESULTS_FB) \\\n    _avail(XrEventDataSpaceQueryResultsAvailableFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) \\\n    _avail(XrEventDataSpaceQueryCompleteFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) \\\n    _avail(XrSpaceSaveInfoFB, XR_TYPE_SPACE_SAVE_INFO_FB) \\\n    _avail(XrSpaceEraseInfoFB, XR_TYPE_SPACE_ERASE_INFO_FB) \\\n    _avail(XrEventDataSpaceSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB) \\\n    _avail(XrEventDataSpaceEraseCompleteFB, XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB) \\\n    _avail(XrSpaceShareInfoFB, XR_TYPE_SPACE_SHARE_INFO_FB) \\\n    _avail(XrEventDataSpaceShareCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SHARE_COMPLETE_FB) \\\n    _avail(XrCompositionLayerSpaceWarpInfoFB, XR_TYPE_COMPOSITION_LAYER_SPACE_WARP_INFO_FB) \\\n    _avail(XrSystemSpaceWarpPropertiesFB, XR_TYPE_SYSTEM_SPACE_WARP_PROPERTIES_FB) \\\n    _avail(XrHapticAmplitudeEnvelopeVibrationFB, XR_TYPE_HAPTIC_AMPLITUDE_ENVELOPE_VIBRATION_FB) \\\n    _avail(XrSemanticLabelsFB, XR_TYPE_SEMANTIC_LABELS_FB) \\\n    _avail(XrRoomLayoutFB, XR_TYPE_ROOM_LAYOUT_FB) \\\n    _avail(XrBoundary2DFB, XR_TYPE_BOUNDARY_2D_FB) \\\n    _avail(XrSemanticLabelsSupportInfoFB, XR_TYPE_SEMANTIC_LABELS_SUPPORT_INFO_FB) \\\n    _avail(XrDigitalLensControlALMALENCE, XR_TYPE_DIGITAL_LENS_CONTROL_ALMALENCE) \\\n    _avail(XrEventDataSceneCaptureCompleteFB, XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB) \\\n    _avail(XrSceneCaptureRequestInfoFB, XR_TYPE_SCENE_CAPTURE_REQUEST_INFO_FB) \\\n    _avail(XrSpaceContainerFB, XR_TYPE_SPACE_CONTAINER_FB) \\\n    _avail(XrFoveationEyeTrackedProfileCreateInfoMETA, XR_TYPE_FOVEATION_EYE_TRACKED_PROFILE_CREATE_INFO_META) \\\n    _avail(XrFoveationEyeTrackedStateMETA, XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META) \\\n    _avail(XrSystemFoveationEyeTrackedPropertiesMETA, XR_TYPE_SYSTEM_FOVEATION_EYE_TRACKED_PROPERTIES_META) \\\n    _avail(XrSystemFaceTrackingPropertiesFB, XR_TYPE_SYSTEM_FACE_TRACKING_PROPERTIES_FB) \\\n    _avail(XrFaceTrackerCreateInfoFB, XR_TYPE_FACE_TRACKER_CREATE_INFO_FB) \\\n    _avail(XrFaceExpressionInfoFB, XR_TYPE_FACE_EXPRESSION_INFO_FB) \\\n    _avail(XrFaceExpressionWeightsFB, XR_TYPE_FACE_EXPRESSION_WEIGHTS_FB) \\\n    _avail(XrEyeTrackerCreateInfoFB, XR_TYPE_EYE_TRACKER_CREATE_INFO_FB) \\\n    _avail(XrEyeGazesInfoFB, XR_TYPE_EYE_GAZES_INFO_FB) \\\n    _avail(XrSystemEyeTrackingPropertiesFB, XR_TYPE_SYSTEM_EYE_TRACKING_PROPERTIES_FB) \\\n    _avail(XrEyeGazesFB, XR_TYPE_EYE_GAZES_FB) \\\n    _avail(XrPassthroughKeyboardHandsIntensityFB, XR_TYPE_PASSTHROUGH_KEYBOARD_HANDS_INTENSITY_FB) \\\n    _avail(XrCompositionLayerSettingsFB, XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB) \\\n    _avail(XrHapticPcmVibrationFB, XR_TYPE_HAPTIC_PCM_VIBRATION_FB) \\\n    _avail(XrDevicePcmSampleRateStateFB, XR_TYPE_DEVICE_PCM_SAMPLE_RATE_STATE_FB) \\\n    _avail(XrCompositionLayerDepthTestFB, XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_FB) \\\n    _avail(XrLocalDimmingFrameEndInfoMETA, XR_TYPE_LOCAL_DIMMING_FRAME_END_INFO_META) \\\n    _avail(XrSystemVirtualKeyboardPropertiesMETA, XR_TYPE_SYSTEM_VIRTUAL_KEYBOARD_PROPERTIES_META) \\\n    _avail(XrVirtualKeyboardCreateInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_CREATE_INFO_META) \\\n    _avail(XrVirtualKeyboardSpaceCreateInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_SPACE_CREATE_INFO_META) \\\n    _avail(XrVirtualKeyboardLocationInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_LOCATION_INFO_META) \\\n    _avail(XrVirtualKeyboardModelVisibilitySetInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_MODEL_VISIBILITY_SET_INFO_META) \\\n    _avail(XrVirtualKeyboardAnimationStateMETA, XR_TYPE_VIRTUAL_KEYBOARD_ANIMATION_STATE_META) \\\n    _avail(XrVirtualKeyboardModelAnimationStatesMETA, XR_TYPE_VIRTUAL_KEYBOARD_MODEL_ANIMATION_STATES_META) \\\n    _avail(XrVirtualKeyboardTextureDataMETA, XR_TYPE_VIRTUAL_KEYBOARD_TEXTURE_DATA_META) \\\n    _avail(XrVirtualKeyboardInputInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_INPUT_INFO_META) \\\n    _avail(XrVirtualKeyboardTextContextChangeInfoMETA, XR_TYPE_VIRTUAL_KEYBOARD_TEXT_CONTEXT_CHANGE_INFO_META) \\\n    _avail(XrEventDataVirtualKeyboardCommitTextMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_COMMIT_TEXT_META) \\\n    _avail(XrEventDataVirtualKeyboardBackspaceMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_BACKSPACE_META) \\\n    _avail(XrEventDataVirtualKeyboardEnterMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_ENTER_META) \\\n    _avail(XrEventDataVirtualKeyboardShownMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_SHOWN_META) \\\n    _avail(XrEventDataVirtualKeyboardHiddenMETA, XR_TYPE_EVENT_DATA_VIRTUAL_KEYBOARD_HIDDEN_META) \\\n    _avail(XrExternalCameraOCULUS, XR_TYPE_EXTERNAL_CAMERA_OCULUS) \\\n    _avail(XrPerformanceMetricsStateMETA, XR_TYPE_PERFORMANCE_METRICS_STATE_META) \\\n    _avail(XrPerformanceMetricsCounterMETA, XR_TYPE_PERFORMANCE_METRICS_COUNTER_META) \\\n    _avail(XrSpaceListSaveInfoFB, XR_TYPE_SPACE_LIST_SAVE_INFO_FB) \\\n    _avail(XrEventDataSpaceListSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_LIST_SAVE_COMPLETE_FB) \\\n    _avail(XrSpaceUserCreateInfoFB, XR_TYPE_SPACE_USER_CREATE_INFO_FB) \\\n    _avail(XrSystemHeadsetIdPropertiesMETA, XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META) \\\n    _avail(XrPassthroughColorLutCreateInfoMETA, XR_TYPE_PASSTHROUGH_COLOR_LUT_CREATE_INFO_META) \\\n    _avail(XrPassthroughColorLutUpdateInfoMETA, XR_TYPE_PASSTHROUGH_COLOR_LUT_UPDATE_INFO_META) \\\n    _avail(XrPassthroughColorMapLutMETA, XR_TYPE_PASSTHROUGH_COLOR_MAP_LUT_META) \\\n    _avail(XrPassthroughColorMapInterpolatedLutMETA, XR_TYPE_PASSTHROUGH_COLOR_MAP_INTERPOLATED_LUT_META) \\\n    _avail(XrSystemPassthroughColorLutPropertiesMETA, XR_TYPE_SYSTEM_PASSTHROUGH_COLOR_LUT_PROPERTIES_META) \\\n    _avail(XrPassthroughCreateInfoHTC, XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC) \\\n    _avail(XrPassthroughColorHTC, XR_TYPE_PASSTHROUGH_COLOR_HTC) \\\n    _avail(XrPassthroughMeshTransformInfoHTC, XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC) \\\n    _avail(XrCompositionLayerPassthroughHTC, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC) \\\n    _avail(XrFoveationApplyInfoHTC, XR_TYPE_FOVEATION_APPLY_INFO_HTC) \\\n    _avail(XrFoveationDynamicModeInfoHTC, XR_TYPE_FOVEATION_DYNAMIC_MODE_INFO_HTC) \\\n    _avail(XrFoveationCustomModeInfoHTC, XR_TYPE_FOVEATION_CUSTOM_MODE_INFO_HTC) \\\n    _avail(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \\\n    _avail(XrSystemForceFeedbackCurlPropertiesMNDX, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX) \\\n    _avail(XrForceFeedbackCurlApplyLocationsMNDX, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX) \\\n    _avail(XrHandTrackingDataSourceInfoEXT, XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT) \\\n    _avail(XrHandTrackingDataSourceStateEXT, XR_TYPE_HAND_TRACKING_DATA_SOURCE_STATE_EXT) \\\n    _avail(XrSystemPlaneDetectionPropertiesEXT, XR_TYPE_SYSTEM_PLANE_DETECTION_PROPERTIES_EXT) \\\n    _avail(XrPlaneDetectorCreateInfoEXT, XR_TYPE_PLANE_DETECTOR_CREATE_INFO_EXT) \\\n    _avail(XrPlaneDetectorBeginInfoEXT, XR_TYPE_PLANE_DETECTOR_BEGIN_INFO_EXT) \\\n    _avail(XrPlaneDetectorGetInfoEXT, XR_TYPE_PLANE_DETECTOR_GET_INFO_EXT) \\\n    _avail(XrPlaneDetectorLocationEXT, XR_TYPE_PLANE_DETECTOR_LOCATION_EXT) \\\n    _avail(XrPlaneDetectorLocationsEXT, XR_TYPE_PLANE_DETECTOR_LOCATIONS_EXT) \\\n    _avail(XrPlaneDetectorPolygonBufferEXT, XR_TYPE_PLANE_DETECTOR_POLYGON_BUFFER_EXT) \\\n\n\n#if defined(XR_USE_GRAPHICS_API_D3D11)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \\\n    _avail(XrGraphicsBindingD3D11KHR, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) \\\n    _avail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \\\n    _avail(XrGraphicsRequirementsD3D11KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \\\n    _unavail(XrGraphicsBindingD3D11KHR, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) \\\n    _unavail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \\\n    _unavail(XrGraphicsRequirementsD3D11KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_D3D12)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \\\n    _avail(XrGraphicsBindingD3D12KHR, XR_TYPE_GRAPHICS_BINDING_D3D12_KHR) \\\n    _avail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \\\n    _avail(XrGraphicsRequirementsD3D12KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \\\n    _unavail(XrGraphicsBindingD3D12KHR, XR_TYPE_GRAPHICS_BINDING_D3D12_KHR) \\\n    _unavail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \\\n    _unavail(XrGraphicsRequirementsD3D12KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \\\n    _avail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \\\n    _avail(XrGraphicsRequirementsOpenGLKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \\\n    _unavail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \\\n    _unavail(XrGraphicsRequirementsOpenGLKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_avail, _unavail) \\\n    _avail(XrGraphicsBindingOpenGLWaylandKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_avail, _unavail) \\\n    _unavail(XrGraphicsBindingOpenGLWaylandKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_avail, _unavail) \\\n    _avail(XrGraphicsBindingOpenGLWin32KHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_avail, _unavail) \\\n    _unavail(XrGraphicsBindingOpenGLWin32KHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_avail, _unavail) \\\n    _avail(XrGraphicsBindingOpenGLXcbKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_avail, _unavail) \\\n    _unavail(XrGraphicsBindingOpenGLXcbKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_avail, _unavail) \\\n    _avail(XrGraphicsBindingOpenGLXlibKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_avail, _unavail) \\\n    _unavail(XrGraphicsBindingOpenGLXlibKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \\\n    _avail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \\\n    _avail(XrGraphicsRequirementsOpenGLESKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR) \\\n    _avail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \\\n    _unavail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \\\n    _unavail(XrGraphicsRequirementsOpenGLESKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR) \\\n    _unavail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _avail(XrGraphicsBindingOpenGLESAndroidKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _unavail(XrGraphicsBindingOpenGLESAndroidKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) \\\n\n#endif\n\n#if defined(XR_USE_GRAPHICS_API_VULKAN)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \\\n    _avail(XrVulkanSwapchainFormatListCreateInfoKHR, XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR) \\\n    _avail(XrGraphicsBindingVulkanKHR, XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) \\\n    _avail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \\\n    _avail(XrGraphicsRequirementsVulkanKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR) \\\n    _avail(XrVulkanInstanceCreateInfoKHR, XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR) \\\n    _avail(XrVulkanDeviceCreateInfoKHR, XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR) \\\n    _avail(XrVulkanGraphicsDeviceGetInfoKHR, XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR) \\\n    _avail(XrSwapchainImageFoveationVulkanFB, XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB) \\\n    _avail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \\\n    _avail(XrVulkanSwapchainCreateInfoMETA, XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \\\n    _unavail(XrVulkanSwapchainFormatListCreateInfoKHR, XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR) \\\n    _unavail(XrGraphicsBindingVulkanKHR, XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) \\\n    _unavail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \\\n    _unavail(XrGraphicsRequirementsVulkanKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR) \\\n    _unavail(XrVulkanInstanceCreateInfoKHR, XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR) \\\n    _unavail(XrVulkanDeviceCreateInfoKHR, XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR) \\\n    _unavail(XrVulkanGraphicsDeviceGetInfoKHR, XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR) \\\n    _unavail(XrSwapchainImageFoveationVulkanFB, XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB) \\\n    _unavail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \\\n    _unavail(XrVulkanSwapchainCreateInfoMETA, XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META) \\\n\n#endif\n\n#if defined(XR_USE_PLATFORM_ANDROID)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _avail(XrInstanceCreateInfoAndroidKHR, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR) \\\n    _avail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \\\n    _avail(XrAndroidSurfaceSwapchainCreateInfoFB, XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB) \\\n    _avail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \\\n    _unavail(XrInstanceCreateInfoAndroidKHR, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR) \\\n    _unavail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \\\n    _unavail(XrAndroidSurfaceSwapchainCreateInfoFB, XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB) \\\n    _unavail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \\\n\n#endif\n\n#if defined(XR_USE_PLATFORM_EGL)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_avail, _unavail) \\\n    _avail(XrGraphicsBindingEGLMNDX, XR_TYPE_GRAPHICS_BINDING_EGL_MNDX) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_avail, _unavail) \\\n    _unavail(XrGraphicsBindingEGLMNDX, XR_TYPE_GRAPHICS_BINDING_EGL_MNDX) \\\n\n#endif\n\n#if defined(XR_USE_PLATFORM_ML)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_ML(_avail, _unavail) \\\n    _avail(XrCoordinateSpaceCreateInfoML, XR_TYPE_COORDINATE_SPACE_CREATE_INFO_ML) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_ML(_avail, _unavail) \\\n    _unavail(XrCoordinateSpaceCreateInfoML, XR_TYPE_COORDINATE_SPACE_CREATE_INFO_ML) \\\n\n#endif\n\n#if defined(XR_USE_PLATFORM_WIN32)\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_avail, _unavail) \\\n    _avail(XrHolographicWindowAttachmentMSFT, XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT) \\\n\n#else\n#define _impl_XR_LIST_ALL_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_avail, _unavail) \\\n    _unavail(XrHolographicWindowAttachmentMSFT, XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT) \\\n\n#endif\n\n\n#endif\n\n"
  },
  {
    "path": "src/buffer.c",
    "content": "#include \"buffer.h\"\n#include \"logging.h\"\n\n#include <stdbool.h>\n#include <stdlib.h>\n\nbuffer_type *create_buffer(int size) {\n    buffer_type *buffer = calloc(1, sizeof(buffer_type));\n    if (buffer == NULL) {\n        return NULL;\n    }\n\n    buffer->size = size;\n    buffer->values = calloc(size, sizeof(float));\n    if (buffer->values == NULL) {\n        free(buffer);\n        buffer = NULL;\n        return NULL;\n    }\n    buffer->index = 0;\n    buffer->count = 0;\n\n    return buffer;\n}\n\nvoid free_buffer(buffer_type *buffer) {\n    if (buffer != NULL) {\n        if (buffer->values != NULL) {\n            free(buffer->values);\n            buffer->values = NULL;\n        }\n        free(buffer);\n    }\n}\n\nbool is_full(buffer_type *buffer) {\n    return buffer->count == buffer->size;\n}\n\nfloat push(buffer_type *buffer, float next_value) {\n    float popped_value = 0;\n    if (is_full(buffer)) {\n        popped_value = buffer->values[buffer->index];\n    } else {\n        buffer->count++;\n    }\n    buffer->values[buffer->index++] = next_value;\n    buffer->index %= buffer->size;\n\n    return popped_value;\n}\n\nimu_buffer_type *create_imu_buffer(int buffer_size) {\n    imu_buffer_type *gyro_buffer = calloc(1, sizeof(imu_buffer_type));\n    if (gyro_buffer == NULL) {\n        return NULL;\n    }\n    gyro_buffer->stage_1 = calloc(GYRO_BUFFERS_COUNT, sizeof(buffer_type*));\n    gyro_buffer->stage_2 = calloc(GYRO_BUFFERS_COUNT, sizeof(buffer_type*));\n    for (int i = 0; i < GYRO_BUFFERS_COUNT; i++) {\n        gyro_buffer->stage_1[i] = create_buffer(buffer_size);\n        gyro_buffer->stage_2[i] = create_buffer(buffer_size);\n        if (gyro_buffer->stage_1[i] == NULL || gyro_buffer->stage_2[i] == NULL) {\n            log_error(\"Error allocating memory\\n\");\n            return NULL;\n        }\n    }\n\n    return gyro_buffer;\n}\n\nvoid free_imu_buffer(imu_buffer_type *gyro_buffer) {\n    if (gyro_buffer != NULL) {\n        if (gyro_buffer->stage_1 != NULL) {\n            for (int i = 0; i < GYRO_BUFFERS_COUNT; i++) {\n                free_buffer(gyro_buffer->stage_1[i]);\n            }\n            free(gyro_buffer->stage_1);\n            gyro_buffer->stage_1 = NULL;\n        }\n        if (gyro_buffer->stage_2 != NULL) {\n            for (int i = 0; i < GYRO_BUFFERS_COUNT; i++) {\n                free_buffer(gyro_buffer->stage_2[i]);\n            }\n            free(gyro_buffer->stage_2);\n            gyro_buffer->stage_2 = NULL;\n        }\n        free(gyro_buffer);\n    }\n}\n\nint imu_buffer_size(imu_buffer_type *gyro_buffer) {\n    if (gyro_buffer != NULL && gyro_buffer->stage_1 != NULL && gyro_buffer->stage_1[0] != NULL) {\n        return gyro_buffer->stage_1[0]->size;\n    }\n    return 0;\n}\n\nimu_buffer_response_type *push_to_imu_buffer(imu_buffer_type *gyro_buffer, imu_quat_type quat, float timestamp_ms) {\n    imu_buffer_response_type *response = calloc(1, sizeof(imu_buffer_response_type));\n    if (response == NULL) {\n        return NULL;\n    }\n    response->ready = false;\n\n    // the oldest values are zero/unset if the buffer hasn't been filled yet, so we check prior to doing a\n    // push/pop, to know if the values that are returned will be relevant to our calculations\n    bool was_full = is_full(gyro_buffer->stage_1[0]);\n    float stage_1_quat_w = push(gyro_buffer->stage_1[0], quat.w);\n    float stage_1_quat_x = push(gyro_buffer->stage_1[1], quat.x);\n    float stage_1_quat_y = push(gyro_buffer->stage_1[2], quat.y);\n    float stage_1_quat_z = push(gyro_buffer->stage_1[3], quat.z);\n\n    // TODO - timestamp_ms can only get as large as 2^24 before it starts to lose precision as a float,\n    //        which is less than 5 hours of usage. Update this to just send two delta times, t0-t1 and t1-t2.\n    float stage_1_ts = push(gyro_buffer->stage_1[4], (float)timestamp_ms);\n\n    if (was_full) {\n        was_full = is_full(gyro_buffer->stage_2[0]);\n        float stage_2_quat_w = push(gyro_buffer->stage_2[0], stage_1_quat_w);\n        float stage_2_quat_x = push(gyro_buffer->stage_2[1], stage_1_quat_x);\n        float stage_2_quat_y = push(gyro_buffer->stage_2[2], stage_1_quat_y);\n        float stage_2_quat_z = push(gyro_buffer->stage_2[3], stage_1_quat_z);\n        float stage_2_ts = push(gyro_buffer->stage_2[4], stage_1_ts);\n\n        if (was_full) {\n            response->ready = true;\n            response->data = calloc(16, sizeof(float));\n\n            // write to shared memory for anyone using the same ipc prefix to consume\n            response->data[0] = quat.x;\n            response->data[1] = quat.y;\n            response->data[2] = quat.z;\n            response->data[3] = quat.w;\n            response->data[4] = stage_1_quat_x;\n            response->data[5] = stage_1_quat_y;\n            response->data[6] = stage_1_quat_z;\n            response->data[7] = stage_1_quat_w;\n            response->data[8] = stage_2_quat_x;\n            response->data[9] = stage_2_quat_y;\n            response->data[10] = stage_2_quat_z;\n            response->data[11] = stage_2_quat_w;\n            response->data[12] = (float)timestamp_ms;\n            response->data[13] = stage_1_ts;\n            response->data[14] = stage_2_ts;\n        }\n    }\n\n    return response;\n}"
  },
  {
    "path": "src/config.c",
    "content": "#include \"config.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"plugins.h\"\n#include \"strings.h\"\n\n#include <errno.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <string.h>\n\nconst char *joystick_output_mode = \"joystick\";\nconst char *mouse_output_mode = \"mouse\";\nconst char *external_only_output_mode = \"external_only\";\n\ndriver_config_type *default_config() {\n    driver_config_type *config = calloc(1, sizeof(driver_config_type));\n    if (config == NULL) {\n        log_error(\"Error allocating config\");\n        exit(1);\n    }\n\n    config->disabled = true;\n    config->mouse_mode = false;\n    config->joystick_mode = false;\n    config->external_mode = false;\n    config->use_roll_axis = false;\n    config->vr_lite_invert_x = false;\n    config->vr_lite_invert_y = false;\n    config->mouse_sensitivity = 30;\n    config->output_mode = strdup(mouse_output_mode);\n    config->multi_tap_enabled = false;\n    config->metrics_disabled = false;\n    config->dead_zone_threshold_deg = 0.0f;\n\n    config->debug_threads = false;\n    config->debug_joystick = false;\n    config->debug_multi_tap = false;\n    config->debug_ipc = false;\n    config->debug_license = false;\n    config->debug_device = false;\n    config->debug_connections = false;\n\n    return config;\n}\n\nvoid update_config(driver_config_type *config, driver_config_type *new_config) {\n    free(config->output_mode);\n    *config = *new_config;\n    free(new_config);\n}\n\nvoid boolean_config(char* key, char *value, bool *config_value) {\n    *config_value = equal(value, \"true\");\n}\n\nvoid float_config(char* key, char *value, float *config_value) {\n    char *endptr;\n    errno = 0;\n    float num = strtof(value, &endptr);\n    if (errno != ERANGE && endptr != value) {\n        *config_value = num;\n    } else {\n        log_error(\"Error parsing %s value: %s\\n\", key, value);\n    }\n}\n\nvoid int_config(char* key, char *value, int *config_value) {\n    char *endptr;\n    errno = 0;\n    long num = strtol(value, &endptr, 10);\n    if (errno != ERANGE && endptr != value) {\n        *config_value = (int) num;\n    } else {\n        log_error(\"Error parsing %s value: %s\\n\", key, value);\n    }\n}\n\nvoid string_config(char* key, char *value, char **config_value) {\n    free_and_clear(config_value);\n    *config_value = strdup(value);\n}\n\ndriver_config_type* parse_config_file(FILE *fp) {\n    driver_config_type *config = default_config();\n    void *plugin_configs = plugins.default_config();\n\n    char line[1024];\n    while (fgets(line, sizeof(line), fp) != NULL) {\n        char *key = strtok(line, \"=\");\n        char *value = strtok(NULL, \"\\n\");\n        if (equal(key, \"disabled\")) {\n            boolean_config(key, value, &config->disabled);\n        } else if (equal(key, \"debug\")) {\n            char *token = strtok(value, \",\");\n            while (token != NULL) {\n                if (equal(token, \"joystick\")) {\n                    config->debug_joystick = true;\n                }\n                if (equal(token, \"taps\")) {\n                    config->debug_multi_tap = true;\n                }\n                if (equal(token, \"threads\")) {\n                    config->debug_threads = true;\n                }\n                if (equal(token, \"ipc\")) {\n                    config->debug_ipc = true;\n                }\n                if (equal(token, \"license\")) {\n                    config->debug_license = true;\n                }\n                if (equal(token, \"device\")) {\n                    config->debug_device = true;\n                }\n                if (equal(token, \"connections\")) {\n                    config->debug_connections = true;\n                }\n                token = strtok(NULL, \",\");\n            }\n        } else if (equal(key, \"use_roll_axis\")) {\n            config->use_roll_axis = true;\n        } else if (equal(key, \"vr_lite_invert_x\")) {\n            boolean_config(key, value, &config->vr_lite_invert_x);\n        } else if (equal(key, \"vr_lite_invert_y\")) {\n            boolean_config(key, value, &config->vr_lite_invert_y);\n        } else if (equal(key, \"mouse_sensitivity\")) {\n            int_config(key, value, &config->mouse_sensitivity);\n        } else if (equal(key, \"output_mode\")) {\n            string_config(key, value, &config->output_mode);\n            config->joystick_mode = strcmp(config->output_mode, joystick_output_mode) == 0;\n            config->mouse_mode = strcmp(config->output_mode, mouse_output_mode) == 0;\n            config->external_mode = strcmp(config->output_mode, external_only_output_mode) == 0;\n        } else if (equal(key, \"multi_tap_enabled\")) {\n            boolean_config(key, value, &config->multi_tap_enabled);\n        } else if (equal(key, \"metrics_disabled\")) {\n            boolean_config(key, value, &config->metrics_disabled);\n        } else if (equal(key, \"dead_zone_threshold_deg\")) {\n            float_config(key, value, &config->dead_zone_threshold_deg);\n        }\n\n        plugins.handle_config_line(plugin_configs, key, value);\n    }\n    plugins.set_config(plugin_configs);\n\n    return config;\n}"
  },
  {
    "path": "src/connection_pool.c",
    "content": "#include \"connection_pool.h\"\n#include \"logging.h\"\n#include \"runtime_context.h\"\n#include \"imu.h\"\n\n#include <pthread.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\nstatic connection_pool_type* pool = NULL;\n\nstatic void ensure_capacity() {\n    if (pool->count >= pool->capacity) {\n        int newcap = pool->capacity == 0 ? 2 : pool->capacity + 1;\n        pool->list = (connection_t**)realloc(pool->list, newcap * sizeof(connection_t*));\n        pool->capacity = newcap;\n    }\n}\n\nstatic pose_handler_t pose_handler = NULL;\nstatic reference_pose_getter_t reference_pose_getter = NULL;\nvoid connection_pool_init(pose_handler_t pose_handler_callback, reference_pose_getter_t reference_pose_getter_callback) {\n    pool = (connection_pool_type*)calloc(1, sizeof(*pool));\n    pthread_mutex_init(&pool->mutex, NULL);\n    pool->primary_index = -1;\n    pool->supplemental_index = -1;\n    pose_handler = pose_handler_callback;\n    reference_pose_getter = reference_pose_getter_callback;\n}\n\nstatic int pick_primary_index() {\n    for (int i = 0; i < pool->count; ++i) {\n        if (!pool->list[i]->device->can_be_supplemental) return i;\n    }\n    return pool->count > 0 ? 0 : -1;\n}\n\nstatic int pick_supplemental_index() {\n    for (int i = 0; i < pool->count; ++i) {\n        if (i != pool->primary_index && pool->list[i]->supplemental) return i;\n    }\n    return -1;\n}\n\n// The pool mutex must already be held when calling these helpers.\nstatic connection_t* find_hid_connection_locked(uint16_t id_vendor, int16_t id_product) {\n    for (int i = 0; i < pool->count; ++i) {\n        connection_t* c = pool->list[i];\n        if (c && c->device && c->device->hid_vendor_id == id_vendor && c->device->hid_product_id == id_product) return c;\n    }\n    return NULL;\n}\n\nstatic int find_driver_connection_index_locked(const char* driver_id) {\n    for (int i = 0; i < pool->count; ++i) {\n        connection_t* c = pool->list[i];\n        if (c && c->driver && c->driver->id && driver_id && strcmp(c->driver->id, driver_id) == 0) return i;\n    }\n    return -1;\n}\n\nstatic connection_t* find_driver_connection_locked(const char* driver_id) {\n    int idx = find_driver_connection_index_locked(driver_id);\n    return idx >= 0 ? pool->list[idx] : NULL;\n}\n\nstatic connection_t* primary() {\n    if (pool->primary_index < 0 || pool->primary_index >= pool->count) return NULL;\n    return pool->list[pool->primary_index];\n}\n\nstatic connection_t* supplemental() {\n    if (pool->supplemental_index < 0 || pool->supplemental_index >= pool->count) return NULL;\n    return pool->list[pool->supplemental_index];\n}\n\nstatic void* block_thread_func(void* arg) {\n    connection_t* c = (connection_t*)arg;\n    if (config()->debug_connections) log_debug(\"block_thread_func %s\\n\", c->driver->id);\n    c->driver->block_on_device_func();\n    c->thread_running = false;\n    return NULL;\n}\n\nstatic void connection_pool_start_connection_thread(connection_t* c) {\n    if (c && !c->thread_running) {\n        c->active = true;\n        c->thread_running = true;\n        pthread_create(&c->thread, NULL, block_thread_func, c);\n    }\n}\n\nbool connection_pool_is_connected() {\n    pthread_mutex_lock(&pool->mutex);\n    connection_t* p = primary();\n    bool connected = p && p->driver->is_connected_func();\n    pthread_mutex_unlock(&pool->mutex);\n    return connected;\n}\n\nbool connection_pool_device_is_sbs_mode() {\n    pthread_mutex_lock(&pool->mutex);\n    connection_t* p = primary();\n    bool enabled = p && p->driver->device_is_sbs_mode_func();\n    pthread_mutex_unlock(&pool->mutex);\n    return enabled;\n}\n\nbool connection_pool_device_set_sbs_mode(bool enabled) {\n    pthread_mutex_lock(&pool->mutex);\n    connection_t* p = primary();\n    bool ok = p && p->driver->device_set_sbs_mode_func(enabled);\n    pthread_mutex_unlock(&pool->mutex);\n    return ok;\n}\n\nvoid connection_pool_disconnect_all(bool soft) {\n    if (config()->debug_connections) log_debug(\"connection_pool_disconnect_all %s\\n\", soft ? \"soft\" : \"hard\");\n    pthread_mutex_lock(&pool->mutex);\n    for (int i = 0; i < pool->count; ++i) {\n        connection_t* c = pool->list[i];\n        if (c) c->driver->disconnect_func(soft);\n        c->active = false;\n    }\n    pthread_mutex_unlock(&pool->mutex);\n}\n\nbool connection_pool_connect_active() {\n    if (config()->debug_connections) log_debug(\"connection_pool_connect_active\\n\");\n    pthread_mutex_lock(&pool->mutex);\n    connection_t* p = primary();\n    connection_t* s = supplemental();\n    pthread_mutex_unlock(&pool->mutex);\n\n    bool pr_ok = false;\n    if (p) pr_ok = p->driver->device_connect_func();\n    if (pr_ok && s) (void)s->driver->device_connect_func();\n    return pr_ok;\n}\n\nvoid connection_pool_block_on_active() {\n    if (config()->debug_connections) log_debug(\"connection_pool_block_on_active\\n\");\n\n    pthread_mutex_lock(&pool->mutex);\n\n    connection_t* p = primary();\n    connection_pool_start_connection_thread(p);\n\n    connection_t* s = supplemental();\n    if (s && s->driver->is_connected_func()) connection_pool_start_connection_thread(s);\n\n    pthread_mutex_unlock(&pool->mutex);\n\n    // Join the primary thread; when it exits, we stop. Supplemental will be joined afterwards.\n    if (p && p->thread_running) pthread_join(p->thread, NULL);\n\n    pthread_mutex_lock(&pool->mutex);\n    if (s && s->thread_running) {\n        s->driver->disconnect_func(true);\n        pthread_mutex_unlock(&pool->mutex);\n        pthread_join(s->thread, NULL);\n        pthread_mutex_lock(&pool->mutex);\n        s->thread_running = false;\n        s->active = false;\n    }\n    if (p) { p->thread_running = false; p->active = false; }\n    pthread_mutex_unlock(&pool->mutex);\n}\n\ndevice_properties_type* connection_pool_primary_device() {\n    pthread_mutex_lock(&pool->mutex);\n    connection_t* p = primary();\n    device_properties_type* d = p ? p->device : NULL;\n    pthread_mutex_unlock(&pool->mutex);\n    return d;\n}\n\ndevice_properties_type* connection_pool_supplemental_device() {\n    pthread_mutex_lock(&pool->mutex);\n    connection_t* s = supplemental();\n    device_properties_type* d = s ? s->device : NULL;\n    pthread_mutex_unlock(&pool->mutex);\n    return d;\n}\n\nconst device_driver_type* connection_pool_primary_driver() {\n    pthread_mutex_lock(&pool->mutex);\n    connection_t* p = primary();\n    const device_driver_type* d = p ? p->driver : NULL;\n    pthread_mutex_unlock(&pool->mutex);\n    return d;\n}\n\nstatic bool supplemental_position_ready = false;\nstatic imu_pose_type last_supplemental_pose = {0};\nvoid connection_pool_handle_device_added(const device_driver_type* driver, device_properties_type* device) {\n    if (config()->debug_connections) log_debug(\"connection_pool_handle_device_added for driver %s, has_orientation %s, has_position %s\\n\", driver->id, device->provides_orientation ? \"true\" : \"false\", device->provides_position ? \"true\" : \"false\");\n\n    pthread_mutex_lock(&pool->mutex);\n    if (device && find_hid_connection_locked(device->hid_vendor_id, device->hid_product_id)) {\n        if (config()->debug_connections) {\n            log_debug(\n                \"connection_pool_handle_device_added: ignoring duplicate HID device for driver %s (0x%04x:0x%04x)\\n\",\n                driver ? driver->id : \"(null)\",\n                (unsigned int)device->hid_vendor_id,\n                (unsigned int)device->hid_product_id);\n        }\n        free(device);\n        pthread_mutex_unlock(&pool->mutex);\n        return;\n    }\n\n    ensure_capacity(pool);\n    connection_t* c = (connection_t*)calloc(1, sizeof(*c));\n    c->driver = driver;\n    c->device = device;\n    c->supplemental = device->can_be_supplemental;\n    c->active = false;\n    pool->list[pool->count++] = c;\n\n    // If no primary selected yet, pick one\n    if (pool->primary_index == -1) {\n        pool->primary_index = pick_primary_index(pool);\n        if (config()->debug_connections) log_debug(\"connection_pool_handle_device_added picked primary %d\\n\", pool->primary_index);\n    }\n\n    // If possible, choose a supplemental distinct from primary\n    if (pool->supplemental_index == -1) {\n        pool->supplemental_index = pick_supplemental_index(pool);\n        if (config()->debug_connections) log_debug(\"connection_pool_handle_device_added picked supplemental %d\\n\", pool->supplemental_index);\n\n        connection_t* p = primary();\n        connection_t* s = supplemental();\n        if (p && s) {\n            last_supplemental_pose = (imu_pose_type){0};\n            bool blocked_on_active = p->active && p->thread_running;\n            if (blocked_on_active) {\n                // supplemental added and primary already connected and blocking.\n                // start supplemental connection thread now.\n                bool connected = s && s->driver->is_connected_func();\n                if (!connected && s) connected = s->driver->device_connect_func();\n                if (connected) connection_pool_start_connection_thread(s);\n            }\n        }\n    }\n\n    pthread_mutex_unlock(&pool->mutex);\n}\n\nvoid connection_pool_handle_device_removed(const char* driver_id) {\n    if (config()->debug_connections) log_debug(\"connection_pool_handle_device_removed for driver %s\\n\", driver_id);\n\n    pthread_mutex_lock(&pool->mutex);\n\n    connection_t* p = primary();\n    bool blocked_on_active = p && p->active && p->thread_running;\n    bool primary_removed = false;\n    bool supplemental_removed = pool->supplemental_index == -1;\n\n    int remove_index = find_driver_connection_index_locked(driver_id);\n    if (remove_index >= 0) {\n        connection_t* c = pool->list[remove_index];\n        \n        // Request a hard disconnect; the driver threads will exit on their own.\n        c->driver->disconnect_func(false);\n\n        primary_removed = remove_index == pool->primary_index;\n        supplemental_removed |= remove_index == pool->supplemental_index;\n        if (primary_removed) {\n            // we'll be reevaluating selections below, so soft disconnect supplemental\n            connection_t* s = supplemental();\n            if (s) s->driver->disconnect_func(true);\n        }\n    }\n\n    if (primary_removed || supplemental_removed) {\n        supplemental_position_ready = false;\n        last_supplemental_pose = (imu_pose_type){0};\n    }\n\n    if (remove_index >= 0) {\n        connection_t* c = pool->list[remove_index];\n        free(c);\n\n        // Remove from array and free the connection wrapper (device is managed externally)\n        for (int j = remove_index + 1; j < pool->count; ++j) pool->list[j - 1] = pool->list[j];\n        pool->count--;\n\n        // Re-evaluate selections\n        pool->primary_index = pick_primary_index(pool);\n        if (config()->debug_connections) log_debug(\"connection_pool_handle_device_removed picked primary %d\\n\", pool->primary_index);\n        pool->supplemental_index = pick_supplemental_index(pool);\n        bool supplemental_changed = supplemental_removed && pool->supplemental_index != -1;\n        if (blocked_on_active && !primary_removed && supplemental_changed) {\n            connection_t* s = supplemental();\n            bool connected = s && s->driver->is_connected_func();\n            if (!connected && s) connected = s->driver->device_connect_func();  \n            if (connected) connection_pool_start_connection_thread(s);\n        }\n        if (config()->debug_connections) log_debug(\"connection_pool_handle_device_removed picked supplemental %d\\n\", pool->supplemental_index);\n    }\n\n    pthread_mutex_unlock(&pool->mutex);\n}\n\nvoid connection_pool_ingest_pose(const char* driver_id, imu_pose_type pose) {\n    connection_t* s = supplemental();\n    if (s) {\n        bool pose_from_supplemental = strcmp(s->driver->id, driver_id) == 0;\n        if (pose_from_supplemental) {\n            // don't forward supplemental poses directly,\n            // store the latest one to be forwarded with the next primary pose\n            if (pose.has_position) {\n                static imu_quat_type reference_supplemental_orientation_conj = {0, 0, 0, 1};\n                // reorient supplemental position into primary reference frame\n                imu_pose_type reference_pose = {0};\n                bool reference_pose_updated = false;\n                supplemental_position_ready = reference_pose_getter(&reference_pose, &reference_pose_updated);\n\n                // when we receive a new reference pose, also capture the supplemental orientation\n                // so we can properly adjust the reference frame\n                if (pose.has_orientation && reference_pose_updated) \n                    reference_supplemental_orientation_conj = conjugate(pose.orientation);\n                    \n                if (supplemental_position_ready) {\n                    if (pose.has_orientation) {\n                        reference_pose.orientation = multiply_quaternions(reference_supplemental_orientation_conj, reference_pose.orientation);\n                    }\n                    pose.position = vector_rotate(pose.position, reference_pose.orientation);\n                }\n            }\n            last_supplemental_pose = pose;\n            return;\n        }\n    }\n\n    // use the data from the supplemental pose to fill in any gaps in the primary pose\n    if (!pose.has_orientation && s && last_supplemental_pose.has_orientation) {\n        pose.orientation = last_supplemental_pose.orientation;\n        pose.has_orientation = true;\n    }\n    if (!pose.has_position && s && last_supplemental_pose.has_position && supplemental_position_ready) {\n        pose.position = last_supplemental_pose.position;\n        pose.has_position = true;\n    }\n    \n    pose_handler(pose);\n}\n\nconnection_t* connection_pool_find_hid_connection(uint16_t id_vendor, int16_t id_product) {\n    if (config()->debug_connections) log_debug(\"connection_pool_find_hid_connection for vendor %d product %d\\n\", id_vendor, id_product);\n    pthread_mutex_lock(&pool->mutex);\n    connection_t* c = find_hid_connection_locked(id_vendor, id_product);\n    pthread_mutex_unlock(&pool->mutex);\n    return c;\n}\n\nconnection_t* connection_pool_find_driver_connection(const char* driver_id) {\n    if (config()->debug_connections) log_debug(\"connection_pool_find_driver_connection for driver %s\\n\", driver_id);\n    pthread_mutex_lock(&pool->mutex);\n    connection_t* c = find_driver_connection_locked(driver_id);\n    pthread_mutex_unlock(&pool->mutex);\n    return c;\n}"
  },
  {
    "path": "src/curl.c",
    "content": "#include <curl/curl.h>\n#include <pthread.h>\n\nstatic pthread_mutex_t curl_lock = PTHREAD_MUTEX_INITIALIZER;\nstatic int ref_count = 0;\n\nvoid curl_init() {\n    pthread_mutex_lock(&curl_lock);\n    if(ref_count == 0) {\n        curl_global_init(CURL_GLOBAL_DEFAULT);\n    }\n    ref_count++;\n    pthread_mutex_unlock(&curl_lock);\n}\n\nvoid curl_cleanup() {\n    pthread_mutex_lock(&curl_lock);\n    ref_count--;\n    if(ref_count == 0) {\n        curl_global_cleanup();\n    }\n    pthread_mutex_unlock(&curl_lock);\n}\n"
  },
  {
    "path": "src/devices/rayneo.c",
    "content": "#include \"devices.h\"\n#include \"devices/rayneo.h\"\n#include \"connection_pool.h\"\n#include \"driver.h\"\n#include \"imu.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"outputs.h\"\n#include \"runtime_context.h\"\n#include \"sdks/rayneo.h\"\n#include \"strings.h\"\n\n#include <math.h>\n#include <pthread.h>\n#include <unistd.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define TS_TO_MS_FACTOR 1000000\n#define EXPECTED_CYCLES_PER_S 500\n#define FORCED_CYCLES_PER_S 250 // let's force 250Hz cycle time so we're doing fewer computations\n#define CYCLE_TIME_CHECK_ERROR_FACTOR 0.95 // cycle times won't be exact, check within a 5% margin\n#define FORCED_CYCLE_TIME_MS 1000.0 / FORCED_CYCLES_PER_S * CYCLE_TIME_CHECK_ERROR_FACTOR\n#define BUFFER_SIZE_TARGET_MS 10 // smooth IMU data over this period of time\n\n#define RAYNEO_ID_VENDOR 0x1bbb\n#define RAYNEO_ID_PRODUCT 0xaf50\n\n#define STATE_EVENT_DEVICE_INFO 0x4000\n#define RAYNEO_DRIVER_ID \"rayneo\"\n\n// RayNeo SDK is returning rotations relative to an east-up-south coordinate system,\n// this converts to to north-west-up, and applies a 15-degree offset based on factory device calibration\nstatic const imu_quat_type adjustment_quat = {\n    .w = 0.561,\n    .x = -0.430,\n    .y = 0.430,\n    .z = 0.561\n};\n\nconst device_properties_type rayneo_properties = {\n    .brand                              = \"\",\n    .model                              = \"\",\n    .hid_vendor_id                      = RAYNEO_ID_VENDOR,\n    .hid_product_id                     = RAYNEO_ID_PRODUCT,\n    .calibration_setup                  = CALIBRATION_SETUP_AUTOMATIC,\n    .resolution_w                       = RESOLUTION_1080P_W,\n    .resolution_h                       = RESOLUTION_1080P_H,\n    .fov                                = 43.0,\n    .lens_distance_ratio                = 0.05,\n    .calibration_wait_s                 = 5,\n    .imu_cycles_per_s                   = FORCED_CYCLES_PER_S,\n    .imu_buffer_size                    = ceil(BUFFER_SIZE_TARGET_MS / FORCED_CYCLE_TIME_MS),\n    .look_ahead_constant                = 15.0,\n    .look_ahead_frametime_multiplier    = 0.45,\n    .look_ahead_scanline_adjust         = 12.0,\n    .look_ahead_ms_cap                  = 40.0,\n    .sbs_mode_supported                 = true,\n    .firmware_update_recommended        = false,\n    .provides_orientation               = true,\n    .provides_position                  = false\n};\n\nstatic uint32_t last_utilized_event_ts = 0;\n\n// hardware connection - device is physically plugged in\nstatic bool hard_connected = false;\n// software connection - we're actively in communication, holding open a connection\nstatic bool soft_connected = false;\n\nstatic bool is_sbs_mode = false;\nvoid rayneo_imu_callback(const float acc[3], const float gyro[3], const float mag[3], uint64_t timestamp){\n    if (!soft_connected || driver_disabled()) return;\n\n    uint32_t ts = (uint32_t) (timestamp / TS_TO_MS_FACTOR);\n    uint32_t elapsed_from_last_utilized = ts - last_utilized_event_ts;\n    if (elapsed_from_last_utilized > FORCED_CYCLE_TIME_MS) {\n        float rotation[4];\n        float position[3];\n        uint64_t time;\n        GetHeadTrackerPose(rotation, position, &time);\n\n        imu_quat_type imu_quat = { .w = rotation[3], .x = rotation[0], .y = rotation[1], .z = rotation[2] };\n        imu_quat_type nwu_quat = multiply_quaternions(imu_quat, adjustment_quat);\n        imu_pose_type pose = (imu_pose_type){0};\n        pose.orientation = nwu_quat;\n        pose.has_orientation = true;\n        pose.timestamp_ms = ts;\n        connection_pool_ingest_pose(RAYNEO_DRIVER_ID, pose);\n\n        last_utilized_event_ts = ts;\n    }\n}\n\nstatic pthread_mutex_t device_name_mutex = PTHREAD_MUTEX_INITIALIZER;\nstatic pthread_cond_t device_name_cond = PTHREAD_COND_INITIALIZER;\nstatic char* device_brand = NULL;\nstatic char* device_model = NULL;\nstatic void rayneo_mcu_callback(uint32_t state, uint64_t timestamp, size_t length, const void* data) {\n    uint32_t ts = (uint32_t) (timestamp / TS_TO_MS_FACTOR);\n    if (!soft_connected) return;\n    if (state == STATE_EVENT_DEVICE_INFO) {\n        pthread_mutex_lock(&device_name_mutex);\n        if (device_brand == NULL && device_model == NULL) {\n            char device_type[64];\n            GetDeviceType(device_type);\n            if (config()->debug_device) log_debug(\"RayNeo driver, received device type: %s\\n\", device_type);\n\n            bool device_found = false;\n            if (strlen(device_type) > 0) {\n                char device_type_copy[64];\n                strncpy(device_type_copy, device_type, sizeof(device_type_copy) - 1);\n                device_type_copy[sizeof(device_type_copy) - 1] = '\\0';\n                \n                char* brand_part = strtok(device_type_copy, \" \");\n                char* model_part = strtok(NULL, \" \");\n                if (brand_part && model_part && strlen(brand_part) > 0 && strlen(model_part) > 0) {\n                    device_brand = strdup(brand_part);\n                    char* version_part = strtok(NULL, \" \");\n                    if (version_part && strlen(version_part) > 0) {\n                        device_model = malloc(strlen(model_part) + strlen(version_part) + 2);\n                        if (device_model) {\n                            sprintf(device_model, \"%s %s\", model_part, version_part);\n                            device_found = true;\n                        }\n                    } else {\n                        device_model = strdup(model_part);\n                        device_found = true;\n                    }\n                }\n            }\n            if (device_found) pthread_cond_signal(&device_name_cond);\n        }\n        pthread_mutex_unlock(&device_name_mutex);\n\n        is_sbs_mode = GetSideBySideStatus() == 1;\n    }\n}\n\nstatic pthread_mutex_t device_connection_mutex = PTHREAD_MUTEX_INITIALIZER;\nbool rayneo_device_connect() {\n    pthread_mutex_lock(&device_connection_mutex);\n    if (!soft_connected) {\n        if (!hard_connected) {\n            RegisterIMUEventCallback(rayneo_imu_callback);\n            RegisterStateEventCallback(rayneo_mcu_callback);\n            if (EstablishUsbConnection(RAYNEO_ID_VENDOR, RAYNEO_ID_PRODUCT) == 0) {\n                NotifyDeviceConnected();\n                hard_connected = true;\n            }\n        }\n        if (hard_connected) {\n            StartXR();\n            OpenIMU();\n            \n            soft_connected = true;\n\n            // this will trigger the STATE_EVENT_DEVICE_INFO event\n            AcquireDeviceInfo();\n        } else {\n            log_message(\"RayNeo driver, failed to establish a connection\\n\");\n        }\n    }\n    pthread_mutex_unlock(&device_connection_mutex);\n\n    return soft_connected;\n};\n\nvoid rayneo_device_disconnect(bool soft, bool is_device_present) {\n    pthread_mutex_lock(&device_connection_mutex);\n    if (soft_connected) {\n        CloseIMU();\n        StopXR();\n        soft_connected = false;\n    }\n\n    bool retain_hard_connection = soft && is_device_present;\n    if (hard_connected && !retain_hard_connection) {\n        NotifyDeviceDisconnected();\n        ResetUsbConnection();\n        UnregisterIMUEventCallback(rayneo_imu_callback);\n        UnregisterStateEventCallback(rayneo_mcu_callback);\n        free_and_clear(&device_brand);\n        free_and_clear(&device_model);\n        hard_connected = false;\n    }\n    pthread_mutex_unlock(&device_connection_mutex);\n};\n\ndevice_properties_type* rayneo_supported_device(uint16_t vendor_id, uint16_t product_id, uint8_t usb_bus, uint8_t usb_address) {\n    if (vendor_id == RAYNEO_ID_VENDOR && product_id == RAYNEO_ID_PRODUCT) {\n        device_properties_type* device = calloc(1, sizeof(device_properties_type));\n        *device = rayneo_properties;\n\n        // trying to connect to the device too quickly seems to cause irrecoverable connection issues\n        sleep(2);\n\n        // device_connect is actually out-of-turn here, the driver would normally call connect after we return the device \n        // properties, but we kick this off now so we can acquire the device name, which unfortunately comes from the SDK \n        // only after establishing a connection.\n        if (rayneo_device_connect()) {\n            pthread_mutex_lock(&device_name_mutex);\n            while (device_brand == NULL && device_model == NULL) {\n                pthread_cond_wait(&device_name_cond, &device_name_mutex);\n            }\n            pthread_mutex_unlock(&device_name_mutex);\n            device->brand = device_brand;\n            device->model = device_model;\n\n            // Leave the connection open if we think it'll be used, but if the driver is disabled, disconnect now\n            if (driver_disabled()) rayneo_device_disconnect(true, true);\n\n            return device;\n        }\n    }\n\n    return NULL;\n};\n\nvoid rayneo_block_on_device() {\n    device_properties_type* device = device_checkout();\n    bool imu_started = false;\n    if (soft_connected && device != NULL) imu_started = wait_for_imu_start();\n    while (soft_connected && device != NULL && imu_started && is_imu_alive()) {\n        sleep(1);\n    }\n\n    rayneo_device_disconnect(true, device != NULL);\n    device_checkin(device);\n};\n\nbool rayneo_device_is_sbs_mode() {\n    return is_sbs_mode;\n};\n\nbool rayneo_device_set_sbs_mode(bool enabled) {\n    // don't explicitly change the is_sbs_mode value here, wait for it to come back around from the MCU deviceinfo response\n    if (enabled) {\n        SwitchTo3D();\n    } else {\n        SwitchTo2D();\n    }\n\n    return true;\n};\n\nbool rayneo_is_connected() {\n    return soft_connected;\n};\n\nvoid rayneo_disconnect(bool soft) {\n    rayneo_device_disconnect(soft, device_present());\n};\n\nconst device_driver_type rayneo_driver = {\n    .id                                 = RAYNEO_DRIVER_ID,\n    .supported_device_func              = rayneo_supported_device,\n    .device_connect_func                = rayneo_device_connect,\n    .block_on_device_func               = rayneo_block_on_device,\n    .device_is_sbs_mode_func            = rayneo_device_is_sbs_mode,\n    .device_set_sbs_mode_func           = rayneo_device_set_sbs_mode,\n    .is_connected_func                  = rayneo_is_connected,\n    .disconnect_func                    = rayneo_disconnect\n};\n"
  },
  {
    "path": "src/devices/rokid.c",
    "content": "#include \"devices.h\"\n#include \"driver.h\"\n#include \"connection_pool.h\"\n#include \"imu.h\"\n#include \"logging.h\"\n#include \"outputs.h\"\n#include \"runtime_context.h\"\n#include \"sdks/rokid.h\"\n#include \"strings.h\"\n\n#include <fcntl.h>\n#include <math.h>\n#include <unistd.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define TS_TO_MS_FACTOR 1000000\n#define ROKID_ID_PRODUCT_COUNT 7\nconst int rokid_supported_id_product[ROKID_ID_PRODUCT_COUNT] = {\n    0x162B, 0x162C, 0x162D, 0x162E, 0x162F, 0x2002, 0x2180\n};\n\n#define RESOLUTION_2D_3840_1080_60HZ 0\n#define RESOLUTION_3D_3840_1080_60HZ 1\n#define RESOLUTION_3D_3840_1200_90HZ 4\n#define RESOLUTION_3D_3840_1200_60HZ 5\n\n#define ROKID_DRIVER_ID \"rokid\"\n\n// Rokid SDK is returning rotations relative to an east-up-south coordinate system,\n// this converts to to north-west-up, and applies a 5-degree offset based on factory device calibration\nstatic const imu_quat_type adjustment_quat = {\n    .w = 0.521,\n    .x = -0.478,\n    .y = 0.478,\n    .z = 0.521\n};\n\nconst device_properties_type rokid_one_properties = {\n    .brand                              = \"\", // replaced by the supported_device() function\n    .model                              = \"\", // replaced by the supported_device() function\n    .hid_vendor_id                      = ROKID_GLASS_VID,\n    .hid_product_id                     = -1, // replaced by the supported_device() function\n    .calibration_setup                  = CALIBRATION_SETUP_AUTOMATIC,\n    .resolution_w                       = RESOLUTION_1080P_W,\n    .resolution_h                       = RESOLUTION_1080P_H,\n    .fov                                = 45,\n    .lens_distance_ratio                = 0.03125,\n    .calibration_wait_s                 = 1,\n    .imu_cycles_per_s                   = 90,\n    .imu_buffer_size                    = 1,\n    .look_ahead_constant                = 20.0,\n    .look_ahead_frametime_multiplier    = 0.6,\n    .look_ahead_scanline_adjust         = 8.0,\n    .look_ahead_ms_cap                  = 40.0,\n    .sbs_mode_supported                 = true,\n    .firmware_update_recommended        = false,\n    .provides_orientation               = true,\n    .provides_position                  = false\n};\n\nstatic void* event_instance = NULL;\nstatic void* event_handle = NULL;\nstatic void* control_instance = NULL;\nstatic bool sbs_mode_enabled = false;\n\n// hardware connection - device is physically plugged in\nstatic bool hard_connected = false;\n// software connection - we're actively in communication, holding open a connection\nstatic bool soft_connected = false;\n\nstatic void cleanup() {\n    if (event_instance && event_handle) {\n        GlassUnRegisterEvent(event_instance, event_handle);\n        event_handle = NULL;\n    }\n\n    if (!hard_connected) {\n        if (event_instance) {\n            GlassEventClose(event_instance);\n            event_instance = NULL;\n        }\n        if (control_instance) {\n            GlassControlClose(control_instance);\n            control_instance = NULL;\n        }\n    }\n}\n\nvoid rokid_disconnect(bool soft) {\n    soft_connected = false;\n    hard_connected = soft;\n}\n\nstatic void handle_display_mode(device_properties_type* device, int display_mode) {\n    sbs_mode_enabled = display_mode != RESOLUTION_2D_3840_1080_60HZ;\n    if (sbs_mode_enabled) {\n        if (display_mode != RESOLUTION_3D_3840_1080_60HZ) {\n            device->resolution_h = RESOLUTION_1200P_H;\n        } else {\n            device->resolution_h = RESOLUTION_1080P_H;\n        }\n    }\n}\n\nstatic bool device_connect(device_properties_type* device) {\n    hard_connected = true;\n    if (!event_instance) event_instance = GlassEventInit();\n    if (!event_instance) {\n        log_error(\"Failed to initialize event instance\\n\");\n    } else {\n        if (!control_instance) control_instance = GlassControlInit();\n        if (!control_instance) {\n            log_error(\"Failed to initialize control instance\\n\");\n        } else {\n            soft_connected = GlassEventOpen(event_instance, device->hid_vendor_id, device->hid_product_id) && \n                             GlassControlOpen(control_instance, device->hid_vendor_id, device->hid_product_id);\n\n            if (soft_connected) {\n                event_handle = GlassRegisterEventWithSize(event_instance, GAME_ROTATION_EVENT, 50);\n                if (!event_handle) {\n                    log_error(\"Failed to register event handle\\n\");\n                    soft_connected = false;\n                } else {\n                    GlassAddFusionEvent(event_instance, true);\n                    handle_display_mode(device, GetDisplayMode(control_instance));\n                }\n            }\n        }\n    }\n    \n    if (!soft_connected) {\n        cleanup();\n    }\n\n    return soft_connected;\n}\n\n// this will already be connected if the driver is enabled\nbool rokid_device_connect() {\n    device_properties_type* device = device_checkout();\n    if (device != NULL) device_connect(device);\n    device_checkin(device);\n\n    return soft_connected;\n}\n\ndevice_properties_type* rokid_supported_device(uint16_t vendor_id, uint16_t product_id, uint8_t usb_bus, uint8_t usb_address) {\n    if (vendor_id == ROKID_GLASS_VID) {\n        for (int i=0; i < ROKID_ID_PRODUCT_COUNT; i++) {\n            if (product_id == rokid_supported_id_product[i]) {\n                device_properties_type* device = calloc(1, sizeof(device_properties_type));\n                *device = rokid_one_properties;\n                device->hid_vendor_id = vendor_id;\n                device->hid_product_id = product_id;\n                device->usb_bus = usb_bus;\n                device->usb_address = usb_address;\n\n                sleep(1);\n\n                if (device_connect(device)) {\n                    // split GetProductName result on the first space to separate brand and model\n                    char* product_name = GetProductName(control_instance);\n                    char* space = strchr(product_name, ' ');\n                    char* version_start = strchr(product_name, '(');\n                    if (space) {\n                        *space = '\\0';\n                        if (version_start) {\n                            *version_start = '\\0';\n                        }\n                        device->model = strdup(space + 1);\n                    }\n                    device->brand = strdup(product_name);\n                    if (driver_disabled()) rokid_disconnect(true);\n                    return device;\n                }\n            }\n        }\n    }\n\n    return NULL;\n};\n\nstatic int imu_counter = 0;\nvoid rokid_block_on_device() {\n    device_properties_type* device = device_checkout();\n    if (device != NULL) {\n        struct EventData ed;\n        while (soft_connected) {\n            if (GlassWaitEvent(event_instance, event_handle, &ed, 1000)) {\n                struct SensorData sd = ed.acc;\n                uint32_t timestamp = (uint32_t) (sd.sensor_timestamp_ns / TS_TO_MS_FACTOR);\n                struct RotationData rd = ed.rotation;\n                imu_quat_type imu_quat = {\n                    .w = rd.Q[3],\n                    .x = rd.Q[0],\n                    .y = rd.Q[1],\n                    .z = rd.Q[2]\n                };\n                imu_quat_type nwu_quat = multiply_quaternions(imu_quat, adjustment_quat);\n\n                if (++imu_counter % device->imu_cycles_per_s == 0) {\n                    imu_counter = 0;\n\n                    // do this every second in the same thread as GlassWaitEvent, it seemed like the\n                    // USB interactions between the two calls may not be thread safe\n                    handle_display_mode(device, GetDisplayMode(control_instance));\n                }\n\n                imu_pose_type pose = (imu_pose_type){0};\n                pose.orientation = nwu_quat;\n                pose.has_orientation = true;\n                pose.timestamp_ms = timestamp;\n                connection_pool_ingest_pose(ROKID_DRIVER_ID, pose);\n            }\n        }\n        cleanup();\n    }\n    device_checkin(device);\n};\n\nbool rokid_device_is_sbs_mode() {\n    return sbs_mode_enabled;\n};\n\nbool rokid_device_set_sbs_mode(bool enabled) {\n    // 3D mode offers 1080p and 1200p options, might as well go with the higher resolution\n    sbs_mode_enabled = GlassSetDisplayMode(\n        control_instance, enabled ? RESOLUTION_3D_3840_1200_60HZ : RESOLUTION_2D_3840_1080_60HZ);\n    return sbs_mode_enabled;\n};\n\nbool rokid_is_connected() {\n    return soft_connected;\n};\n\nconst device_driver_type rokid_driver = {\n    .id                                 = ROKID_DRIVER_ID,\n    .supported_device_func              = rokid_supported_device,\n    .device_connect_func                = rokid_device_connect,\n    .block_on_device_func               = rokid_block_on_device,\n    .device_is_sbs_mode_func            = rokid_device_is_sbs_mode,\n    .device_set_sbs_mode_func           = rokid_device_set_sbs_mode,\n    .is_connected_func                  = rokid_is_connected,\n    .disconnect_func                    = rokid_disconnect\n};\n"
  },
  {
    "path": "src/devices/viture.c",
    "content": "#include \"connection_pool.h\"\n#include \"devices.h\"\n#include \"devices/viture.h\"\n#include \"driver.h\"\n#include \"epoch.h\"\n#include \"imu.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"outputs.h\"\n#include \"runtime_context.h\"\n#include \"sdks/viture_device.h\"\n#include \"sdks/viture_device_carina.h\"\n#include \"sdks/viture_glasses_provider.h\"\n#include \"strings.h\"\n\n#include <math.h>\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#define VITURE_ID_PRODUCT_COUNT 14\n#define VITURE_ID_VENDOR 0x35ca\n#define VITURE_DRIVER_ID \"viture\"\n#define VITURE_ONE_MODEL_NAME \"One\"\n#define VITURE_ONE_LITE_MODEL_NAME \"One Lite\"\n#define VITURE_PRO_MODEL_NAME \"Pro\"\n#define VITURE_LUMA_MODEL_NAME \"Luma\"\n#define VITURE_LUMA_PRO_MODEL_NAME \"Luma Pro\"\n#define VITURE_LUMA_ULTRA_MODEL_NAME \"Luma Ultra\"\n#define VITURE_LUMA_CYBER_MODEL_NAME \"Luma Cyber\"\n#define VITURE_BEAST_MODEL_NAME \"Beast\"\n\n#define VITURE_DISPLAY_MODE_1920_1080_60HZ 0x31\n#define VITURE_DISPLAY_MODE_3840_1080_60HZ 0x32\n#define VITURE_DISPLAY_MODE_3840_1080_90HZ 0x35\n#define VITURE_DISPLAY_MODE_1920_1200_60HZ 0x41\n#define VITURE_DISPLAY_MODE_3840_1200_60HZ 0x42\n#define VITURE_DISPLAY_MODE_3840_1200_90HZ 0x45\n\n#define VITURE_IMU_MODE_RAW 0\n#define VITURE_IMU_MODE_POSE 1\n\n#define VITURE_IMU_FREQ_LOW 0\n#define VITURE_IMU_FREQ_MEDIUM_LOW 1\n#define VITURE_IMU_FREQ_MEDIUM 2\n#define VITURE_IMU_FREQ_MEDIUM_HIGH 3\n#define VITURE_IMU_FREQ_HIGH 4\n#define VITURE_IMU_FREQ_COUNT 5\n#define VITURE_CARINA_CYCLES_PER_S 1000\n#define VITURE_CARINA_POLL_INTERVAL_US (1000000 / VITURE_CARINA_CYCLES_PER_S)\n#define VITURE_FLOAT_EXACT_MS_LIMIT 16777216.0 // 2^24, largest consecutive int in float\n#define VITURE_FLOAT_RESET_MARGIN_MS 1000.0 // avoid running right at the precision edge\n\n#define VITURE_LOG_LEVEL_NONE 0\n#define VITURE_LOG_LEVEL_ERROR 1\n#define VITURE_LOG_LEVEL_INFO 2\n#define VITURE_LOG_LEVEL_DEBUG 3\n\n#define VITURE_STATE_ID_BRIGHTNESS 0\n#define VITURE_STATE_ID_VOLUME 1\n#define VITURE_STATE_ID_DISPLAY_MODE 2\n#define VITURE_STATE_ID_ELECTROCHROMIC_FILM 3\n\nstatic const float VITURE_ONE_PITCH_ADJUSTMENT = 6.0;\nstatic const float VITURE_PRO_PITCH_ADJUSTMENT = 3.0;\nstatic const float VITURE_LUMA_PITCH_ADJUSTMENT = -8.5;\nstatic const float VITURE_BEAST_PITCH_ADJUSTMENT = -8.5; // Placeholder until specs finalized\nstatic const float VITURE_ONE_FOV = 40.0;\nstatic const float VITURE_PRO_FOV = 43.0;\nstatic const float VITURE_LUMA_FOV = 50.0;\nstatic const float VITURE_LUMA_PRO_FOV = 52.0;\nstatic const float VITURE_LUMA_ULTRA_FOV = 52.0;\nstatic const float VITURE_LUMA_CYBER_FOV = 52.0;\nstatic const float VITURE_BEAST_FOV = 58.0;\n\nstatic const int viture_supported_id_product[VITURE_ID_PRODUCT_COUNT] = {\n    0x1011, // One\n    0x1013, // One\n    0x1017, // One\n    0x1015, // One Lite\n    0x101b, // One Lite\n    0x1019, // Pro\n    0x101d, // Pro\n    0x1131, // Luma\n    0x1121, // Luma Pro\n    0x1141, // Luma Pro\n    0x1101, // Luma Ultra\n    0x1104, // Luma Ultra\n    0x1151, // Luma Cyber\n    0x1201  // Viture Beast\n};\nstatic const char* viture_supported_models[VITURE_ID_PRODUCT_COUNT] = {\n    VITURE_ONE_MODEL_NAME, \n    VITURE_ONE_MODEL_NAME,\n    VITURE_ONE_MODEL_NAME,\n    VITURE_ONE_LITE_MODEL_NAME,\n    VITURE_ONE_LITE_MODEL_NAME,\n    VITURE_PRO_MODEL_NAME,\n    VITURE_PRO_MODEL_NAME,\n    VITURE_LUMA_MODEL_NAME,\n    VITURE_LUMA_PRO_MODEL_NAME,\n    VITURE_LUMA_PRO_MODEL_NAME,\n    VITURE_LUMA_ULTRA_MODEL_NAME,\n    VITURE_LUMA_ULTRA_MODEL_NAME,\n    VITURE_LUMA_CYBER_MODEL_NAME,\n    VITURE_BEAST_MODEL_NAME\n};\nstatic const float* viture_pitch_adjustments[VITURE_ID_PRODUCT_COUNT] = {\n    &VITURE_ONE_PITCH_ADJUSTMENT,  // One\n    &VITURE_ONE_PITCH_ADJUSTMENT,  // One\n    &VITURE_ONE_PITCH_ADJUSTMENT,  // One\n    &VITURE_ONE_PITCH_ADJUSTMENT,  // One Lite\n    &VITURE_ONE_PITCH_ADJUSTMENT,  // One Lite\n    &VITURE_PRO_PITCH_ADJUSTMENT,  // Pro\n    &VITURE_PRO_PITCH_ADJUSTMENT,  // Pro\n    &VITURE_LUMA_PITCH_ADJUSTMENT, // Luma\n    &VITURE_LUMA_PITCH_ADJUSTMENT, // Luma Pro\n    &VITURE_LUMA_PITCH_ADJUSTMENT, // Luma Pro\n    &VITURE_LUMA_PITCH_ADJUSTMENT, // Luma Ultra\n    &VITURE_LUMA_PITCH_ADJUSTMENT, // Luma Ultra\n    &VITURE_LUMA_PITCH_ADJUSTMENT, // Luma Cyber\n    &VITURE_BEAST_PITCH_ADJUSTMENT // Beast\n};\nstatic const float* viture_fovs[VITURE_ID_PRODUCT_COUNT] = {\n    &VITURE_ONE_FOV,        // One\n    &VITURE_ONE_FOV,        // One\n    &VITURE_ONE_FOV,        // One\n    &VITURE_ONE_FOV,        // One Lite\n    &VITURE_ONE_FOV,        // One Lite\n    &VITURE_PRO_FOV,        // Pro\n    &VITURE_PRO_FOV,        // Pro\n    &VITURE_LUMA_FOV,       // Luma\n    &VITURE_LUMA_PRO_FOV,   // Luma Pro\n    &VITURE_LUMA_PRO_FOV,   // Luma Pro\n    &VITURE_LUMA_ULTRA_FOV, // Luma Ultra\n    &VITURE_LUMA_ULTRA_FOV, // Luma Ultra\n    &VITURE_LUMA_CYBER_FOV, // Luma Cyber\n    &VITURE_BEAST_FOV       // Beast\n};\nstatic const int viture_resolution_heights[VITURE_ID_PRODUCT_COUNT] = {\n    RESOLUTION_1080P_H, // One\n    RESOLUTION_1080P_H, // One\n    RESOLUTION_1080P_H, // One\n    RESOLUTION_1080P_H, // One Lite\n    RESOLUTION_1080P_H, // One Lite\n    RESOLUTION_1080P_H, // Pro\n    RESOLUTION_1080P_H, // Pro\n    RESOLUTION_1200P_H, // Luma\n    RESOLUTION_1200P_H, // Luma Pro\n    RESOLUTION_1200P_H, // Luma Pro\n    RESOLUTION_1200P_H, // Luma Ultra\n    RESOLUTION_1200P_H, // Luma Ultra\n    RESOLUTION_1200P_H, // Luma Cyber\n    RESOLUTION_1200P_H  // Beast\n};\n\nstatic const int viture_calibration_wait_s[VITURE_ID_PRODUCT_COUNT] = {\n    1, // One\n    1, // One\n    1, // One\n    1, // One Lite\n    1, // One Lite\n    1, // Pro\n    1, // Pro\n    1, // Luma\n    5, // Luma Pro\n    5, // Luma Pro\n    10, // Luma Ultra\n    10, // Luma Ultra\n    5, // Luma Cyber (TBD)\n    1  // Beast (TBD)\n};\n\nstatic const int viture_look_ahead_constant[VITURE_ID_PRODUCT_COUNT] = {\n    20, // One\n    20, // One\n    20, // One\n    20, // One Lite\n    20, // One Lite\n    20, // Pro\n    20, // Pro\n    20, // Luma\n    20, // Luma Pro\n    20, // Luma Pro\n    10, // Luma Ultra\n    10, // Luma Ultra\n    10, // Luma Cyber (TBD)\n    10  // Beast (TBD)\n};\n\nstatic imu_quat_type adjustment_quat;\nstatic XRDeviceProviderHandle viture_provider = NULL;\nstatic XRDeviceType viture_device_type = XR_DEVICE_TYPE_VITURE_GEN1;\nstatic uint16_t viture_last_product_id = 0;\nstatic pthread_mutex_t viture_connection_mutex = PTHREAD_MUTEX_INITIALIZER;\nstatic bool connected = false;\nstatic bool initialized = false;\nstatic bool viture_state_callback_registered = false;\nstatic bool viture_imu_open = false;\nstatic uint8_t viture_requested_frequency = VITURE_IMU_FREQ_MEDIUM_HIGH;\nstatic bool sbs_mode_enabled = false;\nstatic int viture_saved_display_mode = -1;\nstatic int viture_saved_dof = -1;\nstatic int viture_callback_logs_remaining = 10;\n\nstatic const int viture_frequency_hz[VITURE_IMU_FREQ_COUNT] = {60, 90, 120, 240, 500};\n\nstatic const char* viture_open_imu_error_reason(int code) {\n    switch (code) {\n    case -1: return \"param error\";\n    case -2: return \"USB execution error\";\n    case -3: return \"device type not supported\";\n    case -4: return \"other error\";\n    default: return \"unknown\";\n    }\n}\n\nstatic const device_properties_type viture_properties = {\n    .brand                              = \"VITURE\",\n    .model                              = NULL,\n    .hid_vendor_id                      = 0x35ca,\n    .hid_product_id                     = 0x1011,\n    .calibration_setup                  = CALIBRATION_SETUP_AUTOMATIC,\n    .resolution_w                       = RESOLUTION_1080P_W,\n    .resolution_h                       = RESOLUTION_1080P_H,\n    .fov                                = VITURE_ONE_FOV,\n    .lens_distance_ratio                = 0.05,\n    .calibration_wait_s                 = 1,\n    .imu_cycles_per_s                   = 60,\n    .imu_buffer_size                    = 1,\n    .look_ahead_constant                = 20.0,\n    .look_ahead_frametime_multiplier    = 0.6,\n    .look_ahead_scanline_adjust         = 10.0,\n    .look_ahead_ms_cap                  = 40.0,\n    .sbs_mode_supported                 = true,\n    .firmware_update_recommended        = false,\n    .provides_orientation               = true,\n    .provides_position                  = false\n};\n\nstatic bool viture_display_mode_is_sbs(int mode) {\n    switch (mode) {\n        case VITURE_DISPLAY_MODE_3840_1080_60HZ:\n        case VITURE_DISPLAY_MODE_3840_1080_90HZ:\n        case VITURE_DISPLAY_MODE_3840_1200_60HZ:\n        case VITURE_DISPLAY_MODE_3840_1200_90HZ:\n            return true;\n        default:\n            return false;\n    }\n}\n\nstatic void viture_refresh_sbs_state_locked() {\n    if (viture_provider == NULL) return;\n    int mode = xr_device_provider_get_display_mode(viture_provider);\n    if (mode >= 0) {\n        sbs_mode_enabled = viture_display_mode_is_sbs(mode);\n        if (config()->debug_device) {\n            log_debug(\"VITURE: Refreshed SBS state, mode=%d enabled=%d\\n\", mode, sbs_mode_enabled);\n        }\n    }\n}\n\n// TODO - for eventual Beast integration\nstatic void viture_capture_and_override_display_mode_locked() {\n    viture_saved_display_mode = -1;\n    viture_saved_dof = -1;\n\n    if (viture_provider == NULL) {\n        if (config()->debug_device) {\n            log_debug(\"VITURE: Cannot override display mode, provider NULL\\n\");\n        }\n        return;\n    }\n\n    int mode = 0;\n    int dof = 0;\n    if (xr_device_provider_get_display_mode_and_native_dof(viture_provider, &mode, &dof) != 0) {\n        if (config()->debug_device) {\n            log_debug(\"VITURE: Unable to read display mode/dof during override\\n\");\n        }\n        return;\n    }\n\n    viture_saved_display_mode = mode;\n    viture_saved_dof = dof;\n\n    if (xr_device_provider_set_display_mode_and_native_dof(viture_provider, mode, 0) == 0) {\n        sbs_mode_enabled = viture_display_mode_is_sbs(mode);\n        if (config()->debug_device) {\n            log_debug(\"VITURE: Forced display mode=%d to 0DoF\\n\", mode);\n        }\n    } else if (config()->debug_device) {\n        log_debug(\"VITURE: Failed to force 0DoF (mode=%d, dof=%d)\\n\", mode, dof);\n    }\n}\n\n// TODO - for eventual Beast integration\nstatic void viture_restore_display_mode_locked() {\n    if (viture_provider == NULL) {\n        viture_saved_display_mode = -1;\n        viture_saved_dof = -1;\n        if (config()->debug_device) {\n            log_debug(\"VITURE: Cannot restore display mode, provider NULL\\n\");\n        }\n        return;\n    }\n\n    if (viture_saved_display_mode < 0 || viture_saved_dof < 0) {\n        if (config()->debug_device) {\n            log_debug(\"VITURE: No saved display state to restore\\n\");\n        }\n        return;\n    }\n\n    int restore_mode = viture_saved_display_mode;\n    int restore_dof = viture_saved_dof;\n    int result = xr_device_provider_set_display_mode_and_native_dof(\n        viture_provider, restore_mode, restore_dof);\n\n    if (result == 0) {\n        sbs_mode_enabled = viture_display_mode_is_sbs(restore_mode);\n        if (config()->debug_device) {\n            log_debug(\"VITURE: Restored display mode=%d dof=%d\\n\", restore_mode, restore_dof);\n        }\n    } else if (config()->debug_device) {\n        log_debug(\"VITURE: Failed to restore display mode=%d dof=%d (err=%d)\\n\",\n                  restore_mode,\n                  restore_dof,\n                  result);\n    }\n\n    viture_saved_display_mode = -1;\n    viture_saved_dof = -1;\n}\n\nstatic void viture_publish_pose(imu_quat_type orientation, bool has_position,\n                                imu_vec3_type position, uint32_t timestamp_ms) {\n    if (driver_disabled()) return;\n\n    orientation = multiply_quaternions(orientation, adjustment_quat);\n\n    imu_pose_type pose = {0};\n    pose.orientation = orientation;\n    pose.position = has_position ? position : (imu_vec3_type){0};\n    pose.has_orientation = true;\n    pose.has_position = has_position;\n    pose.timestamp_ms = timestamp_ms;\n    connection_pool_ingest_pose(VITURE_DRIVER_ID, pose);\n}\n\nstatic void viture_legacy_pose_callback(float* pose, uint64_t ts) {\n    if (!connected || driver_disabled() || pose == NULL) return;\n\n    // pose received in NWU coordinate system\n    imu_quat_type quat = {.x = pose[4], .y = pose[5], .z = pose[6], .w = pose[3]};\n\n    uint32_t timestamp_ms = (uint32_t)(ts / 1000000ULL);\n    viture_publish_pose(quat, false, (imu_vec3_type){0}, timestamp_ms);\n}\n\nstatic void viture_carina_imu_callback(float* imu, double timestamp) {\n    static double initial_timestamp = -1.0;\n    device_properties_type* device = device_checkout();\n    if (connected && viture_provider != NULL && device != NULL && imu != NULL) {\n        float pose[9] = {0};\n        int result = get_gl_pose_carina(viture_provider, pose, 0.0);\n        if (result == 0) {\n            // pose received in EUS (GL) coordinate system, convert to NWU\n            imu_quat_type quat = {.x = -pose[6], .y = -pose[4], .z = pose[5], .w = pose[3]};\n\n            float full_distance_cm = LENS_TO_PIVOT_CM / device->lens_distance_ratio;\n            float meters_to_full_distance_ratio = 100.0f / full_distance_cm;\n            imu_vec3_type position = {\n                .x = -pose[2] * meters_to_full_distance_ratio, \n                .y = -pose[0] * meters_to_full_distance_ratio,\n                .z = pose[1] * meters_to_full_distance_ratio\n            };\n\n            if (initial_timestamp < 0.0) initial_timestamp = timestamp;\n\n            double elapsed_ms = (timestamp - initial_timestamp) * 1000.0;\n            if (elapsed_ms >= VITURE_FLOAT_EXACT_MS_LIMIT - VITURE_FLOAT_RESET_MARGIN_MS) {\n                initial_timestamp = timestamp;\n                elapsed_ms = 0.0;\n            }\n\n            uint32_t timestamp_ms = (uint32_t)elapsed_ms;\n            \n            viture_publish_pose(quat, true, position, timestamp_ms);\n        } else if (config()->debug_device) {\n            log_debug(\"VITURE: get_gl_pose_carina failed (%d)\\n\", result);\n        }\n    }\n    device_checkin(device);\n}\n\n// static const char* viture_get_model_name(uint16_t product_id) {\n//     char* model_name = calloc(VITURE_MARKET_NAME_MAX, sizeof(char));\n//     int requested_len = VITURE_MARKET_NAME_MAX;\n//     int result = xr_device_provider_get_market_name(product_id, model_name, &requested_len);\n//     if (result != 0) {\n//         snprintf(model_name, VITURE_MARKET_NAME_MAX, \"VITURE 0x%04X\", product_id);\n//     }\n\n//     return model_name;\n// }\n\n// TODO - the SDK doesn't actually reliably call this yet\nstatic void viture_state_callback(int glass_state_id, int glass_value) {\n    if (glass_state_id == VITURE_STATE_ID_DISPLAY_MODE) {\n        sbs_mode_enabled = viture_display_mode_is_sbs(glass_value);\n        if (config()->debug_device) {\n            log_debug(\"VITURE: Display mode changed via callback, mode=%d sbs_enabled=%d\\n\",\n                      glass_value,\n                      sbs_mode_enabled);\n        }\n    } else if (config()->debug_device) {\n        log_debug(\"VITURE: Glass state callback id=%d value=%d\\n\", glass_state_id, glass_value);\n    }\n}\n\nstatic void viture_register_state_callback_locked() {\n    if (viture_provider == NULL || viture_state_callback_registered) return;\n\n    int result = xr_device_provider_register_state_callback(viture_provider, viture_state_callback);\n    if (result == 0) {\n        viture_state_callback_registered = true;\n        if (config()->debug_device) {\n            log_debug(\"VITURE: State callback registered\\n\");\n        }\n    } else {\n        log_error(\"VITURE: Failed to register state callback (%d)\\n\", result);\n    }\n}\n\nstatic void viture_unregister_state_callback_locked() {\n    if (viture_provider == NULL || !viture_state_callback_registered) return;\n\n    int result = xr_device_provider_register_state_callback(viture_provider, NULL);\n    if (result != 0 && config()->debug_device) {\n        log_debug(\"VITURE: Failed to unregister state callback (%d)\\n\", result);\n    }\n    viture_state_callback_registered = false;\n}\n\nstatic device_properties_type* viture_supported_device(uint16_t vendor_id, uint16_t product_id,\n                                                uint8_t usb_bus, uint8_t usb_address) {\n    if (vendor_id == VITURE_ID_VENDOR) {\n        for (int i = 0; i < VITURE_ID_PRODUCT_COUNT; i++) {\n            if (product_id == viture_supported_id_product[i]) {\n                if (!xr_device_provider_is_product_id_valid(product_id)) {\n                    log_message(\"VITURE: Product ID 0x%04x rejected by SDK\\n\", product_id);\n                    continue;\n                }\n\n                device_properties_type* device = calloc(1, sizeof(device_properties_type));\n                *device = viture_properties;\n                device->hid_vendor_id = vendor_id;\n                device->hid_product_id = product_id;\n                device->model = (char *)viture_supported_models[i];\n                device->resolution_h = viture_resolution_heights[i];\n                device->fov = *viture_fovs[i];\n                device->calibration_wait_s = viture_calibration_wait_s[i];\n                device->look_ahead_constant = (float)viture_look_ahead_constant[i];\n\n                adjustment_quat = device_pitch_adjustment(*viture_pitch_adjustments[i]);\n\n                viture_last_product_id = product_id;\n\n                return device;\n            }\n        }\n    }\n\n    return NULL;\n};\n\nstatic bool viture_initialize_provider_locked(uint16_t product_id) {\n    if (product_id == 0) return false;\n\n    xr_device_provider_set_log_level(VITURE_LOG_LEVEL_ERROR);\n\n    viture_provider = xr_device_provider_create(product_id);\n    if (viture_provider == NULL) {\n        log_error(\"VITURE: Failed to create provider handle for product 0x%04x\\n\", product_id);\n        return false;\n    }\n\n    if (config()->debug_device) {\n        log_debug(\"VITURE: Provider handle created for product 0x%04x\\n\", product_id);\n    }\n\n    int sdk_device_type = xr_device_provider_get_device_type(viture_provider);\n    viture_device_type =\n        sdk_device_type >= 0 ? (XRDeviceType)sdk_device_type : XR_DEVICE_TYPE_VITURE_GEN1;\n\n    if (config()->debug_device) {\n        log_debug(\"VITURE: SDK device type reported as %d\\n\", sdk_device_type);\n    }\n\n    int register_result = -1;\n    if (viture_device_type == XR_DEVICE_TYPE_VITURE_CARINA) {\n        // TODO try removing this entirely since we don't need callbacks\n        register_result =\n            register_callbacks_carina(viture_provider, NULL, NULL, viture_carina_imu_callback, NULL);\n    } else {\n        register_result = register_pose_callback(viture_provider, viture_legacy_pose_callback);\n    }\n\n    bool viture_callbacks_registered = (register_result == 0);\n    if (!viture_callbacks_registered) {\n        log_error(\"VITURE: Failed to register SDK callbacks (type=%d)\\n\", viture_device_type);\n        xr_device_provider_destroy(viture_provider);\n        viture_provider = NULL;\n        return false;\n    } else if (config()->debug_device) {\n        log_debug(\"VITURE: Callback registration succeeded for type=%d\\n\", viture_device_type);\n    }\n\n    if (xr_device_provider_initialize(viture_provider, NULL) != 0) {\n        log_error(\"VITURE: Failed to initialize SDK provider\\n\");\n        xr_device_provider_destroy(viture_provider);\n        viture_provider = NULL;\n        return false;\n    }\n\n    if (config()->debug_device) log_debug(\"VITURE: SDK provider initialized\\n\");\n\n    initialized = true;\n    return true;\n}\n\nstatic bool viture_open_imu_locked() {\n    if (viture_imu_open || viture_device_type == XR_DEVICE_TYPE_VITURE_CARINA) {\n        return true;\n    }\n\n    int open_result = open_imu(viture_provider, VITURE_IMU_MODE_POSE, viture_requested_frequency);\n    viture_imu_open = open_result == 0;\n    if (viture_imu_open) {\n        return true;\n    } else {\n        log_error(\"VITURE: open_imu failed (%d: %s)\\n\", open_result,\n                    viture_open_imu_error_reason(open_result));\n    }\n\n    return false;\n}\n\nstatic bool viture_start_stream_locked() {\n    if (!initialized || viture_provider == NULL) return false;\n\n    sleep(1);\n\n    if (xr_device_provider_start(viture_provider) != 0) {\n        log_error(\"VITURE: Failed to start SDK provider\\n\");\n        return false;\n    }\n\n    if (config()->debug_device) {\n        log_debug(\"VITURE: Provider start succeeded\\n\");\n    }\n\n    // viture_register_state_callback_locked();\n\n    if (!viture_open_imu_locked()) {\n        log_error(\"VITURE: Failed to open IMU stream\\n\");\n        return false;\n    }\n\n    // viture_capture_and_override_display_mode_locked();\n    connected = true;\n    // viture_refresh_sbs_state_locked();\n    return true;\n}\n\nstatic void viture_stop_stream_locked() {\n    if (viture_provider == NULL) return;\n\n    // viture_unregister_state_callback_locked();\n    // viture_restore_display_mode_locked();\n\n    if (viture_imu_open) {\n        close_imu(viture_provider, VITURE_IMU_MODE_POSE);\n        viture_imu_open = false;\n        if (config()->debug_device) {\n            log_debug(\"VITURE: Closed IMU stream\\n\");\n        }\n    }\n\n    if (connected) {\n        int stop_result = xr_device_provider_stop(viture_provider);\n        if (stop_result != 0 && config()->debug_device) {\n            log_debug(\"VITURE: xr_device_provider_stop returned %d\\n\", stop_result);\n        } else if (config()->debug_device && stop_result == 0) {\n            log_debug(\"VITURE: Provider stop succeeded\\n\");\n        }\n        connected = false;\n    }\n}\n\nstatic void viture_shutdown_provider_locked() {\n    if (!initialized || viture_provider == NULL) return;\n\n    if (xr_device_provider_shutdown(viture_provider) != 0 && config()->debug_device) {\n        log_debug(\"VITURE: xr_device_provider_shutdown reported an error\\n\");\n    }\n    xr_device_provider_destroy(viture_provider);\n    viture_provider = NULL;\n    initialized = false;\n    viture_device_type = XR_DEVICE_TYPE_VITURE_GEN1;\n    viture_state_callback_registered = false;\n    viture_saved_display_mode = -1;\n    viture_saved_dof = -1;\n    if (config()->debug_device) {\n        log_debug(\"VITURE: Provider shutdown complete\\n\");\n    }\n}\n\nstatic void viture_update_device_properties(device_properties_type* device) {\n    if (device == NULL) return;\n\n    int cycles_per_s;\n    bool provides_position = false;\n    if (viture_device_type == XR_DEVICE_TYPE_VITURE_CARINA) {\n        cycles_per_s = VITURE_CARINA_CYCLES_PER_S;\n        provides_position = true;\n    } else {\n        cycles_per_s = viture_frequency_hz[viture_requested_frequency];\n    }\n\n    device->imu_cycles_per_s = cycles_per_s;\n    device->imu_buffer_size = cycles_per_s / 60;\n    if (device->imu_buffer_size < 1) device->imu_buffer_size = 1;\n    device->provides_position = provides_position;\n    device->sbs_mode_supported = true;\n    device->firmware_update_recommended = false;\n}\n\nstatic void disconnect(bool soft) {\n    if (config()->debug_device) {\n        log_debug(\"VITURE: Disconnect requested (soft=%d)\\n\", soft);\n    }\n    pthread_mutex_lock(&viture_connection_mutex);\n    viture_stop_stream_locked();\n    if (!soft) viture_shutdown_provider_locked();\n    pthread_mutex_unlock(&viture_connection_mutex);\n}\n\nstatic bool viture_device_connect() {\n    if (connected) return true;\n\n    device_properties_type* device = device_checkout();\n    uint16_t product_id = device ? device->hid_product_id : viture_last_product_id;\n    bool success = true;\n\n    pthread_mutex_lock(&viture_connection_mutex);\n    if (!initialized) {\n        success = viture_initialize_provider_locked(product_id);\n    }\n\n    if (success) {\n        success = viture_start_stream_locked();\n    }\n    pthread_mutex_unlock(&viture_connection_mutex);\n\n    if (!success) {\n        if (config()->debug_device) {\n            log_debug(\"VITURE: Connection attempt failed, cleaning up\\n\");\n        }\n        if (device != NULL) device_checkin(device);\n\n        // do a hard disconnect even though the device is still physically connected\n        disconnect(false);\n        \n        return false;\n    }\n\n    if (device != NULL) {\n        viture_update_device_properties(device);\n        device_checkin(device);\n    }\n\n    if (config()->debug_device) {\n        log_debug(\"VITURE: viture_device_connect completed (connected=%d)\\n\", connected);\n    }\n\n    return connected;\n}\n\nstatic void viture_block_on_device() {\n    if (connected) {\n        wait_for_imu_start();\n        while (connected) {\n            if (!is_imu_alive()) break;\n            sleep(1);\n        }\n    }\n\n    disconnect(true);\n};\n\nstatic bool viture_device_is_sbs_mode() {\n    if (viture_provider == NULL || !connected) return false;\n\n    pthread_mutex_lock(&viture_connection_mutex);\n    int mode = xr_device_provider_get_display_mode(viture_provider);\n    if (mode >= 0) sbs_mode_enabled = viture_display_mode_is_sbs(mode);\n    pthread_mutex_unlock(&viture_connection_mutex);\n\n    return sbs_mode_enabled;\n};\n\nstatic bool viture_device_set_sbs_mode(bool enabled) {\n    pthread_mutex_lock(&viture_connection_mutex);\n    bool success = false;\n    if (viture_provider != NULL && connected) {\n        success = xr_device_provider_switch_dimension(viture_provider, enabled) == 0;\n        if (success) {\n            sbs_mode_enabled = enabled;\n            if (config()->debug_device) {\n                log_debug(\"VITURE: SBS mode set to %d\\n\", enabled);\n            }\n        } else if (config()->debug_device) {\n            log_debug(\"VITURE: Failed to set SBS mode to %d\\n\", enabled);\n        }\n    }\n    pthread_mutex_unlock(&viture_connection_mutex);\n    return success;\n};\n\nstatic bool viture_is_connected() {\n    return connected;\n};\n\nstatic void viture_disconnect(bool soft) {\n    disconnect(soft);\n};\n\nconst device_driver_type viture_driver = {\n    .id                                 = VITURE_DRIVER_ID,\n    .supported_device_func              = viture_supported_device,\n    .device_connect_func                = viture_device_connect,\n    .block_on_device_func               = viture_block_on_device,\n    .device_is_sbs_mode_func            = viture_device_is_sbs_mode,\n    .device_set_sbs_mode_func           = viture_device_set_sbs_mode,\n    .is_connected_func                  = viture_is_connected,\n    .disconnect_func                    = viture_disconnect\n};\n"
  },
  {
    "path": "src/devices/xreal.c",
    "content": "#include \"devices.h\"\n#include \"connection_pool.h\"\n#include \"device_imu.h\"\n#include \"device_mcu.h\"\n#include \"driver.h\"\n#include \"imu.h\"\n#include \"logging.h\"\n#include \"outputs.h\"\n#include \"runtime_context.h\"\n#include \"strings.h\"\n\n#include <math.h>\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#define TS_TO_MS_FACTOR 1000000\n#define EXPECTED_CYCLES_PER_S 1000\n#define FORCED_CYCLES_PER_S 250 // glasses may operate at a reduced frequency, let's force a reduced cycle time\n#define CYCLE_TIME_CHECK_ERROR_FACTOR 0.95 // cycle times won't be exact, check within a 5% margin\n#define FORCED_CYCLE_TIME_MS 1000.0 / FORCED_CYCLES_PER_S * CYCLE_TIME_CHECK_ERROR_FACTOR\n#define BUFFER_SIZE_TARGET_MS 10 // smooth IMU data over this period of time\n\n#define MAPPED_DISPLAY_MODE_COUNT 5\n\n#define XREAL_DRIVER_ID \"xreal\"\n\n// These two arrays are not only used as sets to determine what type a display mode is, but they're also used to\n// map back and forth to one another (the index of a display mode in one array is used to find the corresponding\n// display mode in the other array). That's way they're ordered the way they are, and some modes are duplicated.\nconst int sbs_display_modes[MAPPED_DISPLAY_MODE_COUNT] = {\n    DEVICE_MCU_DISPLAY_MODE_3840x1080_60_SBS,\n    DEVICE_MCU_DISPLAY_MODE_3840x1080_72_SBS,\n    DEVICE_MCU_DISPLAY_MODE_3840x1080_90_SBS,\n    DEVICE_MCU_DISPLAY_MODE_3840x1080_90_SBS, // no 120Hz SBS mode, map from 120Hz to 90Hz\n    DEVICE_MCU_DISPLAY_MODE_1920x1080_60_SBS  // put this last so no non-SBS mode will map to it\n};\n\nconst int non_sbs_display_modes[MAPPED_DISPLAY_MODE_COUNT] = {\n    DEVICE_MCU_DISPLAY_MODE_1920x1080_60,\n    DEVICE_MCU_DISPLAY_MODE_1920x1080_72,\n    DEVICE_MCU_DISPLAY_MODE_1920x1080_90,\n    DEVICE_MCU_DISPLAY_MODE_1920x1080_120, // no SBS mode will be able to map to this\n    DEVICE_MCU_DISPLAY_MODE_1920x1080_60   // this duplicates index 0, so the sbs mode mapping here will get remapped\n};\n\n#define XREAL_ID_PRODUCT_COUNT 10\n#define XREAL_ID_VENDOR 0x3318\nconst uint16_t xreal_supported_id_product[XREAL_ID_PRODUCT_COUNT] = {\n    0x0424, // XREAL Air\n    0x0428, // XREAL Air 2\n    0x0432, // XREAL Air 2 Pro\n    0x0426, // XREAL Air 2 Ultra\n    0x0435, // XREAL One Pro\n    0x0436, // XREAL One Pro\n    0x0437, // XREAL One\n    0x0438, // XREAL One\n    0x043e, // XREAL One S\n    0x043d  // XREAL One S\n};\nconst float xreal_fovs[XREAL_ID_PRODUCT_COUNT] = {\n    45.0, // XREAL Air\n    45.0, // XREAL Air 2\n    45.0, // XREAL Air 2 Pro\n    52.0, // XREAL Air 2 Ultra\n    57.0, // XREAL One Pro\n    57.0, // XREAL One Pro\n    50.0, // XREAL One\n    50.0, // XREAL One\n    52.0, // XREAL One S\n    52.0  // XREAL One S\n};\nconst float xreal_look_ahead_constants[XREAL_ID_PRODUCT_COUNT] = {\n    10.0, // XREAL Air\n    10.0, // XREAL Air 2\n    10.0, // XREAL Air 2 Pro\n    10.0, // XREAL Air 2 Ultra\n    25.0, // XREAL One Pro\n    25.0, // XREAL One Pro\n    25.0, // XREAL One\n    25.0, // XREAL One\n    25.0, // XREAL One S\n    25.0  // XREAL One S\n};\nconst int xreal_calibration_wait_s[XREAL_ID_PRODUCT_COUNT] = {\n    15, // XREAL Air\n    15, // XREAL Air 2\n    15, // XREAL Air 2 Pro\n    15, // XREAL Air 2 Ultra\n    5,  // XREAL One Pro\n    5,  // XREAL One Pro\n    5,  // XREAL One\n    5,  // XREAL One\n    5,  // XREAL One S\n    5   // XREAL One S\n};\nconst char* xreal_supported_models[XREAL_ID_PRODUCT_COUNT] = {\n    \"Air\",\n    \"Air 2\",\n    \"Air 2 Pro\",\n    \"Air 2 Ultra\",\n    \"One Pro\",\n    \"One Pro\",\n    \"One\",\n    \"One\",\n    \"1S\",\n    \"1S\"\n};\n\nconst imu_quat_type nwu_conversion_quat = {.x = 1, .y = 0, .z = 0, .w = 0};\n\nconst float xreal_pitch_adjustments[XREAL_ID_PRODUCT_COUNT] = {\n    0.0,  // XREAL Air\n    0.0,  // XREAL Air 2\n    0.0,  // XREAL Air 2 Pro\n    0.0,  // XREAL Air 2 Ultra\n    35.0, // XREAL One Pro\n    35.0, // XREAL One Pro\n    0.0,  // XREAL One\n    0.0,  // XREAL One\n    0.0,  // XREAL One S\n    0.0   // XREAL One S\n};\n\nconst device_properties_type xreal_air_properties = {\n    .brand                              = \"XREAL\",\n    .model                              = NULL,\n    .hid_vendor_id                      = 0,\n    .hid_product_id                     = 0,\n    .calibration_setup                  = CALIBRATION_SETUP_AUTOMATIC,\n    .resolution_w                       = RESOLUTION_1080P_W,\n    .resolution_h                       = RESOLUTION_1080P_H,\n    .fov                                = 45.0,\n    .lens_distance_ratio                = 0.03125,\n    .calibration_wait_s                 = 15,\n    .imu_cycles_per_s                   = FORCED_CYCLES_PER_S,\n    .imu_buffer_size                    = ceil(BUFFER_SIZE_TARGET_MS / FORCED_CYCLE_TIME_MS),\n    .look_ahead_constant                = 10.0,\n    .look_ahead_frametime_multiplier    = 0.3,\n    .look_ahead_scanline_adjust         = 8.0,\n    .look_ahead_ms_cap                  = 40.0,\n    .sbs_mode_supported                 = true,\n    .firmware_update_recommended        = false,\n    .provides_orientation               = true,\n    .provides_position                  = false\n};\n\nstatic pthread_mutex_t device_driver_mutex = PTHREAD_MUTEX_INITIALIZER;\nstatic pthread_cond_t device_driver_mcu_exited_cond = PTHREAD_COND_INITIALIZER;\nstatic bool device_driver_mcu_exited = false;\n\nstatic imu_quat_type device_conversion_quat = nwu_conversion_quat;\nstatic uint32_t last_utilized_event_ts = 0;\nstatic bool connected = false;\nstatic bool mcu_enabled = false;\nvoid handle_xreal_event(uint64_t timestamp,\n                        device_imu_event_type event,\n                        const device_imu_ahrs_type* ahrs) {\n    if (!connected || driver_disabled()) return;\n\n    uint32_t ts = (uint32_t) (timestamp / TS_TO_MS_FACTOR);\n    uint32_t elapsed_from_last_utilized = ts - last_utilized_event_ts;\n    if (event == DEVICE_IMU_EVENT_UPDATE && elapsed_from_last_utilized > FORCED_CYCLE_TIME_MS) {\n        device_imu_quat_type quat = device_imu_get_orientation(ahrs);\n        imu_quat_type imu_quat = { .w = quat.w, .x = quat.x, .y = quat.y, .z = quat.z };\n        imu_quat_type nwu_quat = multiply_quaternions(imu_quat, device_conversion_quat);\n        imu_pose_type pose = {0};\n        pose.orientation = nwu_quat;\n        pose.has_orientation = true;\n        pose.timestamp_ms = ts;\n        connection_pool_ingest_pose(XREAL_DRIVER_ID, pose);\n\n        last_utilized_event_ts = ts;\n    }\n}\n\nvoid handle_xreal_controller_event(\n\t\tuint64_t timestamp,\n\t\tdevice_mcu_event_type event,\n\t\tuint8_t brightness,\n\t\tconst char* msg\n) {\n    // do nothing\n}\n\ndevice_imu_type* glasses_imu;\ndevice_mcu_type* glasses_controller;\nbool xreal_device_connect() {\n    sleep(1);\n    \n    glasses_imu = calloc(1, sizeof(device_imu_type));\n    connected = device_imu_open(glasses_imu, handle_xreal_event) == DEVICE_IMU_ERROR_NO_ERROR;\n    if (connected) {\n        device_imu_clear(glasses_imu);\n        device_imu_calibrate(glasses_imu, 1000, true, true, false);\n\n        glasses_controller = calloc(1, sizeof(device_mcu_type));\n        mcu_enabled = device_mcu_open(glasses_controller, handle_xreal_controller_event) == DEVICE_MCU_ERROR_NO_ERROR;\n        device_mcu_clear(glasses_controller);\n    }\n\n    if (!connected && glasses_imu) {\n        device_imu_close(glasses_imu);\n        free(glasses_imu);\n        glasses_imu = NULL;\n    }\n\n    if (!mcu_enabled) {\n        if (glasses_controller) {\n            device_mcu_close(glasses_controller);\n            free(glasses_controller);\n            glasses_controller = NULL;\n        }\n\n        device_properties_type* device = device_checkout();\n        device->sbs_mode_supported = false;\n        device_checkin(device);\n    }\n\n    return connected;\n};\n\ndevice_properties_type* xreal_supported_device(uint16_t vendor_id, uint16_t product_id, uint8_t usb_bus, uint8_t usb_address) {\n    if (vendor_id == XREAL_ID_VENDOR) {\n        for (int i=0; i < XREAL_ID_PRODUCT_COUNT; i++) {\n            if (product_id == xreal_supported_id_product[i]) {\n                device_properties_type* device = calloc(1, sizeof(device_properties_type));\n                *device = xreal_air_properties;\n                device->hid_vendor_id = vendor_id;\n                device->hid_product_id = product_id;\n                device->model = (char *)xreal_supported_models[i];\n                device->fov = xreal_fovs[i];\n                device->look_ahead_constant = xreal_look_ahead_constants[i];\n                device->calibration_wait_s = xreal_calibration_wait_s[i];\n                device_conversion_quat = multiply_quaternions(nwu_conversion_quat, device_pitch_adjustment(xreal_pitch_adjustments[i]));\n\n                return device;\n            }\n        }\n    }\n\n    return NULL;\n};\n\nvoid *poll_imu_func(void *arg) {\n    if (config()->debug_threads) log_debug(\"poll_imu_func, starting\\n\");\n\n    while (connected && (!mcu_enabled || glasses_controller) && device_imu_read(glasses_imu, 1) == DEVICE_IMU_ERROR_NO_ERROR);\n\n    if (config()->debug_threads) log_debug(\"poll_imu_func, disconnect detected %d %d %d\\n\", connected, mcu_enabled, glasses_controller != NULL);\n\n    pthread_mutex_lock(&device_driver_mutex);\n    while (!device_driver_mcu_exited) pthread_cond_wait(&device_driver_mcu_exited_cond, &device_driver_mutex);\n    device_imu_close(glasses_imu);\n    pthread_mutex_unlock(&device_driver_mutex);\n\n    if (glasses_imu) free(glasses_imu);\n    glasses_imu = NULL;\n\n    if (config()->debug_threads) log_debug(\"poll_imu_func, exiting\\n\");\n};\n\nbool sbs_mode_change_requested = false;\nvoid *poll_controller_func(void *arg) {\n    if (config()->debug_threads) log_debug(\"poll_controller_func, starting\\n\");\n    device_driver_mcu_exited = false;\n\n    while (connected && glasses_imu && mcu_enabled && device_mcu_read(glasses_controller, 100) == DEVICE_MCU_ERROR_NO_ERROR) {\n        if (sbs_mode_change_requested) {\n            device_mcu_error_type error = device_mcu_update_display_mode(glasses_controller);\n            if (error == DEVICE_MCU_ERROR_NO_ERROR) {\n                sbs_mode_change_requested = false;\n            }\n        } else {\n            device_mcu_poll_display_mode(glasses_controller);\n        }\n\n        sleep(1);\n    }\n\n    if (config()->debug_threads) log_debug(\"poll_controller_func, disconnect detected %d %d %d\\n\", connected, mcu_enabled, glasses_controller != NULL);\n\n    pthread_mutex_lock(&device_driver_mutex);\n    device_mcu_close(glasses_controller);\n    device_driver_mcu_exited = true;\n    pthread_cond_signal(&device_driver_mcu_exited_cond);\n    pthread_mutex_unlock(&device_driver_mutex);\n\n    if (glasses_controller) free(glasses_controller);\n    glasses_controller = NULL;\n\n    if (config()->debug_threads) log_debug(\"poll_controller_func, exiting\\n\");\n};\n\nvoid xreal_block_on_device() {\n    if (config()->debug_threads) log_debug(\"xreal_block_on_device, starting\\n\");\n\n    // we'll hold onto our device refcount until we're done blocking and cleaning up\n    device_properties_type* device = device_checkout();\n    if (device != NULL) {\n        pthread_t imu_thread;\n        pthread_create(&imu_thread, NULL, poll_imu_func, NULL);\n\n        pthread_t controller_thread;\n        pthread_create(&controller_thread, NULL, poll_controller_func, NULL);\n\n        connected &= wait_for_imu_start();\n        bool imu_alive = true;\n        while (connected) {\n            sleep(1);\n            imu_alive = is_imu_alive();\n            connected &= glasses_imu && (!mcu_enabled || glasses_controller) && imu_alive;\n        }\n\n        if (config()->debug_threads) log_debug(\"xreal_block_on_device, disconnect detected %d %d %d %d\\n\", glasses_imu != NULL, mcu_enabled, glasses_controller != NULL, imu_alive);\n\n        pthread_join(imu_thread, NULL);\n        pthread_join(controller_thread, NULL);\n    }\n    device_checkin(device);\n\n    if (config()->debug_threads) log_debug(\"xreal_block_on_device, exiting\\n\");\n};\n\nint get_display_mode_index(int display_mode, const int* display_modes) {\n    for (int i = 0; i < MAPPED_DISPLAY_MODE_COUNT; i++) {\n        if (display_mode == display_modes[i]) {\n            return i;\n        }\n    }\n\n    return -1;\n}\n\nbool xreal_device_is_sbs_mode() {\n    if (connected && mcu_enabled && glasses_controller) {\n        if (get_display_mode_index(glasses_controller->disp_mode, sbs_display_modes) != -1) {\n            return true;\n        }\n    }\n\n    return false;\n};\n\nbool xreal_device_set_sbs_mode(bool enable) {\n    if (!connected || !mcu_enabled || !glasses_controller) return false;\n\n    // check what the current mode is\n    int sbs_mode_index = get_display_mode_index(glasses_controller->disp_mode, sbs_display_modes);\n    bool is_sbs_mode = sbs_mode_index != -1;\n\n    // if the current mode matches the requested mode, do nothing, return success\n    if (enable == is_sbs_mode) return true;\n\n    if (enable) {\n        // requesting SBS mode, currently non-SBS, find the corresponding SBS mode and set it\n        int non_sbs_mode_index = get_display_mode_index(glasses_controller->disp_mode, non_sbs_display_modes);\n        if (non_sbs_mode_index == -1) return false;\n\n        glasses_controller->disp_mode = sbs_display_modes[non_sbs_mode_index];\n    } else {\n        // requesting non-SBS mode, currently SBS, find the corresponding non-SBS mode and set it\n        glasses_controller->disp_mode = non_sbs_display_modes[sbs_mode_index];\n    }\n\n    sbs_mode_change_requested = true;\n\n    return true;\n};\n\nbool xreal_is_connected() {\n    return connected;\n};\n\nvoid xreal_disconnect(bool soft) {\n    connected = false;\n};\n\nconst device_driver_type xreal_driver = {\n    .id                                 = XREAL_DRIVER_ID,\n    .supported_device_func              = xreal_supported_device,\n    .device_connect_func                = xreal_device_connect,\n    .block_on_device_func               = xreal_block_on_device,\n    .device_is_sbs_mode_func            = xreal_device_is_sbs_mode,\n    .device_set_sbs_mode_func           = xreal_device_set_sbs_mode,\n    .is_connected_func                  = xreal_is_connected,\n    .disconnect_func                    = xreal_disconnect\n};"
  },
  {
    "path": "src/devices.c",
    "content": "#include \"connection_pool.h\"\n#include \"devices.h\"\n#include \"devices/rayneo.h\"\n#include \"devices/rokid.h\"\n#include \"devices/viture.h\"\n#include \"devices/xreal.h\"\n#include \"logging.h\"\n#include \"runtime_context.h\"\n\n#include <libusb.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/time.h>\n\n#if defined(__aarch64__)\n    #define DEVICE_DRIVER_COUNT 2\n    const device_driver_type* device_drivers[DEVICE_DRIVER_COUNT] = {\n        &xreal_driver,\n        &viture_driver\n    };\n#elif defined(__x86_64__)\n    #define DEVICE_DRIVER_COUNT 4\n    const device_driver_type* device_drivers[DEVICE_DRIVER_COUNT] = {\n        &rayneo_driver,\n        &rokid_driver,\n        &xreal_driver,\n        &viture_driver\n    };\n#else\n    #error \"Unsupported architecture\"\n#endif\n\nstatic connected_device_type* _find_connected_device(libusb_device *usb_device, struct libusb_device_descriptor descriptor) {\n    for (int j = 0; j < DEVICE_DRIVER_COUNT; j++) {\n        const device_driver_type* driver = device_drivers[j];\n        device_properties_type* device = driver->supported_device_func(\n            descriptor.idVendor, \n            descriptor.idProduct,\n            libusb_get_bus_number(usb_device),\n            libusb_get_device_address(usb_device)\n        );\n        if (device != NULL) {\n            log_message(\"Found device with vendor ID 0x%04x and product ID 0x%04x\\n\", descriptor.idVendor, descriptor.idProduct);\n            connected_device_type* connected_device = calloc(1, sizeof(connected_device_type));\n            connected_device->driver = driver;\n            connected_device->device = device;\n            return connected_device;\n        }\n    }\n\n    return NULL;\n}\n\nint hotplug_callback(libusb_context *ctx, libusb_device *usb_device, libusb_hotplug_event event, void *user_data) {\n    struct libusb_device_descriptor descriptor;\n    int r = libusb_get_device_descriptor(usb_device, &descriptor);\n    if (r < 0) {\n        log_error(\"Failed to get device descriptor\\n\");\n        return 1;\n    }\n\n    if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {\n        connection_t* conn = connection_pool_find_hid_connection(descriptor.idVendor, descriptor.idProduct);\n        if (conn) {\n            connected_device_type* connected_device = calloc(1, sizeof(connected_device_type));\n            connected_device->driver = conn->driver;\n            connected_device->device = conn->device;\n            handle_device_connection_changed(false, connected_device);\n        }\n    } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {\n        connected_device_type* connected_device = _find_connected_device(usb_device, descriptor);\n        if (connected_device != NULL) {\n            handle_device_connection_changed(true, connected_device);\n        }\n    }\n\n    return 0;\n}\n\nlibusb_context *ctx = NULL;\nlibusb_hotplug_callback_handle callback_handle;\nvoid init_devices() {\n    int r = libusb_init(&ctx);\n    if (r < 0) {\n        log_error(\"Failed to initialize libusb\\n\");\n        return;\n    }\n\n    r = libusb_hotplug_register_callback(ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,\n                                        LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY,\n                                        LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,\n                                        hotplug_callback, NULL, &callback_handle);\n    if (r < 0) {\n        log_error(\"Failed to register hotplug callback\\n\");\n    }\n}\n\nvoid handle_device_connection_events() {\n    struct timeval tv = {5, 0};\n    libusb_handle_events_timeout_completed(ctx, &tv, NULL);\n}\n\nvoid deinit_devices() {\n    if (callback_handle != 0) libusb_hotplug_deregister_callback(ctx, callback_handle);\n    libusb_exit(ctx);\n}\n\nconnected_device_type* find_connected_device() {\n    libusb_device **usb_device_list;\n    ssize_t usb_device_count = libusb_get_device_list(ctx, &usb_device_list);\n    if (usb_device_count < 0) {\n        log_error(\"Failed to get device list\\n\");\n        libusb_exit(ctx);\n        return NULL;\n    }\n\n    connected_device_type* connected_device = NULL;\n    libusb_device *usb_device;\n    int i = 0;\n    for (i = 0; i < usb_device_count; i++) {\n        usb_device = usb_device_list[i];\n        struct libusb_device_descriptor descriptor;\n        int r = libusb_get_device_descriptor(usb_device, &descriptor);\n        if (r < 0) {\n            log_error(\"Failed to get device descriptor\\n\");\n            continue;\n        }\n\n        connected_device = _find_connected_device(usb_device, descriptor);\n        if (connected_device != NULL) break;\n    }\n\n    libusb_free_device_list(usb_device_list, 1);\n\n    return connected_device;\n}\n\nbool device_equal(device_properties_type* device, device_properties_type* device2) {\n    return device != NULL && device2 != NULL && \n           device->hid_product_id == device2->hid_product_id && \n           device->hid_vendor_id == device2->hid_vendor_id;\n}"
  },
  {
    "path": "src/driver.c",
    "content": "#include \"buffer.h\"\n#include \"driver.h\"\n#include \"config.h\"\n#include \"devices.h\"\n#include \"devices/viture.h\"\n#include \"devices/xreal.h\"\n#include \"connection_pool.h\"\n#include \"files.h\"\n#include \"imu.h\"\n#include \"ipc.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"multitap.h\"\n#include \"ipc.h\"\n#include \"outputs.h\"\n#include \"plugins.h\"\n#include \"plugins/gamescope_reshade_wayland.h\"\n#include \"runtime_context.h\"\n#include \"state.h\"\n#include \"strings.h\"\n#include \"system.h\"\n\n#include <dirent.h>\n#include <errno.h>\n#include <execinfo.h>\n#include <fcntl.h>\n#include <inttypes.h>\n#include <libgen.h>\n#include <limits.h>\n#include <math.h>\n#include <pthread.h>\n#include <signal.h>\n#include <sys/signalfd.h>\n#include <netdb.h>\n#include <limits.h>\n#include <stdbool.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/file.h>\n#include <sys/inotify.h>\n#include <sys/ioctl.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event) + NAME_MAX + 1)\n#define INOTIFY_EVENT_BUFFER_SIZE (1024 * INOTIFY_EVENT_SIZE)\n#define MT_RECENTER_SCREEN 2\n#define MT_RESET_CALIBRATION 3\n\n\nipc_values_type *ipc_values;\n\nbool glasses_calibrated=false;\nlong int glasses_calibration_started_sec=0;\nbool force_quit=false;\ncontrol_flags_type *control_flags;\n\nbool captured_reference_pose=false;\nimu_pose_type reference_pose;\nimu_quat_type reference_orientation_conj;\n\nstatic bool is_driver_connected() {\n    return connection_pool_is_connected();\n}\n\nvoid reset_calibration(bool reset_device) {\n    glasses_calibration_started_sec=0;\n    glasses_calibrated=false;\n    captured_reference_pose=false;\n    control_flags->recalibrate=false;\n    state()->calibration_state = CALIBRATING;\n\n    if (reset_device && is_driver_connected()) {\n        if (config()->debug_device) log_debug(\"reset_calibration, connection_pool_disconnect_all(true)\\n\");\n        connection_pool_disconnect_all(true);\n    } else log_message(\"Waiting on device calibration\\n\");\n}\n\nstatic bool reference_pose_updated = false;\nbool driver_reference_pose(imu_pose_type* out_pose, bool* pose_updated) {\n    if (captured_reference_pose) {\n        *out_pose = reference_pose;\n        *pose_updated = reference_pose_updated;\n        reference_pose_updated = false;\n        return true;\n    }\n\n    return false;\n}\n\nvoid driver_handle_pose(imu_pose_type pose) {\n    // counter that resets every second, for triggering things that we don't want to do every cycle\n    static int imu_counter = 0;\n    static int multi_tap = 0;\n\n    device_properties_type* device = device_checkout();\n    if (is_driver_connected() && device != NULL) {\n        if (config()->debug_device && imu_counter == 0 && pose.has_orientation)\n            log_debug(\"driver_handle_pose_event - quat: %f %f %f %f; pos: %f %f %f\\n\", pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w, pose.position.x, pose.position.y, pose.position.z);\n            \n        if (glasses_calibrated) {\n            if (!captured_reference_pose || multi_tap == MT_RECENTER_SCREEN || control_flags->recenter_screen) {\n                if (multi_tap == MT_RECENTER_SCREEN) log_message(\"Double-tap detected.\\n\");\n                log_message(\"Centering screen\\n\");\n\n                imu_pose_type old_reference_pose = reference_pose;\n\n                if (pose.has_orientation) {\n                    reference_pose.orientation = pose.orientation;\n                    reference_pose.has_orientation = true;\n                    reference_orientation_conj = conjugate(reference_pose.orientation);\n                } else {\n                    imu_quat_type tmp_screen_center = { .w = 1.0, .x = 0.0, .y = 0.0, .z = 0.0 };\n                    reference_pose.orientation = tmp_screen_center;\n                    reference_orientation_conj = tmp_screen_center;\n                    reference_pose.has_orientation = false;\n                }\n\n                if (pose.has_position) {\n                    reference_pose.position = pose.position;\n                    reference_pose.has_position = true;\n                } else {\n                    reference_pose.position = (imu_vec3_type){0.0f, 0.0f, 0.0f};\n                    reference_pose.has_position = false;\n                }\n                \n                captured_reference_pose = true;\n                reference_pose_updated = true;\n                control_flags->recenter_screen = false;\n\n                plugins.handle_reference_pose_updated(old_reference_pose, reference_pose);\n            } else {\n                imu_pose_type current_pose = pose;\n                if (current_pose.has_orientation) current_pose.euler = quaternion_to_euler_zyx(current_pose.orientation);\n                reference_pose_updated |= plugins.modify_reference_pose(current_pose, &reference_pose);\n                if (reference_pose_updated) reference_orientation_conj = conjugate(reference_pose.orientation);\n            }\n        } else {\n            struct timeval tv;\n            gettimeofday(&tv, NULL);\n\n            if (glasses_calibration_started_sec == 0) {\n                // defaults used for mouse/joystick while waiting on calibration\n                imu_quat_type tmp_screen_center = { .w = 1.0, .x = 0.0, .y = 0.0, .z = 0.0 };\n                reference_pose.orientation = tmp_screen_center;\n                reference_orientation_conj = tmp_screen_center;\n                reference_pose.position = (imu_vec3_type){0.0f, 0.0f, 0.0f};\n                reference_pose.has_orientation = pose.has_orientation;\n                reference_pose.has_position = pose.has_position;\n\n                glasses_calibration_started_sec=tv.tv_sec;\n                if (ipc_values) reset_pose_data(ipc_values);\n            } else {\n                glasses_calibrated = (tv.tv_sec - glasses_calibration_started_sec) > device->calibration_wait_s;\n                if (glasses_calibrated) {\n                    state()->calibration_state = CALIBRATED;\n                    log_message(\"Device calibration complete\\n\");\n                }\n            }\n        }\n\n        // be resilient to bad values that may come from device drivers\n        if (!isnan(pose.orientation.w)) {\n            static imu_euler_type prev_unmodified_euler = {0.0f, 0.0f, 0.0f};\n\n            if (pose.has_orientation) {\n                pose.orientation = multiply_quaternions(reference_orientation_conj, pose.orientation);\n                pose.euler = quaternion_to_euler_zyx(pose.orientation);\n            }\n            // interpret all positions relative to the reference orientation\n            if (pose.has_position) {\n                imu_vec3_type rel = {\n                    .x = pose.position.x - reference_pose.position.x,\n                    .y = pose.position.y - reference_pose.position.y,\n                    .z = pose.position.z - reference_pose.position.z\n                };\n                pose.position = vector_rotate(rel, reference_orientation_conj);\n            } else {\n                pose.position = (imu_vec3_type){0.0f, 0.0f, 0.0f};\n            }\n            \n            imu_euler_type euler_velocities;\n            bool velocities_set = false;\n            \n            if (config()->multi_tap_enabled) {\n                euler_velocities = get_euler_velocities(&prev_unmodified_euler, pose.euler, device->imu_cycles_per_s);\n                multi_tap = detect_multi_tap(euler_velocities, pose.timestamp_ms, config()->debug_multi_tap);\n                velocities_set = true;\n            }\n\n            if (multi_tap == MT_RESET_CALIBRATION || control_flags->recalibrate) {\n                if (multi_tap == MT_RESET_CALIBRATION) log_message(\"Triple-tap detected. \");\n                log_message(\"Kicking off calibration\\n\");\n                reset_calibration(true);\n            }\n\n            if (glasses_calibrated) {\n                static imu_euler_type prev_modified_euler = {0.0f, 0.0f, 0.0f};\n                plugins.modify_pose(&pose);\n\n                // recompute velocities after pose modification, since outputs that use them\n                // will want to be relative to the modified pose\n                euler_velocities = get_euler_velocities(&prev_modified_euler, pose.euler, device->imu_cycles_per_s);\n                velocities_set = true;\n            }\n\n            if (!velocities_set) {\n                euler_velocities = get_euler_velocities(&prev_unmodified_euler, pose.euler, device->imu_cycles_per_s);\n            }\n            handle_imu_update(pose, euler_velocities, glasses_calibrated, ipc_values);\n        } else if (config()->debug_device) log_debug(\"driver_handle_pose_event, received invalid quat\\n\");\n\n        // reset the counter every second\n        if ((++imu_counter % device->imu_cycles_per_s) == 0) {\n            imu_counter = 0;\n        }\n    }\n    device_checkin(device);\n}\n\nbool driver_disabled() {\n    return config()->disabled;\n}\n\nvoid setup_ipc() {\n    if (!ipc_values) {\n        if (config()->debug_ipc) log_debug(\"setup_ipc, enabling IPC\\n\");\n        ipc_values = calloc(1, sizeof(*ipc_values));\n        if (!setup_ipc_values(ipc_values, config()->debug_ipc) || !plugins.setup_ipc()) {\n            log_error(\"Error setting up IPC values\\n\");\n            exit(1);\n        }\n    } else if (config()->debug_ipc) log_debug(\"setup_ipc, already enabled, doing nothing\\n\");\n\n    device_properties_type* device = device_checkout();\n    if (device != NULL) {\n        plugins.reset_pose_data();\n\n        // set IPC values that won't change after a device is set\n        ipc_values->display_res[0]        = (float) device->resolution_w;\n        ipc_values->display_res[1]        = (float) device->resolution_h;\n\n        // deprecated - can be removed once this version is widely distributed\n        *ipc_values->display_fov          = device->fov;\n        *ipc_values->lens_distance_ratio  = device->lens_distance_ratio;\n\n        // always start out disabled, let it be explicitly enabled later\n        *ipc_values->disabled             = true;\n\n        // set defaults for everything else\n        ipc_values->date[0]               = 0.0;\n        ipc_values->date[1]               = 0.0;\n        ipc_values->date[2]               = 0.0;\n        ipc_values->date[3]               = 0.0;\n\n        set_gamescope_reshade_effect_uniform_variable(\"display_resolution\", ipc_values->display_res, 2, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"keepalive_date\", ipc_values->date, 4, sizeof(float), false);\n    }\n    device_checkin(device);\n}\n\npthread_mutex_t block_on_device_mutex = PTHREAD_MUTEX_INITIALIZER;\npthread_cond_t block_on_device_cond = PTHREAD_COND_INITIALIZER;\nstatic bool block_on_device_ready = false;\n\n// reevaluates the conditions that determine whether the block_on_device_thread function can be unblocked,\n// we should call this whenever a condition changes that may effect the evaluation of block_on_device_ready\nvoid evaluate_block_on_device_ready() {\n    if (config()->debug_device) \n        log_debug(\"evaluate_block_on_device_ready, %s, %s, %s\\n\", \n            force_quit ? \"force_quit\" : \"no force_quit\", \n            driver_disabled() ? \"driver_disabled\" : \"driver_enabled\", \n            device_present() ? \"device_present\" : \"no device_present\");\n\n    pthread_mutex_lock(&block_on_device_mutex);\n    block_on_device_ready = force_quit || !driver_disabled() && device_present();\n    if (block_on_device_ready) pthread_cond_signal(&block_on_device_cond);\n    pthread_mutex_unlock(&block_on_device_mutex);\n}\n\n// pthread function to wait for a supported device, create outputs, and block on the device while it's connected\nvoid *block_on_device_thread_func(void *arg) {\n    while (!force_quit) {\n        if (config()->debug_device) log_debug(\"block_on_device_thread, loop start\\n\");\n\n        bool first_device_wait = true;\n        pthread_mutex_lock(&block_on_device_mutex);\n        while (!block_on_device_ready) {\n            // if the only thing blocking this thread is the device not being ready, print a message\n            if (!force_quit && !driver_disabled() && first_device_wait) {\n                log_message(\"Waiting for glasses\\n\");\n                first_device_wait = false;\n            } else if (config()->debug_device) log_debug(\"block_on_device_thread, waiting on ready\\n\");\n            pthread_cond_wait(&block_on_device_cond, &block_on_device_mutex);\n        }\n        pthread_mutex_unlock(&block_on_device_mutex);\n\n        if (!force_quit) {\n            if (config()->debug_device) log_debug(\"block_on_device_thread, connection_pool_connect_active()\\n\");\n\n            if (connection_pool_connect_active()) {\n                log_message(\"Device connected, redirecting input to %s...\\n\", config()->output_mode);\n\n                setup_ipc();\n                reset_calibration(false);\n                *ipc_values->disabled = false;\n                plugins.handle_device_connect();\n                init_outputs();\n\n                if (config()->debug_device) log_debug(\"block_on_device_thread, connection_pool_block_on_active()\\n\");\n                connection_pool_block_on_active();\n\n                plugins.handle_device_disconnect();\n                deinit_outputs();\n            } else if (block_on_device_ready) {\n                log_message(\"Device driver connection attempt failed\\n\");\n            }\n            \n            if (block_on_device_ready) {\n                // device is still physically connected and will retry, pause for a moment\n                log_message(\"Retrying driver connection in 1 second\\n\");\n                sleep(1);\n            }\n        }\n\n        if (ipc_values) *ipc_values->disabled = true;\n    }\n\n    if (config()->debug_threads)\n        log_debug(\"Exiting block_on_device thread; force_quit %d\\n\", force_quit);\n}\n\nvoid update_config_from_file(FILE *fp) {\n    driver_config_type* new_config = parse_config_file(fp);\n\n    bool driver_newly_disabled = !driver_disabled() && new_config->disabled;\n    if (driver_newly_disabled)\n        log_message(\"Driver has been disabled\\n\");\n    bool driver_reenabled = driver_disabled() && !new_config->disabled;\n    if (driver_reenabled)\n        log_message(\"Driver has been re-enabled\\n\");\n\n    if (config()->vr_lite_invert_x != new_config->vr_lite_invert_x)\n        log_message(\"VR-Lite invert X-axis has been %s\\n\", new_config->vr_lite_invert_x ? \"enabled\" : \"disabled\");\n    if (config()->vr_lite_invert_y != new_config->vr_lite_invert_y)\n        log_message(\"VR-Lite invert Y-axis has been %s\\n\", new_config->vr_lite_invert_y ? \"enabled\" : \"disabled\");\n\n    if (!config()->use_roll_axis && new_config->use_roll_axis)\n        log_message(\"VR-Lite roll axis has been enabled\\n\");\n    if (config()->use_roll_axis && !new_config->use_roll_axis)\n        log_message(\"VR-Lite roll axis has been disabled\\n\");\n\n    if (config()->mouse_sensitivity != new_config->mouse_sensitivity)\n        log_message(\"Mouse sensitivity has changed to %d\\n\", new_config->mouse_sensitivity);\n\n    bool output_mode_changed = strcmp(config()->output_mode, new_config->output_mode) != 0;\n    if (output_mode_changed)\n        log_message(\"Output mode has been changed to '%s'\\n\", new_config->output_mode);\n\n    if (config()->metrics_disabled != new_config->metrics_disabled)\n        log_message(\"Metrics have been %s\\n\", new_config->metrics_disabled ? \"disabled\" : \"enabled\");\n\n    if (!config()->debug_joystick && new_config->debug_joystick)\n        log_message(\"Joystick debugging has been enabled, to see it, use 'watch -n 0.1 cat $XDG_RUNTIME_DIR/xr_driver/joystick_debug' in bash\\n\");\n    if (config()->debug_joystick && !new_config->debug_joystick)\n        log_message(\"Joystick debugging has been disabled\\n\");\n\n    if (config()->debug_threads != new_config->debug_threads)\n        log_message(\"Threads debugging has been %s\\n\", new_config->debug_threads ? \"enabled\" : \"disabled\");\n\n    if (config()->debug_multi_tap != new_config->debug_multi_tap)\n        log_message(\"Multi-tap debugging has been %s\\n\", new_config->debug_multi_tap ? \"enabled\" : \"disabled\");\n\n    if (config()->debug_ipc != new_config->debug_ipc)\n        log_message(\"IPC debugging has been %s\\n\", new_config->debug_ipc ? \"enabled\" : \"disabled\");\n\n    if (config()->debug_license != new_config->debug_license)\n        log_message(\"License debugging has been %s\\n\", new_config->debug_license ? \"enabled\" : \"disabled\");\n\n    if (config()->debug_device != new_config->debug_device)\n        log_message(\"Device debugging has been %s\\n\", new_config->debug_device ? \"enabled\" : \"disabled\");\n\n    if (config()->dead_zone_threshold_deg != new_config->dead_zone_threshold_deg)\n        log_message(\"IMU dead zone threshold has been changed to %.2f degrees\\n\", new_config->dead_zone_threshold_deg);\n\n    if (config()->debug_connections != new_config->debug_connections)\n        log_message(\"Connection pool debugging has been %s\\n\", new_config->debug_connections ? \"enabled\" : \"disabled\");\n\n    update_config(config(), new_config);\n\n    if (config()->disabled && is_driver_connected()) {\n        if (config()->debug_device) log_debug(\"update_config_from_file, connection_pool_disconnect_all(true)\\n\");\n        connection_pool_disconnect_all(true);\n    }\n    if (driver_reenabled) plugins.start();\n\n    if (output_mode_changed && is_driver_connected()) reinit_outputs();\n\n    if (ipc_values) *ipc_values->disabled = driver_disabled();\n    \n    evaluate_block_on_device_ready();\n}\n\n// pthread function to monitor the config file for changes\nchar *config_filename = NULL;\nFILE *config_fp;\nvoid *monitor_config_file_thread_func(void *arg) {\n    config_fp = freopen(config_filename, \"r\", config_fp);\n    update_config_from_file(config_fp);\n\n    int fd = inotify_init();\n    if (fd < 0) {\n        perror(\"Error initializing inotify\");\n        return NULL;\n    }\n\n    int wd = inotify_add_watch(fd, config_filename, IN_CLOSE_WRITE | IN_DELETE_SELF | IN_ATTRIB);\n    if (wd < 0) {\n        perror(\"Error adding watch\");\n        return NULL;\n    }\n\n    char inotify_event_buffer[INOTIFY_EVENT_BUFFER_SIZE];\n\n    while (!force_quit) {\n        fd_set readfds;\n        FD_ZERO(&readfds);\n        FD_SET(fd, &readfds);\n\n        struct timeval tv;\n        tv.tv_sec = 5;\n        tv.tv_usec = 0;\n\n        // wait for data to be available for reading, do this with select() so we can specify a timeout and make\n        // sure we shouldn't exit due to force_quit\n        int retval = select(fd + 1, &readfds, NULL, NULL, &tv);\n        if (retval == -1) {\n            perror(\"select()\");\n            exit(EXIT_FAILURE);\n        } else if (retval) {\n            int length = read(fd, inotify_event_buffer, INOTIFY_EVENT_BUFFER_SIZE);\n            if (length < 0) {\n                perror(\"Error reading inotify events\");\n                return NULL;\n            }\n\n            bool updated = false;\n            int i = 0;\n            while (i < length) {\n                struct inotify_event *event = (struct inotify_event *) &inotify_event_buffer[i];\n                if (event->mask & IN_DELETE_SELF) {\n                    // The file has been deleted, so we need to re-add the watch\n                    wd = inotify_add_watch(fd, config_filename, IN_CLOSE_WRITE | IN_DELETE_SELF | IN_ATTRIB);\n                    if (wd < 0) {\n                        perror(\"Error re-adding watch\");\n                        exit(EXIT_FAILURE);\n                    }\n                } else {\n                    updated = true;\n                }\n                i += INOTIFY_EVENT_SIZE + event->len;\n            }\n            if (ferror(config_fp) != 0 || feof(config_fp) != 0) {\n                config_fp = freopen(config_filename, \"r\", config_fp);\n                if (config_fp == NULL) {\n                    perror(\"Error reopening config file\");\n                    exit(EXIT_FAILURE);\n                }\n                if (!updated) update_config_from_file(config_fp);\n            }\n            if (updated) update_config_from_file(config_fp);\n        }\n    }\n\n    inotify_rm_watch(fd, wd);\n    close(fd);\n\n    if (config()->debug_threads)\n        log_debug(\"Exiting monitor_config_file thread; force_quit: %d\\n\", force_quit);\n}\n\n// pthread function to update the state and read control flags\nvoid *manage_state_thread_func(void *arg) {\n    while (!force_quit) {\n        device_properties_type* device = device_checkout();\n        device_properties_type* supplemental_device = connection_pool_supplemental_device();\n        const device_driver_type* primary_drv_in_loop = connection_pool_primary_driver();\n        update_state_from_device(state(), device, supplemental_device, (device_driver_type*)primary_drv_in_loop);\n        device_checkin(device);\n        write_state(state());\n        plugins.handle_state();\n\n        sleep(1);\n    }\n\n    // in case any state changed during the last sleep()\n    write_state(state());\n\n    if (config()->debug_threads)\n        log_debug(\"Exiting write_state thread; force_quit: %d\\n\", force_quit);\n}\n\nvoid handle_control_flags_update() {\n    device_properties_type* device = device_checkout();\n    if (is_driver_connected()) {\n        if (device != NULL && device->sbs_mode_supported && control_flags->sbs_mode != SBS_CONTROL_UNSET) {\n            // glasses can be sensitive to rapid mode changes, so only request a change if necessary\n            bool requesting_enabled = control_flags->sbs_mode == SBS_CONTROL_ENABLE;\n            bool is_already_enabled = connection_pool_device_is_sbs_mode();\n            bool change_requested = is_already_enabled != requesting_enabled;\n\n            if (change_requested && config()->debug_device) \n                log_debug(\"handle_control_flags_update, connection_pool_device_set_sbs_mode(%s)\\n\", requesting_enabled ? \"true\" : \"false\");\n\n            if (change_requested && !connection_pool_device_set_sbs_mode(requesting_enabled)) {\n                log_error(\"Error setting requested SBS mode\\n\");\n            }\n            control_flags->sbs_mode = SBS_CONTROL_UNSET;\n        }\n        if (control_flags->force_quit) {\n            log_message(\"Force quit requested, exiting\\n\");\n            force_quit = true;\n\n            if (config()->debug_device) log_debug(\"handle_control_flags_update, connection_pool_disconnect_all(true)\\n\");\n            connection_pool_disconnect_all(true);\n            evaluate_block_on_device_ready();\n\n            control_flags->force_quit = false;\n        }\n    }\n    device_checkin(device);\n}\n\n// pthread function for watching control flags file\nvoid *monitor_control_flags_file_thread_func(void *arg) {\n    char *control_file_path = NULL;\n    FILE* fp = get_driver_state_file(control_flags_filename, \"r\", &control_file_path);\n    if (fp) {\n        read_control_flags(fp, control_flags);\n        write_state(state());\n        handle_control_flags_update();\n\n        fclose(fp);\n        remove(control_file_path);\n    }\n\n    int fd = inotify_init();\n    if (fd < 0) {\n        perror(\"inotify_init\");\n        return NULL;\n    }\n\n    int wd = inotify_add_watch(fd, state_files_directory, IN_CLOSE_WRITE);\n    if (wd < 0) {\n        perror(\"inotify_add_watch\");\n        close(fd);\n        return NULL;\n    }\n\n    char inotify_event_buffer[INOTIFY_EVENT_BUFFER_SIZE];\n    while (!force_quit) {\n        int length = read(fd, inotify_event_buffer, INOTIFY_EVENT_BUFFER_SIZE);\n        if (length < 0) {\n            perror(\"read\");\n            break;\n        }\n\n        int i = 0;\n        while (i < length) {\n            struct inotify_event *event = (struct inotify_event *) &inotify_event_buffer[i];\n            if ((event->mask & IN_CLOSE_WRITE) && strcmp(event->name, control_flags_filename) == 0) {\n                fp = fopen(control_file_path, \"r\");\n                if (fp) {\n                    read_control_flags(fp, control_flags);\n                    write_state(state());\n                    handle_control_flags_update();\n\n                    fclose(fp);\n                    remove(control_file_path);\n                }\n            }\n            i += INOTIFY_EVENT_SIZE + event->len;\n        }\n    }\n\n    close(fd);\n    free_and_clear(&control_file_path);\n\n    if (config()->debug_threads)\n        log_debug(\"Exiting monitor_control_flags_file_thread_func thread; force_quit: %d\\n\", force_quit);\n}\n\nvoid handle_device_connection_changed(bool is_added, connected_device_type* device_info) {\n    // as long as we want a device to remain connected, we need to hold at least one checked out reference to it,\n    // otherwise it will get freed prematurely. since this function manages device dis/connect events,\n    // it has the responsibility of always holding open at least one reference as long as a device remains connected.\n    static device_properties_type* primary_device_ref = NULL;\n\n    if (is_added) {\n        if (config()->debug_device) log_debug(\"device added for driver %s\\n\", device_info->driver->id);\n        connection_pool_handle_device_added(device_info->driver, device_info->device);\n        captured_reference_pose = false;\n    } else {\n        if (config()->debug_device) log_debug(\"device removed for driver %s\\n\", device_info->driver->id);\n        connection_pool_handle_device_removed(device_info->driver->id);\n    }\n    free(device_info);\n\n    // Reflect the pool's current primary in the runtime context\n    device_properties_type* new_primary = connection_pool_primary_device();\n    if (new_primary != primary_device_ref) {\n        if (primary_device_ref) {\n            // Release previous primary\n            device_checkin(primary_device_ref);\n            primary_device_ref = NULL;\n\n            pthread_mutex_lock(&block_on_device_mutex);\n            block_on_device_ready = false;\n            pthread_mutex_unlock(&block_on_device_mutex);\n        }\n        if (new_primary) {\n            state()->calibration_state = NOT_CALIBRATED;\n            set_device_and_checkout(new_primary);\n            init_multi_tap(new_primary->imu_cycles_per_s);\n            primary_device_ref = new_primary;\n        }\n    }\n\n    const device_driver_type* primary_drv = connection_pool_primary_driver();\n    device_properties_type* supplemental_device = connection_pool_supplemental_device();\n    update_state_from_device(state(), new_primary, supplemental_device, (device_driver_type*)primary_drv);\n}\n\nvoid *monitor_usb_devices_thread_func(void *arg) {\n    init_devices();\n    while (!force_quit) {\n        handle_device_connection_events();\n        sleep(1);\n    }\n\n    if (config()->debug_threads)\n        log_debug(\"Exiting monitor_usb_devices_thread_func thread; force_quit: %d\\n\", force_quit);\n}\n\nvoid segfault_handler(int sig) {\n    (void)sig;\n    log_error(\"Segmentation fault occurred\\n\");\n    void *buffer[10];\n    int nptrs = backtrace(buffer, 10);\n    backtrace_symbols_fd(buffer, nptrs, 2);\n    exit(EXIT_FAILURE);\n}\n\nint main(int argc, const char** argv) {\n    signal(SIGSEGV, segfault_handler);\n\n    log_init();\n\n    // set a lock so only one instance of the driver can be running at a time\n    char *lock_file_path = NULL;\n    FILE *lock_file = get_or_create_runtime_file(\"lock.pid\", \"r\", &lock_file_path, NULL);\n    int rc = flock(fileno(lock_file), LOCK_EX | LOCK_NB);\n    if(rc) {\n        if(EWOULDBLOCK == errno)\n            log_error(\"Another instance of this program is already running.\\n\");\n        exit(1);\n    }\n    free_and_clear(&lock_file_path);\n\n    set_config(default_config());\n    set_state(calloc(1, sizeof(driver_state_type)));\n    connection_pool_init(driver_handle_pose, driver_reference_pose);\n\n    config_fp = get_or_create_config_file(\"config.ini\", \"r\", &config_filename, NULL);\n    update_config_from_file(config_fp);\n\n    if (driver_disabled()) log_message(\"Driver is disabled\\n\");\n\n    control_flags = calloc(1, sizeof(control_flags_type));\n    control_flags->recenter_screen = false;\n    control_flags->recalibrate = false;\n    control_flags->force_quit = false;\n    control_flags->sbs_mode = SBS_CONTROL_UNSET;\n    control_flags->request_features = NULL;\n\n    plugins.start();\n    write_state(state());\n    set_on_device_change_callback(evaluate_block_on_device_ready);\n    log_message(\"Starting up XR driver\\n\");\n\n    pthread_t monitor_control_flags_file_thread;\n    pthread_t monitor_config_file_thread;\n    pthread_t manage_state_thread;\n    pthread_t monitor_usb_devices_thread;\n    pthread_t device_thread;\n    pthread_create(&monitor_control_flags_file_thread, NULL, monitor_control_flags_file_thread_func, NULL);\n    pthread_create(&monitor_config_file_thread, NULL, monitor_config_file_thread_func, NULL);\n    pthread_create(&manage_state_thread, NULL, manage_state_thread_func, NULL);\n    pthread_create(&monitor_usb_devices_thread, NULL, monitor_usb_devices_thread_func, NULL);\n    pthread_create(&device_thread, NULL, block_on_device_thread_func, NULL);\n\n    pthread_join(monitor_control_flags_file_thread, NULL);\n    pthread_join(monitor_config_file_thread, NULL);\n    pthread_join(manage_state_thread, NULL);\n    pthread_join(monitor_usb_devices_thread, NULL);\n    pthread_join(device_thread, NULL);\n\n    return 0;\n}\n"
  },
  {
    "path": "src/epoch.c",
    "content": "#include \"epoch.h\"\n\n#include <time.h>\n\nstruct timespec ts;\nuint64_t get_epoch_time_ms() {\n    timespec_get(&ts, TIME_UTC);\n\n    long int sec_ms = ts.tv_sec * 1000;\n    long int nsec_ms = ts.tv_nsec / 1000000;\n\n    return (uint64_t)(sec_ms + nsec_ms);\n}"
  },
  {
    "path": "src/features/breezy_desktop.c",
    "content": "#include \"runtime_context.h\"\n#include \"strings.h\"\n\n#include <stdatomic.h>\n\nconst char* productivity_basic_feature_name = \"productivity\";\nconst char* productivity_pro_feature_name = \"productivity_pro\";\n\nstatic atomic_int productivity_basic_granted_cached = ATOMIC_VAR_INIT(-1);\nstatic atomic_int productivity_pro_granted_cached = ATOMIC_VAR_INIT(-1);\nstatic atomic_int productivity_granted_cached = ATOMIC_VAR_INIT(-1);\n\nvoid reset_productivity_features() {\n    atomic_store_explicit(&productivity_basic_granted_cached, -1, memory_order_release);\n    atomic_store_explicit(&productivity_pro_granted_cached, -1, memory_order_release);\n    atomic_store_explicit(&productivity_granted_cached, -1, memory_order_release);\n}\n\nbool is_productivity_basic_granted() {\n    int cached = atomic_load_explicit(&productivity_basic_granted_cached, memory_order_acquire);\n    if (cached != -1) return cached;\n\n    driver_state_type* s = state();\n    bool granted = s && s->granted_features && s->granted_features_count &&\n                   in_array(productivity_basic_feature_name, (const char**)s->granted_features, s->granted_features_count);\n\n    atomic_store_explicit(&productivity_basic_granted_cached, granted ? 1 : 0, memory_order_release);\n    return granted;\n}\n\nbool is_productivity_pro_granted() {\n    int cached = atomic_load_explicit(&productivity_pro_granted_cached, memory_order_acquire);\n    if (cached != -1) return cached;\n\n    driver_state_type* s = state();\n    bool granted = s && s->granted_features && s->granted_features_count &&\n                   in_array(productivity_pro_feature_name, (const char**)s->granted_features, s->granted_features_count);\n\n    atomic_store_explicit(&productivity_pro_granted_cached, granted ? 1 : 0, memory_order_release);\n    return granted;\n}\n\nbool is_productivity_granted() {\n    int cached = atomic_load_explicit(&productivity_granted_cached, memory_order_acquire);\n    if (cached != -1) return cached;\n\n    bool granted = is_productivity_basic_granted() || is_productivity_pro_granted();\n    atomic_store_explicit(&productivity_granted_cached, granted ? 1 : 0, memory_order_release);\n    return granted;\n}"
  },
  {
    "path": "src/features/sbs.c",
    "content": "#include \"runtime_context.h\"\n#include \"strings.h\"\n\n#include <stdatomic.h>\n\nconst char* sbs_feature_name = \"sbs\";\n\nstatic atomic_int sbs_granted_cached = ATOMIC_VAR_INIT(-1);\n\nvoid reset_sbs_features() {\n    atomic_store_explicit(&sbs_granted_cached, -1, memory_order_release);\n}\n\nbool is_sbs_granted() {\n    int cached = atomic_load_explicit(&sbs_granted_cached, memory_order_acquire);\n    if (cached != -1) return cached;\n\n    driver_state_type* s = state();\n    bool granted = s && s->granted_features && s->granted_features_count &&\n                   in_array(sbs_feature_name, (const char**)s->granted_features, s->granted_features_count);\n\n    atomic_store_explicit(&sbs_granted_cached, granted ? 1 : 0, memory_order_release);\n    return granted;\n}"
  },
  {
    "path": "src/features/smooth_follow.c",
    "content": "#include \"runtime_context.h\"\n#include \"strings.h\"\n\n#include <stdatomic.h>\n\nconst char* smooth_follow_feature_name = \"smooth_follow\";\n\nstatic atomic_int smooth_follow_granted_cached = ATOMIC_VAR_INIT(-1);\n\nvoid reset_smooth_follow_features() {\n    atomic_store_explicit(&smooth_follow_granted_cached, -1, memory_order_release);\n}\n\nbool is_smooth_follow_granted() {\n    int cached = atomic_load_explicit(&smooth_follow_granted_cached, memory_order_acquire);\n    if (cached != -1) return cached;\n\n    driver_state_type* s = state();\n    bool granted = s && s->granted_features && s->granted_features_count &&\n                   in_array(smooth_follow_feature_name, (const char**)s->granted_features, s->granted_features_count);\n\n    atomic_store_explicit(&smooth_follow_granted_cached, granted ? 1 : 0, memory_order_release);\n    return granted;\n}"
  },
  {
    "path": "src/files.c",
    "content": "#include <errno.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdbool.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/file.h>\n#include <sys/types.h>\n#include <unistd.h>\n\nconst char* XR_DRIVER_DIR = \"xr_driver\";\nconst char* XDG_STATE_ENV_VAR = \"XDG_STATE_HOME\";\nconst char* XDG_RUNTIME_ENV_VAR = \"XDG_RUNTIME_DIR\";\nconst char* XDG_CONFIG_ENV_VAR = \"XDG_CONFIG_HOME\";\nconst char* XDG_DATA_ENV_VAR = \"XDG_DATA_HOME\";\nconst char* XDG_STATE_FALLBACK_DIR = \"/.local/state\";\nconst char* XDG_CONFIG_FALLBACK_DIR = \"/.config\";\nconst char* XDG_RUNTIME_FALLBACK_DIR = \"/tmp\";\nconst char* XDG_DATA_FALLBACK_DIR = \"/.local/share\";\n\n// TODO - this uses the parent directories to determine the ownership of the new directory, which can be removed\n// when the driver is no longer running as root\nFILE* get_or_create_file(const char *full_path, mode_t directory_mode, const char *file_mode, bool *file_created) {\n    FILE *fp = fopen(full_path, file_mode ? file_mode : \"r\");\n    if (fp == NULL) {\n        char *copypath = strdup(full_path);\n        char *pp = copypath;\n        char *sp;\n        int status = 0;\n        struct stat st;\n\n        while (status == 0 && (sp = strchr(pp, '/')) != 0) {\n            if (sp != pp) {\n                *sp = '\\0';\n                if (stat(copypath, &st) != 0) {\n                    if (mkdir(copypath, directory_mode) != 0) {\n                        if (errno != EEXIST) {\n                            status = -1;\n                            break;\n                        }\n                    }\n                    else {\n                        char *parent = strdup(copypath);\n                        char *last_slash = strrchr(parent, '/');\n                        if (last_slash) {\n                            *last_slash = '\\0';\n                            if (stat(parent, &st) == 0) {\n                                if (chown(copypath, st.st_uid, st.st_gid) == -1) {\n                                    perror(\"Error setting directory ownership\");\n                                }\n                            }\n                        }\n                        free(parent);\n                    }\n                }\n                *sp = '/';\n            }\n            pp = sp + 1;\n        }\n\n        if (status == 0) {\n            char *parent = strdup(full_path);\n            char *last_slash = strrchr(parent, '/');\n            if (last_slash) {\n                *last_slash = '\\0';\n                if (stat(parent, &st) == 0) {\n                    fp = fopen(full_path, \"w\");\n                    if (file_created != NULL)\n                        *file_created = true;\n\n                    if (chmod(full_path, directory_mode) == -1) {\n                        perror(\"Error setting file permissions\");\n                    }\n                    if (chown(full_path, st.st_uid, st.st_gid) == -1) {\n                        perror(\"Error setting directory ownership\");\n                    }\n                }\n            }\n            free(parent);\n        }\n\n        free(copypath);\n    } else if (file_created != NULL) {\n        *file_created = false;\n    }\n\n    return fp;\n}\n\nchar* get_xdg_file_path_for_app(const char *app_name, const char *filename, const char *xdg_env_var, const char *xdg_fallback_dir) {\n    struct stat st = {0};\n\n    char* base_directory = getenv(xdg_env_var);\n\n    if (base_directory == NULL) {\n        char* home = getenv(\"HOME\");\n        base_directory = (char*)concat(home, xdg_fallback_dir);\n    }\n\n    int path_length = strlen(base_directory) + strlen(app_name) + strlen(filename) + 3;\n    char *full_path = (char*)malloc(path_length * sizeof(char));\n    snprintf(full_path, path_length, \"%s/%s/%s\", base_directory, app_name, filename);\n\n    return full_path;\n}\n\nchar* get_xdg_file_path(const char *filename, const char *xdg_env_var, const char *xdg_fallback_dir) {\n    return get_xdg_file_path_for_app(XR_DRIVER_DIR, filename, xdg_env_var, xdg_fallback_dir);\n}\n\nchar* get_state_file_path(const char *filename) {\n    return get_xdg_file_path(filename, XDG_STATE_ENV_VAR, XDG_STATE_FALLBACK_DIR);\n}\n\nchar* get_runtime_file_path(const char *filename) {\n    return get_xdg_file_path(filename, XDG_RUNTIME_ENV_VAR, XDG_RUNTIME_FALLBACK_DIR);\n}\n\nchar* get_config_file_path(const char *filename) {\n    return get_xdg_file_path(filename, XDG_CONFIG_ENV_VAR, XDG_CONFIG_FALLBACK_DIR);\n}\n\nFILE* get_or_create_state_file(const char *filename, const char *mode, char **full_path, bool *created) {\n    *full_path = get_state_file_path(filename);\n    return get_or_create_file(*full_path, 0777, mode, created);\n}\n\nFILE* get_or_create_runtime_file(const char *filename, const char *mode, char **full_path, bool *created) {\n    *full_path = get_runtime_file_path(filename);\n    return get_or_create_file(*full_path, 0700, mode, created);\n}\n\nFILE* get_or_create_config_file(const char *filename, const char *mode, char **full_path, bool *created) {\n    *full_path = get_config_file_path(filename);\n    return get_or_create_file(*full_path, 0777, mode, created);\n}"
  },
  {
    "path": "src/imu.c",
    "content": "#include \"imu.h\"\n\n#include <math.h>\n#include <stdbool.h>\n\nconst float pose_orientation_reset_data[16] = {\n    0.0, 0.0, 0.0, 1.0,\n    0.0, 0.0, 0.0, 1.0,\n    0.0, 0.0, 0.0, 1.0,\n    0.0, 0.0, 0.0, 1.0\n};\nconst float pose_position_reset_data[3] = {\n    0.0, 0.0, 0.0\n};\n\nfloat degree_to_radian(float deg) {\n    return deg * M_PI / 180.0f;\n}\n\nfloat radian_to_degree(float rad) {\n    return rad * 180.0f / M_PI;\n}\n\nimu_quat_type normalize_quaternion(imu_quat_type q) {\n    float magnitude = sqrtf(q.w*q.w + q.x*q.x + q.y*q.y + q.z*q.z);\n    if (!isfinite(magnitude) || magnitude <= 0.0f) {\n        imu_quat_type identity = { .w = 1.0f, .x = 0.0f, .y = 0.0f, .z = 0.0f };\n        return identity;\n    }\n    q.w /= magnitude;\n    q.x /= magnitude;\n    q.y /= magnitude;\n    q.z /= magnitude;\n\n    return q;\n}\n\nimu_quat_type conjugate(imu_quat_type q) {\n    imu_quat_type q_conj = {\n        .w = q.w,\n        .x = -q.x,\n        .y = -q.y,\n        .z = -q.z\n    };\n\n    return q_conj;\n}\n\nimu_quat_type multiply_quaternions(imu_quat_type q1, imu_quat_type q2) {\n    imu_quat_type q = {\n        .w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z,\n        .x = q1.w*q2.x + q1.x*q2.w + q1.y*q2.z - q1.z*q2.y,\n        .y = q1.w*q2.y - q1.x*q2.z + q1.y*q2.w + q1.z*q2.x,\n        .z = q1.w*q2.z + q1.x*q2.y - q1.y*q2.x + q1.z*q2.w\n    };\n\n    return normalize_quaternion(q);\n}\n\nimu_quat_type euler_to_quaternion_xyz(imu_euler_type euler) {\n    // Convert degrees to radians\n    float roll = degree_to_radian(euler.roll);\n    float pitch = degree_to_radian(euler.pitch);\n    float yaw = degree_to_radian(euler.yaw);\n\n    // Compute the half angles\n    float cx = cos(roll * 0.5f);\n    float cy = cos(pitch * 0.5f);\n    float cz = cos(yaw * 0.5f);\n    float sx = sin(roll * 0.5f);\n    float sy = sin(pitch * 0.5f);\n    float sz = sin(yaw * 0.5f);\n\n    // Compute the quaternion components\n    imu_quat_type q = {\n        .x = sx * cy * cz + cx * sy * sz,\n        .y = cx * sy * cz - sx * cy * sz,\n        .z = cx * cy * sz + sx * sy * cz,\n        .w = cx * cy * cz - sx * sy * sz\n    };\n\n    return normalize_quaternion(q);\n}\n\nimu_quat_type euler_to_quaternion_zyx(imu_euler_type euler) {\n    // Convert degrees to radians\n    float roll = degree_to_radian(euler.roll);\n    float pitch = degree_to_radian(euler.pitch);\n    float yaw = degree_to_radian(euler.yaw);\n\n    // Compute the half angles\n    float cx = cos(roll * 0.5f);\n    float cy = cos(pitch * 0.5f);\n    float cz = cos(yaw * 0.5f);\n    float sx = sin(roll * 0.5f);\n    float sy = sin(pitch * 0.5f);\n    float sz = sin(yaw * 0.5f);\n\n    // Compute the quaternion components\n    imu_quat_type q = {\n        .x = sx * cy * cz - cx * sy * sz,\n        .y = cx * sy * cz + sx * cy * sz,\n        .z = cx * cy * sz - sx * sy * cz,\n        .w = cx * cy * cz + sx * sy * sz\n    };\n\n    return normalize_quaternion(q);\n}\n\nimu_quat_type euler_to_quaternion_zxy(imu_euler_type euler) {\n    // Convert degrees to radians\n    float roll = degree_to_radian(euler.roll);\n    float pitch = degree_to_radian(euler.pitch);\n    float yaw = degree_to_radian(euler.yaw);\n\n    // Compute the half angles\n    float cx = cos(roll * 0.5f);\n    float cy = cos(pitch * 0.5f);\n    float cz = cos(yaw * 0.5f);\n    float sx = sin(roll * 0.5f);\n    float sy = sin(pitch * 0.5f);\n    float sz = sin(yaw * 0.5f);\n\n    // Compute the quaternion components\n    imu_quat_type q = {\n        .x = sx * cy * cz - cx * sy * sz,\n        .y = cx * sy * cz + sx * cy * sz,\n        .z = cx * cy * sz + sx * sy * cz,\n        .w = cx * cy * cz - sx * sy * sz\n    };\n\n    return normalize_quaternion(q);\n}\n\nimu_euler_type quaternion_to_euler_xyz(imu_quat_type q) {\n    imu_euler_type euler;\n    \n    // Calculate roll (x-axis rotation)\n    float sinr_cosp = 2.0f * (q.w * q.x + q.y * q.z);\n    float cosr_cosp = 1.0f - 2.0f * (q.x * q.x + q.y * q.y);\n    euler.roll = radian_to_degree(atan2f(sinr_cosp, cosr_cosp));\n    \n    // Calculate pitch (y-axis rotation)\n    float sinp = 2.0f * (q.w * q.y - q.z * q.x);\n    if (fabsf(sinp) >= 1.0f) {\n        // Use 90 degrees if out of range\n        euler.pitch = radian_to_degree(copysignf(M_PI / 2.0f, sinp));\n    } else {\n        euler.pitch = radian_to_degree(asinf(sinp));\n    }\n    \n    // Calculate yaw (z-axis rotation)\n    float siny_cosp = 2.0f * (q.w * q.z + q.x * q.y);\n    float cosy_cosp = 1.0f - 2.0f * (q.y * q.y + q.z * q.z);\n    euler.yaw = radian_to_degree(atan2f(siny_cosp, cosy_cosp));\n    \n    return euler;\n}\n\nimu_euler_type quaternion_to_euler_zyx(imu_quat_type q) {\n    imu_euler_type euler;\n    \n    // Calculate pitch (y-axis rotation)\n    float sinp = 2.0f * (q.w * q.y - q.z * q.x);\n    if (fabsf(sinp) >= 1.0f) {\n        // Use 90 degrees if out of range\n        euler.pitch = radian_to_degree(copysignf(M_PI / 2.0f, sinp));\n        \n        // Gimbal lock case\n        // In the gimbal lock case with pitch at +/-90 degrees,\n        // yaw and roll rotate around the same axis\n        // We can choose any convention; here we set roll to 0\n        // and calculate yaw\n        euler.roll = 0.0f;\n        float siny = 2.0f * (q.w * q.z + q.x * q.y);\n        float cosy = 2.0f * (q.w * q.x - q.y * q.z);\n        euler.yaw = radian_to_degree(atan2f(siny, cosy));\n    } else {\n        // Normal case\n        euler.pitch = radian_to_degree(asinf(sinp));\n        \n        // Calculate yaw (z-axis rotation)\n        float siny_cosp = 2.0f * (q.w * q.z + q.x * q.y);\n        float cosy_cosp = 1.0f - 2.0f * (q.y * q.y + q.z * q.z);\n        euler.yaw = radian_to_degree(atan2f(siny_cosp, cosy_cosp));\n        \n        // Calculate roll (x-axis rotation)\n        float sinr_cosp = 2.0f * (q.w * q.x + q.y * q.z);\n        float cosr_cosp = 1.0f - 2.0f * (q.x * q.x + q.y * q.y);\n        euler.roll = radian_to_degree(atan2f(sinr_cosp, cosr_cosp));\n    }\n    \n    return euler;\n}\n\nimu_euler_type quaternion_to_euler_zxy(imu_quat_type q) {\n    imu_euler_type euler;\n    \n    // Calculate roll (x-axis rotation)\n    float sinr = 2.0f * (q.w * q.x + q.y * q.z);\n    float cosr = 1.0f - 2.0f * (q.x * q.x + q.z * q.z);\n    euler.roll = radian_to_degree(atan2f(sinr, cosr));\n    \n    // Calculate pitch (y-axis rotation)\n    float sinp = 2.0f * (q.w * q.y - q.x * q.z);\n    if (fabsf(sinp) >= 1.0f) {\n        // Use 90 degrees if out of range\n        euler.pitch = radian_to_degree(copysignf(M_PI / 2.0f, sinp));\n    } else {\n        euler.pitch = radian_to_degree(asinf(sinp));\n    }\n    \n    // Calculate yaw (z-axis rotation)\n    float siny = 2.0f * (q.w * q.z + q.x * q.y);\n    float cosy = 1.0f - 2.0f * (q.y * q.y + q.z * q.z);\n    euler.yaw = radian_to_degree(atan2f(siny, cosy));\n    \n    return euler;\n}\n\nimu_quat_type device_pitch_adjustment(float adjustment_degrees) {\n    float half = degree_to_radian(adjustment_degrees) * 0.5f;\n    imu_quat_type q = {\n        .w = cosf(half),\n        .x = 0.0f,\n        .y = sinf(half),\n        .z = 0.0f\n    };\n    return q;\n}\n\nbool quat_equal(imu_quat_type q1, imu_quat_type q2) {\n    return q1.w == q2.w && q1.x == q2.x && q1.y == q2.y && q1.z == q2.z;\n}\n\nimu_vec3_type vector_rotate(imu_vec3_type v, imu_quat_type q) {\n    q = normalize_quaternion(q);\n\n    float w = q.w;\n    float qx = q.x, qy = q.y, qz = q.z;\n\n    float tx = 2.0f * (qy * v.z - qz * v.y);\n    float ty = 2.0f * (qz * v.x - qx * v.z);\n    float tz = 2.0f * (qx * v.y - qy * v.x);\n\n    imu_vec3_type out;\n    out.x = v.x + w * tx + (qy * tz - qz * ty);\n    out.y = v.y + w * ty + (qz * tx - qx * tz);\n    out.z = v.z + w * tz + (qx * ty - qy * tx);\n\n    return out;\n}\n\nfloat quat_small_angle_rad(imu_quat_type q1, imu_quat_type q2) {\n    imu_quat_type q_rel = multiply_quaternions(conjugate(q1), q2);\n    float v_norm = sqrtf(q_rel.x * q_rel.x + q_rel.y * q_rel.y + q_rel.z * q_rel.z);\n    float w_abs = fabsf(q_rel.w);\n    return 2.0f * atan2f(v_norm, w_abs);\n}"
  },
  {
    "path": "src/ipc.c",
    "content": "#include \"ipc.h\"\n#include \"logging.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <glob.h>\n#include <pthread.h>\n#include <sys/ipc.h>\n#include <sys/shm.h>\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdbool.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\nconst char *sombrero_ipc_file_prefix = \"/tmp/shader_runtime_\";\n\nconst char *display_res_ipc_name = \"display_resolution\";\nconst char *disabled_ipc_name = \"disabled\";\nconst char *date_ipc_name = \"keepalive_date\";\nconst char *pose_orientation_ipc_name = \"pose_orientation\";\nconst char *pose_orientation_mutex_ipc_name = \"pose_orientation_mutex\";\nconst char *pose_position_ipc_name = \"pose_position\";\n\n// deprecated - can be removed once this version is widely distributed\nconst char *display_fov_ipc_name = \"display_fov\";\nconst char *lens_distance_ratio_ipc_name = \"lens_distance_ratio\";\n\nbool setup_ipc_values(ipc_values_type *ipc_values, bool debug) {\n    setup_ipc_value(display_res_ipc_name, (void**) &ipc_values->display_res, sizeof(float) * 2, debug);\n    setup_ipc_value(disabled_ipc_name, (void**) &ipc_values->disabled, sizeof(bool), debug);\n    setup_ipc_value(date_ipc_name, (void**) &ipc_values->date, sizeof(float) * 4, debug);\n    setup_ipc_value(pose_orientation_ipc_name, (void**) &ipc_values->pose_orientation, sizeof(float) * 16, debug);\n    setup_ipc_value(pose_position_ipc_name, (void**) &ipc_values->pose_position, sizeof(float) * 3, debug);\n\n    setup_ipc_value(display_fov_ipc_name, (void**) &ipc_values->display_fov, sizeof(float), debug);\n    setup_ipc_value(lens_distance_ratio_ipc_name, (void**) &ipc_values->lens_distance_ratio, sizeof(float), debug);\n\n    // attempt to destroy the mutex if it already existed from a previous run\n    setup_ipc_value(pose_orientation_mutex_ipc_name, (void**) &ipc_values->pose_orientation_mutex, sizeof(pthread_mutex_t), debug);\n    int ret = pthread_mutex_destroy(ipc_values->pose_orientation_mutex);\n    if (ret != 0) {\n        perror(\"pthread_mutex_destroy\");\n        if (ret != EINVAL) return false;\n    }\n\n    pthread_mutexattr_t attr;\n    if (pthread_mutexattr_init(&attr) != 0) {\n        perror(\"pthread_mutexattr_init\");\n        return false;\n    }\n    if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) != 0) {\n        perror(\"pthread_mutexattr_setpshared\");\n        return false;\n    }\n    if (pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST) != 0) {\n        perror(\"pthread_mutexattr_setrobust\");\n        return false;\n    }\n    if (pthread_mutex_init(ipc_values->pose_orientation_mutex, &attr) != 0) {\n        perror(\"pthread_mutex_init\");\n        return false;\n    }\n\n    return true;\n}\n\nvoid setup_ipc_value(const char *name, void **shmemValue, size_t size, bool debug) {\n    char *path = malloc(strlen(sombrero_ipc_file_prefix) + strlen(name) + 1);\n    strcpy(path, sombrero_ipc_file_prefix);\n    strcat(path, name);\n\n    mode_t old_umask = umask(0);\n    int fd = open(path, O_CREAT, 0666);\n    if (fd == -1) {\n        log_error(\"Could not create IPC shared file\\n\");\n        exit(1);\n    }\n    close(fd);\n    umask(old_umask);\n\n    key_t key = ftok(path, 0);\n    if (debug) log_debug(\"ipc_key, got key %d for path %s\\n\", key, path);\n    free(path);\n\n    int shmid = shmget(key, size, 0666|IPC_CREAT);\n    if (shmid == -1) {\n        // it may have been allocated using a different size, attempt to find and delete it\n        shmid = shmget(key, 0, 0);\n        if (shmid != -1) {\n            if (debug) log_debug(\"ipc_key, deleting shared memory segment with key %d\\n\", key);\n            shmctl(shmid, IPC_RMID, NULL);\n        } else {\n            if (debug) log_debug(\"ipc_key, couldn't delete, no shmid for key %d\\n\", key);\n        }\n    }\n\n    if (shmid != -1) {\n        *shmemValue = shmat(shmid,(void*)0,0);\n        if (*shmemValue == (void *) -1) {\n            log_error(\"Error calling shmat\\n\");\n            exit(1);\n        }\n    } else {\n        log_error(\"Error calling shmget\\n\");\n        exit(1);\n    }\n}\n\nvoid cleanup_ipc(char* file_prefix, bool debug) {\n    if (debug) log_debug(\"cleanup_ipc, disabling IPC\\n\");\n    char pattern[256];\n    snprintf(pattern, sizeof(pattern), \"%s*\", file_prefix);\n\n    glob_t glob_result;\n    glob(pattern, GLOB_TILDE, NULL, &glob_result);\n\n    for(unsigned int i=0; i<glob_result.gl_pathc; ++i){\n        char* file = glob_result.gl_pathv[i];\n        key_t key = ftok(file, 0);\n        int shmid = shmget(key, 0, 0);\n        if (shmid != -1) {\n            if (debug) log_debug(\"cleanup_ipc, deleting shared memory segment with key %d\\n\", key);\n            shmctl(shmid, IPC_RMID, NULL);\n        } else {\n            if (debug) log_debug(\"cleanup_ipc, couldn't delete, no shmid for key %d\\n\", key);\n        }\n    }\n\n    globfree(&glob_result);\n}"
  },
  {
    "path": "src/logging.c",
    "content": "#include \"files.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"state.h\"\n#include \"strings.h\"\n#include \"version.h\"\n\n#include <stdio.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <sys/time.h>\n#include <time.h>\n\nvoid log_init() {\n    // ensure the log file exists, reroute stdout and stderr there\n    char *log_file_path = NULL;\n    FILE *log_file = get_or_create_state_file(\"driver.log\", NULL, &log_file_path, NULL);\n    fclose(log_file);\n    freopen(log_file_path, \"a\", stdout);\n    freopen(log_file_path, \"a\", stderr);\n    free_and_clear(&log_file_path);\n\n    // when redirecting stdout/stderr to a file, it becomes fully buffered, requiring lots of manual flushing of the\n    // stream, this makes them unbuffered, which is fine since we log so little\n    setbuf(stdout, NULL);\n    setbuf(stderr, NULL);\n\n    log_message(\"Project version: %s\\n\", PROJECT_VERSION);\n}\n\nstatic void do_log(const char* prefix, const char* format, va_list args) {\n    struct timeval tv;\n    gettimeofday(&tv, NULL);\n    struct tm *tm = localtime(&tv.tv_sec);\n    printf(\"%04d-%02d-%02d %02d:%02d:%02d.%03d %s\",\n           tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,\n           tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), prefix);\n\n    vprintf(format, args);\n}\n\nvoid log_message(const char* format, ...) {\n    va_list args;\n    va_start(args, format);\n    do_log(\"\", format, args);\n    va_end(args);\n}\n\nvoid log_error(const char* format, ...) {\n    va_list args;\n    va_start(args, format);\n    do_log(\"[ERROR] \", format, args);\n    va_end(args);\n}\n\nvoid log_debug(const char* format, ...) {\n    va_list args;\n    va_start(args, format);\n    do_log(\"[DEBUG] \", format, args);\n    va_end(args);\n}"
  },
  {
    "path": "src/multitap.c",
    "content": "#include \"imu.h\"\n#include \"buffer.h\"\n\n#include \"logging.h\"\n#include <math.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <stdio.h>\n\n#define MT_BUFFER_MS 25\n\n#define MT_STATE_IDLE 0\n#define MT_STATE_RISE 1\n#define MT_STATE_FALL 2\n#define MT_STATE_PAUSE 3\n\nint mt_buffer_size;\nint imu_cycles_per_s;\nbuffer_type *mt_buffer = NULL;\nint mt_state = MT_STATE_IDLE;\nconst float mt_detect_threshold = 2000.0;\nconst float mt_pause_threshold = 100.0;\nuint64_t tap_start_time = 0;\nuint64_t pause_start_time = 0;\nuint64_t last_logged_peak_time = 0;\nconst int max_tap_period_ms = 750; // longest time-frame to allow between tap starts/rises\nconst int max_tap_duration_ms = 70; // a single tap should be very quick, ignore long accelerations\nconst int min_pause_ms = 10; // must detect a pause (~0 acceleration) between taps\nfloat peak_max = 0.0;\nint tap_count = 0;\n\nfloat accel_adjust_constant;\n\nvoid init_multi_tap(int init_imu_cycles_per_s) {\n    imu_cycles_per_s = init_imu_cycles_per_s;\n    float desired_buffer_size = (float)MT_BUFFER_MS / 1000.0 * imu_cycles_per_s;\n    mt_buffer_size = floor(desired_buffer_size);\n\n    // this is the ratio based on how much we had to round\n    accel_adjust_constant = (float)mt_buffer_size/desired_buffer_size;\n\n    if (mt_buffer) {\n        free(mt_buffer);\n        mt_buffer = NULL;\n    }\n    mt_buffer = create_buffer(mt_buffer_size);\n}\n\n// returns the number of taps observed\nint detect_multi_tap(imu_euler_type velocities, uint32_t timestamp, bool debug) {\n    if (mt_buffer) {\n        // the oldest value is zero/unset if the buffer hasn't been filled yet, so we check prior to doing a\n        // push/pop, to know if the value returned will be relevant to our calculations\n        bool was_full = is_full(mt_buffer);\n        float next_value = sqrt(velocities.roll * velocities.roll + velocities.pitch * velocities.pitch + velocities.yaw * velocities.yaw);\n        float oldest_value = push(mt_buffer, next_value);\n\n        if (was_full) {\n            // extrapolate out to seconds, so the threshold can stay the same regardless of buffer size\n            float acceleration = (next_value - oldest_value) * (float)imu_cycles_per_s / mt_buffer_size * accel_adjust_constant;\n            int tap_elapsed_ms = timestamp - tap_start_time;\n            if ((tap_count > 0 || mt_state != MT_STATE_IDLE) && tap_elapsed_ms > max_tap_period_ms) {\n                peak_max = 0.0;\n                mt_state = MT_STATE_IDLE;\n                int final_tap_count = tap_count;\n                tap_count = 0;\n\n                if (final_tap_count > 0 && debug) log_debug(\"detected multi-tap of %d\\n\", final_tap_count);\n                return final_tap_count;\n            } else {\n                switch(mt_state) {\n                    case MT_STATE_IDLE: {\n                        if (acceleration > mt_detect_threshold) {\n                            tap_start_time = timestamp;\n                            peak_max = 0.0;\n                            mt_state = MT_STATE_RISE;\n                            if (debug) log_debug(\"tap-rise detected %f\\n\", acceleration);\n                        } else {\n                            if (debug) {\n                                if (acceleration > peak_max) peak_max = acceleration;\n                                if ((timestamp - last_logged_peak_time) > 1000) {\n                                    log_debug(\"no-tap detected, peak was %f\\n\", peak_max);\n                                    peak_max = 0.0;\n                                    last_logged_peak_time = timestamp;\n                                }\n                            }\n                        }\n                        break;\n                    }\n                    case MT_STATE_RISE: {\n                        if (acceleration < 0) // accelerating in the opposite direction\n                            mt_state = MT_STATE_FALL;\n                        break;\n                    }\n                    case MT_STATE_FALL: {\n                        if (acceleration > 0) { // acceleration switches back, stopping the fall\n                            if (tap_elapsed_ms > max_tap_duration_ms) {\n                                if (debug) log_debug(\"rise and fall took %d, too long for a tap\\n\", tap_elapsed_ms);\n                                peak_max = 0.0;\n                                mt_state = MT_STATE_IDLE;\n                                tap_count == 0;\n                            } else {\n                                if (debug) log_debug(\"rise and fall took %d\\n\", tap_elapsed_ms);\n                                tap_count++;\n                                pause_start_time = timestamp;\n                                mt_state = MT_STATE_PAUSE;\n                            }\n                        }\n                        break;\n                    }\n                    case MT_STATE_PAUSE: {\n                        if (fabs(acceleration) < mt_pause_threshold) {\n                            int pause_elapsed_ms = timestamp - pause_start_time;\n                            if (pause_elapsed_ms > min_pause_ms)\n                                // paused long enough, wrap back around to idle where we can detect the next rise\n                                mt_state = MT_STATE_IDLE;\n                        } else {\n                            // not idle, reset pause state timer\n                            pause_start_time = timestamp;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}"
  },
  {
    "path": "src/outputs.c",
    "content": "#include \"buffer.h\"\n#include \"config.h\"\n#include \"devices.h\"\n#include \"imu.h\"\n#include \"files.h\"\n#include \"ipc.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"outputs.h\"\n#include \"plugins.h\"\n#include \"plugins/gamescope_reshade_wayland.h\"\n#include \"runtime_context.h\"\n#include \"strings.h\"\n#include \"epoch.h\"\n\n#include <errno.h>\n#include <libevdev/libevdev.h>\n#include <libevdev/libevdev-uinput.h>\n#include <math.h>\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <unistd.h>\n\n#define MS_PER_SEC 1000\n#define IMU_CHECKPOINT_MS MS_PER_SEC / 4\n\nimu_buffer_type *imu_buffer;\n\nstatic int last_imu_checkpoint_ms = 0;\nstatic imu_quat_type last_imu_checkpoint_quat = {.x = 0.0f, .y = 0.0f, .z = 0.0f, .w = 1.0f};\nstatic uint64_t last_healthy_imu_timestamp_ms = 0;\n\n// Cached perceptual threshold for when tiny orientation changes become effectively invisible.\n// Reset on output deinit/reinit.\nstatic float dead_zone_cached_device_visible_angle_rad = -1.0f;\nstatic float dead_zone_cached_threshold_visible_angle_rad = -1.0f;\n\nstatic pthread_mutex_t outputs_mutex = PTHREAD_MUTEX_INITIALIZER;\nstruct libevdev* evdev;\nstruct libevdev_uinput* uinput;\n\nint joystick_debug_imu_cycles;\nint prev_joystick_x = 0;\nint prev_joystick_y = 0;\n\nconst int max_input = 1 << 16;\nconst int mid_input = 0;\nconst int min_input = -max_input;\n\nfloat joystick_max_degrees_per_s;\n\nstatic float clampf(float v, float lo, float hi) {\n    if (v < lo) return lo;\n    if (v > hi) return hi;\n    return v;\n}\n\nstatic imu_quat_type quat_slerp(imu_quat_type a, imu_quat_type b, float t) {\n    t = clampf(t, 0.0f, 1.0f);\n\n    float dot = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;\n    if (dot < 0.0f) {\n        dot = -dot;\n        b.x = -b.x;\n        b.y = -b.y;\n        b.z = -b.z;\n        b.w = -b.w;\n    }\n\n    // When the quaternions are very close, fall back to lerp to avoid numeric issues.\n    if (dot > 0.9995f) {\n        imu_quat_type out = {\n            .x = a.x + (b.x - a.x) * t,\n            .y = a.y + (b.y - a.y) * t,\n            .z = a.z + (b.z - a.z) * t,\n            .w = a.w + (b.w - a.w) * t,\n        };\n        float len = sqrtf(out.x * out.x + out.y * out.y + out.z * out.z + out.w * out.w);\n        if (len > 0.0f) {\n            out.x /= len;\n            out.y /= len;\n            out.z /= len;\n            out.w /= len;\n        }\n        return out;\n    }\n\n    dot = clampf(dot, -1.0f, 1.0f);\n    float theta_0 = acosf(dot);\n    float sin_theta_0 = sinf(theta_0);\n    if (sin_theta_0 <= 0.0f) {\n        return b;\n    }\n\n    float theta = theta_0 * t;\n    float sin_theta = sinf(theta);\n\n    float s0 = cosf(theta) - dot * sin_theta / sin_theta_0;\n    float s1 = sin_theta / sin_theta_0;\n\n    imu_quat_type out = {\n        .x = (s0 * a.x) + (s1 * b.x),\n        .y = (s0 * a.y) + (s1 * b.y),\n        .z = (s0 * a.z) + (s1 * b.z),\n        .w = (s0 * a.w) + (s1 * b.w),\n    };\n\n    float len = sqrtf(out.x * out.x + out.y * out.y + out.z * out.z + out.w * out.w);\n    if (len > 0.0f) {\n        out.x /= len;\n        out.y /= len;\n        out.z /= len;\n        out.w /= len;\n    }\n\n    return out;\n}\n\nstatic float dead_zone_exponential_curve(float ratio01) {\n    // Exponential curve with very low values near 0 and a smooth rise towards 1.\n    // ratio01 is expected in [0, 1].\n    const float k = 8.0f;\n    ratio01 = clampf(ratio01, 0.0f, 1.0f);\n\n    float e0 = expf(-k);\n    float e = expf(k * (ratio01 - 1.0f));\n    return (e - e0) / (1.0f - e0);\n}\n\nstatic float dead_zone_slerp_alpha(float angle_rad, float threshold_rad, int imu_cycles_per_s) {\n    float ratio = clampf(angle_rad / threshold_rad, 0.0f, 1.0f);\n    float curve = dead_zone_exponential_curve(ratio);\n\n    // Floor the alpha so extremely small deltas still converge over a few seconds.\n    // Using a time constant keeps behavior stable across different IMU rates.\n    const float tau_slow_s = 5.0f;\n    float dt_s = 1.0f / (float)imu_cycles_per_s;\n    float alpha_min = 1.0f - expf(-dt_s / tau_slow_s);\n    float alpha = alpha_min + curve * (1.0f - alpha_min);\n    return clampf(alpha, 0.0f, 1.0f);\n}\n\nstatic float dead_zone_min_visible_angle_rad(const device_properties_type* device) {\n    if (!device) return -1.0f;\n\n    // Convert the device's diagonal FOV into horizontal/vertical FOV using the display aspect ratio.\n    float aspect = (float)device->resolution_w / (float)device->resolution_h;\n    float diag_to_vert_ratio = sqrtf((aspect * aspect) + 1.0f);\n    float fov_v_rad = degree_to_radian(device->fov / diag_to_vert_ratio);\n    float fov_h_rad = fov_v_rad * aspect;\n\n    // Conservative: use the smaller angular size-per-pixel so that being sub-pixel in either axis is treated as invisible.\n    float rad_per_px_h = fov_h_rad / (float)device->resolution_w;\n    float rad_per_px_v = fov_v_rad / (float)device->resolution_h;\n    float rad_per_px = fminf(rad_per_px_h, rad_per_px_v);\n    if (!isfinite(rad_per_px) || rad_per_px <= 0.0f) return 0.0f;\n\n    return rad_per_px;\n}\n\n// Given a desired angle change, find what initial angle would produce it\nstatic float inverse_angle_for_change(float desired_change_rad, float threshold_rad, int imu_cycles_per_s) {\n    if (desired_change_rad <= 0.0f) {\n        return 0.0f;\n    }\n    \n    // Use bisection search\n    float angle_low = 0.0f;\n    float angle_high = fmaxf(threshold_rad * 2.0f, desired_change_rad * 2.0f);\n    \n    const int max_iterations = 20;\n    const float tolerance = 1e-6f;\n    \n    for (int i = 0; i < max_iterations; i++) {\n        float angle_mid = (angle_low + angle_high) * 0.5f;\n        \n        // Compute what change this angle would produce\n        float alpha = dead_zone_slerp_alpha(angle_mid, threshold_rad, imu_cycles_per_s);\n        float cos_theta = cosf(angle_mid);\n        float theta_new = acosf(cos_theta + alpha * (1.0f - cos_theta));\n        float actual_change = angle_mid - theta_new;\n        \n        if (fabsf(actual_change - desired_change_rad) < tolerance) {\n            return angle_mid;\n        }\n        \n        if (actual_change < desired_change_rad) {\n            angle_low = angle_mid;\n        } else {\n            angle_high = angle_mid;\n        }\n    }\n    \n    return (angle_low + angle_high) * 0.5f;\n}\n\nstatic int evdev_check(char * function, int i) {\n    if (i < 0) {\n        log_message(\"libevdev.%s: %s\\n\", function, strerror(-i));\n        exit(1);\n    }\n\n    return i;\n}\n\n// returns an integer between -max_input and max_input, the magnitude of which is just the ratio of\n// input_velocity to max_input_velocity (where velocity is degrees/sec)\nint joystick_value(float input_velocity, float max_input_velocity) {\n  int value = round(input_velocity * max_input / max_input_velocity);\n  if (value < min_input) {\n    return min_input;\n  } else if (value > max_input) {\n    return max_input;\n  }\n\n  return value;\n}\n\n#define JOYSTICK_DEBUG_LINES 17\n#define JOYSTICK_DEBUG_LINES_MIDDLE 8 // zero-indexed from 17 total lines\n\n// converts a value in the joystick min/max range to a value in the file row/col range\nint joystick_debug_val_to_line(int value) {\n    int joystick_middle = (max_input + min_input) / 2;\n    int value_from_middle = value - joystick_middle;\n    float value_percent_of_total = (float)value_from_middle / (max_input - min_input);\n    int line_value_from_middle = value_percent_of_total < 0 ? ceil(value_percent_of_total * JOYSTICK_DEBUG_LINES) : floor(value_percent_of_total * JOYSTICK_DEBUG_LINES);\n\n    return JOYSTICK_DEBUG_LINES_MIDDLE + line_value_from_middle;\n}\n\n// write a character to a coordinate -- as a grid of characters -- in a file\nvoid write_character_to_joystick_debug_file(FILE *fp, int col, int row, char new_char) {\n    if (row < 0 || row >= JOYSTICK_DEBUG_LINES || col < 0 || col >= JOYSTICK_DEBUG_LINES) {\n        log_error(\"joystick_debug: invalid row or column index: %d %d\\n\", row, col);\n    } else {\n        for (int i = 0; i < row; i++) {\n            for (int j = 0; j < JOYSTICK_DEBUG_LINES; j++) {\n                fgetc(fp);\n            }\n            char c = fgetc(fp);\n            if (c != '\\n') {\n                return;\n            }\n        }\n\n        for (int j = 0; j <= col; j++) {\n            fgetc(fp);\n        }\n\n        fseek(fp, -1, SEEK_CUR);\n        fputc(new_char, fp);\n    }\n}\n\n// debug visual joystick from bash: watch -n 0.1 cat $XDG_RUNTIME_DIR/xr_driver/joystick_debug\nvoid joystick_debug(int old_joystick_x, int old_joystick_y, int new_joystick_x, int new_joystick_y) {\n    int old_x = joystick_debug_val_to_line(old_joystick_x);\n    int old_y = joystick_debug_val_to_line(old_joystick_y);\n    int new_x = joystick_debug_val_to_line(new_joystick_x);\n    int new_y = joystick_debug_val_to_line(new_joystick_y);\n\n    if (old_x != new_x || old_y != new_y) {\n        char *full_path = NULL;\n        bool file_created = false;\n        FILE *fp = get_or_create_runtime_file(\"joystick_debug\", \"r+\", &full_path, &file_created);\n        if (file_created) {\n            for (int i = 0; i < JOYSTICK_DEBUG_LINES; i++) {\n                for (int j = 0; j < JOYSTICK_DEBUG_LINES; j++) {\n                    char grid_char = ' ';\n                    if (i == JOYSTICK_DEBUG_LINES_MIDDLE && j == JOYSTICK_DEBUG_LINES_MIDDLE)\n                        grid_char = 'X';\n                    fputc(grid_char, fp);\n                }\n                fputc('\\n', fp);\n            }\n            fclose(fp);\n\n            fp = fopen(full_path, \"r+\");\n        }\n        free_and_clear(&full_path);\n        if (fp == NULL) {\n            return;\n        }\n\n        char reset_char = ' ';\n        if (old_x == JOYSTICK_DEBUG_LINES_MIDDLE && old_y == JOYSTICK_DEBUG_LINES_MIDDLE)\n            reset_char = 'X';\n\n        write_character_to_joystick_debug_file(fp, old_x, old_y, reset_char);\n        rewind(fp);\n        write_character_to_joystick_debug_file(fp, new_x, new_y, 'O');\n        fclose(fp);\n    }\n}\n\n// Starting from degree 0, 180 and -180 are the same. If the previous value was 179 and the new value is -179,\n// the diff is 2 (-179 is equivalent to 181). This function takes the diff and then adjusts it if it detects\n// that we've crossed the +/-180 threshold.\nfloat degree_delta(float prev, float next) {\n    float delta = fmod(next - prev, 360);\n    if (delta > 180) {\n        return delta - 360;\n    } else if (delta < -180) {\n        return delta + 360;\n    }\n\n    return delta;\n}\n\nimu_euler_type get_euler_velocities(imu_euler_type* previous, imu_euler_type current, int imu_cycles_per_sec) {\n    imu_euler_type velocities = {\n        .roll=degree_delta(previous->roll, current.roll) * imu_cycles_per_sec,\n        .pitch=degree_delta(previous->pitch, current.pitch) * imu_cycles_per_sec,\n        .yaw=degree_delta(previous->yaw, current.yaw) * imu_cycles_per_sec\n    };\n\n    *previous = current;\n\n    return velocities;\n}\n\nstatic void _init_outputs() {\n    device_properties_type* device = device_checkout();\n    joystick_debug_imu_cycles = device == NULL ? 6 : ceil(100.0 * device->imu_cycles_per_s / 1000.0); // update joystick debug file roughly every 100 ms\n    joystick_max_degrees_per_s = 360.0 / 4;\n    float joystick_max_radians_per_s = joystick_max_degrees_per_s * M_PI / 180.0;\n\n    dead_zone_cached_device_visible_angle_rad = device ? dead_zone_min_visible_angle_rad(device) : -1.0f;\n    if (dead_zone_cached_device_visible_angle_rad > 0.0f && isfinite(dead_zone_cached_device_visible_angle_rad)) {\n        if (config()->debug_device) log_debug(\"dead_zone device visible angle: %.9f rad\\n\", dead_zone_cached_device_visible_angle_rad);\n    }\n    dead_zone_cached_threshold_visible_angle_rad = -1.0f;\n    device_checkin(device);\n\n    evdev = libevdev_new();\n    if (config()->joystick_mode) {\n        struct input_absinfo absinfo;\n        absinfo.minimum = min_input;\n        absinfo.maximum = max_input;\n        absinfo.resolution = max_input / joystick_max_radians_per_s;\n        absinfo.value = mid_input;\n        absinfo.flat = 2;\n        absinfo.fuzz = 0;\n\n        evdev_check(\"libevdev_enable_property\", libevdev_enable_property(evdev, INPUT_PROP_BUTTONPAD));\n        libevdev_set_name(evdev, \"XR virtual joystick\");\n        evdev_check(\"libevdev_enable_event_type\", libevdev_enable_event_type(evdev, EV_ABS));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_ABS, ABS_X, &absinfo));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_ABS, ABS_Y, &absinfo));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_ABS, ABS_Z, &absinfo));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_ABS, ABS_RX, &absinfo));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_ABS, ABS_RY, &absinfo));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_ABS, ABS_RZ, &absinfo));\n\n        /* do not remove next 3 lines or udev scripts won't assign 0664 permissions -sh */\n        evdev_check(\"libevdev_enable_event_type\", libevdev_enable_event_type(evdev, EV_KEY));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_KEY, BTN_JOYSTICK, NULL));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_KEY, BTN_TRIGGER, NULL));\n\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_KEY, BTN_A, NULL));\n    } else if (config()->mouse_mode) {\n        libevdev_set_name(evdev, \"XR virtual mouse\");\n\n        evdev_check(\"libevdev_enable_event_type\", libevdev_enable_event_type(evdev, EV_REL));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_REL, REL_X, NULL));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_REL, REL_Y, NULL));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_REL, REL_WHEEL, NULL));\n\n        evdev_check(\"libevdev_enable_event_type\", libevdev_enable_event_type(evdev, EV_KEY));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_KEY, BTN_LEFT, NULL));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_KEY, BTN_MIDDLE, NULL));\n        evdev_check(\"libevdev_enable_event_code\", libevdev_enable_event_code(evdev, EV_KEY, BTN_RIGHT, NULL));\n    }\n    if (config()->mouse_mode || config()->joystick_mode)\n        evdev_check(\"libevdev_uinput_create_from_device\", libevdev_uinput_create_from_device(evdev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uinput));\n}\n\nstatic void _deinit_outputs() {\n    last_imu_checkpoint_ms = 0;\n    dead_zone_cached_device_visible_angle_rad = -1.0f;\n    dead_zone_cached_threshold_visible_angle_rad = -1.0f;\n    if (uinput) {\n        libevdev_uinput_destroy(uinput);\n        uinput = NULL;\n    }\n    if (evdev) {\n        libevdev_free(evdev);\n        evdev = NULL;\n    }\n}\n\nvoid init_outputs() {\n    pthread_mutex_lock(&outputs_mutex);\n    _init_outputs();\n    pthread_mutex_unlock(&outputs_mutex);\n}\n\nvoid deinit_outputs() {\n    pthread_mutex_lock(&outputs_mutex);\n    _deinit_outputs();\n    pthread_mutex_unlock(&outputs_mutex);\n}\n\nvoid reinit_outputs() {\n    pthread_mutex_lock(&outputs_mutex);\n    _deinit_outputs();\n    _init_outputs();\n    pthread_mutex_unlock(&outputs_mutex);\n}\n\n#define WAIT_FOR_IMU_ATTEMPTS 5\nbool wait_for_imu_start() {\n    int attempts = 0;\n    while (!is_imu_alive()) {\n        if (attempts++ == WAIT_FOR_IMU_ATTEMPTS) return false;\n        sleep(1);\n    }\n\n    return true;\n}\n\nvoid handle_imu_update(imu_pose_type pose, imu_euler_type velocities, bool imu_calibrated, ipc_values_type *ipc_values) {\n    // counter that resets every second, for triggering things that we don't want to do every cycle\n    static int imu_counter = 0;\n\n    // periodically run checks to keep an eye on the health of the IMU\n    if (pose.timestamp_ms - last_imu_checkpoint_ms > IMU_CHECKPOINT_MS) {\n        last_imu_checkpoint_ms = pose.timestamp_ms;\n\n        // in practice, no two quats will be exactly equal even if the glasses are stationary\n        if (!quat_equal(pose.orientation, last_imu_checkpoint_quat)) {\n            last_healthy_imu_timestamp_ms = get_epoch_time_ms();\n            last_imu_checkpoint_quat = pose.orientation;\n        } else if (config()->debug_device) {\n            log_debug(\"handle_imu_update, device failed health check\\n\");\n        }\n    }\n\n    device_properties_type* device = device_checkout();\n    if (device != NULL) {\n        pthread_mutex_lock(&outputs_mutex);\n        if (ipc_values) {\n            // send keepalive every counter period\n            if (imu_counter == 0) {\n                time_t now = time(NULL);\n                struct tm *t = localtime(&now);\n\n                // match the float4 date uniform type definition\n                ipc_values->date[0] = (float)(t->tm_year + 1900);\n                ipc_values->date[1] = (float)(t->tm_mon + 1);\n                ipc_values->date[2] = (float)t->tm_mday;\n                ipc_values->date[3] = (float)(t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec);\n                set_skippable_gamescope_reshade_effect_uniform_variable(\"keepalive_date\", ipc_values->date, 4, sizeof(float), true);\n            }\n\n            if (imu_calibrated) {\n                if (imu_buffer != NULL && imu_buffer_size(imu_buffer) != device->imu_buffer_size) {\n                    free_imu_buffer(imu_buffer);\n                    imu_buffer = NULL;\n                }\n\n                if (imu_buffer == NULL) {\n                    imu_buffer = create_imu_buffer(device->imu_buffer_size);\n                    if (imu_buffer == NULL) {\n                        log_error(\"Error allocating memory\\n\");\n                        exit(1);\n                    }\n                }\n\n                imu_buffer_response_type *response = push_to_imu_buffer(imu_buffer, pose.orientation, (float)pose.timestamp_ms);\n\n                if (response && response->ready) {\n                    // Deadzone smoothing: below the configured threshold, slerp towards the new quat.\n                    // The closer the angle is to the threshold, the more aggressively we slerp (exponential curve).\n                    // Past the threshold, we effectively \"snap\" (copy) to preserve responsiveness.\n                    static bool dead_zone_initialized = false;\n                    static imu_quat_type dead_zone_quat = {0};\n\n                    static float dead_zone_threshold_deg = 0.0f;\n                    static float dead_zone_threshold_rad = 0.0f;\n                    if (config()->dead_zone_threshold_deg != dead_zone_threshold_deg) {\n                        dead_zone_threshold_deg = config()->dead_zone_threshold_deg;\n                        dead_zone_threshold_rad = degree_to_radian(dead_zone_threshold_deg);\n                        dead_zone_initialized = false;\n                        dead_zone_cached_threshold_visible_angle_rad = -1.0f;\n                    }\n\n                    if (dead_zone_threshold_deg > 0.0f) {\n                        if (dead_zone_cached_threshold_visible_angle_rad < 0.0f && dead_zone_cached_device_visible_angle_rad > 0.0f) {\n                            // this is the minimum angle needed to produce a visible change when factoring in the lerp logic,\n                            // anything smaller than this should just be ignored\n                            dead_zone_cached_threshold_visible_angle_rad = inverse_angle_for_change(\n                                dead_zone_cached_device_visible_angle_rad,\n                                dead_zone_threshold_rad,\n                                device->imu_cycles_per_s\n                            );\n                            if (dead_zone_cached_threshold_visible_angle_rad > 0.0f && isfinite(dead_zone_cached_threshold_visible_angle_rad)) {\n                                if (config()->debug_device) log_debug(\"dead_zone threshold visible angle: %.9f rad\\n\", dead_zone_cached_threshold_visible_angle_rad);\n                            }\n                        }\n                        imu_quat_type current_quat = {\n                            .x = response->data[0],\n                            .y = response->data[1],\n                            .z = response->data[2],\n                            .w = response->data[3],\n                        };\n\n                        if (!dead_zone_initialized) {\n                            dead_zone_initialized = true;\n                            dead_zone_quat = current_quat;\n                        } else {\n                            float angle_rad = quat_small_angle_rad(dead_zone_quat, current_quat);\n                            if (angle_rad >= dead_zone_threshold_rad) {\n                                dead_zone_quat = current_quat;\n                            } else {\n                                if (dead_zone_cached_threshold_visible_angle_rad < 0.0f || angle_rad >= dead_zone_cached_threshold_visible_angle_rad) {\n                                    float alpha = dead_zone_slerp_alpha(angle_rad, dead_zone_threshold_rad, device->imu_cycles_per_s);\n                                    if (!isfinite(alpha) || alpha <= 0.0f) {\n                                        dead_zone_quat = current_quat;\n                                    } else {\n                                        dead_zone_quat = quat_slerp(dead_zone_quat, current_quat, alpha);\n                                    }\n                                }\n                            }\n                        }\n\n                        // Overwrite quaternions with smoothed orientation (timestamps left unchanged).\n                        response->data[0] = dead_zone_quat.x;\n                        response->data[1] = dead_zone_quat.y;\n                        response->data[2] = dead_zone_quat.z;\n                        response->data[3] = dead_zone_quat.w;\n                        response->data[4] = dead_zone_quat.x;\n                        response->data[5] = dead_zone_quat.y;\n                        response->data[6] = dead_zone_quat.z;\n                        response->data[7] = dead_zone_quat.w;\n                        response->data[8] = dead_zone_quat.x;\n                        response->data[9] = dead_zone_quat.y;\n                        response->data[10] = dead_zone_quat.z;\n                        response->data[11] = dead_zone_quat.w;\n                    }\n\n                    pthread_mutex_lock(ipc_values->pose_orientation_mutex);\n\n                    memcpy(ipc_values->pose_orientation, response->data, sizeof(float) * 16);\n                    memcpy(ipc_values->pose_position, &pose.position, sizeof(float) * 3);\n                    // trigger flush on just the last write\n                    set_skippable_gamescope_reshade_effect_uniform_variable(\"pose_orientation\", ipc_values->pose_orientation, 16, sizeof(float), false);\n                    set_skippable_gamescope_reshade_effect_uniform_variable(\"pose_position\", ipc_values->pose_position, 3, sizeof(float), true);\n\n                    pthread_mutex_unlock(ipc_values->pose_orientation_mutex);\n                }\n                free(response);\n            }\n        }\n\n        int x_velocity;\n        int y_velocity;\n        int next_joystick_x;\n        int next_joystick_y;\n        bool do_joystick_debug = config()->debug_joystick && (imu_counter % joystick_debug_imu_cycles) == 0;\n        if (uinput || do_joystick_debug) {\n            // tracking head movements in euler (roll, pitch, yaw) against 2d joystick/mouse (x,y) coordinates means that yaw\n            // maps to horizontal movements (x) and pitch maps to vertical (y) movements. Because the euler values use a NWU\n            // coordinate system, positive yaw/pitch values move left/down, respectively, and the mouse/joystick coordinate\n            // systems are right-down, so a positive yaw should result in a negative x, and a positive pitch should result in a\n            // positive y.\n            x_velocity = config()->vr_lite_invert_x ? velocities.yaw : -velocities.yaw;\n            y_velocity = config()->vr_lite_invert_y ? -velocities.pitch : velocities.pitch;\n            next_joystick_x = joystick_value(x_velocity, joystick_max_degrees_per_s);\n            next_joystick_y = joystick_value(y_velocity, joystick_max_degrees_per_s);\n        }\n\n        if (uinput) {\n            if (config()->joystick_mode) {\n                int next_joystick_z = joystick_value(-velocities.roll, joystick_max_degrees_per_s);\n                libevdev_uinput_write_event(uinput, EV_ABS, ABS_RX, next_joystick_x);\n                libevdev_uinput_write_event(uinput, EV_ABS, ABS_RY, next_joystick_y);\n                if (config()->use_roll_axis)\n                    libevdev_uinput_write_event(uinput, EV_ABS, ABS_RZ, next_joystick_z);\n            } else if (config()->mouse_mode) {\n                // keep track of the remainder (the amount that was lost with round()) for smoothing out mouse movements\n                static float mouse_x_remainder = 0.0;\n                static float mouse_y_remainder = 0.0;\n                static float mouse_z_remainder = 0.0;\n\n                // smooth out the mouse values using the remainders left over from previous writes\n                float mouse_sensitivity_seconds = (float) config()->mouse_sensitivity / device->imu_cycles_per_s;\n                float next_x = x_velocity * mouse_sensitivity_seconds + mouse_x_remainder;\n                int next_x_int = round(next_x);\n                mouse_x_remainder = next_x - next_x_int;\n\n                float next_y = y_velocity * mouse_sensitivity_seconds + mouse_y_remainder;\n                int next_y_int = round(next_y);\n                mouse_y_remainder = next_y - next_y_int;\n\n                float next_z = -velocities.roll * mouse_sensitivity_seconds + mouse_z_remainder;\n                int next_z_int = round(next_z);\n                mouse_z_remainder = next_z - next_z_int;\n\n                libevdev_uinput_write_event(uinput, EV_REL, REL_X, next_x_int);\n                libevdev_uinput_write_event(uinput, EV_REL, REL_Y, next_y_int);\n                if (config()->use_roll_axis)\n                    libevdev_uinput_write_event(uinput, EV_REL, REL_Z, next_z_int);\n            } else if (!config()->external_mode) {\n                log_error(\"Unsupported output mode: %s\\n\", config()->output_mode);\n            }\n\n            if (config()->mouse_mode || config()->joystick_mode)\n                libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);\n        }\n\n        // always use joystick debugging as it adds a helpful visual\n        if (do_joystick_debug)\n            joystick_debug(prev_joystick_x, prev_joystick_y, next_joystick_x, next_joystick_y);\n\n        prev_joystick_x = next_joystick_x;\n        prev_joystick_y = next_joystick_y;\n\n        plugins.handle_pose_data(pose, velocities, imu_calibrated, ipc_values);\n\n        // reset the counter every second\n        if ((++imu_counter % device->imu_cycles_per_s) == 0) {\n            imu_counter = 0;\n        }\n        pthread_mutex_unlock(&outputs_mutex);\n    }\n    device_checkin(device);\n}\n\nvoid reset_pose_data(ipc_values_type *ipc_values) {\n    if (ipc_values) {    \n        pthread_mutex_lock(ipc_values->pose_orientation_mutex);\n        memcpy(ipc_values->pose_orientation, pose_orientation_reset_data, sizeof(float) * 16);\n        memcpy(ipc_values->pose_position, pose_position_reset_data, sizeof(float) * 3);\n        pthread_mutex_unlock(ipc_values->pose_orientation_mutex);\n    }\n\n    plugins.reset_pose_data();\n}\n\nbool is_imu_alive() {\n    return get_epoch_time_ms() - last_healthy_imu_timestamp_ms < MS_PER_SEC;\n}"
  },
  {
    "path": "src/plugins/breezy_desktop.c",
    "content": "#include \"devices.h\"\n#include \"features/breezy_desktop.h\"\n#include \"logging.h\"\n#include \"plugins.h\"\n#include \"plugins/breezy_desktop.h\"\n#include \"plugins/custom_banner.h\"\n#include \"runtime_context.h\"\n#include \"state.h\"\n#include \"system.h\"\n#include \"epoch.h\"\n\n#include <inttypes.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/inotify.h>\n#include <unistd.h>\n\n#include <sys/stat.h>\n#include <sys/mman.h>\n#include <pthread.h>\n\n#define BREEZY_DESKTOP_FD_RESET -2\n\nconst char* shared_mem_directory = \"/dev/shm\";\nconst char* shared_mem_filename = \"breezy_desktop_imu\";\nconst int breezy_desktop_feature_count = 1;\nstatic bool has_started = false;\nstatic pthread_mutex_t file_mutex = PTHREAD_MUTEX_INITIALIZER;\n\nstatic int fd = BREEZY_DESKTOP_FD_RESET;\nstatic pthread_once_t shared_mem_path_once = PTHREAD_ONCE_INIT;\n\n#define NUM_ORIENTATION_VALUES 16\nfloat ORIENTATION_RESET[NUM_ORIENTATION_VALUES] = {\n        0.0, 0.0, 0.0, 1.0,\n        0.0, 0.0, 0.0, 1.0,\n        0.0, 0.0, 0.0, 1.0,\n        0.0, 0.0, 0.0, 0.0\n};\n\n#define NUM_POSITION_VALUES 3\nfloat POSITION_RESET[NUM_POSITION_VALUES] = {\n    0.0, 0.0, 0.0\n};\n\nbreezy_desktop_config *bd_config;\n\nvoid breezy_desktop_reset_config(breezy_desktop_config *config) {\n    config->enabled = false;\n    config->look_ahead_override = 0.0;\n    config->display_distance = 1.0;\n    config->display_size = 1.0;\n    config->sbs_content = false;\n    config->sbs_mode_stretched = false;\n};\n\nvoid *breezy_desktop_default_config_func() {\n    breezy_desktop_config *config = calloc(1, sizeof(breezy_desktop_config));\n    breezy_desktop_reset_config(config);\n\n    return config;\n};\n\nvoid breezy_desktop_handle_config_line_func(void* config, char* key, char* value) {\n    breezy_desktop_config* temp_config = (breezy_desktop_config*) config;\n\n    if (equal(key, \"external_mode\")) {\n        temp_config->enabled = list_string_contains(\"breezy_desktop\", value) && is_productivity_granted();\n    } else if (equal(key, \"display_distance\")) {\n        float_config(key, value, &temp_config->display_distance);\n    } else if (equal(key, \"display_size\")) {\n        float_config(key, value, &temp_config->display_size);\n    } else if (equal(key, \"sbs_content\")) {\n        boolean_config(key, value, &temp_config->sbs_content);\n    } else if (equal(key, \"sbs_mode_stretched\")) {\n        boolean_config(key, value, &temp_config->sbs_mode_stretched);\n    }\n};\n\nconst uint8_t DATA_LAYOUT_VERSION = 5;\n#define BOOL_TRUE 1\n#define BOOL_FALSE 0\n\n// IMU data is written more frequently, so we need to know the offset in the file\nconst int CONFIG_DATA_END_OFFSET =\n    sizeof(uint8_t) + // version\n    sizeof(uint8_t) + // enabled\n    sizeof(float) * 4 + // look_ahead_cfg\n    sizeof(uint32_t) * 2 + // display_res\n    sizeof(float) + // fov\n    sizeof(float) + // lens_distance_ratio\n    sizeof(uint8_t) + // sbs_enabled\n    sizeof(uint8_t); // custom_banner_enabled\n\nconst int IMU_RECORD_SIZE =\n    sizeof(uint8_t) + // smooth_follow_enabled\n    sizeof(float) * NUM_ORIENTATION_VALUES + // smooth_follow_origin (4 quaternion rows, 4 values each)\n    sizeof(float) * NUM_POSITION_VALUES + // pose_position\n    sizeof(uint64_t) + // imu_date_ms\n    sizeof(float) * NUM_ORIENTATION_VALUES + // pose_orientation (4 quaternion rows, 4 values each)\n    sizeof(uint8_t); // imu_parity_byte\n\nuint64_t last_config_write_ts = 0;\n\n// https://stackoverflow.com/a/12340725\nstatic int fd_is_valid(int fd) {\n    return fd >= 0 && (fcntl(fd, F_GETFD) != -1 || errno != EBADF);\n}\n\nstatic char* shared_mem_file_path = NULL;\nstatic void init_shared_mem_file_path() {\n    char buf[1024];\n    snprintf(buf, sizeof(buf), \"%s/%s\", shared_mem_directory, shared_mem_filename);\n    shared_mem_file_path = strdup(buf);\n}\nstatic char* get_shared_mem_file_path_once() {\n    pthread_once(&shared_mem_path_once, init_shared_mem_file_path);\n    return shared_mem_file_path;\n}\nstatic int full_write(int wfd, const void* buf, size_t len) {\n    const uint8_t *p = (const uint8_t*)buf;\n    while (len) {\n        ssize_t n = write(wfd, p, len);\n        if (n < 0) { if (errno == EINTR) continue; return -1; }\n        if (n == 0) { errno = EIO; return -1; }\n        p += (size_t)n; len -= (size_t)n;\n    }\n    return 0;\n}\n\nchar* get_shared_mem_file_path() { return get_shared_mem_file_path_once(); }\n\nstatic off_t expected_file_size() { return (off_t)(CONFIG_DATA_END_OFFSET + IMU_RECORD_SIZE); }\nstatic int create_or_open_shared_mem_file() {\n#ifndef O_CLOEXEC\n#define O_CLOEXEC 0\n#endif\n#ifndef O_NOFOLLOW\n#define O_NOFOLLOW 0\n#endif\n    char* path = get_shared_mem_file_path();\n    char shm_name[256];\n    snprintf(shm_name, sizeof(shm_name), \"/%s\", shared_mem_filename);\n    int new_fd = shm_open(shm_name, O_RDWR | O_CREAT | O_CLOEXEC, 0644);\n    if (new_fd == -1) {\n        new_fd = open(path, O_RDWR | O_CLOEXEC | O_CREAT | O_NOFOLLOW, 0644);\n        if (new_fd == -1) { log_error(\"breezy_desktop: open failed %s: %s\\n\", path, strerror(errno)); return -1; }\n    }\n    struct stat st; if (fstat(new_fd, &st) == -1) { log_error(\"breezy_desktop: fstat failed: %s\\n\", strerror(errno)); close(new_fd); return -1; }\n    off_t want = expected_file_size();\n    if (st.st_size != want) {\n        if (ftruncate(new_fd, want) == -1) { log_error(\"breezy_desktop: ftruncate(%lld) failed: %s\\n\", (long long)want, strerror(errno)); close(new_fd); return -1; }\n        if (lseek(new_fd, 0, SEEK_SET) != -1) {\n            size_t sz = (size_t)want; uint8_t *zero = calloc(1, sz);\n            if (zero) { if (full_write(new_fd, zero, sz) == -1) log_error(\"breezy_desktop: zero init write failed: %s\\n\", strerror(errno)); free(zero);} else log_error(\"breezy_desktop: calloc zero init failed\\n\");\n        }\n    }\n    return new_fd;\n}\nstatic int get_shared_mem_fd() {\n    if (!fd_is_valid(fd)) fd = BREEZY_DESKTOP_FD_RESET;\n    if (fd == BREEZY_DESKTOP_FD_RESET) {\n        int new_fd = create_or_open_shared_mem_file();\n        if (new_fd != -1) fd = new_fd;\n    }\n    return fd;\n}\n\nvoid do_write_config_data(int target_fd) {\n    if (!bd_config) bd_config = breezy_desktop_default_config_func();\n    if (lseek(target_fd, 0, SEEK_SET) == -1) {\n        int first_err = errno;\n        if (first_err == EBADF) {\n            // Attempt single reopen and retry\n            fd = BREEZY_DESKTOP_FD_RESET;\n            int new_fd = get_shared_mem_fd();\n            if (new_fd != -1) {\n                target_fd = new_fd;\n                if (lseek(target_fd, 0, SEEK_SET) == -1) {\n                    log_error(\"lseek config retry failed: %s\\n\", strerror(errno));\n                    goto error;\n                }\n            } else {\n                log_error(\"reopen after EBADF failed: %s\\n\", strerror(first_err));\n                goto error;\n            }\n        } else {\n            log_error(\"lseek config: %s\\n\", strerror(first_err));\n            goto error;\n        }\n    }\n    uint8_t enabled = BOOL_FALSE;\n    if (full_write(target_fd, &DATA_LAYOUT_VERSION, sizeof(uint8_t)) == -1) goto error;\n    device_properties_type* device = device_checkout();\n    if (device) {\n        enabled = (!config()->disabled && bd_config->enabled) ? BOOL_TRUE : BOOL_FALSE;\n        float look_ahead_cfg[4] = { device->look_ahead_constant, device->look_ahead_frametime_multiplier, device->look_ahead_scanline_adjust, device->look_ahead_ms_cap };\n        int display_res[2] = { device->resolution_w, device->resolution_h };\n        uint8_t sbs_enabled = state()->sbs_mode_enabled ? BOOL_TRUE : BOOL_FALSE;\n        uint8_t custom_banner_enabled = (custom_banner_ipc_values && custom_banner_ipc_values->enabled && *custom_banner_ipc_values->enabled) ? BOOL_TRUE : BOOL_FALSE;\n        if (full_write(target_fd, &enabled, sizeof(uint8_t)) == -1) goto error;\n        if (full_write(target_fd, look_ahead_cfg, sizeof(float) * 4) == -1) goto error;\n        if (full_write(target_fd, display_res, sizeof(uint32_t) * 2) == -1) goto error;\n        if (full_write(target_fd, &device->fov, sizeof(float)) == -1) goto error;\n        if (full_write(target_fd, &device->lens_distance_ratio, sizeof(float)) == -1) goto error;\n        if (full_write(target_fd, &sbs_enabled, sizeof(uint8_t)) == -1) goto error;\n        if (full_write(target_fd, &custom_banner_enabled, sizeof(uint8_t)) == -1) goto error;\n    } else {\n        if (full_write(target_fd, &enabled, sizeof(uint8_t)) == -1) goto error;\n        const int remaining = CONFIG_DATA_END_OFFSET - (int)(sizeof(uint8_t) * 2);\n        uint8_t *zero_data = calloc(1, remaining);\n        if (!zero_data) { log_error(\"breezy_desktop: calloc zero config failed\\n\"); goto error; }\n        if (full_write(target_fd, zero_data, remaining) == -1) { free(zero_data); goto error; }\n        free(zero_data);\n    }\n    device_checkin(device);\n    last_config_write_ts = get_epoch_time_ms();\n    return;\nerror:\n    log_error(\"breezy_desktop: config write failed: %s\\n\", strerror(errno));\n    fd = BREEZY_DESKTOP_FD_RESET;\n}\n\nvoid write_config_data() {\n    if (fd_is_valid(fd) || bd_config && bd_config->enabled) {\n        pthread_mutex_lock(&file_mutex);\n        if (!fd_is_valid(fd)) (void)get_shared_mem_fd();\n        if (fd_is_valid(fd)) do_write_config_data(fd);\n        pthread_mutex_unlock(&file_mutex);\n    }\n}\n\nvoid breezy_desktop_write_pose_data(float *orientation, float *position) {\n    pthread_mutex_lock(&file_mutex);\n    int wfd = get_shared_mem_fd();\n    if (wfd != -1) {\n        uint64_t epoch_ms = get_epoch_time_ms();\n        if (last_config_write_ts == 0 || epoch_ms - last_config_write_ts > 250) {\n            do_write_config_data(wfd);\n            if (fd == BREEZY_DESKTOP_FD_RESET) { pthread_mutex_unlock(&file_mutex); return; }\n        }\n        if (lseek(wfd, CONFIG_DATA_END_OFFSET, SEEK_SET) == -1) {\n            log_error(\"breezy_desktop: lseek imu: %s\\n\", strerror(errno)); goto imu_error; }\n        uint8_t smooth_follow_enabled = state()->breezy_desktop_smooth_follow_enabled ? BOOL_TRUE : BOOL_FALSE;\n        if (full_write(wfd, &smooth_follow_enabled, sizeof(uint8_t)) == -1) goto imu_error;\n        if (state()->smooth_follow_origin_ready && state()->smooth_follow_origin) {\n            if (full_write(wfd, state()->smooth_follow_origin, sizeof(float) * NUM_ORIENTATION_VALUES) == -1) goto imu_error;\n        } else if (full_write(wfd, orientation, sizeof(float) * NUM_ORIENTATION_VALUES) == -1) goto imu_error;\n        if (full_write(wfd, position, sizeof(float) * NUM_POSITION_VALUES) == -1) goto imu_error;\n        if (full_write(wfd, &epoch_ms, sizeof(uint64_t)) == -1) goto imu_error;\n        if (full_write(wfd, orientation, sizeof(float) * NUM_ORIENTATION_VALUES) == -1) goto imu_error;\n        uint8_t parity = 0; uint8_t* d = (uint8_t*)&epoch_ms; for (size_t i=0;i<sizeof(uint64_t);++i) parity ^= d[i];\n        d = (uint8_t*)orientation; for (size_t i=0;i<sizeof(float)*NUM_ORIENTATION_VALUES;++i) parity ^= d[i];\n        if (full_write(wfd, &parity, sizeof(uint8_t)) == -1) goto imu_error;\n        pthread_mutex_unlock(&file_mutex); return;\n    }\nimu_error:\n    if (errno) log_error(\"breezy_desktop: imu write failed: %s\\n\", strerror(errno));\n    if (fd_is_valid(wfd)) { close(wfd); fd = BREEZY_DESKTOP_FD_RESET; }\n    pthread_mutex_unlock(&file_mutex);\n}\n\nvoid breezy_desktop_reset_pose_data_func() {\n    if (fd_is_valid(fd) || bd_config && bd_config->enabled) {\n        breezy_desktop_write_pose_data(&ORIENTATION_RESET[0], &POSITION_RESET[0]);\n    }\n}\n\nvoid breezy_desktop_set_config_func(void* new_config) {\n    if (!new_config) return;\n    \n    breezy_desktop_config* temp_config = (breezy_desktop_config*) new_config;\n    if (bd_config) {\n        if (bd_config->enabled != temp_config->enabled)\n            log_message(\"Breezy desktop has been %s\\n\", temp_config->enabled ? \"enabled\" : \"disabled\");\n        free(bd_config);\n    }\n    bd_config = temp_config;\n    if (has_started) {\n        write_config_data();\n        if (state()->calibration_state == CALIBRATING) breezy_desktop_reset_pose_data_func();\n    }\n};\n\nvoid breezy_desktop_handle_pose_data_func(imu_pose_type pose, imu_euler_type velocities, bool imu_calibrated, ipc_values_type *ipc_values) {\n    if (bd_config && bd_config->enabled) {\n        if (imu_calibrated && ipc_values) {\n            breezy_desktop_write_pose_data(ipc_values->pose_orientation, \n                is_productivity_pro_granted() ? ipc_values->pose_position : &POSITION_RESET[0]);\n        } else {\n            breezy_desktop_reset_pose_data_func();\n        }\n    }\n}\n\nvoid breezy_desktop_start_func() {\n    pthread_mutex_init(&file_mutex, NULL);\n}\n\nvoid breezy_desktop_device_connect_func() {\n    pthread_mutex_lock(&file_mutex);\n    if (fd_is_valid(fd)) close(fd);\n    fd = BREEZY_DESKTOP_FD_RESET;\n    pthread_mutex_unlock(&file_mutex);\n    has_started = true;\n    write_config_data();\n    breezy_desktop_reset_pose_data_func();\n}\n\nconst plugin_type breezy_desktop_plugin = {\n    .id = \"breezy_desktop\",\n    .start = breezy_desktop_start_func,\n    .default_config = breezy_desktop_default_config_func,\n    .handle_config_line = breezy_desktop_handle_config_line_func,\n    .set_config = breezy_desktop_set_config_func,\n    .handle_pose_data = breezy_desktop_handle_pose_data_func,\n    .reset_pose_data = breezy_desktop_reset_pose_data_func,\n    .handle_device_disconnect = write_config_data,\n    .handle_device_connect = breezy_desktop_device_connect_func\n};"
  },
  {
    "path": "src/plugins/custom_banner.c",
    "content": "#include \"custom_banner_config.h\"\n#include \"plugins/custom_banner.h\"\n#include \"plugins/gamescope_reshade_wayland.h\"\n#include \"ipc.h\"\n#include \"runtime_context.h\"\n\n#include <stdlib.h>\n#include <time.h>\n\nconst uint32_t banner_start_date = CUSTOM_BANNER_START_DATE;\nconst uint32_t banner_end_date = CUSTOM_BANNER_END_DATE;\nconst int target_device_vendor_id = CUSTOM_BANNER_TARGET_DEVICE_VENDOR_ID;\nconst int target_device_product_id = CUSTOM_BANNER_TARGET_DEVICE_PRODUCT_ID;\n\ncustom_banner_ipc_values_type *custom_banner_ipc_values;\nvoid evaluate_banner_conditions() {\n    device_properties_type* device = device_checkout();\n    if (device != NULL) {\n        if (custom_banner_ipc_values) {\n            bool any_conditions_set = false;\n            bool banner_device_conditions_met = true;\n            if (target_device_vendor_id != 0) {\n                any_conditions_set = true;\n                banner_device_conditions_met = device->hid_vendor_id == target_device_vendor_id;\n                if (target_device_product_id != 0) {\n                    banner_device_conditions_met &= device->hid_product_id == target_device_product_id;\n                }\n            }\n\n            bool banner_time_conditions_met = true;\n            time_t now = time(NULL);\n            if (banner_start_date != 0) {\n                any_conditions_set = true;\n                banner_time_conditions_met = now > banner_start_date;\n            }\n            if (banner_end_date != 0) {\n                any_conditions_set = true;\n                banner_time_conditions_met &= now < banner_end_date;\n            }\n\n            *custom_banner_ipc_values->enabled = any_conditions_set && banner_device_conditions_met && banner_time_conditions_met;\n        }\n    }\n    set_gamescope_reshade_effect_uniform_variable(\"custom_banner_enabled\", custom_banner_ipc_values->enabled, 1, sizeof(bool), false);\n    device_checkin(device);\n}\n\nconst char *custom_banner_enabled_name = \"custom_banner_enabled\";\n\nbool custom_banner_setup_ipc_func() {\n    bool debug = config()->debug_ipc;\n    if (!custom_banner_ipc_values) custom_banner_ipc_values = calloc(1, sizeof(custom_banner_ipc_values_type));\n    setup_ipc_value(custom_banner_enabled_name, (void**) &custom_banner_ipc_values->enabled, sizeof(bool), debug);\n\n    evaluate_banner_conditions();\n\n    return true;\n}\n\nvoid custom_banner_handle_device_connect_func() {\n    evaluate_banner_conditions();\n};\n\nvoid custom_banner_reset_pose_data_func() {\n    evaluate_banner_conditions();\n};\n\nconst plugin_type custom_banner_plugin = {\n    .id = \"custom_banner\",\n    .setup_ipc = custom_banner_setup_ipc_func,\n    .reset_pose_data = custom_banner_reset_pose_data_func,\n    .handle_device_connect = custom_banner_handle_device_connect_func\n};"
  },
  {
    "path": "src/plugins/device_license.c",
    "content": "#include \"curl.h\"\n#include \"features/breezy_desktop.h\"\n#include \"features/sbs.h\"\n#include \"features/smooth_follow.h\"\n#include \"files.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"plugins/device_license.h\"\n#include \"runtime_context.h\"\n#include \"strings.h\"\n#include \"system.h\"\n\n#include <curl/curl.h>\n#include <json-c/json.h>\n#include <openssl/evp.h>\n#include <openssl/pem.h>\n#include <openssl/bio.h>\n#include <openssl/err.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n\n#define SECONDS_PER_DAY 86400\n\nconst char* DEVICE_LICENSE_FILE_NAME = \"%.8s_license.json\";\nconst char* DEVICE_LICENSE_TEMP_FILE_NAME = \"license.tmp.json\";\n\n// Declare mutexes early so they can be used in helper functions\npthread_mutex_t refresh_license_lock = PTHREAD_MUTEX_INITIALIZER;\n\n// Helper function to check if all requested features are present in the license\nbool all_features_in_license(char** requested_features, int requested_count) {\n    if (requested_count == 0) return true;\n    \n    pthread_mutex_lock(&refresh_license_lock);\n    bool result = true;\n    \n    if (!state()->license_features || state()->license_features_count == 0) {\n        result = false;\n    } else {\n        for (int i = 0; i < requested_count; i++) {\n            if (!in_array(requested_features[i], (const char**)state()->license_features, state()->license_features_count)) {\n                result = false;\n                break;\n            }\n        }\n    }\n    \n    pthread_mutex_unlock(&refresh_license_lock);\n    return result;\n}\n\n#ifdef DEVICE_LICENSE_PUBLIC_KEY\n    char* postbody(char* hardwareId, char** features, int features_count) {\n        json_object *root = json_object_new_object();\n        json_object_object_add(root, \"hardwareId\", json_object_new_string(hardwareId));\n        json_object *featuresArray = json_object_new_array();\n        if (features && features_count > 0) {\n            for (int i = 0; i < features_count; i++) {\n                if (features[i]) {\n                    json_object_array_add(featuresArray, json_object_new_string(features[i]));\n                }\n            }\n        }\n        json_object_object_add(root, \"features\", featuresArray);\n        const char* json_str = json_object_to_json_string(root);\n        char* result = strdup(json_str);\n        json_object_put(root);\n        return result;\n    }\n\n    bool is_valid_license_signature(const char* license, const char* signature) {\n        if (!license || !signature) {\n            log_error(\"License or signature is NULL.\\n\");\n            return false;\n        }\n\n        BIO *bio = BIO_new_mem_buf((void*)DEVICE_LICENSE_PUBLIC_KEY, -1);\n        if (!bio) {\n            log_error(\"Error creating BIO for public key.\\n\");\n            ERR_print_errors_fp(stderr);\n            return false;\n        }\n\n        EVP_PKEY *publicKey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);\n        BIO_free(bio);\n        if (!publicKey) {\n            log_error(\"Error reading the public key.\\n\");\n            ERR_print_errors_fp(stderr);\n            return false;\n        }\n\n        EVP_MD_CTX *mdctx = EVP_MD_CTX_new();\n        if (!mdctx) {\n            log_error(\"Failed to create the EVP_MD_CTX structure.\\n\");\n            ERR_print_errors_fp(stderr);\n            return false;\n        }\n\n        if (1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, publicKey)) {\n            log_error(\"Failed to initialize the digest context for verification.\\n\");\n            ERR_print_errors_fp(stderr);\n            return false;\n        }\n\n        if (1 != EVP_DigestVerifyUpdate(mdctx, license, strlen((char*)license))) {\n            log_error(\"Failed to update the digest context.\\n\");\n            ERR_print_errors_fp(stderr);\n            return false;\n        }\n\n        // Convert the signature from hex string to binary\n        int sig_len = strlen(signature) / 2;\n        unsigned char* binary_sig = calloc(1, sig_len);\n        for (int i = 0; i < sig_len; i++) {\n            unsigned int temp;\n            sscanf(signature + 2*i, \"%02x\", &temp);\n            binary_sig[i] = temp;\n        }\n\n        int result = EVP_DigestVerifyFinal(mdctx, binary_sig, sig_len);\n        free(binary_sig);\n        binary_sig = NULL;\n\n        if (result == 0) {\n            log_error(\"Signature is not valid.\\n\");\n        } else if (result != 1) {\n            log_error(\"Error occurred while checking the signature.\\n\");\n            ERR_print_errors_fp(stderr);\n        }\n\n        EVP_MD_CTX_free(mdctx);\n        EVP_PKEY_free(publicKey);\n\n        return result == 1;\n    }\n\n\n    bool get_license_features(FILE* file, char*** granted_features, int* granted_features_count, char*** all_features, int* all_features_count) {\n        fseek(file, 0, SEEK_END);\n        long length = ftell(file);\n        fseek(file, 0, SEEK_SET);\n        char* buffer = calloc(1, length);\n        if (buffer) {\n            fread(buffer, 1, length, file);\n        }\n\n        json_object *root = json_tokener_parse(buffer);\n        free(buffer);\n        buffer = NULL;\n\n        // check for the \"message\" property, indicating an error from the server\n        json_object *message;\n        json_object_object_get_ex(root, \"message\", &message);\n        if (message) {\n            log_error(\"Error from server: %s\\n\", json_object_get_string(message));\n            json_object_put(root);\n            return false;\n        }\n\n        json_object *license;\n        json_object_object_get_ex(root, \"license\", &license);\n        json_object *signature;\n        json_object_object_get_ex(root, \"signature\", &signature);\n\n        int transient_granted_count = 0;\n        int transient_all_features_count = 0;\n        bool valid_license = false;\n        if (is_valid_license_signature(json_object_get_string(license), json_object_get_string(signature))) {\n            json_object *license_root = json_tokener_parse(json_object_get_string(license));\n            json_object *hardwareId;\n            json_object_object_get_ex(license_root, \"hardwareId\", &hardwareId);\n            if (strcmp(json_object_get_string(hardwareId), get_hardware_id()) == 0) {\n                valid_license = true;\n                free_and_clear(&state()->device_license);\n                state()->device_license = strdup(json_object_get_string(license));\n\n                json_object *features_root;\n                json_object_object_get_ex(license_root, \"features\", &features_root);\n                if (features_root) {\n                    json_object_object_foreach(features_root, featureName, val) {\n                        json_object *featureObject;\n                        json_object_object_get_ex(features_root, featureName, &featureObject);\n                        json_object *featureStatusObject;\n                        json_object_object_get_ex(featureObject, \"status\", &featureStatusObject);\n                        const char* featureStatus = json_object_get_string(featureStatusObject);\n                        json_object *featureEndDate;\n                        json_object_object_get_ex(featureObject, \"endDate\", &featureEndDate);\n\n                        // Add all features to the license features list\n                        char** temp = realloc(*all_features, (transient_all_features_count + 1) * sizeof(char*));\n                        if (!temp) {\n                            log_error(\"Failed to allocate memory for license features\\n\");\n                            continue;\n                        }\n                        *all_features = temp;\n                        char* feature_copy = strdup(featureName);\n                        if (!feature_copy) {\n                            log_error(\"Failed to allocate memory for feature name\\n\");\n                            continue;\n                        }\n                        (*all_features)[transient_all_features_count++] = feature_copy;\n\n                        // if status is \"on\" or \"trial\" and the current system time is not past the endDate, add to the granted features array\n                        bool enabled = false;\n                        if (strcmp(featureStatus, \"on\") == 0 || strcmp(featureStatus, \"trial\") == 0) {\n                            struct timeval tv;\n                            gettimeofday(&tv, NULL);\n                            if (!featureEndDate || json_object_get_int(featureEndDate) > tv.tv_sec) {\n                                char** granted_temp = realloc(*granted_features, (transient_granted_count + 1) * sizeof(char*));\n                                if (!granted_temp) {\n                                    log_error(\"Failed to allocate memory for granted features\\n\");\n                                } else {\n                                    *granted_features = granted_temp;\n                                    char* granted_copy = strdup(featureName);\n                                    if (!granted_copy) {\n                                        log_error(\"Failed to allocate memory for granted feature name\\n\");\n                                    } else {\n                                        (*granted_features)[transient_granted_count++] = granted_copy;\n                                        enabled = true;\n                                    }\n                                }\n                            }\n                        }\n                        log_message(\"Feature %s %s.\\n\", featureName, enabled ? \"granted\" : \"denied\");\n                    }\n                }\n            } else {\n                if (config() && config()->debug_license) {\n                    log_debug(\"License hardwareId mismatch;\\n\\t\\treceived: %s\\n\\t\\texpected: %s\\n\",\n                        json_object_get_string(hardwareId), get_hardware_id());\n                }\n            }\n            json_object_put(license_root);\n        }\n        json_object_put(root);\n\n        *granted_features_count = transient_granted_count;\n        *all_features_count = transient_all_features_count;\n        return valid_license;\n    }\n#endif\n\n\n\nvoid refresh_license(bool force, char** requested_features, int requested_features_count) {\n    int granted_count = 0;\n    char** granted_features = NULL;\n    int all_features_count = 0;\n    char** all_features = NULL;\n\n    #ifdef DEVICE_LICENSE_PUBLIC_KEY\n        char* hw_id = get_hardware_id();\n        if (hw_id) {\n            pthread_mutex_lock(&refresh_license_lock);\n\n            // prefix the license file name with the hardware id we can still have this one saved in \n            // the case where it changes in the future, which can happen due to network interface ordering or\n            // startup sequence timing\n            char* file_name = malloc(strlen(hw_id) + strlen(DEVICE_LICENSE_FILE_NAME));\n            sprintf(file_name, DEVICE_LICENSE_FILE_NAME, hw_id);\n            const char* device_license_path = get_state_file_path(file_name);\n            free(file_name);\n            const char* device_license_path_tmp = get_state_file_path(DEVICE_LICENSE_TEMP_FILE_NAME);\n\n            int attempt = 0;\n            bool valid_license = false;\n            bool debug_license = config() && config()->debug_license;\n            while (!valid_license && attempt < 2) {\n                if (debug_license) log_debug(\"Attempt %d to refresh license\\n\", attempt);\n                char* file_path = strdup(device_license_path);\n                FILE *file = force ? NULL : fopen(file_path, \"r\");\n                if (file) {\n                    if (debug_license) log_debug(\"License file already exists\\n\");\n                    // remove the file if it hasn't been touched in over a day\n                    struct stat attr;\n                    stat(device_license_path, &attr);\n                    struct timeval tv;\n                    gettimeofday(&tv, NULL);\n                    if (tv.tv_sec - attr.st_mtime > SECONDS_PER_DAY) {\n                        // do this to force a refresh\n                        fclose(file);\n                        file = NULL;\n                        if (debug_license) log_debug(\"License file is 1 day old, attempting to refresh it\\n\");\n                    }\n                }\n\n                if (file == NULL) {\n                    free(file_path);\n                    file_path = strdup(device_license_path_tmp);\n\n                    CURL *curl;\n                    CURLcode res;\n                    struct curl_slist *headers = NULL;\n\n                    curl_init();\n                    curl = curl_easy_init();\n                    if(curl) {\n                        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);\n                        file = get_or_create_file(file_path, 0777, \"w\", NULL);\n                        if (file == NULL) {\n                            log_error(\"Error opening file (%s): %d\\n\", file_path, errno);\n                            break;\n                        }\n\n                        curl_easy_setopt(curl, CURLOPT_URL, \"https://eu.driver-backend.xronlinux.com/licenses/v1\");\n                        char* postbody_string = postbody(get_hardware_id(), requested_features, requested_features_count);\n                        if (debug_license) log_debug(\"License curl with postbody %s\\n\", postbody_string);\n                        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postbody_string);\n\n                        headers = curl_slist_append(headers, \"Content-Type: application/json\");\n                        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);\n\n                        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);\n                        curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);\n\n                        long http_code = 0;\n                        CURLcode res = curl_easy_perform(curl);\n\n                        bool failed = false;\n                        if(res != CURLE_OK) {\n                            failed = true;\n                            log_error(\"curl_easy_perform() failed: %s\\n\", curl_easy_strerror(res));\n                        } else {\n                            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);\n                            if(http_code != 200) {\n                                failed = true;\n                                log_error(\"Unexpected HTTP response: %ld\\n\", http_code);\n                                res = CURLE_HTTP_RETURNED_ERROR;\n                            }\n                        }\n\n                        fclose(file);\n                        if(failed) {\n                            remove(file_path);\n                            free(file_path);\n                            file_path = strdup(device_license_path);\n                        }\n\n                        free(postbody_string);\n                        curl_easy_cleanup(curl);\n                    }\n\n                    // Reopen the file\n                    file = fopen(file_path, \"r\");\n                    if (file == NULL) {\n                        free(file_path);\n                        log_error(\"Error opening file (%s): %d\\n\", file_path, errno);\n                        break;\n                    }\n                }\n\n                valid_license = get_license_features(file, &granted_features, &granted_count, &all_features, &all_features_count);\n                fclose(file);\n                if (valid_license) {\n                    if (strcmp(file_path, device_license_path_tmp) == 0) {\n                        rename(file_path, device_license_path);\n                    }\n                } else {\n                    remove(file_path);\n                }\n                free(file_path);\n                attempt++;\n            }\n            pthread_mutex_unlock(&refresh_license_lock);\n\n            free((void*)device_license_path);\n            free((void*)device_license_path_tmp);\n        } else {\n            log_error(\"No hardwareId found, not retrieving license\\n\");\n        }\n    #endif\n\n    pthread_mutex_lock(&refresh_license_lock);\n    free_string_array(state()->granted_features, state()->granted_features_count);\n    state()->granted_features = granted_features;\n    state()->granted_features_count = granted_count;\n\n    // granted_features has changed; clear cached feature checks\n    reset_productivity_features();\n    reset_sbs_features();\n    reset_smooth_follow_features();\n    \n    free_string_array(state()->license_features, state()->license_features_count);\n    state()->license_features = all_features;\n    state()->license_features_count = all_features_count;\n    pthread_mutex_unlock(&refresh_license_lock);\n}\n\nvoid device_license_start_func() {\n    refresh_license(false, NULL, 0);\n}\n\nvoid device_license_handle_control_flag_line_func(char* key, char* value) {\n    if (strcmp(key, \"refresh_device_license\") == 0) {\n        if (strcmp(value, \"true\") == 0) refresh_license(true, NULL, 0);\n    } else if (strcmp(key, \"request_features\") == 0) {\n        // Parse the comma-separated features string\n        char** requested_features = NULL;\n        int requested_count = parse_comma_separated_string(value, &requested_features);\n\n        // Check if all requested features are present in the license\n        if (requested_count > 0 && !all_features_in_license(requested_features, requested_count)) {\n            refresh_license(true, requested_features, requested_count);\n        }\n        \n        free_string_array(requested_features, requested_count);\n    }\n}\n\nvoid device_license_handle_device_connect_func() {\n    refresh_license(false, NULL, 0);\n}\n\nconst plugin_type device_license_plugin = {\n    .id = \"device_license\",\n    .start = device_license_start_func,\n    .handle_control_flag_line = device_license_handle_control_flag_line_func,\n    .handle_device_connect = device_license_handle_device_connect_func\n};"
  },
  {
    "path": "src/plugins/gamescope_reshade_wayland.c",
    "content": "#include \"epoch.h\"\n#include \"files.h\"\n#include \"imu.h\"\n#include \"logging.h\"\n#include \"plugins/gamescope_reshade_wayland.h\"\n#include \"runtime_context.h\"\n#include \"strings.h\"\n#include \"wl_client/gamescope_reshade.h\"\n\n#include <errno.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <unistd.h>\n#include <string.h>\n#include <pthread.h>\n\n/**\n * The wayland-client library may not be present, so we create a weak reference to wl_proxy_create just\n * for the sake of checking if the library is linked. All function calls should be preceeded by a check\n * for the presence of wl_proxy_create or the presence of the reshade_object (which implies the presence \n * of the former has already succeeded previously).\n */\n#include <wayland-client.h>\n__attribute__((weak)) struct wl_proxy *wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface);\n\n#define GAMESCOPE_RESHADE_INTERFACE_NAME \"gamescope_reshade\"\n#define GAMESCOPE_RESHADE_EFFECT_FILE \"Sombrero.frag\"\n#define GAMESCOPE_RESHADE_EFFECT_PATH \"reshade/Shaders/\" GAMESCOPE_RESHADE_EFFECT_FILE\n#define GAMESCOPE_RESHADE_WAIT_TIME_MS 500\n\nstatic gamescope_reshade_wayland_config *gamescope_config;\nstatic struct wl_display *display = NULL;\nstatic struct wl_registry *registry = NULL;\nstatic struct gamescope_reshade *reshade_object = NULL;\nstatic gamescope_reshade_effect_ready_callback effect_ready_callback = NULL;\nstatic uint64_t gamescope_reshade_effect_request_time = 0;\nstatic bool gamescope_reshade_ipc_connected = false;\nstatic pthread_mutex_t wayland_mutex = PTHREAD_MUTEX_INITIALIZER;\n\nvoid *gamescope_reshade_wayland_default_config_func() {\n    gamescope_reshade_wayland_config *config = calloc(1, sizeof(gamescope_reshade_wayland_config));\n    config->disabled = false;\n\n    return config;\n};\n\nvoid gamescope_reshade_wayland_handle_config_line_func(void* config, char* key, char* value) {\n    gamescope_reshade_wayland_config* temp_config = (gamescope_reshade_wayland_config*) config;\n\n    if (equal(key, \"gamescope_reshade_wayland_disabled\")) {\n        boolean_config(key, value, &temp_config->disabled);\n    }\n};\n\nvoid gamescope_reshade_wayland_set_config_func(void* config) {\n    if (!config) return;\n    gamescope_reshade_wayland_config* temp_config = (gamescope_reshade_wayland_config*) config;\n\n    if (gamescope_config) {\n        if (gamescope_config->disabled != temp_config->disabled)\n            log_message(\"Gamescope ReShade integration has been %s\\n\", temp_config->disabled ? \"disabled\" : \"enabled\");\n\n        free(gamescope_config);\n    }\n    gamescope_config = temp_config;\n};\n\nstatic char* sombrero_shader_file_path() {\n    static char* shader_file_path = NULL;\n    if (!shader_file_path)\n        shader_file_path = get_xdg_file_path_for_app(\"gamescope\", GAMESCOPE_RESHADE_EFFECT_PATH, XDG_DATA_ENV_VAR, XDG_DATA_FALLBACK_DIR);\n\n    return shader_file_path;\n}\n\nstatic bool sombrero_file_exists() {\n    return access(sombrero_shader_file_path(), F_OK) != -1;\n}\n\nstatic void gamescope_reshade_wl_handle_global(void *data, struct wl_registry *registry,\n                       uint32_t name, const char *interface, uint32_t version) {\n    if (config()->debug_ipc) log_debug(\"gamescope_reshade_wl_handle_global %s\\n\", interface);\n    if (strcmp(interface, GAMESCOPE_RESHADE_INTERFACE_NAME) == 0) {\n        reshade_object = wl_registry_bind(registry, name, \n                                          &gamescope_reshade_interface, version);\n    }\n}\n\nbool is_gamescope_reshade_ipc_connected() {\n    return gamescope_reshade_ipc_connected;\n}\n\nstatic void do_wl_server_disconnect() {\n    gamescope_reshade_ipc_connected = false;\n    if (config()->debug_ipc) log_debug(\"gamescope_reshade_wl_server_disconnect\\n\");\n    if (effect_ready_callback) effect_ready_callback = NULL;\n    if (reshade_object) {\n        gamescope_reshade_destroy(reshade_object);\n        reshade_object = NULL;\n    }\n    if (registry) {\n        wl_registry_destroy(registry);\n        registry = NULL;\n    }\n    if (display) {\n        wl_display_flush(display);\n        wl_display_disconnect(display);\n        display = NULL;\n    }\n}\n\nstatic bool do_wl_server_connect() {\n    if (gamescope_config->disabled || gamescope_reshade_ipc_connected) return false;\n\n    if (config()->debug_ipc) log_debug(\"gamescope_reshade_wl_server_connect\\n\");\n    if (wl_proxy_create == NULL) {\n        if (config()->debug_ipc)\n            log_debug(\"gamescope_reshade_wl_server_connect wayland-client library not present\\n\");\n        return false;\n    }\n\n    if (!display) display = wl_display_connect(\"gamescope-0\");\n    if (!display) {\n        if (config()->debug_ipc) log_debug(\"gamescope_reshade_wl_server_connect no display\\n\");\n        return false;\n    }\n    \n    if (!registry) registry = wl_display_get_registry(display);\n    if (!registry) {\n        if (config()->debug_ipc) log_debug(\"gamescope_reshade_wl_server_connect no registry\\n\");\n        wl_display_disconnect(display);\n        display = NULL;\n        return false;\n    }\n    \n    if (!reshade_object) {\n        static const struct wl_registry_listener registry_listener = {\n            .global = gamescope_reshade_wl_handle_global\n        };\n    \n        wl_registry_add_listener(registry, &registry_listener, NULL);\n        wl_display_roundtrip(display);\n    }\n\n    if (reshade_object) {\n        wl_display_dispatch_pending(display);\n        wl_display_flush(display);\n        int wl_display_error = wl_display_get_error(display);\n        if (wl_display_error != 0) {\n            if (config()->debug_ipc) \n                log_debug(\"gamescope_reshade_wl_server_connect wl_display_error: %d\\n\", wl_display_error);\n            do_wl_server_disconnect();\n            return false;\n        }\n\n        gamescope_reshade_set_effect(reshade_object, GAMESCOPE_RESHADE_EFFECT_FILE);\n        int wl_result = wl_display_flush(display);\n        if (wl_result < 0) {\n            log_error(\"gamescope_reshade_wl_server_connect error %d on wl_display_flush: %s\\n\", wl_result, strerror(errno));\n            do_wl_server_disconnect();\n            return false;\n        }\n\n        gamescope_reshade_effect_request_time = get_epoch_time_ms();\n        gamescope_reshade_ipc_connected = true;\n        return true;\n    } else {\n        if (config()->debug_ipc) log_debug(\"gamescope_reshade_wl_server_connect no reshade_object\\n\");\n        do_wl_server_disconnect();\n        return false;\n    }\n}\n\nstatic bool gamescope_reshade_wl_setup_ipc() {\n    if (config()->debug_ipc) log_debug(\"gamescope_reshade_wl_setup_ipc\\n\");\n\n    pthread_mutex_lock(&wayland_mutex);\n    do_wl_server_connect();\n    pthread_mutex_unlock(&wayland_mutex);\n\n    return true;\n}\n\nstatic bool do_wl_enable_gamescope_effect() {\n    if (!reshade_object) return false;\n\n    if (config()->debug_ipc) log_debug(\"enable_gamescope_effect\\n\");\n    gamescope_reshade_enable_effect(reshade_object);\n    wl_display_flush(display);\n    return true;\n}\n\nstatic bool do_wl_disable_gamescope_effect() {\n    if (!reshade_object) return false;\n    \n    if (config()->debug_ipc) log_debug(\"disable_gamescope_effect\\n\");\n    gamescope_reshade_disable_effect(reshade_object);\n    wl_display_flush(display);\n    \n    return true;\n}\n\nstatic bool plugins_ipc_change_call_in_progress = false;\n\n// must only be called from within the wayland mutex\nstatic void do_trigger_plugins_ipc_change() {\n    // prevent recursive calls to this function\n    if (plugins_ipc_change_call_in_progress) return;\n\n    plugins_ipc_change_call_in_progress = true;\n\n    // we're sending control to outside plugins which may trigger other calls to set unifrom variables,\n    // so we have to unlock the mutex to be safe and prevent deadlocks\n    pthread_mutex_unlock(&wayland_mutex);\n    plugins.handle_ipc_change();\n    pthread_mutex_lock(&wayland_mutex);\n\n    plugins_ipc_change_call_in_progress = false;\n}\n\nstatic void do_wl_cleanup() {\n    do_wl_disable_gamescope_effect();\n\n    // set this early so other plugins can check if it's connected and change runtime variables\n    // before the actual connection is closed\n    gamescope_reshade_ipc_connected = false;\n    state()->is_gamescope_reshade_ipc_connected = false;\n    do_trigger_plugins_ipc_change();\n    \n    do_wl_server_disconnect();\n    gamescope_reshade_effect_request_time = 0;\n}\n\nstatic void wayland_cleanup() {\n    if (config()->debug_ipc) log_debug(\"wayland_cleanup\\n\");\n\n    pthread_mutex_lock(&wayland_mutex);\n    do_wl_cleanup();\n    pthread_mutex_unlock(&wayland_mutex);\n}\n\nstatic bool do_wl_set_uniform_variable(const char *variable_name, const void *data, int entries, \n                                       size_t element_size, bool flush) {\n    if (!reshade_object) return false;\n\n    struct wl_array array;\n    wl_array_init(&array);\n    size_t total_size = entries * element_size;\n    void *array_data = wl_array_add(&array, total_size);\n    if (!array_data) {\n        wl_array_release(&array);\n        return false;\n    }\n    memcpy(array.data, data, total_size);\n\n    gamescope_reshade_set_uniform_variable(reshade_object, variable_name, &array);\n    wl_array_release(&array);\n\n    if (flush) {\n        int wl_result;\n        if (effect_ready_callback) {\n            // this is a blocking call, so only use it if we're waiting on an event callback\n            wl_result = wl_display_roundtrip(display);\n        } else {\n            wl_result = wl_display_flush(display);\n        }\n\n        if (wl_result < 0) {\n            log_error(\"Error %d on gamescope wl_display_flush: %s\\n\", wl_result, strerror(errno));\n            return false;\n        }\n    }\n    \n    return true;\n}\n\nstatic void _effect_ready_callback(void *data,\n                                   struct gamescope_reshade *gamescope_reshade,\n                                   const char *effect_path) {\n    if (config()->debug_ipc) log_debug(\"_effect_ready_callback: %s\\n\", effect_path);\n    if (effect_ready_callback && equal(effect_path, GAMESCOPE_RESHADE_EFFECT_FILE)) {\n        effect_ready_callback();\n        effect_ready_callback = NULL;\n    }\n}\n\nstatic bool do_wl_add_gamescope_effect_ready_listener(gamescope_reshade_effect_ready_callback callback) {\n    if (!reshade_object) return false;\n\n    effect_ready_callback = callback;\n    static const struct gamescope_reshade_listener listener = {\n        .effect_ready = _effect_ready_callback\n    };\n\n    gamescope_reshade_add_listener(reshade_object, &listener, NULL);\n    \n    return true;\n}\n\nstatic void _gamescope_reshade_effect_ready() {\n    gamescope_reshade_effect_request_time = 0;\n}\n\nvoid set_gamescope_reshade_effect_uniform_variable(const char *variable_name, const void *data, int entries, \n                                                   size_t element_size, bool flush) {\n    if (!reshade_object) return;\n\n    pthread_mutex_lock(&wayland_mutex);\n    bool success = do_wl_set_uniform_variable(variable_name, data, entries, element_size, flush);\n    if (!success && flush) {\n        do_wl_cleanup();\n    }\n    pthread_mutex_unlock(&wayland_mutex);\n}\n\nvoid set_skippable_gamescope_reshade_effect_uniform_variable(const char *variable_name, const void *data, \n                                                             int entries, size_t element_size, bool flush) {\n    // if already locked, just skip this call\n    if (!reshade_object || pthread_mutex_trylock(&wayland_mutex) != 0) return;\n\n    bool success = do_wl_set_uniform_variable(variable_name, data, entries, element_size, flush);\n    if (!success && flush) {\n        do_wl_cleanup();\n    }\n    pthread_mutex_unlock(&wayland_mutex);\n}\n\nvoid gamescope_reshade_wl_handle_state_func() {\n    pthread_mutex_lock(&wayland_mutex);\n    if (device_present() && sombrero_file_exists() && !gamescope_config->disabled) {\n        if (!gamescope_reshade_ipc_connected) {\n            do_wl_server_connect();\n            if (gamescope_reshade_ipc_connected) {\n                if (config()->debug_ipc) log_debug(\"gamescope_reshade_wl_handle_state_func connected to gamescope\\n\");\n                state()->is_gamescope_reshade_ipc_connected = true;\n\n                do_trigger_plugins_ipc_change();\n\n                do_wl_add_gamescope_effect_ready_listener(_gamescope_reshade_effect_ready);\n                do_wl_enable_gamescope_effect();\n            }\n        }\n    } else {\n        if (gamescope_reshade_ipc_connected) do_wl_cleanup();\n    }\n    pthread_mutex_unlock(&wayland_mutex);\n};\n\nvoid gamescope_reshade_wl_handle_pose_data_func(imu_pose_type pose, imu_euler_type velocities, bool imu_calibrated, ipc_values_type *ipc_values) {\n    if (!reshade_object) return;\n    \n    pthread_mutex_lock(&wayland_mutex);\n    if (gamescope_reshade_effect_request_time != 0 && \n            get_epoch_time_ms() - gamescope_reshade_effect_request_time > \n            GAMESCOPE_RESHADE_WAIT_TIME_MS) {\n        log_error(\"gamescope effect_ready event never received, falling back to shared memory IPC\\n\");\n        do_wl_cleanup();\n    }\n    pthread_mutex_unlock(&wayland_mutex);\n}\n\nvoid gamescope_reshade_wl_reset_pose_data_func() {\n    set_skippable_gamescope_reshade_effect_uniform_variable(\"pose_orientation\", pose_orientation_reset_data, 16, sizeof(float), false);\n    set_skippable_gamescope_reshade_effect_uniform_variable(\"pose_position\", pose_position_reset_data, 3, sizeof(float), true);\n}\n\nconst plugin_type gamescope_reshade_wayland_plugin = {\n    .id = \"gamescope_reshade_wayland\",\n    .default_config = gamescope_reshade_wayland_default_config_func,\n    .handle_config_line = gamescope_reshade_wayland_handle_config_line_func,\n    .set_config = gamescope_reshade_wayland_set_config_func,\n    .setup_ipc = gamescope_reshade_wl_setup_ipc,\n    .handle_state = gamescope_reshade_wl_handle_state_func,\n    .handle_pose_data = gamescope_reshade_wl_handle_pose_data_func,\n    .reset_pose_data = gamescope_reshade_wl_reset_pose_data_func,\n    .handle_device_disconnect = wayland_cleanup,\n};"
  },
  {
    "path": "src/plugins/metrics.c",
    "content": "#include \"config.h\"\n#include \"curl.h\"\n#include \"devices.h\"\n#include \"memory.h\"\n#include \"plugins.h\"\n#include \"runtime_context.h\"\n#include \"system.h\"\n\n#include <curl/curl.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\nconst char *UA_MEASUREMENT_ID = \"G-Z94MXP18T6\";\nconst char *UA_CLIENT_ID=\"ARLinuxDriver\";\nvoid log_metric(char *event_name) {\n    #ifdef UA_API_SECRET\n        if (config()->metrics_disabled) return;\n\n        CURL *curl;\n        CURLcode res;\n\n        struct curl_slist *headers = NULL;\n\n        curl_init();\n\n        curl = curl_easy_init();\n        if(curl) {\n            curl_easy_setopt(curl, CURLOPT_TIMEOUT, 2L);\n            headers = curl_slist_append(headers, \"Content-Type: application/json\");\n\n            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);\n\n            char url[1024];\n            snprintf(url, 1024, \"https://www.google-analytics.com/mp/collect?api_secret=%s&measurement_id=%s&aip=1\", UA_API_SECRET, UA_MEASUREMENT_ID);\n            curl_easy_setopt(curl, CURLOPT_URL, url);\n\n            char post_data[1024];\n            snprintf(post_data, 1024, \"{\\\"client_id\\\": \\\"%s\\\", \\\"events\\\": [{\\\"name\\\": \\\"%s\\\"}]}\", UA_CLIENT_ID, event_name);\n            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);\n\n            /* Perform the request, res will get the return code */\n            res = curl_easy_perform(curl);\n\n            /* always cleanup */\n            curl_easy_cleanup(curl);\n        }\n    #endif\n};\n\n// Distill all possible modes into one enum. It's spread across multiple configs, so it's not a perfect representation.\nenum metrics_output_mode {\n    OUTPUT_MODE_DISABLED,\n    OUTPUT_MODE_SIDEVIEW,\n    OUTPUT_MODE_VIRTUAL_DISPLAY,\n    OUTPUT_MODE_MOUSE,\n    OUTPUT_MODE_JOYSTICK,\n    OUTPUT_MODE_BREEZY_DESKTOP,\n    OUTPUT_MODE_OPENTRACK\n};\n\nchar *metrics_output_mode_to_event_name[7] = {\n    \"output_mode_disabled\",\n    \"output_mode_follow\",\n    \"output_mode_virtual_display\",\n    \"output_mode_mouse\",\n    \"output_mode_joystick\",\n    \"output_mode_breezy_desktop\",\n    \"output_mode_opentrack\"\n};\n\nenum metrics_output_mode current_output_mode = OUTPUT_MODE_DISABLED;\nbool config_disabled = true;\nchar *config_output_mode = NULL;\nchar *config_external_mode = NULL;\nchar *current_device = NULL;\nbool state_sbs_enabled = false;\nbool was_smooth_follow_enabled = false;\nbool config_smooth_follow_enabled = false;\nbool was_auto_recenter_enabled = false;\nbool config_auto_recenter_enabled = false;\n\nvoid metrics_handle_config_line_func(void* config, char* key, char* value) {\n    if (!config_output_mode) config_output_mode = strdup(mouse_output_mode);\n    if (!config_external_mode) config_external_mode = strdup(\"none\");\n    if (equal(key, \"output_mode\")) {\n        string_config(key, value, &config_output_mode);\n    } else if (equal(key, \"external_mode\")) {\n        string_config(key, value, &config_external_mode);\n    } else if (equal(key, \"disabled\")) {\n        boolean_config(key, value, &config_disabled);\n    } else if (equal(key, \"virtual_display_smooth_follow_enabled\")) {\n        boolean_config(key, value, &config_auto_recenter_enabled);\n    } else if (equal(key, \"sideview_smooth_follow_enabled\")) {\n        boolean_config(key, value, &config_smooth_follow_enabled);\n    }\n};\n\nvoid metrics_set_config_func(void* config) {\n    enum metrics_output_mode new_output_mode = OUTPUT_MODE_DISABLED;\n    if (!config_disabled) {\n        if (!config_output_mode || equal(config_output_mode, mouse_output_mode)) {\n            new_output_mode = OUTPUT_MODE_MOUSE;\n        } else if (equal(config_output_mode, joystick_output_mode)) {\n            new_output_mode = OUTPUT_MODE_JOYSTICK;\n        } else if (list_string_contains(\"virtual_display\", config_external_mode)) {\n            new_output_mode = OUTPUT_MODE_VIRTUAL_DISPLAY;\n        } else if (list_string_contains(\"sideview\", config_external_mode)) {\n            new_output_mode = OUTPUT_MODE_SIDEVIEW;\n        } else if (list_string_contains(\"breezy_desktop\", config_external_mode)) {\n            new_output_mode = OUTPUT_MODE_BREEZY_DESKTOP;\n        } else if (list_string_contains(\"opentrack\", config_external_mode)) {\n            new_output_mode = OUTPUT_MODE_OPENTRACK;\n        }\n    }\n\n    if (device_present()) {\n        bool output_mode_changed = current_output_mode != new_output_mode;\n        if (output_mode_changed && new_output_mode != OUTPUT_MODE_DISABLED) {\n            log_metric(metrics_output_mode_to_event_name[new_output_mode]);\n        }\n        current_output_mode = new_output_mode;\n\n        if (config_smooth_follow_enabled && (!was_smooth_follow_enabled ||\n                output_mode_changed && new_output_mode == OUTPUT_MODE_SIDEVIEW)) {\n            log_metric(\"smooth_follow_enabled\");\n        }\n        was_smooth_follow_enabled = config_smooth_follow_enabled;\n\n        if (config_auto_recenter_enabled && (!was_auto_recenter_enabled ||\n                output_mode_changed && new_output_mode == OUTPUT_MODE_VIRTUAL_DISPLAY)) {\n            log_metric(\"auto_recenter_enabled\");\n        }\n        was_auto_recenter_enabled = config_auto_recenter_enabled;\n    }\n};\n\n\nvoid metrics_handle_state_func() {\n    if (!state_sbs_enabled && state()->sbs_mode_enabled) {\n        log_metric(\"sbs_enabled\");\n        state_sbs_enabled = state()->sbs_mode_enabled;\n    }\n};\n\nvoid metrics_handle_device_connect_func() {\n    device_properties_type* device = device_checkout();\n    if (device != NULL) {\n        char new_device[1024];\n        snprintf(new_device, 1024, \"device_%x_%x\", device->hid_vendor_id, device->hid_product_id);\n\n        if (!current_device || strcmp(new_device, current_device) != 0) {\n            log_metric(new_device);\n            free_and_clear(&current_device);\n            current_device = strdup(new_device);\n        }\n    }\n    device_checkin(device);\n};\n\nconst plugin_type metrics_plugin = {\n    .id = \"metrics\",\n    .handle_config_line = metrics_handle_config_line_func,\n    .set_config = metrics_set_config_func,\n    .handle_state = metrics_handle_state_func,\n    .handle_device_connect = metrics_handle_device_connect_func\n};"
  },
  {
    "path": "src/plugins/neck_saver.c",
    "content": "#include \"plugins/neck_saver.h\"\n#include \"imu.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"strings.h\"\n#include \"config.h\"\n\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n\nstatic neck_saver_config_type *ns_config = NULL;\n\nstatic void *neck_saver_default_config_func() {\n    neck_saver_config_type *config = calloc(1, sizeof(neck_saver_config_type));\n    config->horizontal_multiplier = 1.0f;\n    config->vertical_multiplier = 1.0f;\n    return config;\n}\n\nstatic void neck_saver_handle_config_line_func(void *config, char *key, char *value) {\n    neck_saver_config_type *c = (neck_saver_config_type*)config;\n    if (equal(key, \"neck_saver_horizontal_multiplier\")) {\n        float_config(key, value, &c->horizontal_multiplier);\n    } else if (equal(key, \"neck_saver_vertical_multiplier\")) {\n        float_config(key, value, &c->vertical_multiplier);\n    }\n}\n\nstatic void neck_saver_set_config_func(void *config) {\n    neck_saver_config_type *new_config = (neck_saver_config_type*)config;\n    if (!ns_config) {\n        ns_config = new_config;\n        return;\n    }\n\n    if (ns_config->horizontal_multiplier != new_config->horizontal_multiplier) {\n        log_message(\"Neck Saver horizontal multiplier changed to %f\\n\", new_config->horizontal_multiplier);\n    }\n    if (ns_config->vertical_multiplier != new_config->vertical_multiplier) {\n        log_message(\"Neck Saver vertical multiplier changed to %f\\n\", new_config->vertical_multiplier);\n    }\n\n    free(ns_config);\n    ns_config = new_config;\n}\n\nstatic void neck_saver_modify_pose_func(imu_pose_type* pose) {\n    if (!ns_config || !pose) return;\n    if (ns_config->horizontal_multiplier == 1.0f && ns_config->vertical_multiplier == 1.0f) return;\n\n    // euler is XYZ (roll,pitch,yaw). Apply multipliers accordingly.\n    pose->euler.yaw *= ns_config->horizontal_multiplier;\n    pose->euler.pitch *= ns_config->vertical_multiplier;\n\n    // Keep quaternion consistent with updated euler angles\n    pose->orientation = euler_to_quaternion_zyx(pose->euler);\n}\n\nconst plugin_type neck_saver_plugin = {\n    .id = \"neck_saver\",\n    .default_config = neck_saver_default_config_func,\n    .handle_config_line = neck_saver_handle_config_line_func,\n    .set_config = neck_saver_set_config_func,\n    .modify_pose = neck_saver_modify_pose_func\n};\n"
  },
  {
    "path": "src/plugins/opentrack_listener.c",
    "content": "#include \"config.h\"\n#include \"connection_pool.h\"\n#include \"devices.h\"\n#include \"driver.h\"\n#include \"imu.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"plugins/opentrack_listener.h\"\n#include \"runtime_context.h\"\n#include \"strings.h\"\n\n#include <arpa/inet.h>\n#include <errno.h>\n#include <netinet/in.h>\n#include <netdb.h>\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <netdb.h>\n#include <unistd.h>\n#include <sys/select.h>\n#include <sys/time.h>\n\n#define OT_DEVICE_BRAND \"OpenTrack\"\n#define OT_DRIVER_ID \"opentrack\"\n\n// This plugin exposes an OpenTrack UDP stream as a synthetic IMU device.\n// It binds a UDP socket, blocks waiting for 6-double payloads (x,y,z,yaw,pitch,roll),\n// converts yaw/pitch/roll (degrees) to a quaternion, and feeds the driver loop.\n\nstatic opentrack_listener_config *ot_cfg = NULL;\n\n// Socket state\nstatic int udp_fd = -1;\nstatic struct sockaddr_storage bind_addr;\nstatic socklen_t bind_addr_len = 0;\nstatic volatile bool connected = false;\nstatic pthread_t listener_thread;\nstatic bool listener_running = false;\nstatic pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER;\nstatic pthread_cond_t conn_cond = PTHREAD_COND_INITIALIZER;\nstatic volatile bool block_active = false;\n\n// Track OpenTrack source plugin config to prevent feedback loops\nstatic bool ot_source_enabled = false;\nstatic char *ot_source_ip = NULL;\nstatic int ot_source_port = 4242;\nstatic volatile bool feedback_loop_ignore = false;\n\nstatic void listener_device_disconnect() {\n    connection_t* c = connection_pool_find_driver_connection(OT_DRIVER_ID);\n    if (c) {\n        connected_device_type* connected_device = calloc(1, sizeof(connected_device_type));\n        connected_device->driver = c->driver;\n        connected_device->device = c->device;\n        handle_device_connection_changed(false, connected_device);\n    }\n\n    pthread_mutex_lock(&conn_mutex);\n    if (connected) {\n        connected = false;\n        pthread_cond_broadcast(&conn_cond);\n    }\n    pthread_mutex_unlock(&conn_mutex);\n}\n\n// Utility: check if a target IP string refers to localhost/unspecified\nstatic bool is_localhostish_ip(const char *ip_raw) {\n    // defaults to localhost if unset, return true\n    if (!ip_raw || !ip_raw[0]) return true;\n\n    // make a scratch copy to strip brackets and zone-id\n    char buf[256];\n    size_t len = strlen(ip_raw);\n    if (len >= sizeof(buf)) len = sizeof(buf) - 1;\n    memcpy(buf, ip_raw, len);\n    buf[len] = '\\0';\n\n    // Strip surrounding [ ] for IPv6 literals\n    if (buf[0] == '[') {\n        size_t blen = strlen(buf);\n        if (blen >= 2 && buf[blen - 1] == ']') {\n            memmove(buf, buf + 1, blen - 2);\n            buf[blen - 2] = '\\0';\n        }\n    }\n    // Strip zone id (e.g., fe80::1%lo0)\n    char *pct = strchr(buf, '%');\n    if (pct) *pct = '\\0';\n\n    // Quick textual checks\n    if (strcmp(buf, \"localhost\") == 0) return true;\n    if (strcmp(buf, \"0.0.0.0\") == 0) return true; // unspecified IPv4\n    if (strcmp(buf, \"::\") == 0) return true;      // unspecified IPv6\n\n    // Parse as IPv4\n    struct in_addr a4;\n    if (inet_pton(AF_INET, buf, &a4) == 1) {\n        uint32_t host = ntohl(a4.s_addr);\n        if (host == 0) return true;               // 0.0.0.0\n        if ((host & 0xFF000000u) == 0x7F000000u)  // 127.0.0.0/8\n            return true;\n        return false;\n    }\n\n    // Parse as IPv6\n    struct in6_addr a6;\n    if (inet_pton(AF_INET6, buf, &a6) == 1) {\n        if (IN6_IS_ADDR_LOOPBACK(&a6)) return true;     // ::1\n        if (IN6_IS_ADDR_UNSPECIFIED(&a6)) return true;  // ::\n        return false;\n    }\n\n    // Unknown format; be conservative and do not consider it localhost\n    return false;\n}\n\nstatic void update_feedback_guard() {\n    bool prev = feedback_loop_ignore;\n    int listener_port = (ot_cfg && ot_cfg->port > 0) ? ot_cfg->port : 4242;\n    feedback_loop_ignore = (ot_cfg && ot_cfg->enabled && ot_source_enabled && is_localhostish_ip(ot_source_ip) && (ot_source_port == listener_port));\n    if (feedback_loop_ignore && !prev) {\n        log_message(\"OpenTrack listener: ignoring loopback packets (source enabled; target %s:%d matches listen port %d)\\n\",\n                    ot_source_ip ? ot_source_ip : \"127.0.0.1\", ot_source_port, listener_port);\n        listener_device_disconnect();\n    } else if (!feedback_loop_ignore && prev) {\n        log_message(\"OpenTrack listener: feedback guard disabled; accepting packets\\n\");\n    }\n}\n\n// Placeholder device properties for an OpenTrack source\nstatic device_properties_type *make_opentrack_device_properties() {\n    device_properties_type *d = calloc(1, sizeof(*d));\n    d->brand = OT_DEVICE_BRAND;\n    d->model = \"UDP\";\n    d->hid_vendor_id = 0;\n    d->hid_product_id = 0;\n    d->usb_bus = 0;\n    d->usb_address = 0;\n    d->calibration_setup = CALIBRATION_SETUP_AUTOMATIC;\n    d->resolution_w = RESOLUTION_1080P_W;\n    d->resolution_h = RESOLUTION_1080P_H;\n    d->fov = 45.0f;\n    d->lens_distance_ratio = 0.03125f;\n    d->calibration_wait_s = 1;\n    d->imu_cycles_per_s = 120; // nominal rate; actual rate comes from incoming stream timing\n    d->imu_buffer_size = 1;\n    d->look_ahead_constant = 25.0f;\n    d->look_ahead_frametime_multiplier = 0.3f;\n    d->look_ahead_scanline_adjust = 8.0f;\n    d->look_ahead_ms_cap = 40.0f;\n    d->sbs_mode_supported = false;\n    d->firmware_update_recommended = false;\n    d->can_be_supplemental = true;\n    d->provides_orientation = true;\n    d->provides_position = true;\n    return d;\n}\n\nstatic void opentrack_close_socket() {\n    if (udp_fd != -1) {\n        close(udp_fd);\n        udp_fd = -1;\n    }\n    bind_addr_len = 0;\n}\n\nstatic bool opentrack_bind_socket(const char *ip, int port) {\n    opentrack_close_socket();\n\n    struct addrinfo hints;\n    memset(&hints, 0, sizeof(hints));\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_DGRAM;\n    hints.ai_flags = AI_PASSIVE;\n\n    char port_str[16];\n    snprintf(port_str, sizeof(port_str), \"%d\", port);\n\n    const char *host = ip;\n    char hostbuf[256];\n    if (!host || host[0] == '\\0') {\n        host = NULL;\n    } else {\n        size_t len = strlen(host);\n        if (len >= 2 && host[0] == '[' && host[len - 1] == ']') {\n            size_t n = len - 2;\n            if (n >= sizeof(hostbuf)) n = sizeof(hostbuf) - 1;\n            memcpy(hostbuf, host + 1, n);\n            hostbuf[n] = '\\0';\n            host = hostbuf;\n        }\n    }\n\n    struct addrinfo *res = NULL, *rp = NULL;\n    int rc = getaddrinfo(host, port_str, &hints, &res);\n    if (rc != 0) {\n        log_error(\"opentrack (consumer): getaddrinfo('%s', %d) failed: %s\\n\", host ? host : \"*\", port, gai_strerror(rc));\n        return false;\n    }\n\n    for (rp = res; rp != NULL; rp = rp->ai_next) {\n        udp_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\n        if (udp_fd < 0) continue;\n\n        int one = 1;\n        setsockopt(udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));\n\n        if (rp->ai_family == AF_INET6) {\n            int v6only = 0;\n            (void)setsockopt(udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only));\n        }\n\n        if (bind(udp_fd, rp->ai_addr, rp->ai_addrlen) == 0) {\n            memset(&bind_addr, 0, sizeof(bind_addr));\n            memcpy(&bind_addr, rp->ai_addr, rp->ai_addrlen);\n            bind_addr_len = (socklen_t)rp->ai_addrlen;\n            break;\n        } else {\n            if (config()->debug_device)\n                log_debug(\"opentrack listener: bind failed: %s\\n\", strerror(errno));\n            close(udp_fd);\n            udp_fd = -1;\n        }\n    }\n\n    if (rp == NULL) {\n    log_error(\"opentrack listener: failed to bind %s:%d\\n\", ip && ip[0] ? ip : \"*\", port);\n        freeaddrinfo(res);\n        return false;\n    }\n\n    freeaddrinfo(res);\n    return true;\n}\n\n// --- device driver impl ---\nstatic device_properties_type *opentrack_supported_device(uint16_t id_vendor, uint16_t id_product, uint8_t usb_bus, uint8_t usb_address) {\n    (void)id_vendor; (void)id_product; (void)usb_bus; (void)usb_address;\n    // This hook is specific to the libusb hotplug event, which will never be triggered for the OpenTrack source.\n    return NULL;\n}\n\nstatic bool opentrack_device_connect() {\n    connected = ot_cfg && ot_cfg->enabled && udp_fd != -1;\n    return connected;\n}\n\nstatic void opentrack_block_on_device() {\n    device_properties_type *device = device_checkout();\n    pthread_mutex_lock(&conn_mutex);\n    block_active = true;\n    while (connected) {\n        pthread_cond_wait(&conn_cond, &conn_mutex);\n    }\n    block_active = false;\n    pthread_mutex_unlock(&conn_mutex);\n    device_checkin(device);\n}\n\nstatic bool opentrack_device_is_sbs_mode() { return false; }\nstatic bool opentrack_device_set_sbs_mode(bool enabled) { (void)enabled; return false; }\nstatic bool opentrack_is_connected() { return connected; }\nstatic void opentrack_disconnect(bool soft) {\n    pthread_mutex_lock(&conn_mutex);\n    connected = false;\n    pthread_cond_broadcast(&conn_cond);\n    pthread_mutex_unlock(&conn_mutex);\n}\n\nstatic const device_driver_type opentrack_driver = {\n    .id                                 = OT_DRIVER_ID,\n    .supported_device_func              = opentrack_supported_device,\n    .device_connect_func                = opentrack_device_connect,\n    .block_on_device_func               = opentrack_block_on_device,\n    .device_is_sbs_mode_func            = opentrack_device_is_sbs_mode,\n    .device_set_sbs_mode_func           = opentrack_device_set_sbs_mode,\n    .is_connected_func                  = opentrack_is_connected,\n    .disconnect_func                    = opentrack_disconnect\n};\n\n// --- plugin impl ---\nstatic void *opentrack_default_config_func() {\n    // Reset static variables tied to the opentrack_source plugin\n    ot_source_enabled = false;\n    if (ot_source_ip) free_and_clear(&ot_source_ip);\n    ot_source_port = 4242;\n\n    opentrack_listener_config *cfg = calloc(1, sizeof(*cfg));\n    cfg->enabled = false;\n    cfg->ip = strdup(\"0.0.0.0\");\n    cfg->port = 4242;\n    return cfg;\n}\n\nstatic void opentrack_handle_config_line_func(void *config, char *key, char *value) {\n    opentrack_listener_config *cfg = (opentrack_listener_config *)config;\n    if (!cfg) return;\n\n    if (equal(key, \"opentrack_listener_enabled\")) {\n        boolean_config(key, value, &cfg->enabled);\n    } else if (equal(key, \"opentrack_listen_ip\")) {\n        string_config(key, value, &cfg->ip);\n    } else if (equal(key, \"opentrack_listen_port\")) {\n        int_config(key, value, &cfg->port);\n    } else if (equal(key, \"external_mode\")) {\n        ot_source_enabled = list_string_contains(\"opentrack\", value);\n    } else if (equal(key, \"opentrack_app_ip\")) {\n        string_config(key, value, &ot_source_ip);\n    } else if (equal(key, \"opentrack_app_port\")) {\n        int_config(key, value, &ot_source_port);\n    }\n}\n\n#define OT_UDP_TIMEOUT_MS 500\nstatic const struct timeval OT_SELECT_TIMEOUT = {\n    .tv_sec = 0,\n    .tv_usec = OT_UDP_TIMEOUT_MS * 1000\n};\nstatic void* opentrack_listener_thread_func(void* arg) {\n    (void)arg;\n    uint8_t buf[6 * sizeof(double) + sizeof(uint32_t)];\n    while (!driver_disabled() && ot_cfg && ot_cfg->enabled && udp_fd != -1) {\n        fd_set rfds; FD_ZERO(&rfds); FD_SET(udp_fd, &rfds);\n        struct timeval tv = OT_SELECT_TIMEOUT;\n        int sel = select(udp_fd + 1, &rfds, NULL, NULL, &tv);\n        if (sel == 0) {\n            // timed out\n            if (connected) listener_device_disconnect();\n            continue;\n        } else if (sel < 0) {\n            if (errno == EINTR) continue;\n            if (config()->debug_device)\n                log_debug(\"opentrack listener: select error: %s\\n\", strerror(errno));\n            usleep(1000);\n            continue;\n        }\n\n        ssize_t n = recvfrom(udp_fd, buf, sizeof(buf), 0, NULL, NULL);\n        if (n < 0) {\n            if (errno == EINTR) continue;\n            if (config()->debug_device)\n                log_debug(\"opentrack listener: recvfrom error: %s\\n\", strerror(errno));\n            usleep(1000);\n            continue;\n        }\n        if (n < (ssize_t)(6 * sizeof(double))) continue;\n\n        // If we're guarding against a feedback loop, discard packets silently\n        if (feedback_loop_ignore) {\n            continue;\n        }\n\n        if (!connected) {\n            connected_device_type *nd = calloc(1, sizeof(connected_device_type));\n            nd->driver = &opentrack_driver;\n            nd->device = make_opentrack_device_properties();\n            handle_device_connection_changed(true, nd);\n            pthread_mutex_lock(&conn_mutex);\n            connected = true;\n            pthread_mutex_unlock(&conn_mutex);\n        }\n\n        static bool prev_block_active = false;\n        if (block_active) {\n            device_properties_type *device = device_checkout();\n            if (device) {\n                // Only feed events when block_on_device is active\n                double vals[6];\n                memcpy(vals, buf, 6 * sizeof(double));\n                imu_euler_type e = { .roll = (float)vals[5], .pitch = (float)vals[4], .yaw = (float)vals[3] };\n                imu_quat_type q = euler_to_quaternion_zyx(e);\n                struct timeval tv2; gettimeofday(&tv2, NULL);\n                uint32_t ts_ms = (uint32_t)((tv2.tv_sec * 1000ULL) + (tv2.tv_usec / 1000ULL));\n                static uint32_t start_ts_ms = 0; // set on first active event\n                if (!prev_block_active) {\n                    start_ts_ms = ts_ms;\n                }\n\n                // OpenTrack reports in EUS; convert to NWU\n                float full_distance_cm = LENS_TO_PIVOT_CM / device->lens_distance_ratio;\n                imu_vec3_type pos = { \n                    .x = (float)-vals[2] / full_distance_cm,\n                    .y = (float)-vals[0] / full_distance_cm,\n                    .z = (float)vals[1] / full_distance_cm\n                };\n\n                imu_pose_type pose = (imu_pose_type){0};\n                pose.orientation = q;\n                pose.position = pos;\n                pose.has_orientation = true;\n                pose.has_position = true;\n                pose.timestamp_ms = ts_ms - start_ts_ms;\n                connection_pool_ingest_pose(OT_DRIVER_ID, pose);\n            }\n            device_checkin(device);\n        }\n        prev_block_active = block_active;\n    }\n\n    listener_running = false;\n    return NULL;\n}\n\nstatic void opentrack_start_func() {\n    // If disabled, stop listener and close socket\n    if (driver_disabled() || !ot_cfg || !ot_cfg->enabled) {\n        listener_device_disconnect();\n        opentrack_close_socket();\n        if (listener_running) {\n            pthread_join(listener_thread, NULL);\n            listener_running = false;\n        }\n        return;\n    }\n\n    // Enabled: ensure bound\n    if (udp_fd == -1) {\n        const char *ip = ot_cfg->ip && ot_cfg->ip[0] ? ot_cfg->ip : NULL;\n        int port = ot_cfg->port > 0 ? ot_cfg->port : 4242;\n        if (!opentrack_bind_socket(ip, port)) {\n            log_error(\"OpenTrack listener: failed to bind on %s:%d; leaving disabled\\n\", ip ? ip : \"*\", port);\n            return;\n        }\n        char ipstr[128] = {0};\n        if (ip && ip[0]) strncpy(ipstr, ip, sizeof(ipstr)-1); else strncpy(ipstr, \"*\", sizeof(ipstr)-1);\n        log_message(\"OpenTrack listener bound on %s:%d\\n\", ipstr, port);\n    }\n\n    // Start listener thread to manage registration, feeding, and idle disconnect\n    if (!listener_running) {\n        listener_running = true;\n        pthread_create(&listener_thread, NULL, opentrack_listener_thread_func, NULL);\n    }\n}\n\nstatic void opentrack_set_config_func(void *new_config) {\n    opentrack_listener_config *new_cfg = (opentrack_listener_config *)new_config;\n    if (!new_cfg) return;\n\n    bool first = (ot_cfg == NULL);\n    if (!first) {\n        bool was_enabled = ot_cfg && ot_cfg->enabled;\n        if (was_enabled != new_cfg->enabled)\n            log_message(\"OpenTrack listener has been %s\\n\", new_cfg->enabled ? \"enabled\" : \"disabled\");\n        free(ot_cfg->ip);\n        free(ot_cfg);\n    }\n    ot_cfg = new_cfg;\n\n    opentrack_start_func();\n    update_feedback_guard();\n}\n\nstatic void opentrack_handle_device_disconnect_func() {\n    opentrack_disconnect(false);\n}\n\nconst plugin_type opentrack_listener_plugin = {\n    .id = \"opentrack_listener\",\n    .default_config = opentrack_default_config_func,\n    .handle_config_line = opentrack_handle_config_line_func,\n    .set_config = opentrack_set_config_func,\n    .start = opentrack_start_func,\n    .handle_device_disconnect = opentrack_handle_device_disconnect_func\n};\n"
  },
  {
    "path": "src/plugins/opentrack_source.c",
    "content": "#include \"config.h\"\n#include \"logging.h\"\n#include \"plugins.h\"\n#include \"plugins/opentrack_source.h\"\n#include \"runtime_context.h\"\n#include \"strings.h\"\n\n#include <arpa/inet.h>\n#include <errno.h>\n#include <netinet/in.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <netdb.h>\n#include <unistd.h>\n\nstatic opentrack_source_config *ot_config = NULL;\nstatic int udp_fd = -1;\nstatic struct sockaddr_storage udp_addr;\nstatic socklen_t udp_addr_len = 0;\nstatic uint32_t frame_number = 0;\n\nstatic void opentrack_close_socket() {\n    if (udp_fd != -1) {\n        close(udp_fd);\n        udp_fd = -1;\n    }\n    udp_addr_len = 0;\n}\n\nstatic bool opentrack_open_socket(const char *ip, int port) {\n    opentrack_close_socket();\n\n    struct addrinfo hints;\n    memset(&hints, 0, sizeof(hints));\n    hints.ai_family = AF_UNSPEC;      // Allow IPv4 or IPv6\n    hints.ai_socktype = SOCK_DGRAM;   // UDP\n    hints.ai_flags = 0;               // No special flags; numeric or hostname\n\n    char port_str[16];\n    snprintf(port_str, sizeof(port_str), \"%d\", port);\n\n    // Accept IPv6 literals optionally wrapped in brackets like [::1]\n    const char *host = ip;\n    char hostbuf[256];\n    if (!host || host[0] == '\\0') {\n        host = \"127.0.0.1\";\n    } else {\n        size_t len = strlen(host);\n        if (len >= 2 && host[0] == '[' && host[len - 1] == ']') {\n            size_t n = len - 2;\n            if (n >= sizeof(hostbuf)) n = sizeof(hostbuf) - 1;\n            memcpy(hostbuf, host + 1, n);\n            hostbuf[n] = '\\0';\n            host = hostbuf;\n        }\n    }\n\n    struct addrinfo *res = NULL, *rp = NULL;\n    int rc = getaddrinfo(host, port_str, &hints, &res);\n    if (rc != 0) {\n        log_error(\"opentrack: getaddrinfo('%s', %d) failed: %s\\n\", host, port, gai_strerror(rc));\n        return false;\n    }\n\n    for (rp = res; rp != NULL; rp = rp->ai_next) {\n        udp_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);\n        if (udp_fd < 0)\n            continue;\n\n        memset(&udp_addr, 0, sizeof(udp_addr));\n        memcpy(&udp_addr, rp->ai_addr, rp->ai_addrlen);\n        udp_addr_len = (socklen_t)rp->ai_addrlen;\n        break;\n    }\n\n    if (rp == NULL) {\n        log_error(\"opentrack: socket() failed for all addresses for '%s': %s\\n\", ip, strerror(errno));\n        freeaddrinfo(res);\n        return false;\n    }\n\n    freeaddrinfo(res);\n    return true;\n}\n\nstatic void *opentrack_default_config_func() {\n    opentrack_source_config *cfg = calloc(1, sizeof(opentrack_source_config));\n    cfg->enabled = false;\n    cfg->ip = strdup(\"127.0.0.1\");\n    cfg->port = 4242;\n    return cfg;\n}\n\nstatic void opentrack_handle_config_line_func(void *config, char *key, char *value) {\n    opentrack_source_config *cfg = (opentrack_source_config *)config;\n    if (!cfg) return;\n\n    if (equal(key, \"external_mode\")) {\n        cfg->enabled = list_string_contains(\"opentrack\", value);\n    } else if (equal(key, \"opentrack_app_ip\")) {\n        string_config(key, value, &cfg->ip);\n    } else if (equal(key, \"opentrack_app_port\")) {\n        int_config(key, value, &cfg->port);\n    }\n}\n\nstatic void opentrack_set_config_func(void *new_config) {\n    opentrack_source_config *new_cfg = (opentrack_source_config *)new_config;\n    if (!new_cfg) return;\n\n    bool first = ot_config == NULL;\n    bool reopen = false;\n\n    if (!first) {\n        if (ot_config->enabled != new_cfg->enabled)\n            log_message(\"OpenTrack UDP source has been %s\\n\", new_cfg->enabled ? \"enabled\" : \"disabled\");\n        if (strcmp(ot_config->ip ? ot_config->ip : \"\", new_cfg->ip ? new_cfg->ip : \"\") != 0) {\n            log_message(\"OpenTrack source's target IP changed to %s\\n\", new_cfg->ip);\n            reopen = true;\n        }\n        if (ot_config->port != new_cfg->port) {\n            log_message(\"OpenTrack source port changed to %d\\n\", new_cfg->port);\n            reopen = true;\n        }\n\n        free(ot_config->ip);\n        free(ot_config);\n    }\n\n    ot_config = new_cfg;\n\n    if (ot_config->enabled) {\n        if (first || reopen || udp_fd == -1) {\n            if (opentrack_open_socket(ot_config->ip, ot_config->port)) {\n                log_message(\"OpenTrack UDP target: %s:%d\\n\", ot_config->ip, ot_config->port);\n            }\n        }\n    } else {\n        opentrack_close_socket();\n    }\n}\n\nstatic void opentrack_handle_device_disconnect_func() {\n    // keep socket open; opentrack may still accept data for other sources\n    frame_number = 0;\n}\n\nstatic void opentrack_handle_pose_data_func(imu_pose_type pose, imu_euler_type velocities, bool imu_calibrated, ipc_values_type *ipc_values) {\n    (void)ipc_values;\n\n    if (!ot_config || !ot_config->enabled || !imu_calibrated || udp_fd == -1) return;\n\n    // Map to OpenTrack expected payload: 6 doubles (x,y,z,yaw,pitch,roll) + uint32 frame number\n    // Units: the PHP PoC scaled position by 10 and used degrees for yaw/pitch/roll.\n    double payload[6] = {0};\n\n    // XR driver tracks in NWU, convert to EUS\n    if (pose.has_position) {\n        payload[0] = -pose.position.y;\n        payload[1] = pose.position.z;\n        payload[2] = -pose.position.x;\n    }\n    \n    if (pose.has_orientation) {\n        payload[3] = pose.euler.yaw;\n        payload[4] = pose.euler.pitch;\n        payload[5] = pose.euler.roll;\n    }\n\n    // Build buffer: 6 doubles + uint32\n    uint8_t buffer[6 * sizeof(double) + sizeof(uint32_t)];\n    memcpy(buffer, payload, 6 * sizeof(double));\n    uint32_t fn = frame_number++;\n    memcpy(buffer + 6 * sizeof(double), &fn, sizeof(uint32_t));\n\n    ssize_t to_send = sizeof(buffer);\n    ssize_t sent = sendto(udp_fd, buffer, to_send, 0, (struct sockaddr *)&udp_addr, udp_addr_len);\n    if (sent < 0) {\n        static int err_count = 0;\n        if (err_count++ % 100 == 0) // rate limit errors\n            log_error(\"opentrack: sendto failed: %s\\n\", strerror(errno));\n    }\n}\n\nstatic void opentrack_reset_pose_data_func() {\n    frame_number = 0;\n}\n\nconst plugin_type opentrack_source_plugin = {\n    .id = \"opentrack_source\",\n    .default_config = opentrack_default_config_func,\n    .handle_config_line = opentrack_handle_config_line_func,\n    .set_config = opentrack_set_config_func,\n    .handle_pose_data = opentrack_handle_pose_data_func,\n    .reset_pose_data = opentrack_reset_pose_data_func,\n    .handle_device_disconnect = opentrack_handle_device_disconnect_func\n};\n"
  },
  {
    "path": "src/plugins/sideview.c",
    "content": "#include \"config.h\"\n#include \"devices.h\"\n#include \"ipc.h\"\n#include \"logging.h\"\n#include \"plugins.h\"\n#include \"plugins/gamescope_reshade_wayland.h\"\n#include \"plugins/sideview.h\"\n#include \"runtime_context.h\"\n#include \"strings.h\"\n\n#include <stdbool.h>\n#include <stdlib.h>\n\nconst char *sideview_position_names[SIDEVIEW_POSITION_COUNT] = {\n    \"top_left\",\n    \"top_right\",\n    \"bottom_left\",\n    \"bottom_right\",\n    \"center\"\n};\n\nsideview_config *sv_config;\nsideview_ipc_values_type *sideview_ipc_values;\n\nvoid *sideview_default_config_func() {\n    sideview_config *config = calloc(1, sizeof(sideview_config));\n    config->enabled = false;\n    config->position = 4; // center\n\n    return config;\n};\n\nvoid sideview_handle_config_line_func(void* config, char* key, char* value) {\n    sideview_config* temp_config = (sideview_config*) config;\n    if (equal(key, \"external_mode\")) {\n        temp_config->enabled = list_string_contains(\"sideview\", value);\n    } else if (equal(key, \"sideview_position\")) {\n        for (int i = 0; i < SIDEVIEW_POSITION_COUNT; i++) {\n            if (equal(value, sideview_position_names[i])) {\n                temp_config->position = i;\n                return;\n            }\n        }\n    }\n};\n\nvoid sideview_handle_device_disconnect_func() {\n    bool enabled = false;\n    if (sideview_ipc_values) *sideview_ipc_values->enabled = enabled;\n    set_gamescope_reshade_effect_uniform_variable(\"sideview_enabled\", &enabled, 1, sizeof(bool), true);\n};\n\nvoid set_sideview_ipc_values_from_config() {\n    if (!sv_config) sv_config = sideview_default_config_func();\n\n    if (device_present()) {\n        bool enabled = sv_config->enabled && !config()->disabled;\n        float position = (float) sv_config->position;\n        if (sideview_ipc_values) {\n            *sideview_ipc_values->enabled = enabled && !is_gamescope_reshade_ipc_connected();\n            *sideview_ipc_values->position = position;\n        }\n        bool gamescope_enabled = enabled && is_gamescope_reshade_ipc_connected();\n        set_gamescope_reshade_effect_uniform_variable(\"sideview_enabled\", &gamescope_enabled, 1, sizeof(bool), false);\n        set_gamescope_reshade_effect_uniform_variable(\"sideview_position\", &position, 1, sizeof(float), false);\n    } else {\n        sideview_handle_device_disconnect_func();\n    }\n}\n\nvoid sideview_set_config_func(void* config) {\n    if (!config) return;\n    sideview_config* temp_config = (sideview_config*) config;\n\n    if (sv_config) {\n        if (sv_config->enabled != temp_config->enabled)\n            log_message(\"Sideview has been %s\\n\", temp_config->enabled ? \"enabled\" : \"disabled\");\n\n        if (sv_config->position != temp_config->position)\n            log_message(\"Sideview position has been changed to %s\\n\", sideview_position_names[temp_config->position]);\n\n        free(sv_config);\n    }\n    sv_config = temp_config;\n\n    set_sideview_ipc_values_from_config();\n};\n\nconst char *sideview_enabled_name = \"sideview_enabled\";\nconst char *sideview_position_name = \"sideview_position\";\n\nbool sideview_setup_ipc_func() {\n    bool debug = config()->debug_ipc;\n    if (!sideview_ipc_values) sideview_ipc_values = calloc(1, sizeof(sideview_ipc_values_type));\n    setup_ipc_value(sideview_enabled_name, (void**) &sideview_ipc_values->enabled, sizeof(bool), debug);\n    setup_ipc_value(sideview_position_name, (void**) &sideview_ipc_values->position, sizeof(float), debug);\n\n    set_sideview_ipc_values_from_config();\n\n    return true;\n}\n\nconst plugin_type sideview_plugin = {\n    .id = \"sideview\",\n    .default_config = sideview_default_config_func,\n    .handle_config_line = sideview_handle_config_line_func,\n    .set_config = sideview_set_config_func,\n    .setup_ipc = sideview_setup_ipc_func,\n    .handle_ipc_change = set_sideview_ipc_values_from_config,\n    .handle_device_connect = set_sideview_ipc_values_from_config,\n    .handle_device_disconnect = sideview_handle_device_disconnect_func\n};"
  },
  {
    "path": "src/plugins/smooth_follow.c",
    "content": "#include \"buffer.h\"\n#include \"config.h\"\n#include \"features/breezy_desktop.h\"\n#include \"features/smooth_follow.h\"\n#include \"imu.h\"\n#include \"ipc.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"plugins/gamescope_reshade_wayland.h\"\n#include \"plugins/smooth_follow.h\"\n#include \"runtime_context.h\"\n#include \"state.h\"\n#include \"strings.h\"\n\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/time.h>\n\ntypedef enum {\n    FOLLOW_STATE_NONE,\n    FOLLOW_STATE_INIT,\n    FOLLOW_STATE_WAITING,\n    FOLLOW_STATE_SLERPING\n} follow_state_type;\n\nconst smooth_follow_params init_params = {\n    .lower_angle_threshold = 2.0,\n    .upper_angle_threshold = 2.0,\n    .delay_ms = 0,\n    .return_to_angle = 2.0,\n\n    // moves 99.9% of the way to the center in 1 second\n    .interpolation_ratio_ms = 1-pow(1 - 0.999, 1.0/1000.0)\n};\n\nconst smooth_follow_params sticky_params = {\n    .lower_angle_threshold = 0.5,\n    .upper_angle_threshold = 0.5,\n    .delay_ms = 0,\n    .return_to_angle = 0.5,\n\n    // moves 99% of the way to the center in 1 second\n    .interpolation_ratio_ms = 1-pow(1 - 0.99, 1.0/1000.0)\n};\n\nconst smooth_follow_params loose_follow_params = {\n    .lower_angle_threshold = 20.0,\n    .upper_angle_threshold = 40.0,\n    .delay_ms = 2000,\n    .return_to_angle = 5.0,\n\n    // moves 99% of the way to the center in 1.5 seconds\n    .interpolation_ratio_ms = 1-pow(1 - 0.99, 1.0/1500.0)\n};\n\nuint32_t get_time_ms() {\n    struct timeval tv;\n    gettimeofday(&tv, NULL);\n    return tv.tv_sec * 1000 + tv.tv_usec / 1000;\n}\n\nsmooth_follow_config* sf_config = NULL;\nsmooth_follow_params* sf_params = NULL;\n\nvoid *smooth_follow_default_config_func() {\n    smooth_follow_config *config = calloc(1, sizeof(smooth_follow_config));\n    config->virtual_display_enabled = false;\n    config->virtual_display_follow_enabled = false;\n    config->sideview_enabled = false;\n    config->sideview_follow_enabled = false;\n    config->sideview_follow_threshold = 0.5;\n    config->breezy_desktop_enabled = false;\n    config->display_distance = 1.0;\n    config->display_size = 1.0;\n    config->track_roll = false;\n    config->track_pitch = true;\n    config->track_yaw = true;\n\n    return config;\n};\n\n// TODO -   This has become a bit of a mess with smooth_follow having to be aware of how it interacts with\n//          3 other plugins and their configs and control flags. Smooth follow should just become a utility \n//          function that any plugin can utilize however it deems appropriate.\nvoid smooth_follow_handle_config_line_func(void* config, char* key, char* value) {\n    smooth_follow_config* temp_config = (smooth_follow_config*) config;\n    if (equal(key, \"virtual_display_smooth_follow_enabled\")) {\n        boolean_config(key, value, &temp_config->virtual_display_follow_enabled);\n    } else if (equal(key, \"sideview_smooth_follow_enabled\")) {\n        boolean_config(key, value, &temp_config->sideview_follow_enabled);\n    } else if (equal(key, \"sideview_follow_threshold\")) {\n        float_config(key, value, &temp_config->sideview_follow_threshold);\n    } else if (equal(key, \"external_mode\")) {\n        if (list_string_contains(\"virtual_display\", value)) {\n            temp_config->virtual_display_enabled = true;\n        }\n        if (list_string_contains(\"sideview\", value)) {\n            temp_config->sideview_enabled = true;\n        }\n        if (list_string_contains(\"breezy_desktop\", value)) {\n            temp_config->breezy_desktop_enabled = true;\n        }\n    } else if (equal(key, \"display_distance\")) {\n        float_config(key, value, &temp_config->display_distance);\n    } else if (equal(key, \"display_size\")) {\n        float_config(key, value, &temp_config->display_size);\n    } else if (equal(key, \"smooth_follow_track_roll\")) {\n        boolean_config(key, value, &temp_config->track_roll);\n    } else if (equal(key, \"smooth_follow_track_pitch\")) {\n        boolean_config(key, value, &temp_config->track_pitch);\n    } else if (equal(key, \"smooth_follow_track_yaw\")) {\n        boolean_config(key, value, &temp_config->track_yaw);\n    }\n}\n\nstatic bool smooth_follow_enabled=false;\nfollow_state_type follow_state = FOLLOW_STATE_NONE;\nuint32_t last_timestamp_ms = -1;\nstatic imu_pose_type *origin_pose = NULL;\n\nuint32_t start_snap_back_timestamp_ms = -1;\nstatic bool was_sbs_mode_enabled = false;\nstatic void update_smooth_follow_params() {\n    if (!sf_params) sf_params = calloc(1, sizeof(smooth_follow_params));\n    bool virtual_display_follow = sf_config->virtual_display_enabled && sf_config->virtual_display_follow_enabled;\n    bool smooth_follow = sf_config->sideview_enabled && sf_config->sideview_follow_enabled;\n    bool breezy_desktop_follow = sf_config->breezy_desktop_enabled && state()->breezy_desktop_smooth_follow_enabled;\n    device_properties_type* device = device_checkout();\n    if (device != NULL) {\n        float half_fov = device->fov / 2.0;\n        if (virtual_display_follow) {\n            *sf_params = loose_follow_params;\n            float device_fov_threshold = device->fov * sf_config->display_size / sf_config->display_distance;\n\n            sf_params->lower_angle_threshold = device_fov_threshold;\n            sf_params->upper_angle_threshold = device_fov_threshold * 2.0;\n        } else if (smooth_follow) {\n            *sf_params = sticky_params;\n            bool widescreen = state()->sbs_mode_enabled && is_gamescope_reshade_ipc_connected();\n            float threshold = sf_params->lower_angle_threshold;\n            if (sf_config->sideview_follow_threshold) threshold = sf_config->sideview_follow_threshold;\n            float display_size = fmax(1.0, sf_config->display_size * (widescreen ? 2.0 : 1.0));\n\n            // this calculation tends to fall short for sizes > 1.0, so increase by 25%\n            threshold += half_fov * (display_size  - 1.0) * 1.25;\n\n            threshold = fmax(sf_params->lower_angle_threshold, threshold);\n\n            sf_params->lower_angle_threshold = threshold;\n            sf_params->upper_angle_threshold = threshold;\n            sf_params->return_to_angle = threshold;\n        } else if (breezy_desktop_follow) {\n            *sf_params = sticky_params;\n            float display_distance = 1.0;\n            float threshold = sf_params->lower_angle_threshold;\n            if (state()->breezy_desktop_display_distance) display_distance = state()->breezy_desktop_display_distance;\n            if (state()->breezy_desktop_follow_threshold) threshold = state()->breezy_desktop_follow_threshold;\n            threshold += half_fov * (1.0 / display_distance - 1.0);\n            threshold = fmax(sf_params->lower_angle_threshold, threshold);\n            \n            sf_params->lower_angle_threshold = threshold;\n            sf_params->upper_angle_threshold = threshold;\n            sf_params->return_to_angle = threshold;\n        }\n    }\n    device_checkin(device);\n\n    was_sbs_mode_enabled = state()->sbs_mode_enabled;\n    bool was_smooth_follow_enabled = smooth_follow_enabled;\n    smooth_follow_enabled = is_smooth_follow_granted() && (virtual_display_follow || smooth_follow);\n    smooth_follow_enabled |= is_productivity_granted() && breezy_desktop_follow;\n    \n    if (!smooth_follow_enabled && was_smooth_follow_enabled && origin_pose) {\n        // we'll want to return as close to the original center as possible\n        *sf_params = sticky_params;\n    }\n\n    if (smooth_follow_enabled && !was_smooth_follow_enabled) {\n        start_snap_back_timestamp_ms = -1;\n        last_timestamp_ms = -1;\n        *sf_params = init_params;\n        follow_state = FOLLOW_STATE_INIT;\n    }\n}\n\nvoid smooth_follow_set_config_func(void* config) {\n    if (!config) return;\n    smooth_follow_config* temp_config = (smooth_follow_config*) config;\n\n    if (sf_config) {\n        if (temp_config->virtual_display_enabled && (\n                sf_config->virtual_display_follow_enabled != temp_config->virtual_display_follow_enabled ||\n                sf_config->virtual_display_enabled != temp_config->virtual_display_enabled))\n            log_message(\"Virtual display follow has been %s\\n\", temp_config->virtual_display_follow_enabled ? \"enabled\" : \"disabled\");\n\n        if (temp_config->sideview_enabled && \n                sf_config->sideview_follow_enabled != temp_config->sideview_follow_enabled ||\n            sf_config->sideview_enabled != temp_config->sideview_enabled && temp_config->sideview_follow_enabled)\n            log_message(\"Sideview follow has been %s\\n\", temp_config->sideview_follow_enabled ? \"enabled\" : \"disabled\");\n\n        if (temp_config->sideview_follow_threshold != sf_config->sideview_follow_threshold)\n            log_message(\"Sideview follow threshold has been changed to %f\\n\", temp_config->sideview_follow_threshold);\n\n        free(sf_config);\n    }\n\n    sf_config = temp_config;\n    update_smooth_follow_params();\n}\n\nuint32_t follow_wait_time_start_ms = -1;\nfollow_state_type next_state_for_angle(float angle_degrees) {\n    if (follow_state == FOLLOW_STATE_INIT) {\n        // double the return-to-angle so the movement will be more aggressive towards the center than usual\n        if (!isnan(angle_degrees) && angle_degrees < sf_params->return_to_angle * 2.0) {\n            follow_state = FOLLOW_STATE_NONE;\n            update_smooth_follow_params();\n        }\n    } else {\n        if (isnan(angle_degrees) || angle_degrees < sf_params->return_to_angle ||\n            follow_state != FOLLOW_STATE_SLERPING && angle_degrees < sf_params->lower_angle_threshold) {\n            follow_state = FOLLOW_STATE_NONE;\n        } else if (angle_degrees > sf_params->lower_angle_threshold &&\n                angle_degrees < sf_params->upper_angle_threshold &&\n                sf_params->delay_ms > 0) {\n            if (follow_state == FOLLOW_STATE_NONE) {\n                follow_state = FOLLOW_STATE_WAITING;\n                follow_wait_time_start_ms = get_time_ms();\n            } else if (follow_state == FOLLOW_STATE_WAITING) {\n                if (get_time_ms() - follow_wait_time_start_ms > sf_params->delay_ms) {\n                    follow_state = FOLLOW_STATE_SLERPING;\n                }\n            }\n        } else {\n            follow_state = FOLLOW_STATE_SLERPING;\n        }\n    }\n\n    return follow_state;\n}\n\nfloat percent_adjust(float multiplier, float percent, bool inverse) {\n    float percent_compliment = 1.0 - percent;\n    if (!inverse) return multiplier * percent_compliment + percent;\n\n    float multiplier_compliment = 1.0 - multiplier;\n    return 1.0 - (multiplier_compliment * percent_compliment + percent); \n}\n\n// ported and modified from https://github.com/g-truc/glm/blob/master/glm/ext/quaternion_common.inl\n// if slerping threshold is met, this returns a quaternion that's \"a\" percent of the way between \"from\" and \"to\"\nimu_quat_type slerp(imu_quat_type from, imu_quat_type to, float a) {\n    imu_quat_type target = to;\n\n    // modify the target orientation to filter out unwanted axes based on configured tracking preferences\n    if (origin_pose && smooth_follow_enabled && (!sf_config->track_roll || !sf_config->track_pitch || !sf_config->track_yaw)) {\n        // since we're going to convert the target to euler angles, we should first understand the target\n        // relative to the origin to reduce the chances of gimbal locking (the user is more likely to be facing \n        // towards the origin). this will also lock the non-tracked axes relative to the origin, which makes the\n        // most sense for smooth follow.\n        imu_quat_type to_rel = multiply_quaternions(conjugate(origin_pose->orientation), to);\n        imu_euler_type to_euler = quaternion_to_euler_zyx(to_rel);\n        \n        // ignore tracking preferences if smooth_follow_enabled is false, since we want to fully return to\n        // the original center\n        imu_euler_type target_euler;\n        target_euler.roll = sf_config->track_roll ? to_euler.roll : 0.0;\n        target_euler.pitch = sf_config->track_pitch ? to_euler.pitch : 0.0;\n        target_euler.yaw = sf_config->track_yaw ? to_euler.yaw : 0.0;\n\n        // the result is relative to origin_quat, so we need to reapply it\n        target = multiply_quaternions(origin_pose->orientation, euler_to_quaternion_zyx(target_euler));\n    }\n\n    if (a < 0.0f) a = 0.0f;\n    if (a > 1.0f) a = 1.0f;\n\n    from = normalize_quaternion(from);\n    target = normalize_quaternion(target);\n\n    float cosTheta = from.w * target.w + from.x * target.x + from.y * target.y + from.z * target.z;\n    if (cosTheta < 0) {\n        imu_quat_type tmp = {\n            .w = -target.w,\n            .x = -target.x,\n            .y = -target.y,\n            .z = -target.z\n        };\n        target = tmp;\n        cosTheta = -cosTheta;\n    }\n    if (cosTheta > 1.0f) cosTheta = 1.0f;\n    if (cosTheta < -1.0f) cosTheta = -1.0f;\n    float half_angle = acosf(cosTheta);\n    follow_state_type next_state = next_state_for_angle(radian_to_degree(2 * half_angle));\n    if (next_state == FOLLOW_STATE_SLERPING || next_state == FOLLOW_STATE_INIT) {\n        // our return-to-angle gives us a margin around the center of the target, and we want to stop when\n        // we hit that margin, not the center. if we don't factor that margin into the target, then we may still\n        // be slerping pretty quickly when we hit the return-to-angle, then stop very abruptly. the below factors\n        // return-to-angle into the target so we accelerate very smoothly to the edge of that margin.\n\n        // target 95% of the return-to-angle, otherwise it becomes an asymptote and we'll never stop slerping\n        float target_half_angle = degree_to_radian(sf_params->return_to_angle * 0.95) / 2.0;\n\n        // how much of the current angle is the target angle, 100% means we're already at the desired return-to-angle\n        float target_percent = half_angle > 0.0f ? (target_half_angle / half_angle) : 1.0f;\n\n        // half of the remaining angle to the target\n        half_angle -= target_half_angle;\n\n        float a_compliment = 1 - a;\n        float sin_of_angle = sinf(half_angle);\n        if (fabsf(sin_of_angle) <= 1e-6f) {\n            imu_quat_type result = {\n                .w = (1.0f - a) * from.w + a * target.w,\n                .x = (1.0f - a) * from.x + a * target.x,\n                .y = (1.0f - a) * from.y + a * target.y,\n                .z = (1.0f - a) * from.z + a * target.z\n            };\n            return normalize_quaternion(result);\n        }\n\n        float from_weight = percent_adjust(sinf(a_compliment * half_angle) / sin_of_angle, target_percent, false);\n        float target_weight = percent_adjust(sinf(a * half_angle) / sin_of_angle, target_percent, true);\n        imu_quat_type result = {\n            .w = from_weight * from.w + target_weight * target.w,\n            .x = from_weight * from.x + target_weight * target.x,\n            .y = from_weight * from.y + target_weight * target.y,\n            .z = from_weight * from.z + target_weight * target.z\n        };\n\n        return normalize_quaternion(result);\n    }\n\n    return from;\n}\n\nimu_buffer_type *smooth_follow_imu_buffer = NULL;\nbool smooth_follow_modify_reference_pose_func(imu_pose_type pose, imu_pose_type* ref_pose) {\n    if ((!smooth_follow_enabled && !origin_pose) || !sf_params) {\n        return false;\n    }\n\n    if (last_timestamp_ms == -1) {\n        last_timestamp_ms = pose.timestamp_ms;\n        return false;\n    }\n\n    if (follow_state == FOLLOW_STATE_NONE) {\n        last_timestamp_ms = pose.timestamp_ms;\n    }\n\n    uint32_t elapsed_ms = pose.timestamp_ms - last_timestamp_ms;\n    last_timestamp_ms = pose.timestamp_ms;\n\n    if (origin_pose) {\n        // allow 6DoF some freedom to move around in the forward/back direction within a half-meter\n        float full_distance_cm = state()->connected_device_full_distance_cm;\n        if (full_distance_cm > 0.0f && state()->connected_device_pose_has_position) {\n            float half_meter_units = 50.0f / full_distance_cm;\n            \n            // transiently rotate into the current pose frame so we clamp along \"forward\"\n            // instead of a fixed world axis, then rotate back.\n            imu_quat_type inv_pose_orientation = conjugate(pose.orientation);\n            imu_vec3_type pose_local = vector_rotate(pose.position, inv_pose_orientation);\n            imu_vec3_type ref_local = vector_rotate(ref_pose->position, inv_pose_orientation);\n            float delta_forward = pose_local.x - ref_local.x;\n\n            // always follow in the up/down/left/right axes\n            ref_local.y = pose_local.y;\n            ref_local.z = pose_local.z;\n\n            // forward axes has freedom to move around unless it's more than a half-meter away\n            if (fabsf(delta_forward) >= half_meter_units) {\n                float scale = half_meter_units / fabsf(delta_forward);\n                ref_local.x = pose_local.x - delta_forward * scale;\n            }\n            ref_pose->position = vector_rotate(ref_local, pose.orientation);\n        } else {\n            ref_pose->position = pose.position;\n        }\n\n        if (!smooth_follow_imu_buffer) {\n            device_properties_type* device = device_checkout();\n            if (device != NULL) smooth_follow_imu_buffer = create_imu_buffer(device->imu_buffer_size);\n            device_checkin(device);\n        }\n\n        if (smooth_follow_imu_buffer) {\n            // capture how far we are from the original screen center\n            imu_quat_type delta_quat = multiply_quaternions(conjugate(origin_pose->orientation), pose.orientation);\n\n            // for visual consistency with how screen placement behaves when smooth follow is disabled,\n            // trigger the modify_pose hook\n            imu_pose_type delta_pose = { .timestamp_ms = pose.timestamp_ms, .orientation = delta_quat, .position = (imu_vec3_type){0.0f,0.0f,0.0f}, .euler = quaternion_to_euler_zyx(delta_quat) };\n            plugins.modify_pose(&delta_pose);\n            delta_quat = delta_pose.orientation;\n\n            imu_buffer_response_type* response = push_to_imu_buffer(\n                smooth_follow_imu_buffer, \n                delta_quat,\n                pose.timestamp_ms\n            );\n            state()->smooth_follow_origin_ready = response && response->ready;\n            if (state()->smooth_follow_origin_ready) {\n                memcpy(state()->smooth_follow_origin, response->data, sizeof(float) * 16);\n            }\n            free(response);\n        }\n\n        // smooth follow has been disabled, slerp the screen back to its original center\n        if (!smooth_follow_enabled) {\n            if (start_snap_back_timestamp_ms == -1) {\n                start_snap_back_timestamp_ms = pose.timestamp_ms;\n            }\n            uint32_t elapsed_snap_back_ms = pose.timestamp_ms - start_snap_back_timestamp_ms;\n            ref_pose->orientation = slerp(ref_pose->orientation, origin_pose->orientation, 1 - pow(1 - sf_params->interpolation_ratio_ms, elapsed_ms));\n            \n            // our return-to-angle is so small it will never hit the target, kill the snap-back slerp after 2 seconds\n            if (follow_state == FOLLOW_STATE_NONE || elapsed_snap_back_ms > 2000) {\n                follow_state = FOLLOW_STATE_NONE;\n                ref_pose->orientation = origin_pose->orientation;\n                ref_pose->position = origin_pose->position;\n\n                // we've reached our destination, clear this out to stop slerping\n                free_and_clear(&origin_pose);\n                free_and_clear(&state()->smooth_follow_origin);\n                state()->smooth_follow_origin_ready = false;\n\n                start_snap_back_timestamp_ms = -1;\n            }\n\n            return true;\n        }\n    } else {\n        // smooth follow was just enabled, capture the origin before it changes\n        origin_pose = calloc(1, sizeof(imu_pose_type));\n        origin_pose->orientation = ref_pose->orientation;\n        origin_pose->position = ref_pose->position;\n        origin_pose->has_orientation = ref_pose->has_orientation;\n        origin_pose->has_position = ref_pose->has_position;\n\n        if (!state()->smooth_follow_origin) state()->smooth_follow_origin = calloc(16, sizeof(float));\n        state()->smooth_follow_origin_ready = false;\n    }\n\n    ref_pose->orientation = slerp(ref_pose->orientation, pose.orientation, 1 - pow(1 - sf_params->interpolation_ratio_ms, elapsed_ms));\n    return true;\n}\n\n// unlike gaming, smooth follow for desktop is a temporary state, handled via control flags rather than persistent config\nvoid smooth_follow_handle_control_flag_line_func(char* key, char* value) {\n    if (is_productivity_granted() && sf_config->breezy_desktop_enabled) {\n        bool was_enabled = state()->breezy_desktop_smooth_follow_enabled == true;\n        if (equal(key, \"enable_breezy_desktop_smooth_follow\")) {\n            boolean_config(key, value, &state()->breezy_desktop_smooth_follow_enabled);\n        } else if (equal(key, \"toggle_breezy_desktop_smooth_follow\")) {\n            state()->breezy_desktop_smooth_follow_enabled = !state()->breezy_desktop_smooth_follow_enabled;\n        }\n\n        // these will be applied to the thresholds on the next call to update_smooth_follow_params()\n        if (equal(key, \"breezy_desktop_follow_threshold\")) {\n            float_config(key, value, &state()->breezy_desktop_follow_threshold);\n        }\n        if (equal(key, \"breezy_desktop_display_distance\")) {\n            float_config(key, value, &state()->breezy_desktop_display_distance);\n        }\n\n        if (was_enabled != state()->breezy_desktop_smooth_follow_enabled)\n            log_message(\"Breezy Desktop follow has been %s\\n\", state()->breezy_desktop_smooth_follow_enabled ? \"enabled\" : \"disabled\");\n        \n        update_smooth_follow_params();\n    }\n}\n\nstatic void smooth_follow_handle_state_func() {\n    if (was_sbs_mode_enabled != state()->sbs_mode_enabled) {\n        update_smooth_follow_params();\n    }\n}\n\nstatic void handle_device_disconnect() {\n    last_timestamp_ms = -1;\n    follow_state = FOLLOW_STATE_NONE;\n    follow_wait_time_start_ms = -1;\n    start_snap_back_timestamp_ms = -1;\n\n    free_and_clear(&origin_pose);\n    free_and_clear(&state()->smooth_follow_origin);\n    state()->smooth_follow_origin_ready = false;\n}\n\nstatic void smooth_follow_handle_reference_pose_updated_func(imu_pose_type old_reference_pose, imu_pose_type new_reference_pose) {\n    (void)old_reference_pose;\n\n    if (!origin_pose) return;\n\n    origin_pose->orientation = new_reference_pose.orientation;\n    origin_pose->position = new_reference_pose.position;\n    origin_pose->has_orientation = new_reference_pose.has_orientation;\n    origin_pose->has_position = new_reference_pose.has_position;\n\n    follow_state = FOLLOW_STATE_NONE;\n    follow_wait_time_start_ms = -1;\n    start_snap_back_timestamp_ms = -1;\n}\n\nconst plugin_type smooth_follow_plugin = {\n    .id = \"smooth_follow\",\n    .default_config = smooth_follow_default_config_func,\n    .handle_config_line = smooth_follow_handle_config_line_func,\n    .handle_control_flag_line = smooth_follow_handle_control_flag_line_func,\n    .set_config = smooth_follow_set_config_func,\n    .handle_state = smooth_follow_handle_state_func,\n    .handle_ipc_change = update_smooth_follow_params,\n    .modify_reference_pose = smooth_follow_modify_reference_pose_func,\n    .handle_reference_pose_updated = smooth_follow_handle_reference_pose_updated_func,\n    .handle_device_connect = update_smooth_follow_params,\n    .handle_device_disconnect = handle_device_disconnect\n};"
  },
  {
    "path": "src/plugins/virtual_display.c",
    "content": "#include \"config.h\"\n#include \"devices.h\"\n#include \"features/smooth_follow.h\"\n#include \"features/sbs.h\"\n#include \"imu.h\"\n#include \"ipc.h\"\n#include \"logging.h\"\n#include \"plugins.h\"\n#include \"plugins/gamescope_reshade_wayland.h\"\n#include \"plugins/smooth_follow.h\"\n#include \"plugins/virtual_display.h\"\n#include \"runtime_context.h\"\n#include \"state.h\"\n\n#include <math.h>\n#include <stdbool.h>\n#include <string.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <pthread.h>\n\nvirtual_display_config *vd_config;\nvirtual_display_ipc_values_type *virtual_display_ipc_values;\n\nconst int virtual_display_feature_count = 2;\n\nvoid virtual_display_reset_config(virtual_display_config *config) {\n    config->enabled = false;\n    config->look_ahead_override = 0.0;\n    config->display_distance = 1.0;\n    config->display_size = 1.0;\n    config->sbs_content = false;\n    config->sbs_mode_stretched = true;\n    config->passthrough_smooth_follow_enabled = false;\n    config->follow_mode_enabled = false;\n    config->curved_display = false;\n};\n\nvoid *virtual_display_default_config_func() {\n    virtual_display_config *config = calloc(1, sizeof(virtual_display_config));\n    virtual_display_reset_config(config);\n\n    return config;\n};\n\nvoid virtual_display_handle_config_line_func(void* config, char* key, char* value) {\n    virtual_display_config* temp_config = (virtual_display_config*) config;\n\n    if (equal(key, \"external_mode\")) {\n        temp_config->enabled = list_string_contains(\"virtual_display\", value);\n        temp_config->follow_mode_enabled = list_string_contains(\"sideview\", value);\n    } else if (equal(key, \"look_ahead\")) {\n        float_config(key, value, &temp_config->look_ahead_override);\n    } else if (equal(key, \"display_distance\")) {\n        float_config(key, value, &temp_config->display_distance);\n    } else if (equal(key, \"display_size\")) {\n        float_config(key, value, &temp_config->display_size);\n    } else if (equal(key, \"sbs_content\")) {\n        boolean_config(key, value, &temp_config->sbs_content);\n    } else if (equal(key, \"sbs_mode_stretched\")) {\n        boolean_config(key, value, &temp_config->sbs_mode_stretched);\n    } else if (equal(key, \"sideview_smooth_follow_enabled\") && is_smooth_follow_granted()) {\n        boolean_config(key, value, &temp_config->passthrough_smooth_follow_enabled);\n    } else if (equal(key, \"curved_display\")) {\n        boolean_config(key, value, &temp_config->curved_display);\n    }\n};\n\nvoid virtual_display_handle_device_disconnect_func() {\n    bool enabled = false;\n    if (virtual_display_ipc_values) *virtual_display_ipc_values->enabled = enabled;\n    set_gamescope_reshade_effect_uniform_variable(\"virtual_display_enabled\", &enabled, 1, sizeof(bool), true);\n};\n\nvoid set_virtual_display_ipc_values() {\n    if (!vd_config) vd_config = virtual_display_default_config_func();\n\n    device_properties_type* device = device_checkout();\n    if (device != NULL) {\n        bool enabled = !config()->disabled && \n                            (vd_config->enabled ||\n                            vd_config->follow_mode_enabled &&\n                            vd_config->passthrough_smooth_follow_enabled);\n        bool show_banner = enabled && state()->calibration_state == CALIBRATING;\n\n        float look_ahead_constant = vd_config->look_ahead_override == 0 ?\n                                        device->look_ahead_constant :\n                                        vd_config->look_ahead_override;\n        float look_ahead_ftm =  vd_config->look_ahead_override == 0 ? \n                                    device->look_ahead_frametime_multiplier : \n                                    0.0;\n        float look_ahead_cfg[4] = {look_ahead_constant, look_ahead_ftm, device->look_ahead_scanline_adjust, device->look_ahead_ms_cap};\n\n        // computed values based on display config/state\n        bool pose_has_position = state()->connected_device_pose_has_position;\n        float display_north_offset = (pose_has_position || state()->sbs_mode_enabled)\n                                         ? vd_config->display_distance\n                                         : 1.0;\n        float display_aspect_ratio = (float)device->resolution_w / (float)device->resolution_h;\n        float diag_to_vert_ratio = sqrt(pow(display_aspect_ratio, 2) + 1);\n        float half_fov_z_rads = degree_to_radian(device->fov / diag_to_vert_ratio) / 2;\n        float half_fov_y_rads = half_fov_z_rads * display_aspect_ratio;\n        float fov_half_widths[2] = {tan(half_fov_y_rads), tan(half_fov_z_rads)};\n        float fov_widths[2] = {fov_half_widths[0] * 2, fov_half_widths[1] * 2};\n        float texcoord_x_limits[2] = {0.0, 1.0};\n        float texcoord_x_limits_r[2] = {0.0, 1.0};\n\n        // for 3DoF-only devices, the north offset creates a realistic shift in viewport position based \n        // on orientation, but 6DoF devices give us the actual position, so we don't use the lens north\n        // offset to avoid double shifting\n        float lens_north_offset = pose_has_position ? 0.0 : device->lens_distance_ratio;\n        float lens_vector[3] = {lens_north_offset, 0.0, 0.0};\n        float lens_vector_r[3] = {lens_north_offset, 0.0, 0.0};\n\n        // gamescope's texture will always be full width (no black bars)\n        bool sbs_mode_full_width = is_gamescope_reshade_ipc_connected() || vd_config->sbs_mode_stretched;\n\n        // if using vkBasalt as an implicit layer and the content is full screen, it must have been stretched,\n        // if this is true it tells the shader to consider the real width of the content to be half of the texture width\n        bool sbs_mode_stretched = !is_gamescope_reshade_ipc_connected() && vd_config->sbs_mode_stretched;\n\n        if (state()->sbs_mode_enabled) {\n            lens_vector[1] = device->lens_distance_ratio / 3.0;\n            lens_vector_r[1] = -lens_vector[1];\n            if (vd_config->sbs_content) {\n                texcoord_x_limits[1] = 0.5;\n                texcoord_x_limits_r[0] = 0.5;\n                if (!sbs_mode_full_width) {\n                    texcoord_x_limits[0] = 0.25;\n                    texcoord_x_limits_r[1] = 0.75;\n                }\n            } else if (!sbs_mode_full_width) {\n                texcoord_x_limits[0] = 0.25;\n                texcoord_x_limits[1] = 0.75;\n                texcoord_x_limits_r[0] = 0.25;\n                texcoord_x_limits_r[1] = 0.75;\n            }\n        }\n        if (virtual_display_ipc_values) {\n            *virtual_display_ipc_values->enabled                = enabled && !is_gamescope_reshade_ipc_connected();\n            *virtual_display_ipc_values->show_banner            = show_banner;\n            *virtual_display_ipc_values->display_size           = vd_config->display_size;\n            *virtual_display_ipc_values->sbs_mode_stretched     = sbs_mode_stretched;\n            *virtual_display_ipc_values->display_north_offset   = display_north_offset;\n            *virtual_display_ipc_values->curved_display         = vd_config->curved_display;\n            *virtual_display_ipc_values->half_fov_z_rads        = half_fov_z_rads;\n            *virtual_display_ipc_values->half_fov_y_rads        = half_fov_y_rads;\n            memcpy(virtual_display_ipc_values->look_ahead_cfg, look_ahead_cfg, sizeof(look_ahead_cfg));\n            memcpy(virtual_display_ipc_values->fov_half_widths, fov_half_widths, sizeof(fov_half_widths));\n            memcpy(virtual_display_ipc_values->fov_widths, fov_widths, sizeof(fov_widths));\n            memcpy(virtual_display_ipc_values->texcoord_x_limits, texcoord_x_limits, sizeof(texcoord_x_limits));\n            memcpy(virtual_display_ipc_values->texcoord_x_limits_r, texcoord_x_limits_r, sizeof(texcoord_x_limits_r));\n            memcpy(virtual_display_ipc_values->lens_vector, lens_vector, sizeof(lens_vector));\n            memcpy(virtual_display_ipc_values->lens_vector_r, lens_vector_r, sizeof(lens_vector_r));\n        }\n\n        // don't set the \"flush\" flag here if gamescope is enabled, we'll let the frequent IMU data writes trigger the flush\n        bool gamescope_enabled = enabled && is_gamescope_reshade_ipc_connected();\n        set_gamescope_reshade_effect_uniform_variable(\"virtual_display_enabled\", &gamescope_enabled, 1, sizeof(bool), !gamescope_enabled);\n        set_gamescope_reshade_effect_uniform_variable(\"show_banner\", &show_banner, 1, sizeof(bool), false);\n        set_gamescope_reshade_effect_uniform_variable(\"display_size\", &vd_config->display_size, 1, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"sbs_mode_stretched\", &sbs_mode_stretched, 1, sizeof(bool), false);\n        set_gamescope_reshade_effect_uniform_variable(\"display_north_offset\", &display_north_offset, 1, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"look_ahead_cfg\", (void*) look_ahead_cfg, 4, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"curved_display\", &vd_config->curved_display, 1, sizeof(bool), false);\n        set_gamescope_reshade_effect_uniform_variable(\"half_fov_z_rads\", &half_fov_z_rads, 1, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"half_fov_y_rads\", &half_fov_y_rads, 1, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"fov_half_widths\", (void*) fov_half_widths, 2, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"fov_widths\", (void*) fov_widths, 2, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"texcoord_x_limits\", (void*) texcoord_x_limits, 2, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"texcoord_x_limits_r\", (void*) texcoord_x_limits_r, 2, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"lens_vector\", (void*) lens_vector, 3, sizeof(float), false);\n        set_gamescope_reshade_effect_uniform_variable(\"lens_vector_r\", (void*) lens_vector_r, 3, sizeof(float), false);\n    } else {\n        virtual_display_handle_device_disconnect_func();\n    }\n    device_checkin(device);\n}\n\nvoid virtual_display_set_config_func(void* config) {\n    if (!config) return;\n    virtual_display_config* temp_config = (virtual_display_config*) config;\n\n    if (vd_config) {\n        if (vd_config->enabled != temp_config->enabled)\n            log_message(\"Virtual display has been %s\\n\", temp_config->enabled ? \"enabled\" : \"disabled\");\n\n        if (temp_config->enabled || temp_config->follow_mode_enabled) {\n            if (vd_config->look_ahead_override != temp_config->look_ahead_override)\n                log_message(\"Look ahead override has changed to %f\\n\", temp_config->look_ahead_override);\n\n            if (vd_config->display_size != temp_config->display_size)\n                log_message(\"Display size has changed to %f\\n\", temp_config->display_size);\n\n            if (vd_config->display_distance != temp_config->display_distance)\n                log_message(\"Display distance has changed to %f\\n\", temp_config->display_distance);\n\n            if (vd_config->sbs_content != temp_config->sbs_content)\n                log_message(\"SBS content has been changed to %s\\n\", temp_config->sbs_content ? \"enabled\" : \"disabled\");\n\n            if (vd_config->sbs_mode_stretched != temp_config->sbs_mode_stretched)\n                log_message(\"SBS mode has been changed to %s\\n\", temp_config->sbs_mode_stretched ? \"stretched\" : \"centered\");\n\n            if (vd_config->curved_display != temp_config->curved_display)\n                log_message(\"Curved display has been %s\\n\", temp_config->curved_display ? \"enabled\" : \"disabled\");\n        }\n\n        free(vd_config);\n    }\n    vd_config = temp_config;\n\n    set_virtual_display_ipc_values();\n};\n\nconst char *virtual_display_enabled_ipc_name = \"virtual_display_enabled\";\nconst char *virtual_display_show_banner_ipc_name = \"show_banner\";\nconst char *virtual_display_look_ahead_cfg_ipc_name = \"look_ahead_cfg\";\nconst char *virtual_display_display_size_ipc_name = \"display_size\";\nconst char *virtual_display_display_north_offset_ipc_name = \"display_north_offset\";\nconst char *virtual_display_sbs_enabled_ipc_name = \"sbs_enabled\";\nconst char *virtual_display_sbs_content_ipc_name = \"sbs_content\";\nconst char *virtual_display_sbs_mode_stretched_ipc_name = \"sbs_mode_stretched\";\nconst char *virtual_display_half_fov_z_rads_ipc_name = \"half_fov_z_rads\";\nconst char *virtual_display_half_fov_y_rads_ipc_name = \"half_fov_y_rads\";\nconst char *virtual_display_fov_half_widths_ipc_name = \"fov_half_widths\";\nconst char *virtual_display_fov_widths_ipc_name = \"fov_widths\";\nconst char *virtual_display_texcoord_x_limits_ipc_name = \"texcoord_x_limits\";\nconst char *virtual_display_texcoord_x_limits_r_ipc_name = \"texcoord_x_limits_r\";\nconst char *virtual_display_lens_vector_ipc_name = \"lens_vector\";\nconst char *virtual_display_lens_vector_r_ipc_name = \"lens_vector_r\";\nconst char *virtual_display_curved_display_ipc_name = \"curved_display\";\n\nbool virtual_display_setup_ipc_func() {\n    bool debug = config()->debug_ipc;\n    if (!virtual_display_ipc_values) virtual_display_ipc_values = calloc(1, sizeof(virtual_display_ipc_values_type));\n    setup_ipc_value(virtual_display_enabled_ipc_name, (void**) &virtual_display_ipc_values->enabled, sizeof(bool), debug);\n    setup_ipc_value(virtual_display_show_banner_ipc_name, (void**) &virtual_display_ipc_values->show_banner, sizeof(bool), debug);\n    setup_ipc_value(virtual_display_look_ahead_cfg_ipc_name, (void**) &virtual_display_ipc_values->look_ahead_cfg, sizeof(float) * 4, debug);\n    setup_ipc_value(virtual_display_display_size_ipc_name, (void**) &virtual_display_ipc_values->display_size, sizeof(float), debug);\n    setup_ipc_value(virtual_display_display_north_offset_ipc_name, (void**) &virtual_display_ipc_values->display_north_offset, sizeof(float), debug);\n    setup_ipc_value(virtual_display_sbs_enabled_ipc_name, (void**) &virtual_display_ipc_values->sbs_enabled, sizeof(bool), debug);\n    setup_ipc_value(virtual_display_sbs_content_ipc_name, (void**) &virtual_display_ipc_values->sbs_content, sizeof(bool), debug);\n    setup_ipc_value(virtual_display_sbs_mode_stretched_ipc_name, (void**) &virtual_display_ipc_values->sbs_mode_stretched, sizeof(bool), debug);\n    setup_ipc_value(virtual_display_half_fov_z_rads_ipc_name, (void**) &virtual_display_ipc_values->half_fov_z_rads, sizeof(float), debug);\n    setup_ipc_value(virtual_display_half_fov_y_rads_ipc_name, (void**) &virtual_display_ipc_values->half_fov_y_rads, sizeof(float), debug);\n    setup_ipc_value(virtual_display_fov_half_widths_ipc_name, (void**) &virtual_display_ipc_values->fov_half_widths, sizeof(float) * 2, debug);\n    setup_ipc_value(virtual_display_fov_widths_ipc_name, (void**) &virtual_display_ipc_values->fov_widths, sizeof(float) * 2, debug);\n    setup_ipc_value(virtual_display_texcoord_x_limits_ipc_name, (void**) &virtual_display_ipc_values->texcoord_x_limits, sizeof(float) * 2, debug);\n    setup_ipc_value(virtual_display_texcoord_x_limits_r_ipc_name, (void**) &virtual_display_ipc_values->texcoord_x_limits_r, sizeof(float) * 2, debug);\n    setup_ipc_value(virtual_display_lens_vector_ipc_name, (void**) &virtual_display_ipc_values->lens_vector, sizeof(float) * 3, debug);\n    setup_ipc_value(virtual_display_lens_vector_r_ipc_name, (void**) &virtual_display_ipc_values->lens_vector_r, sizeof(float) * 3, debug);\n    setup_ipc_value(virtual_display_curved_display_ipc_name, (void**) &virtual_display_ipc_values->curved_display, sizeof(bool), debug);\n\n    set_virtual_display_ipc_values();\n\n    return true;\n}\n\nvoid virtual_display_handle_state_func() {\n    bool sbs_enabled = state()->sbs_mode_enabled && is_sbs_granted();\n    if (virtual_display_ipc_values) *virtual_display_ipc_values->sbs_enabled = sbs_enabled;\n    set_gamescope_reshade_effect_uniform_variable(\"sbs_enabled\", &sbs_enabled, 1, sizeof(bool), true);\n\n    set_virtual_display_ipc_values();\n}\n\nconst plugin_type virtual_display_plugin = {\n    .id = \"virtual_display\",\n    .default_config = virtual_display_default_config_func,\n    .handle_config_line = virtual_display_handle_config_line_func,\n    .set_config = virtual_display_set_config_func,\n    .setup_ipc = virtual_display_setup_ipc_func,\n    .handle_ipc_change = set_virtual_display_ipc_values,\n    .handle_state = virtual_display_handle_state_func,\n    .handle_device_connect = set_virtual_display_ipc_values,\n    .handle_device_disconnect = virtual_display_handle_device_disconnect_func\n};"
  },
  {
    "path": "src/plugins.c",
    "content": "#include \"logging.h\"\n#include \"plugins.h\"\n#include \"plugins/custom_banner.h\"\n#include \"plugins/breezy_desktop.h\"\n#include \"plugins/device_license.h\"\n#include \"plugins/gamescope_reshade_wayland.h\"\n#include \"plugins/metrics.h\"\n#include \"plugins/sideview.h\"\n#include \"plugins/smooth_follow.h\"\n#include \"plugins/virtual_display.h\"\n#include \"plugins/neck_saver.h\"\n#include \"plugins/opentrack_source.h\"\n#include \"plugins/opentrack_listener.h\"\n#include \"state.h\"\n\n#include <stdlib.h>\n\n#define PLUGIN_COUNT 11\nconst plugin_type* all_plugins[PLUGIN_COUNT] = {\n    &device_license_plugin,\n    &virtual_display_plugin,\n    &sideview_plugin,\n    &metrics_plugin,\n    &custom_banner_plugin,\n    &smooth_follow_plugin,\n    &breezy_desktop_plugin,\n    &gamescope_reshade_wayland_plugin,\n    &neck_saver_plugin,\n    &opentrack_source_plugin,\n    &opentrack_listener_plugin\n};\n\n\nvoid all_plugins_start_func() {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->start == NULL) continue;\n        all_plugins[i]->start();\n    }\n}\nvoid* all_plugins_default_config_func() {\n    void** configs = calloc(PLUGIN_COUNT, sizeof(void*));\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->default_config == NULL) continue;\n        configs[i] = all_plugins[i]->default_config();\n    }\n\n    return configs;\n}\nvoid all_plugins_handle_config_line_func(void* config, char* key, char* value) {\n    void **configs = (void**)config;\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->handle_config_line == NULL) continue;\n        all_plugins[i]->handle_config_line(configs[i], key, value);\n    }\n}\nvoid all_plugins_handle_control_flag_line_func(char* key, char* value) {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->handle_control_flag_line == NULL) continue;\n        all_plugins[i]->handle_control_flag_line(key, value);\n    }\n}\nvoid all_plugins_set_config_func(void* config) {\n    void **configs = (void**)config;\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->set_config == NULL) continue;\n        all_plugins[i]->set_config(configs[i]);\n    }\n}\nbool all_plugins_setup_ipc_func() {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->setup_ipc == NULL) continue;\n        if (!all_plugins[i]->setup_ipc()) {\n            log_error(\"Failed to setup IPC for plugin %s\\n\", all_plugins[i]->id);\n            exit(1);\n        }\n    }\n\n    return true;\n}\nvoid all_plugins_handle_ipc_change_func() {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->handle_ipc_change == NULL) continue;\n        all_plugins[i]->handle_ipc_change();\n    }\n}\nbool all_plugins_modify_reference_pose_func(imu_pose_type pose, imu_pose_type* ref_pose) {\n    bool modified = false;\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->modify_reference_pose == NULL) continue;\n        modified |= all_plugins[i]->modify_reference_pose(pose, ref_pose);\n    }\n    return modified;\n}\n\nvoid all_plugins_handle_reference_pose_updated_func(imu_pose_type old_reference_pose, imu_pose_type new_reference_pose) {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->handle_reference_pose_updated == NULL) continue;\n        all_plugins[i]->handle_reference_pose_updated(old_reference_pose, new_reference_pose);\n    }\n}\n\nvoid all_plugins_modify_pose_func(imu_pose_type* pose) {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->modify_pose == NULL) continue;\n        all_plugins[i]->modify_pose(pose);\n    }\n}\nvoid all_plugins_handle_pose_data_func(imu_pose_type pose, imu_euler_type velocities, bool imu_calibrated, ipc_values_type *ipc_values) {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->handle_pose_data == NULL) continue;\n        all_plugins[i]->handle_pose_data(pose, velocities, imu_calibrated, ipc_values);\n    }\n}\n\nvoid all_plugins_reset_pose_data_func() {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->reset_pose_data == NULL) continue;\n        all_plugins[i]->reset_pose_data();\n    }\n}\nvoid all_plugins_handle_state_func() {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->handle_state == NULL) continue;\n        all_plugins[i]->handle_state();\n    }\n}\nvoid all_plugins_handle_device_connect_func() {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->handle_device_connect == NULL) continue;\n        all_plugins[i]->handle_device_connect();\n    }\n}\nvoid all_plugins_handle_device_disconnect_func() {\n    for (int i = 0; i < PLUGIN_COUNT; i++) {\n        if (all_plugins[i]->handle_device_disconnect == NULL) continue;\n        all_plugins[i]->handle_device_disconnect();\n    }\n}\n\nconst plugin_type plugins = {\n    .id = \"all_plugins\",\n    .start = all_plugins_start_func,\n    .default_config = all_plugins_default_config_func,\n    .handle_config_line = all_plugins_handle_config_line_func,\n    .handle_control_flag_line = all_plugins_handle_control_flag_line_func,\n    .set_config = all_plugins_set_config_func,\n    .setup_ipc = all_plugins_setup_ipc_func,\n    .handle_ipc_change = all_plugins_handle_ipc_change_func,\n    .modify_reference_pose = all_plugins_modify_reference_pose_func,\n    .handle_reference_pose_updated = all_plugins_handle_reference_pose_updated_func,\n    .modify_pose = all_plugins_modify_pose_func,\n    .handle_pose_data = all_plugins_handle_pose_data_func,\n    .reset_pose_data = all_plugins_reset_pose_data_func,\n    .handle_state = all_plugins_handle_state_func,\n    .handle_device_connect = all_plugins_handle_device_connect_func,\n    .handle_device_disconnect = all_plugins_handle_device_disconnect_func\n};"
  },
  {
    "path": "src/runtime_context.c",
    "content": "#include \"devices.h\"\n#include \"runtime_context.h\"\n\n#include <pthread.h>\n#include <stdlib.h>\n\nruntime_context g_runtime_context;\n\nstatic int device_ref_count = 0;\npthread_mutex_t device_ref_count_mutex = PTHREAD_MUTEX_INITIALIZER;\nstatic device_properties_type* queued_device = NULL;\nstatic on_device_change_callback on_device_change_callback_func = NULL;\n\n// the mutex must already be locked when calling this function\nstatic bool _check_and_set_queued_device() {\n    if (g_runtime_context.device == NULL && queued_device != NULL) {\n        g_runtime_context.device = queued_device;\n        queued_device = NULL;\n        device_ref_count = 1;\n        return true;\n    }\n\n    return false;\n}\n\nvoid set_device_and_checkout(device_properties_type* device) {\n    bool device_changed = false;\n    pthread_mutex_lock(&device_ref_count_mutex);\n    if (!device_equal(device, g_runtime_context.device)) {\n        queued_device = device;\n        device_changed = _check_and_set_queued_device();\n    } else {\n        device_ref_count++;\n    }\n    pthread_mutex_unlock(&device_ref_count_mutex);\n\n    if (device_changed && on_device_change_callback_func != NULL) on_device_change_callback_func();     \n}\n\ndevice_properties_type* device_checkout() {\n    device_properties_type* device = NULL;\n\n    pthread_mutex_lock(&device_ref_count_mutex);\n    if (device_present()) {\n        device_ref_count++;\n        device = g_runtime_context.device;\n    }\n    pthread_mutex_unlock(&device_ref_count_mutex);\n\n    return device;\n}\n\nvoid device_checkin(device_properties_type* device) {\n    bool device_changed = false;\n    \n    pthread_mutex_lock(&device_ref_count_mutex);\n    if (device_ref_count > 0 && device_equal(device, g_runtime_context.device)) {\n        device_ref_count--;\n        if (device_ref_count == 0) {\n            free(g_runtime_context.device);\n            g_runtime_context.device = NULL;\n            _check_and_set_queued_device();\n            device_changed = true;\n        }\n    } else if (device_equal(device, queued_device)) {\n        free(queued_device);\n        queued_device = NULL;\n    }\n    pthread_mutex_unlock(&device_ref_count_mutex);\n\n    if (device_changed && on_device_change_callback_func != NULL) on_device_change_callback_func();\n}\n\n// if a device is queued, the current device is already disconnected, return false until queued device takes over\nbool device_present() {\n    return g_runtime_context.device != NULL && queued_device == NULL;\n}\n\nvoid set_on_device_change_callback(on_device_change_callback callback) {\n    on_device_change_callback_func = callback;\n}"
  },
  {
    "path": "src/state.c",
    "content": "#include \"devices.h\"\n#include \"imu.h\"\n#include \"logging.h\"\n#include \"memory.h\"\n#include \"plugins.h\"\n#include \"state.h\"\n#include \"strings.h\"\n#include \"system.h\"\n\n#include <inttypes.h>\n#include <errno.h>\n#include <pthread.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/inotify.h>\n#include <sys/time.h>\n#include <math.h>\n\nconst char *calibration_setup_strings[2] = {\n    \"AUTOMATIC\",\n    \"INTERACTIVE\"\n};\nconst char *calibration_state_strings[4] = {\n    \"NOT_CALIBRATED\",\n    \"CALIBRATED\",\n    \"CALIBRATING\",\n    \"WAITING_ON_USER\"\n};\n\nconst char* state_files_directory = \"/dev/shm\";\nconst char* state_filename = \"xr_driver_state\";\nconst char* control_flags_filename = \"xr_driver_control\";\n\nFILE* get_driver_state_file(const char *filename, char *mode, char **full_path) {\n    int full_path_length = strlen(state_files_directory) + strlen(filename) + 2;\n    *full_path = malloc(full_path_length);\n    snprintf(*full_path, full_path_length, \"%s/%s\", state_files_directory, filename);\n    return fopen(*full_path, mode ? mode : \"r\");\n}\n\npthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER;\nvoid write_state(driver_state_type *state) {\n    pthread_mutex_lock(&state_mutex);\n    char *full_path = NULL;\n    FILE* fp = get_driver_state_file(state_filename, \"w\", &full_path);\n\n    fprintf(fp, \"heartbeat=%d\\n\", state->heartbeat);\n    if (get_hardware_id()) fprintf(fp, \"hardware_id=%s\\n\", get_hardware_id());\n    if (state->device_license) fprintf(fp, \"device_license=%s\\n\", state->device_license);\n    if (state->connected_device_model && state->connected_device_brand) {\n        fprintf(fp, \"connected_device_brand=%s\\n\", state->connected_device_brand);\n        fprintf(fp, \"connected_device_model=%s\\n\", state->connected_device_model);\n        fprintf(fp, \"calibration_setup=%s\\n\", calibration_setup_strings[state->calibration_setup]);\n        fprintf(fp, \"calibration_state=%s\\n\", calibration_state_strings[state->calibration_state]);\n        fprintf(fp, \"sbs_mode_supported=%s\\n\", state->sbs_mode_supported ? \"true\" : \"false\");\n        fprintf(fp, \"sbs_mode_enabled=%s\\n\", state->sbs_mode_enabled ? \"true\" : \"false\");\n        fprintf(fp, \"connected_device_full_distance_cm=%.2f\\n\", state->connected_device_full_distance_cm);\n        fprintf(fp, \"connected_device_full_size_cm=%.2f\\n\", state->connected_device_full_size_cm);\n        fprintf(fp, \"connected_device_pose_has_position=%s\\n\", state->connected_device_pose_has_position ? \"true\" : \"false\");\n        if (state->breezy_desktop_smooth_follow_enabled)\n            fprintf(fp, \"breezy_desktop_smooth_follow_enabled=true\\n\");\n        if (state->is_gamescope_reshade_ipc_connected)\n            fprintf(fp, \"is_gamescope_reshade_ipc_connected=true\\n\");\n        fprintf(fp, \"firmware_update_recommended=%s\\n\", state->firmware_update_recommended ? \"true\" : \"false\");\n    }\n\n    fclose(fp);\n    pthread_mutex_unlock(&state_mutex);\n}\n\nvoid read_control_flags(FILE *fp, control_flags_type *flags) {\n    if (fp) {\n        char line[1024];\n        while (fgets(line, sizeof(line), fp) != NULL) {\n            char *key = strtok(line, \"=\");\n            char *value = strtok(NULL, \"\\n\");\n            if (strcmp(key, \"recenter_screen\") == 0) {\n                flags->recenter_screen = strcmp(value, \"true\") == 0;\n            } else if (strcmp(key, \"recalibrate\") == 0) {\n                flags->recalibrate = strcmp(value, \"true\") == 0;\n            } else if (strcmp(key, \"sbs_mode\") == 0) {\n                if (strcmp(value, \"unset\") == 0) {\n                    flags->sbs_mode = SBS_CONTROL_UNSET;\n                } else if (strcmp(value, \"disable\") == 0) {\n                    flags->sbs_mode = SBS_CONTROL_DISABLE;\n                } else if (strcmp(value, \"enable\") == 0) {\n                    flags->sbs_mode = SBS_CONTROL_ENABLE;\n                } else {\n                    log_message(\"Invalid sbs_mode value: %s\\n\", value);\n                }\n            } else if (strcmp(key, \"force_quit\") == 0) {\n                flags->force_quit = strcmp(value, \"true\") == 0;\n            } else if (strcmp(key, \"request_features\") == 0) {\n                free_and_clear(&flags->request_features);\n                if (value && strlen(value) > 0) {\n                    flags->request_features = strdup(value);\n                    if (!flags->request_features) {\n                        log_error(\"Failed to allocate memory for request_features\\n\");\n                    }\n                }\n            }\n            plugins.handle_control_flag_line(key, value);\n        }\n    }\n}\n\nvoid update_state_from_device(driver_state_type *state, device_properties_type *primary_device, device_properties_type *supplemental_device, device_driver_type *device_driver) {\n    pthread_mutex_lock(&state_mutex);\n\n    bool was_sbs_mode_enabled = state->sbs_mode_enabled;\n    struct timeval tv;\n    gettimeofday(&tv, NULL);\n    state->heartbeat = tv.tv_sec;\n    state->calibration_setup = CALIBRATION_SETUP_AUTOMATIC;\n    state->sbs_mode_supported = false;\n    state->sbs_mode_enabled = false;\n    state->firmware_update_recommended = false;\n    if (primary_device == NULL) {\n        // not connected\n        free_and_clear(&state->connected_device_brand);\n        free_and_clear(&state->connected_device_model);\n    } else {\n        state->sbs_mode_enabled = false;\n        if (primary_device->sbs_mode_supported && device_driver != NULL && device_driver->is_connected_func()) {\n            state->sbs_mode_enabled = device_driver->device_is_sbs_mode_func();\n        }\n        state->firmware_update_recommended = primary_device->firmware_update_recommended;\n        if (state->connected_device_brand == NULL || !equal(state->connected_device_brand, primary_device->brand)) {\n            free_and_clear(&state->connected_device_brand);\n            state->connected_device_brand = strdup(primary_device->brand);\n        }\n        if (state->connected_device_model == NULL || !equal(state->connected_device_model, primary_device->model)) {\n            free_and_clear(&state->connected_device_model);\n            state->connected_device_model = strdup(primary_device->model);\n        }\n\n        // Rough estimate of display parameters based on lens distance ratio and FOV\n        float full_distance_cm = LENS_TO_PIVOT_CM / primary_device->lens_distance_ratio;\n        state->connected_device_full_distance_cm = full_distance_cm;\n        state->connected_device_full_size_cm = 2.0f * full_distance_cm * tanf(degree_to_radian(primary_device->fov) * 0.5f);\n        state->connected_device_pose_has_position = primary_device->provides_position || (supplemental_device != NULL && supplemental_device->provides_position);\n\n        state->calibration_setup = primary_device->calibration_setup;\n        state->sbs_mode_supported = primary_device->sbs_mode_supported;\n    }\n\n    if (was_sbs_mode_enabled != state->sbs_mode_enabled) {\n        if (state->sbs_mode_enabled) {\n            log_message(\"SBS mode has been enabled\\n\");\n        } else {\n            log_message(\"SBS mode has been disabled\\n\");\n        }\n    }\n\n    pthread_mutex_unlock(&state_mutex);\n}"
  },
  {
    "path": "src/strings.c",
    "content": "#include <string.h>\n#include <stdio.h>\n#include <stdbool.h>\n#include <stdlib.h>\n\nbool equal(const char *a, const char *b) {\n    return strcmp(a, b) == 0;\n}\n\nbool list_string_contains(const char* str, const char* list_string) {\n    if (str == NULL || list_string == NULL) return false;\n\n    const char* p = list_string;\n    size_t len = strlen(str);\n\n    while (*p) {\n        // Find the end of the current token\n        const char* start = p;\n        while (*p && *p != ',') p++;\n        size_t token_len = (size_t)(p - start);\n        // Compare lengths and content\n        if (token_len == len && strncmp(start, str, len) == 0) {\n            return true;\n        }\n        // Move to the next token if not at the end\n        if (*p == ',') p++;\n    }\n\n    return false;\n}\n\nbool in_array(const char *str, const char **array, int size) {\n    if (array == NULL || str == NULL) return false;\n\n    for (int i = 0; i < size; i++) {\n        if (equal(str, array[i])) {\n            return true;\n        }\n    }\n    return false;\n}\n\nconst char* concat(const char* path, const char* extension) {\n    char* s = malloc((strlen(path) + strlen(extension) + 1) * sizeof(char));\n    strcpy(s, path);\n    strcat(s, extension);\n\n    return s;\n}\n\n// Comparison function intended for qsort\nint compare_strings(const void* a, const void* b) {\n    return strcmp(*(const char**)a, *(const char**)b);\n}\n\n// Deep copy an array of strings\nchar** deep_copy_string_array(char** array, int count) {\n    if (count == 0 || !array) return NULL;\n    \n    char** copy = calloc(count, sizeof(char*));\n    if (!copy) return NULL;\n    \n    int i;\n    for (i = 0; i < count; i++) {\n        if (!array[i]) {\n            goto cleanup_and_fail;\n        }\n        copy[i] = strdup(array[i]);\n        if (!copy[i]) {\n            goto cleanup_and_fail;\n        }\n    }\n    return copy;\n\ncleanup_and_fail:\n    for (int j = 0; j < i; j++) {\n        free(copy[j]);\n    }\n    free(copy);\n    return NULL;\n}\n\n// Parse comma-separated string into array of strings\nint parse_comma_separated_string(const char* str, char*** result) {\n    if (!str || strlen(str) == 0) {\n        *result = NULL;\n        return 0;\n    }\n\n    char* str_copy = strdup(str);\n    if (!str_copy) {\n        *result = NULL;\n        return 0;\n    }\n    \n    int count = 0;\n    *result = NULL;\n\n    char* token = strtok(str_copy, \",\");\n    while (token != NULL) {\n        // Trim whitespace\n        while (*token == ' ') token++;\n        char* end = token + strlen(token) - 1;\n        while (end > token && *end == ' ') end--;\n        *(end + 1) = '\\0';\n\n        if (strlen(token) > 0) {\n            char** temp = realloc(*result, (count + 1) * sizeof(char*));\n            if (!temp) {\n                // Clean up on allocation failure\n                for (int i = 0; i < count; i++) {\n                    free((*result)[i]);\n                }\n                free(*result);\n                free(str_copy);\n                *result = NULL;\n                return 0;\n            }\n            *result = temp;\n            (*result)[count] = strdup(token);\n            if (!(*result)[count]) {\n                // Clean up on strdup failure\n                for (int i = 0; i < count; i++) {\n                    free((*result)[i]);\n                }\n                free(*result);\n                free(str_copy);\n                *result = NULL;\n                return 0;\n            }\n            count++;\n        }\n        token = strtok(NULL, \",\");\n    }\n\n    free(str_copy);\n    return count;\n}"
  },
  {
    "path": "src/system.c",
    "content": "#include \"logging.h\"\n#include \"strings.h\"\n\n#include <ifaddrs.h>\n#include <net/if.h>\n#include <netinet/in.h>\n#include <openssl/sha.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdbool.h>\n#include <sys/ioctl.h>\n#include <sys/socket.h>\n#include <unistd.h>\n\n#define NET_INTERFACE_COUNT 2\nconst char *network_interfaces[NET_INTERFACE_COUNT] = {\"eth0\", \"wlan0\"};\n\nbool get_mac_address_hash(char **mac_address_hash, const char *interface) {\n    int fd;\n    struct ifreq ifr;\n\n    fd = socket(AF_INET, SOCK_DGRAM, 0);\n    if (fd < 0) return false;\n\n    ifr.ifr_addr.sa_family = AF_INET;\n    strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);\n\n    bool found = false;\n    if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0) {\n        unsigned char *mac = (unsigned char *)ifr.ifr_hwaddr.sa_data;\n\n        bool isZeroMac = true;\n        for (int i = 0; i < 6; ++i) {\n            if (mac[i] != 0) {\n                isZeroMac = false;\n                break;\n            }\n        }\n\n        if (isZeroMac) return false;\n\n        char mac_str[18];\n        snprintf(mac_str, sizeof(mac_str), \"%02x:%02x:%02x:%02x:%02x:%02x\",\n                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);\n\n        unsigned char hash[SHA256_DIGEST_LENGTH];\n        SHA256((unsigned char*)mac_str, strlen(mac_str), hash);\n\n        *mac_address_hash = calloc(1, SHA256_DIGEST_LENGTH*2 + 1);\n        for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)\n            sprintf(*mac_address_hash + (i*2), \"%02x\", hash[i]);\n\n        found = true;\n        log_message(\"Using hardware id %s\\n\", *mac_address_hash);\n    }\n    close(fd);\n\n    return found;\n}\n\n#define RETRY_ATTEMPTS 6\n#define RETRY_DELAY_SEC 5 // with 6 retries: 30 seconds of total attempts\n\npthread_mutex_t get_hardware_id_lock = PTHREAD_MUTEX_INITIALIZER;\nchar *get_hardware_id() {\n    static char *mac_address_hash = NULL;\n    static bool no_mac_address = false;\n\n    pthread_mutex_lock(&get_hardware_id_lock);\n    if (!mac_address_hash && !no_mac_address) {\n        int attempts = 0;\n        bool found = false;\n        while (!found && attempts <= RETRY_ATTEMPTS) {\n            // check these first so that hardwareIds don't change from the old logic here\n            for (int i = 0; i < NET_INTERFACE_COUNT && !found; i++) {\n                found = get_mac_address_hash(&mac_address_hash, network_interfaces[i]);\n            }\n\n            if (!found) {\n                // find and sort the remaining interfaces before generating a hash \n                // in an attempt to get a consistent hardwareId\n                struct ifaddrs *ifaddr, *ifa;\n                char **remaining_interfaces = NULL;\n                int remaining_count = 0;\n\n                if (getifaddrs(&ifaddr) != -1) {\n                    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {\n                        if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET ||\n                            in_array(ifa->ifa_name, network_interfaces, NET_INTERFACE_COUNT))\n                            continue;\n                        remaining_count++;\n                    }\n\n                    remaining_interfaces = malloc(remaining_count * sizeof(char*));\n                    if (remaining_interfaces == NULL) {\n                        log_error(\"Memory allocation failed\\n\");\n                        freeifaddrs(ifaddr);\n                        break;\n                    }\n\n                    int index = 0;\n                    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {\n                        if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET ||\n                            in_array(ifa->ifa_name, network_interfaces, NET_INTERFACE_COUNT))\n                            continue;\n                        remaining_interfaces[index++] = strdup(ifa->ifa_name);\n                    }\n\n                    // sort by ifa->ifa_name\n                    qsort(remaining_interfaces, remaining_count, sizeof(char*), compare_strings);\n                    for (int i = 0; i < remaining_count && !found; i++) {\n                        found = get_mac_address_hash(&mac_address_hash, remaining_interfaces[i]);\n                    }\n\n                    for (int i = 0; i < remaining_count; i++) {\n                        free(remaining_interfaces[i]);\n                    }\n                    free(remaining_interfaces);\n                    freeifaddrs(ifaddr);\n                }\n            }\n\n            if (!found && ++attempts <= RETRY_ATTEMPTS) {\n                log_error(\"Failed to get hardwareId, retrying in %d seconds\\n\", RETRY_DELAY_SEC);\n                sleep(RETRY_DELAY_SEC);\n            }\n        }\n\n        no_mac_address = !found;\n    }\n    pthread_mutex_unlock(&get_hardware_id_lock);\n\n    return mac_address_hash;\n}"
  },
  {
    "path": "src/wl_client/gamescope_reshade.c",
    "content": "/* Generated by wayland-scanner 1.23.0 */\n\n/*\n * Copyright © 2024 Wayne Heaney\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"wayland-util.h\"\n\n#ifndef __has_attribute\n# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n\n#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n#else\n#define WL_PRIVATE\n#endif\n\n\nstatic const struct wl_interface *gamescope_reshade_types[] = {\n\tNULL,\n\tNULL,\n};\n\nstatic const struct wl_message gamescope_reshade_requests[] = {\n\t{ \"destroy\", \"\", gamescope_reshade_types + 0 },\n\t{ \"set_effect\", \"s\", gamescope_reshade_types + 0 },\n\t{ \"enable_effect\", \"\", gamescope_reshade_types + 0 },\n\t{ \"set_uniform_variable\", \"sa\", gamescope_reshade_types + 0 },\n\t{ \"disable_effect\", \"\", gamescope_reshade_types + 0 },\n};\n\nstatic const struct wl_message gamescope_reshade_events[] = {\n\t{ \"effect_ready\", \"s\", gamescope_reshade_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface gamescope_reshade_interface = {\n\t\"gamescope_reshade\", 1,\n\t5, gamescope_reshade_requests,\n\t1, gamescope_reshade_events,\n};\n\n"
  },
  {
    "path": "systemd/xr-driver.service",
    "content": "[Unit]\nDescription=XR user-space driver\nAfter=network.target\n\n[Service]\nType=simple\nEnvironment=LD_LIBRARY_PATH={ld_library_path}\nExecStart={bin_dir}/xrDriver\nRestart=always\n\n[Install]\nWantedBy=default.target\n"
  },
  {
    "path": "udev/70-rayneo-xr.rules",
    "content": "SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"1bbb\", MODE=\"0660\", TAG+=\"uaccess\""
  },
  {
    "path": "udev/70-rokid-xr.rules",
    "content": "SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"04d2\", MODE=\"0660\", TAG+=\"uaccess\""
  },
  {
    "path": "udev/70-uinput-xr.rules",
    "content": "# Mouse output\nKERNEL==\"uinput\", SUBSYSTEM==\"misc\" MODE=\"0660\", TAG+=\"uaccess\", OPTIONS+=\"static_node=uinput\""
  },
  {
    "path": "udev/70-viture-xr.rules",
    "content": "SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"35ca\", MODE=\"0660\", TAG+=\"uaccess\"\nSUBSYSTEM==\"usb\", KERNEL==\"hiddev[0-9]*\", ATTRS{idVendor}==\"35ca\", MODE=\"0660\", TAG+=\"uaccess\"\nSUBSYSTEM==\"tty\", KERNEL==\"ttyACM[0-9]*\", ATTRS{idVendor}==\"35ca\", MODE=\"0660\", TAG+=\"uaccess\"\nSUBSYSTEM==\"hidraw\", KERNEL==\"hidraw[0-9]*\", ATTRS{idVendor}==\"35ca\", MODE=\"0660\", TAG+=\"uaccess\""
  },
  {
    "path": "udev/70-xreal-xr.rules",
    "content": "# Rule for USB devices\nSUBSYSTEM==\"usb\", ACTION==\"add\", ATTR{idVendor}==\"3318\", MODE=\"0660\", TAG+=\"uaccess\"\n\n# Rule for Input devices (such as eventX)\nSUBSYSTEM==\"input\", KERNEL==\"event[0-9]*\", ATTRS{idVendor}==\"3318\", MODE=\"0660\", TAG+=\"uaccess\"\n\n# Rule for Sound devices (pcmCxDx and controlCx)\nSUBSYSTEM==\"sound\", KERNEL==\"pcmC[0-9]D[0-9]p\", ATTRS{idVendor}==\"3318\", MODE=\"0660\", TAG+=\"uaccess\"\nSUBSYSTEM==\"sound\", KERNEL==\"controlC[0-9]\", ATTRS{idVendor}==\"3318\", MODE=\"0660\", TAG+=\"uaccess\"\n\n# Rule for HID Devices (hidraw)\nSUBSYSTEM==\"hidraw\", KERNEL==\"hidraw[0-9]*\", ATTRS{idVendor}==\"3318\", MODE=\"0660\", TAG+=\"uaccess\"\n\n# Rule for HID Devices (hiddev)\nSUBSYSTEM==\"usb\", KERNEL==\"hiddev[0-9]*\", ATTRS{idVendor}==\"3318\", MODE=\"0660\", TAG+=\"uaccess\""
  }
]